Skip to content

fix: harden legacy host-state migration and documentation#228

Merged
ian-pascoe merged 2 commits into
mainfrom
worktree/silver-field-9497
Jul 19, 2026
Merged

fix: harden legacy host-state migration and documentation#228
ian-pascoe merged 2 commits into
mainfrom
worktree/silver-field-9497

Conversation

@ian-pascoe

@ian-pascoe ian-pascoe commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Summary

  • make storage migrate-legacy use platform default paths while retaining explicit overrides and actionable tracked-Caplet errors
  • preserve legacy Vault grants and shared key access while importing auth, remote security, setup, activity, and tracked installation provenance transactionally
  • add focused migration and CLI regression coverage plus the required package changeset
  • add public guides for Authoritative Host State, Project Binding, privacy/network activity, and the CLI; correct migration, Vault, dashboard, catalog-indexing, attach, and native-integration guidance
  • expand generated config reference, navigation, cross-links, and public-doc guardrails

Verification

  • pnpm verify (pre-push gate)
  • rendered desktop/mobile documentation review for storage, Project Binding, privacy, and CLI routes

Notable disclosures documented

  • catalog indexing can submit the full installed CAPLET.md, and GitHub-shaped eligibility does not verify repository visibility
  • managed Project Binding is currently wired for native Cloud and loopback-daemon sessions; ordinary CLI attach remains a thin MCP adapter

Summary by CodeRabbit

  • New Features

    • Added authoritative host-state support documentation for SQLite, PostgreSQL, backups, migrations, and optional S3-compatible asset storage.
    • Added guidance for project binding, runtime selection, CLI commands, privacy controls, and catalog indexing.
    • Legacy migration now detects platform-default paths and provides clearer guidance for missing tracked Caplets.
  • Bug Fixes

    • Improved migration of authentication, Vault, remote security, setup, activity, and tracked-Caplet state.
  • Documentation

    • Added a required upgrade notice for versions 0.25.x and earlier.
    • Updated the minimum Node.js requirement to 22.

@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR generalizes legacy Vault grant migration to support both stored-record and file-origin grants, updates CLI defaults for storage migrate-legacy to use platform paths, adds regression/integration tests, and adds/rewrites extensive documentation covering required upgrade migration, Authoritative Host State, project binding, privacy, and CLI reference.

Changes

Legacy Migration Code and Tests

Layer / File(s) Summary
Generalized vault grant types and storage APIs
packages/core/src/storage/vault-grants.ts
Introduces LegacyVaultGrantImport with originKind/originPath, replacing record-only legacy import/verify methods with generalized SQLite/Postgres APIs.
Legacy migration planner and backup moves
packages/core/src/storage/legacy-migration.ts
Reworks planning of vault grant imports, adds preserved-source copy-based backup moves, and refines missing-tracked-path error messages.
CLI default path resolution
packages/core/src/cli.ts
Makes --caplets-root/--lockfile optional for migrate-legacy, computing platform defaults when omitted.
Migration tests
packages/core/test/legacy-migration.test.ts, packages/core/test/storage-records-cli.test.ts
Adds a missing-path regression test and a full platform-default dry-run/write migration integration test.
Changelogs
.changeset/clean-cups-help.md, packages/cli/CHANGELOG.md, packages/core/CHANGELOG.md
Documents required migration steps for the release.

Documentation Additions and Rewrites

Layer / File(s) Summary
Upgrade migration notices
README.md, apps/docs/src/content/docs/index.mdx, install.mdx, troubleshooting.mdx, docs/operations/sql-authoritative-host-state.md
Adds required legacy migration warnings and dry-run/write command instructions.
Authoritative Host State / storage docs
apps/docs/src/content/docs/storage.mdx, configuration.mdx, reference/config.mdx, vault.mdx, scripts/generate-docs-reference.ts
Adds storage backend documentation and generated schema section for SQLite/PostgreSQL config.
CLI reference
apps/docs/src/content/docs/reference/cli.mdx
Adds a complete CLI command reference page.
Project binding and runtime selection
project-binding.mdx, agent-integrations.mdx, remote-attach.mdx, dashboard.mdx, troubleshooting.mdx
Adds project binding docs and updates runtime-selection/approval-flow guidance.
Privacy and catalog indexing
privacy.mdx, privacy/indexing.mdx, catalog.mdx, install.mdx
Adds telemetry/update-check/indexing privacy docs and reworded catalog eligibility text.
Navigation and doc checks
apps/docs/astro.config.mjs, scripts/check-public-docs.ts
Restructures sidebar groups and expands required-docs validation.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Operator
  participant CLI as "caplets CLI"
  participant Migration as "migrateLegacyHostState"
  participant VaultGrantStore
  participant SQLStorage as "SQL Host Storage"

  Operator->>CLI: storage migrate-legacy --dry-run
  CLI->>Migration: resolve default caplets root/lockfile paths
  Migration->>Migration: plan vault grants (stored-record vs file origin)
  Migration->>VaultGrantStore: assertLegacyGrantsImportable(grants)
  VaultGrantStore-->>Migration: validation result
  Migration-->>CLI: dry-run report (counts, no writes)
  CLI-->>Operator: JSON status

  Operator->>CLI: storage migrate-legacy
  CLI->>Migration: run write migration
  Migration->>SQLStorage: import domains in transaction
  Migration->>VaultGrantStore: importLegacyGrantsInTransaction(grants)
  VaultGrantStore->>SQLStorage: insert pending grants
  Migration->>VaultGrantStore: verifyLegacyGrantsInTransaction(grants)
  Migration->>Migration: move legacy artifacts to timestamped backup
  Migration-->>CLI: migrated status + backupPath
  CLI-->>Operator: JSON status
Loading

Poem

A rabbit hopped through Vault and grant,
stitched stored and file paths with a plant of care,
migrate-legacy now finds its own way,
platform paths default, backups tucked away.
Docs bloom like carrots, page by page —
🥕 hop on, upgrade, and turn the sage!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: legacy host-state migration hardening plus related documentation updates.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree/silver-field-9497

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

@greptile-apps

greptile-apps Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR hardens the storage migrate-legacy command by replacing required --caplets-root/--lockfile flags with platform-default path resolution, and expands migration scope to preserve legacy Vault grants for both tracked (stored-record) and file-origin (overlay) caplets. The vault-key file is now copied rather than moved when the SQL vault root co-locates with the legacy vault, and the backup rollback path handles this correctly.

  • cli.ts: --caplets-root and --lockfile become optional; CLI resolves platform-default paths for auth, vault, remote-security, setup, and operator-activity dirs.
  • vault-grants.ts: LegacyRecordVaultGrantImport is generalized to LegacyVaultGrantImport supporting both stored-record and file-origin subjects; all downstream assert/import/verify methods are updated accordingly.
  • legacy-migration.ts: plannedVaultGrants promotes global-file grants for tracked caplets to stored-record, adds preserveSource flag to copy-rather-than-move the vault-key, and sharpens the missing-caplet error message with actionable path detail. A comprehensive CLI integration test exercises auth, remote-security, vault, and operator-activity domains end-to-end.

Confidence Score: 5/5

Safe to merge; all migration paths are transactional, the vault-key copy/preserve logic is correctly guarded, and the end-to-end CLI test now exercises every newly wired domain.

The migration refactoring is internally consistent: vault-grant promotion logic, the preserveSource copy-vs-move distinction, and the pre-check split for pending stored-record grants all hold under the scenarios exercised by the new tests. The CLI default-path resolution matches the test fixture. Both previously noted concerns (shared remoteSecurityDir/operatorActivityDir and the pre-check gap for pending grants) now have explanatory comments in the code. No new logic gaps were identified during the review.

No files require special attention.

Important Files Changed

Filename Overview
packages/core/src/storage/legacy-migration.ts Core migration logic refactored to support both stored-record and file-origin vault grants, preserve the vault-key file in-place, and supply clearer actionable error messages; logic is consistent and correct.
packages/core/src/storage/vault-grants.ts LegacyVaultGrantImport generalized from record-only to multi-origin; all assert/import/verify paths updated consistently; subject resolution split into SQLite/Postgres helpers with proper error handling.
packages/core/src/cli.ts Options made optional with platform-default fallbacks; all new path computations (authDir, legacyVaultRoot, setupStateDir, operatorActivityDir) are consistent with the test fixture; shared-directory comment added per prior review.
packages/core/test/storage-records-cli.test.ts Expanded from a dry-run-only stub to a full end-to-end test covering auth tokens, remote-security pairing codes and clients, pending logins, vault values and grants (both record and file origins), and operator-activity entries.
packages/core/test/legacy-migration.test.ts New test exercises the missing-tracked-caplet error message format (including destination path and lockfile path), matching the improved error string in planArtifacts.
scripts/generate-docs-reference.ts Adds a dedicated handcrafted section for the storage config in the generated reference (SQLite/PostgreSQL tables and asset/limit descriptions); existing schema-driven path unchanged for other keys.
scripts/check-public-docs.ts Extends the required-pages and required-content guardrails to cover the new public documentation pages added in this PR.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[caplets storage migrate-legacy] --> B{Options provided?}
    B -- "--caplets-root / --lockfile" --> C[Use explicit paths]
    B -- "No flags" --> D[Resolve platform defaults\nauthDir · lockfilePath\nlegacyVaultRoot · setupStateDir\nremoteSecurityDir · operatorActivityDir]
    C --> E[planLegacyState]
    D --> E

    E --> F[planArtifacts\ncapletsRoot + lockfile]
    E --> G[snapshotWithBackupFallback\nfor each domain]
    G --> H[backendAuth · vault · vaultGrants\nremoteSecurity · setup · operatorActivity]
    F --> I[plannedVaultGrants\nglobal-file + tracked → stored-record\nglobal-file + overlay → global-file]
    I --> H

    H --> K[assertLegacyGrantsImportable\nonly grants with caplets already in DB]
    K --> L{--dry-run?}
    L -- Yes --> M[Return verified report]
    L -- No --> N[SQL Transaction\nimportBundles · importBackendAuth\nimportVaultValues · importVaultGrants\nimportRemoteSecurity · importSetup · importActivity]
    N --> O[Verify all domains in same transaction]
    O --> P[moveLegacyArtifactsToBackup\nrename regular files\ncopyFileSync EXCL for vault-key]
    P --> Q[Return migrated report]
    P -- "Error rollback" --> R[Reverse completed moves\nrm copy targets · rename back originals]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[caplets storage migrate-legacy] --> B{Options provided?}
    B -- "--caplets-root / --lockfile" --> C[Use explicit paths]
    B -- "No flags" --> D[Resolve platform defaults\nauthDir · lockfilePath\nlegacyVaultRoot · setupStateDir\nremoteSecurityDir · operatorActivityDir]
    C --> E[planLegacyState]
    D --> E

    E --> F[planArtifacts\ncapletsRoot + lockfile]
    E --> G[snapshotWithBackupFallback\nfor each domain]
    G --> H[backendAuth · vault · vaultGrants\nremoteSecurity · setup · operatorActivity]
    F --> I[plannedVaultGrants\nglobal-file + tracked → stored-record\nglobal-file + overlay → global-file]
    I --> H

    H --> K[assertLegacyGrantsImportable\nonly grants with caplets already in DB]
    K --> L{--dry-run?}
    L -- Yes --> M[Return verified report]
    L -- No --> N[SQL Transaction\nimportBundles · importBackendAuth\nimportVaultValues · importVaultGrants\nimportRemoteSecurity · importSetup · importActivity]
    N --> O[Verify all domains in same transaction]
    O --> P[moveLegacyArtifactsToBackup\nrename regular files\ncopyFileSync EXCL for vault-key]
    P --> Q[Return migrated report]
    P -- "Error rollback" --> R[Reverse completed moves\nrm copy targets · rename back originals]
Loading

Reviews (2): Last reviewed commit: "test: cover shared legacy admin state" | Re-trigger Greptile

Comment thread packages/core/src/cli.ts Outdated
Comment thread packages/core/src/storage/legacy-migration.ts
@ian-pascoe

Copy link
Copy Markdown
Contributor Author

Addressed all three Greptile findings in b6dbac8:

  • documented why legacy remote credentials and Operator Activity share the remote-server directory
  • documented why pending stored-record Vault grants bypass the pre-transaction availability check
  • populated both legacy files in the default-path CLI integration test and verified remote pairing/client/pending-login state, Operator Activity, source removal, distinct backup destinations, and SQL round-trips

Verification: targeted migration CLI test, @caplets/core typecheck, targeted oxlint, and the full pre-push pnpm verify gate.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
apps/docs/src/content/docs/reference/cli.mdx (1)

85-86: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Keep inline code blocks on a single line.

Line breaks inside inline code snippets can sometimes render unpredictably (e.g., as a literal newline or with missing spacing) depending on the Markdown parser. Consider keeping the inline code block entirely on a single line.

♻️ Proposed fix
-`attach` is stdio-only and does not open an HTTP listener. Use `serve --transport http
---upstream-url <url>` for a long-running stacked HTTP runtime.
+`attach` is stdio-only and does not open an HTTP listener. Use `serve --transport http --upstream-url <url>`
+for a long-running stacked HTTP runtime.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/docs/src/content/docs/reference/cli.mdx` around lines 85 - 86, Keep the
inline command example in the `attach` documentation on a single line by
removing the line break between `--transport http` and `--upstream-url <url>`,
without changing the command text or surrounding explanation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@apps/docs/src/content/docs/reference/cli.mdx`:
- Around line 85-86: Keep the inline command example in the `attach`
documentation on a single line by removing the line break between `--transport
http` and `--upstream-url <url>`, without changing the command text or
surrounding explanation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 38609ef3-9b76-42f0-ad20-9a02d8e79edd

📥 Commits

Reviewing files that changed from the base of the PR and between 8f93b49 and b6dbac8.

📒 Files selected for processing (28)
  • .changeset/clean-cups-help.md
  • README.md
  • apps/docs/astro.config.mjs
  • apps/docs/src/content/docs/agent-integrations.mdx
  • apps/docs/src/content/docs/catalog.mdx
  • apps/docs/src/content/docs/configuration.mdx
  • apps/docs/src/content/docs/dashboard.mdx
  • apps/docs/src/content/docs/index.mdx
  • apps/docs/src/content/docs/install.mdx
  • apps/docs/src/content/docs/privacy.mdx
  • apps/docs/src/content/docs/privacy/indexing.mdx
  • apps/docs/src/content/docs/project-binding.mdx
  • apps/docs/src/content/docs/reference/cli.mdx
  • apps/docs/src/content/docs/reference/config.mdx
  • apps/docs/src/content/docs/remote-attach.mdx
  • apps/docs/src/content/docs/storage.mdx
  • apps/docs/src/content/docs/troubleshooting.mdx
  • apps/docs/src/content/docs/vault.mdx
  • docs/operations/sql-authoritative-host-state.md
  • packages/cli/CHANGELOG.md
  • packages/core/CHANGELOG.md
  • packages/core/src/cli.ts
  • packages/core/src/storage/legacy-migration.ts
  • packages/core/src/storage/vault-grants.ts
  • packages/core/test/legacy-migration.test.ts
  • packages/core/test/storage-records-cli.test.ts
  • scripts/check-public-docs.ts
  • scripts/generate-docs-reference.ts

@ian-pascoe
ian-pascoe merged commit b620ec5 into main Jul 19, 2026
8 checks passed
@ian-pascoe
ian-pascoe deleted the worktree/silver-field-9497 branch July 19, 2026 09:47
ian-pascoe added a commit that referenced this pull request Jul 19, 2026
* fix: harden legacy storage migration

* test: cover shared legacy admin state
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.

1 participant