Skip to content

Feat/kiloclaw provision pin support#753

Merged
St0rmz1 merged 8 commits intomainfrom
feat/kiloclaw-provision-pin-support
Mar 3, 2026
Merged

Feat/kiloclaw provision pin support#753
St0rmz1 merged 8 commits intomainfrom
feat/kiloclaw-provision-pin-support

Conversation

@St0rmz1
Copy link
Contributor

@St0rmz1 St0rmz1 commented Mar 3, 2026

feat: KiloClaw Phase 2 — provision pin support and admin UI

Wire pinnedImageTag through the full provision flow so pinned users get their specific image version instead of :latest.

Provision flow:

  • Query kiloclaw_version_pins before provision (kiloclaw-router.ts)
  • Pass pinnedImageTag through worker route to DO (platform.ts)
  • DO resolves pin metadata from KV first, Postgres catalog fallback
  • Add lookupCatalogVersion() for Postgres-based tag resolution
  • Track trackedImageDigest through full DO lifecycle

Admin UI:

  • Reframe Version Pin UI around image tag as primary identity
  • Add 'latest' badge on Versions tab via /versions/latest endpoint
  • Show OpenClaw Version, Variant, Image Tag, Digest on instance detail
  • Image tag shown as primary in pin dropdowns and badges

Safety:

  • Block disabling :latest version (must push new image first)
  • Friendly error on FK violation when pinning to non-existent tag
  • Fail-open if worker unreachable during latest check

Dev tooling:

  • push-dev.sh captures image digest via --metadata-file
  • Debug logging in provision and start paths

St0rmz1 added 2 commits March 2, 2026 16:16
Wire pinnedImageTag through the full provision flow so pinned users get their specific image version instead of :latest.
@kilo-code-bot
Copy link
Contributor

kilo-code-bot bot commented Mar 3, 2026

Code Review Summary

Status: No New Issues Found | Recommendation: Merge

Overview

This PR adds version pinning support to KiloClaw, allowing admins to pin specific users to specific image tags during provision. The implementation is thorough and well-structured:

  • Provision flow: Pinned users resolve their image tag via KV (O(1) lookup) → Postgres catalog fallback → raw tag fallback. Unpinned users continue using the latest registered version.
  • Admin tooling: New getLatestTag, syncCatalog endpoints, disable-latest guard, FK error handling on setPin, and UI improvements for version/pin management.
  • Data model: trackedImageDigest added throughout the DO lifecycle (provision, restart, restore, destroy, getStatus).
  • Cross-platform fix: sed -i '' replaced with temp file + mv pattern.

All previously identified issues (35 inline comments) have been addressed in subsequent commits:

  • as ImageVariantImageVariantSchema.safeParse() runtime validation
  • getLatestVersion() error swallowing → only catches 404
  • ✅ O(n) KV scan → O(1) tag lookup key with backfill fallback
  • ✅ N+1 query → bulk inArray() query with early empty-array guard
  • ✅ Missing runtime import → value import for ImageVariantSchema
  • ✅ Stale metadata on fallback → explicit null assignments
  • pinnedImageTag validation → regex + max length via IMAGE_TAG_RE
  • syncCatalog validation → inline regex matching validateEntry() rules
  • ✅ Overly broad FK error matching → narrowed to 'foreign key'
  • ✅ Misleading toast → separate counts for synced/existed/invalid
Other Observations (not in diff)
File Line Issue
src/routers/admin-kiloclaw-versions-router.test.ts [SUGGESTION]: No test coverage for syncCatalog or getLatestTag endpoints. The mock returns null for getLatestVersion, so the disable-latest guard is never exercised in tests. Consider adding tests that mock a non-null latest version to verify the guard blocks disabling it.
src/routers/admin-kiloclaw-versions-router.ts 296 [SUGGESTION]: syncCatalog inline validation omits the future-date and old-date checks present in validateEntry(). This means KV entries with timestamps >1 year old or in the future will be synced to Postgres but would be rejected by direct registration. Low risk since KV data is written by trusted code, but worth noting for consistency.
Files Reviewed (14 files)
  • kiloclaw/scripts/push-dev.sh - 0 new issues (cross-platform sed fix applied)
  • kiloclaw/src/durable-objects/kiloclaw-instance.ts - 0 new issues (pin resolution, digest tracking)
  • kiloclaw/src/lib/catalog-registration.ts - 0 new issues (new lookupCatalogVersion)
  • kiloclaw/src/lib/image-version.ts - 0 new issues (O(1) tag lookup, scan fallback)
  • kiloclaw/src/routes/platform.ts - 0 new issues (new /versions/latest endpoint)
  • kiloclaw/src/schemas/instance-config.ts - 0 new issues (pinnedImageTag, trackedImageDigest)
  • src/app/(app)/claw/components/withStatusQueryBoundary.test.ts - 0 new issues (fixture update)
  • src/app/admin/components/KiloclawInstances/KiloclawInstanceDetail.tsx - 0 new issues (UI label updates)
  • src/app/admin/components/KiloclawVersions/KiloclawVersionsPage.tsx - 0 new issues (sync button, latest badge)
  • src/lib/kiloclaw/kiloclaw-internal-client.ts - 0 new issues (listVersions, getLatestVersion)
  • src/lib/kiloclaw/types.ts - 0 new issues (type additions)
  • src/routers/admin-kiloclaw-versions-router.test.ts - 0 new issues (mock setup)
  • src/routers/admin-kiloclaw-versions-router.ts - 0 new issues (sync, latest guard, FK handling)
  • src/routers/kiloclaw-router.ts - 0 new issues (pin lookup during provision)

} else {
// Pinned tag not found in KV or Postgres — use the tag directly but metadata is unknown.
// Clear version metadata to avoid stale values from a previous provision.
console.warn(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this correspond to? As in, where did this tag come from if we don't know about it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tag comes from the admin panel — an admin sets a version pin for a user via the Pins tab, which stores the image tag in the kiloclaw_version_pins Postgres table. When that user's instance is provisioned, the cloud app reads their pin and passes pinnedImageTag to the worker.

The tag might not be found in KV or the catalog if:

  1. The catalog was cleared/rebuilt and the tag wasn't re-synced
  2. The image was pushed directly to the Fly registry without going through registerVersionIfNeeded() (e.g. a manual docker push)
  3. Race condition during first deploy of a new version

In all these cases, the tag is still valid in the Fly registry — we just don't have metadata (version, variant, digest) for it. Provision proceeds with the raw tag and Fly resolves it. The warn log makes this visible for investigation.

@St0rmz1 St0rmz1 requested a review from pandemicsyn March 3, 2026 16:43
@St0rmz1 St0rmz1 merged commit a8fb193 into main Mar 3, 2026
12 checks passed
@St0rmz1 St0rmz1 deleted the feat/kiloclaw-provision-pin-support branch March 3, 2026 18:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants