Skip to content

fix(onboard): preserve durable journal compatibility - #8080

Closed
ericksoa wants to merge 10 commits into
hold/podman-stack/pr8080-base-9d4dc59cfrom
fix/managed-bootstrap-durable-journal-compatibility
Closed

fix(onboard): preserve durable journal compatibility#8080
ericksoa wants to merge 10 commits into
hold/podman-stack/pr8080-base-9d4dc59cfrom
fix/managed-bootstrap-durable-journal-compatibility

Conversation

@ericksoa

@ericksoa ericksoa commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Preserve managed-bootstrap recovery across exact atomic-write leftovers and historical durable journal schemas without weakening identity authority. Recovery now compares preparation and completion receipts canonically, upgrades only records backed by immutable evidence, and fails closed instead of inferring a missing agent.

Related Issue

Part of #7744.

Stack Position

  • Base: fix(onboard): preserve shared-state commit authority #8078 at 9d4dc59c331aca42f4ead7bc8831db61d1deee0e
  • This exact head: 9096a968f13e0c00fdaaa43e8f63e03993f11277
  • Stable parent-relative patch ID: db839e079517b66c087f4bdfce12a6be480f3eb1
  • Parent-relative scope: 11 files changed, 984 insertions(+), 118 deletions(-)
  • Next slice: honest owner-cleanup-pending state and lossless per-journal recovery reporting

Changes

  • Recognize only exact journal, rollback-decision, and finalization atomic-write temporary names during enumeration; preserve near-misses and never treat them as recoverable records.
  • Parse the exact supported journal and finalization schema generations explicitly, upgrade a missing agent only from an exact immutable runtime handle or journal, and return a typed unsupported-record failure otherwise.
  • Export provider-neutral canonical preparation and completion comparators so durable receipt equality does not depend on caller object-key order.
  • Preserve commit acknowledgement across reversed key order and lost acknowledgements while rejecting materially different receipts.
  • Strengthen event-order and rollback-finalization assertions so recovery tests prove durable behavior instead of passing vacuously.
  • Validate every normalized finalization-context field before any legacy finalization read or rewrite; mismatches preserve existing bytes and create no new record.
  • Reject a direct-provider snapshot whose immutable image differs from the held workload plan before replacement creation or journaling.
  • Close exact-head CodeRabbit feedback with delimiter-safe key comparison, frozen legacy-schema rationale, distinct context diagnostics, one provider-neutral test helper, and one cached finalization context per operation.
  • Clarify that mutable OpenShell names are read only to detect ownership reuse, closing the assigned prior CodeRabbit documentation debt.
  • Keep the implementation provider-neutral, MXC-pluggable, and dormant; this slice does not register, select, or advertise buildless or Podman support.

This compatibility boundary is required because interrupted atomic writes and older durable records can remain on disk across upgrades. Ignoring exact temporary artifacts would strand recoverable state, while guessing an agent from mutable names or images would grant unsafe authority. The journal, adapter, and Docker composition tests protect the accepted schemas, exact-name boundary, canonical equality, and fail-closed behavior.

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Quality Gates

  • Tests added or updated for changed behavior
  • Existing tests cover changed behavior — justification:
  • Tests not applicable — justification:
  • Docs updated for behavior and architecture changes — the managed-bootstrap README carries the dormant recovery contract.
  • Docs not applicable — justification:
  • Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging)
  • Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: Independent code/security review found no P0-P2 issue and all five remaining P3 review items are fixed; fresh exact-head advisors, CodeRabbit, CodeQL, CI, and protected E2E remain required before merge.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Documentation Writer Review

  • Documentation writer subagent reviewed the completed changes
  • Result: docs-updated
  • Evidence: src/lib/onboard/managed-bootstrap/README.md documents that mutable names are used only to detect ownership reuse while recovery remains provider-owned and activation remains dormant. The append-only review cleanup and provider-neutral test-fixture inventory change no user-facing support claim; exact-head focused validation passed.
  • Agent: Codex Desktop

DGX Station Hardware Evidence

  • Tested on DGX Station
  • Tested commit:
  • Station profile/scenario:
  • Result:
  • Supporting evidence:

Verification

  • Append-only ancestry refresh: exact head 9096a968f13e0c00fdaaa43e8f63e03993f11277 is signed-DCO and GitHub Verified on exact fix(onboard): preserve shared-state commit authority #8078 base 9d4dc59c331aca42f4ead7bc8831db61d1deee0e; the parent-relative slice patch is db839e079517b66c087f4bdfce12a6be480f3eb1. Focused exact-head qualification passed, and fresh public CI and protected E2E are running.
  • PR description includes a Signed-off-by: line and every commit appears as Verified in GitHub
  • Normal pre-commit, commit-msg, and pre-push hooks passed, or npm run validate:pr passed after refreshing origin/main when hooks were skipped or unavailable — the normal pre-push hook passed CLI typecheck and tag-sync checks; focused exact-head build, typecheck, managed-bootstrap, source-shape, Biome, patch-preservation, and diff checks also passed.
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above — 59 focused managed-bootstrap tests, 2 source-shape tests, CLI build and typecheck, Biome across all 10 changed TypeScript files, byte-for-byte patch preservation, and diff checks passed at 9096a968f13e. The added fixture inventory keeps the provider-neutral source-shape tripwire exact.
  • Applicable broad gate passed — public exact-head CI and protected E2E are running at the exact head above.
  • Quality Gates section completed with required justifications or waivers
  • No secrets, API keys, or credentials committed
  • npm run docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: Aaron Erickson aerickson@nvidia.com

Summary by CodeRabbit

  • Bug Fixes
    • Improved managed bootstrap recovery and finalization when acknowledgements are delayed or lost.
    • Receipt comparisons now work reliably regardless of object key ordering while still detecting meaningful changes.
    • Added safer handling for legacy records, temporary files, invalid identities, and missing agent context.
    • Finalization records are validated, upgraded, and reconciled more reliably to prevent inconsistent bootstrap state.
    • Prevented replacement or recovery when snapshot image details do not match the planned image.
  • Reliability
    • Strengthened validation and event-order handling across activation, finalization, and rollback flows.

Recognize exact atomic-write leftovers and fail closed on agentless legacy journals.

Upgrade legacy finalizations only with durable context.

Compare provider-neutral durable receipts by canonical value.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Assert both events before comparing lifecycle order and require exact rollback finalization.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Preserve the exact E1 patch while advancing its parent to 654f8f3.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@ericksoa ericksoa self-assigned this Aug 2, 2026
@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change adds canonical receipt comparison helpers, validates legacy Docker journal schemas, adds context-aware finalization upgrades, and improves durable write reconciliation. Tests cover reordered receipts, malformed records, filename identity mismatches, acknowledgement loss, event ordering, rollback state, and image validation.

Changes

Managed bootstrap journal lifecycle

Layer / File(s) Summary
Canonical receipt comparison
src/lib/onboard/managed-bootstrap/adapter.ts, src/lib/onboard/managed-bootstrap/adapter.test.ts, src/lib/onboard/managed-bootstrap/docker.ts, src/lib/onboard/managed-bootstrap/docker-test-fixture.ts, src/lib/onboard/managed-bootstrap/index.ts
Receipt comparisons use canonical JSON values. Docker validation and fixture checks accept reordered keys while rejecting changed receipt values.
Journal schema validation and discovery
src/lib/onboard/managed-bootstrap/docker-journal.ts, src/lib/onboard/managed-bootstrap/docker-journal.test.ts
Journal parsing validates legacy schemas, normalizes identities and receipts, checks filename identities, and recognizes finalized temporary files.
Context-aware finalization and recovery
src/lib/onboard/managed-bootstrap/docker-journal.ts, src/lib/onboard/managed-bootstrap/docker.ts, src/lib/onboard/managed-bootstrap/docker-journal.test.ts, src/lib/onboard/managed-bootstrap/docker.test.ts, src/lib/onboard/managed-bootstrap/README.md
Finalization parsing uses durable context for legacy upgrades and current-record validation. Store writes reconcile acknowledgement loss and revalidate persisted records. Lifecycle tests cover ordering, rollback state, and snapshot image validation.

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

Sequence Diagram(s)

sequenceDiagram
  participant Docker as Docker managed bootstrap
  participant Store as DockerManagedBootstrapJournalStore
  participant Parser as Finalization parser
  participant FileStore as Durable finalization file
  Docker->>Store: Load finalization with authenticated context
  Store->>Parser: Validate or upgrade record
  Parser-->>Store: Return normalized record
  Store->>FileStore: Persist upgraded record
  FileStore-->>Store: Re-read persisted record
  Store-->>Docker: Return validated finalization
Loading
🚥 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
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: preserving compatibility for durable managed-bootstrap journals.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/managed-bootstrap-durable-journal-compatibility

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

@ericksoa ericksoa added bug-fix PR fixes a bug or regression area: onboarding Onboarding FSM, provider setup, sandbox launch, or first-run flow area: security Security controls, permissions, secrets, or hardening platform: container Affects Docker, containerd, Podman, or images labels Aug 2, 2026
@github-code-quality

github-code-quality Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in commit 9096a96 in the fix/managed-bootstra... branch remains at 96%, unchanged from commit c63e7eb in the hold/podman-stack/pr... branch.

TypeScript / code-coverage/cli

The overall coverage in commit 9096a96 in the fix/managed-bootstra... branch remains at 81%, unchanged from commit c63e7eb in the hold/podman-stack/pr... branch.

Show a code coverage summary of the most impacted files.
File hold/podman-stack/pr... c63e7eb fix/managed-bootstra... 9096a96 +/-
src/lib/onboard...trap/adapter.ts 84% 64% -20%
src/lib/onboard...ndbox-create.ts 91% 82% -9%
src/lib/state/sandbox.ts 85% 81% -4%
src/lib/onboard...eway-service.ts 86% 82% -4%
src/lib/onboard...cker-journal.ts 86% 83% -3%
src/lib/onboard...-transaction.ts 78% 80% +2%
src/lib/onboard...strap/docker.ts 60% 65% +5%
src/lib/onboard...shared-state.ts 73% 78% +5%
src/lib/onboard...cker-runtime.ts 0% 52% +52%
src/lib/onboard...ntime-create.ts 0% 100% +100%

Updated August 03, 2026 19:23 UTC

@ericksoa

ericksoa commented Aug 2, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — No blocking findings reported

Advisor assessment: No blocking advisor findings reported
Next action: No advisor follow-up needed.
Findings: 0 blockers · 0 warnings · 0 suggestions

Model lanes

  • GPT-5.6 Terra (primary): Completed · high confidence · 0 blockers · 0 warnings · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Failed after a partial review · low confidence · 1 blocker · 1 warning · 0 suggestions

Second-opinion terminology and E2E selections are advisory. They do not change the primary assessment or E2E / PR Gate.

2 semantic terminology decisions

Terminology decisions are advisory. They affect the assessment only when a separate finding identifies concrete semantic impact.

  • define — durable agent identity at src/lib/onboard/managed-bootstrap/docker-journal.ts:134: Define this phrase where it first appears in explanatory text if it becomes part of a supported recovery contract; retain the precise error text as needed.
  • justified — finalization context at src/lib/onboard/managed-bootstrap/docker-journal.ts:797: Retain the modifier because the interface identifies a distinct immutable validation input.

E2E guidance

Advisory only. E2E / PR Gate selects and runs jobs independently.

Recommended E2E: onboard-repair, onboard-resume, cloud-onboard

Workflow run details

This automated review informs maintainers. Warnings and suggestions do not require a response. A maintainer decides whether to merge.

@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.

Actionable comments posted: 1

🧹 Nitpick comments (5)
src/lib/onboard/managed-bootstrap/docker-journal.ts (3)

159-161: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Compare key sets instead of joined strings.

hasExactKeys joins sorted keys with commas. A key that contains a comma can make two different key sets produce the same joined string. Downstream field validators still reject such input, so this is not exploitable today. A set comparison removes the ambiguity and reads more directly.

♻️ Proposed refactor
 function hasExactKeys(record: Readonly<Record<string, unknown>>, expected: readonly string[]) {
-  return Object.keys(record).sort().join(",") === [...expected].sort().join(",");
+  const keys = Object.keys(record);
+  return keys.length === expected.length && expected.every((key) => keys.includes(key));
 }
🤖 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 `@src/lib/onboard/managed-bootstrap/docker-journal.ts` around lines 159 - 161,
Update hasExactKeys to compare the sorted record keys and expected keys
element-by-element, rather than joining them with commas. Preserve exact key-set
matching, including matching lengths, while avoiding ambiguity when keys contain
commas.

225-377: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document that the legacy normalizers are frozen schema snapshots.

normalizeLegacyDockerManagedBootstrapJournal duplicates most of normalizeDockerManagedBootstrapJournal, including the runtime-ID, name-distinctness, provider, rollback, and receipt invariants. The duplication is necessary, because the legacy canonical form must reproduce the exact historical byte sequence and must not change when the current schema evolves.

That intent is not stated in the code. A future maintainer may try to deduplicate these branches and break historical record recognition. Add a short comment on this function that marks schema 1 and schema 2 as frozen and forbids sharing logic with the current normalizer.

♻️ Proposed comment
+// Frozen historical schemas. The canonical form produced here must reproduce the
+// exact bytes written by the schema 1 and schema 2 writers. Do not share logic with
+// normalizeDockerManagedBootstrapJournal, and do not update these branches when the
+// current journal schema changes.
 function normalizeLegacyDockerManagedBootstrapJournal(
   journal: Readonly<Record<string, unknown>>,
   schemaVersion: 1 | 2,
 ): { readonly bootstrapIdentity: string; readonly canonical: string } {
🤖 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 `@src/lib/onboard/managed-bootstrap/docker-journal.ts` around lines 225 - 377,
Add a short comment immediately above
normalizeLegacyDockerManagedBootstrapJournal stating that the schema 1 and
schema 2 branches are frozen historical snapshots and must not share
implementation logic with normalizeDockerManagedBootstrapJournal, because their
canonical byte output must remain unchanged.

810-825: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Distinguish a missing context from a mismatched context.

upgradeLegacyFinalization throws the same missingAgent() error for two different conditions: no context supplied, and context supplied but not matching the record. The message states "lacks durable agent identity" in both cases. During recovery of a real interrupted bootstrap, an operator cannot tell whether the caller omitted the context or whether the durable record belongs to another transaction.

Keep the same error type so callers still branch on it. Add a distinguishing detail for the mismatch case.

🤖 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 `@src/lib/onboard/managed-bootstrap/docker-journal.ts` around lines 810 - 825,
Update upgradeLegacyFinalization so a supplied context that fails
matchesFinalizationContext throws the same
DockerManagedBootstrapLegacyRecordRequiresAgentError type with a distinct
mismatch detail, while preserving missingAgent() for absent context and
retaining the existing matching path.
src/lib/onboard/managed-bootstrap/docker.test.ts (1)

20-22: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

reverseKeys is defined three times in one directory. This PR adds the same helper to three test files in src/lib/onboard/managed-bootstrap/. The shared root cause is that no shared test helper module exports it, while docker-test-fixture.ts already serves as the shared test module for this directory.

Export reverseKeys once from src/lib/onboard/managed-bootstrap/docker-test-fixture.ts and import it in the three test files.

  • src/lib/onboard/managed-bootstrap/docker.test.ts#L20-L22: delete the local definition and import reverseKeys from ./docker-test-fixture.
  • src/lib/onboard/managed-bootstrap/docker-journal.test.ts#L29-L31: delete the local definition and import reverseKeys from ./docker-test-fixture.
  • src/lib/onboard/managed-bootstrap/adapter.test.ts#L47-L49: delete the local definition and import reverseKeys from ./docker-test-fixture.
🤖 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 `@src/lib/onboard/managed-bootstrap/docker.test.ts` around lines 20 - 22,
Export reverseKeys from
src/lib/onboard/managed-bootstrap/docker-test-fixture.ts, then remove each local
definition and import the shared helper from ./docker-test-fixture in
src/lib/onboard/managed-bootstrap/docker.test.ts#L20-L22,
src/lib/onboard/managed-bootstrap/docker-journal.test.ts#L29-L31, and
src/lib/onboard/managed-bootstrap/adapter.test.ts#L47-L49.
src/lib/onboard/managed-bootstrap/docker.ts (1)

1826-1842: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Compute the finalization context once per call.

persistFinalization calls finalizationContext(handle) three times. Each call recomputes createManagedBootstrapPlanFingerprint(handle.plan), which hashes the canonical JSON of the whole plan. finalizationRecord repeats the same computation. Hoist the context into one local constant and reuse it.

♻️ Proposed refactor
     const serialized = serializeDockerManagedBootstrapFinalizationRecord(record);
+    const context = finalizationContext(handle);
     try {
-      deps.journalStore.recordFinalization(record, finalizationContext(handle));
+      deps.journalStore.recordFinalization(record, context);
     } catch (error) {
-      const recovered = deps.journalStore.loadFinalization(
-        handle.bootstrapIdentity,
-        finalizationContext(handle),
-      );
+      const recovered = deps.journalStore.loadFinalization(handle.bootstrapIdentity, context);
       if (
         !recovered ||
         serializeDockerManagedBootstrapFinalizationRecord(recovered) !== serialized
       ) {
         throw error;
       }
     }
-    const persisted = deps.journalStore.loadFinalization(
-      handle.bootstrapIdentity,
-      finalizationContext(handle),
-    );
+    const persisted = deps.journalStore.loadFinalization(handle.bootstrapIdentity, context);
🤖 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 `@src/lib/onboard/managed-bootstrap/docker.ts` around lines 1826 - 1842, Update
persistFinalization to compute finalizationContext(handle) once in a local
constant, then reuse it for journalStore.recordFinalization and both
journalStore.loadFinalization calls; also reuse that context when constructing
finalizationRecord to avoid repeating createManagedBootstrapPlanFingerprint.
🤖 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.

Inline comments:
In `@src/lib/onboard/managed-bootstrap/docker.ts`:
- Around line 1765-1777: Update prepareBootstrapReplacement and the finalization
flow around finalizationContext to reject any snapshot whose image differs from
handle.plan.image before journaling, or derive both the journaled snapshot image
and persistFinalization’s record from the same validated source. Ensure
divergent direct callers cannot create recovery-invalid finalization records.

---

Nitpick comments:
In `@src/lib/onboard/managed-bootstrap/docker-journal.ts`:
- Around line 159-161: Update hasExactKeys to compare the sorted record keys and
expected keys element-by-element, rather than joining them with commas. Preserve
exact key-set matching, including matching lengths, while avoiding ambiguity
when keys contain commas.
- Around line 225-377: Add a short comment immediately above
normalizeLegacyDockerManagedBootstrapJournal stating that the schema 1 and
schema 2 branches are frozen historical snapshots and must not share
implementation logic with normalizeDockerManagedBootstrapJournal, because their
canonical byte output must remain unchanged.
- Around line 810-825: Update upgradeLegacyFinalization so a supplied context
that fails matchesFinalizationContext throws the same
DockerManagedBootstrapLegacyRecordRequiresAgentError type with a distinct
mismatch detail, while preserving missingAgent() for absent context and
retaining the existing matching path.

In `@src/lib/onboard/managed-bootstrap/docker.test.ts`:
- Around line 20-22: Export reverseKeys from
src/lib/onboard/managed-bootstrap/docker-test-fixture.ts, then remove each local
definition and import the shared helper from ./docker-test-fixture in
src/lib/onboard/managed-bootstrap/docker.test.ts#L20-L22,
src/lib/onboard/managed-bootstrap/docker-journal.test.ts#L29-L31, and
src/lib/onboard/managed-bootstrap/adapter.test.ts#L47-L49.

In `@src/lib/onboard/managed-bootstrap/docker.ts`:
- Around line 1826-1842: Update persistFinalization to compute
finalizationContext(handle) once in a local constant, then reuse it for
journalStore.recordFinalization and both journalStore.loadFinalization calls;
also reuse that context when constructing finalizationRecord to avoid repeating
createManagedBootstrapPlanFingerprint.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 708ae29c-0bab-4d10-88b0-ea8b2b59fe8a

📥 Commits

Reviewing files that changed from the base of the PR and between 654f8f3 and acc760c.

📒 Files selected for processing (8)
  • src/lib/onboard/managed-bootstrap/adapter.test.ts
  • src/lib/onboard/managed-bootstrap/adapter.ts
  • src/lib/onboard/managed-bootstrap/docker-journal.test.ts
  • src/lib/onboard/managed-bootstrap/docker-journal.ts
  • src/lib/onboard/managed-bootstrap/docker-test-fixture.ts
  • src/lib/onboard/managed-bootstrap/docker.test.ts
  • src/lib/onboard/managed-bootstrap/docker.ts
  • src/lib/onboard/managed-bootstrap/index.ts

Comment thread src/lib/onboard/managed-bootstrap/docker.ts
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@ericksoa

ericksoa commented Aug 2, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
ericksoa added a commit that referenced this pull request Aug 2, 2026
# Conflicts:
#	src/lib/onboard/managed-bootstrap/docker-journal.test.ts
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
ericksoa added a commit that referenced this pull request Aug 2, 2026
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Append #8078 head 9d4dc59.

Preserve the durable-journal compatibility slice byte-for-byte.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@ericksoa
ericksoa changed the base branch from fix/managed-bootstrap-shared-state-commit-authority to pull-request/8078 August 2, 2026 20:59
@ericksoa
ericksoa changed the base branch from pull-request/8078 to fix/managed-bootstrap-shared-state-commit-authority August 2, 2026 20:59
ericksoa added a commit that referenced this pull request Aug 2, 2026
Append #8080 head 9096a96.

Preserve the durable cleanup and recovery slice byte-for-byte.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@ericksoa
ericksoa changed the base branch from fix/managed-bootstrap-shared-state-commit-authority to hold/podman-stack/pr8080-base-9d4dc59c August 3, 2026 19:10

@apurvvkumaria apurvvkumaria left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approve — reviewed exact head 9096a96. The durable-journal compatibility path keeps persisted schema/version handling fail-closed, preserves recovery semantics across adapter evolution, and is covered at the adapter, journal, and Docker boundaries. I found no blocking correctness, security, compatibility, or regression defect. The current dependency-resolution CI failures are inherited from the exact ancestor/base and are not attributable to this delta.

ericksoa added a commit that referenced this pull request Aug 4, 2026
## Summary

Hardens the dormant managed-bootstrap path so create outcomes are
explicit, shared-state rollback remains transaction-owned, and recovery
receipts replay durably across runtime providers. This consolidates the
additive source work from #8077, #8078, #8080, and the
already-incorporated behavior from #8083 without registering or
activating a managed runtime.

## Related Issue

Refs #7744

## Changes

- Return terminal managed-bootstrap outcomes and preserve explicit
rollback evidence through Docker sandbox creation.
- Keep application environment and shared-state rollback authority
inside the managed-startup transaction, including environment-neutral
status and rollback probes.
- Move receipt comparison into the provider-neutral adapter, validate
pre-journal snapshot identity, and retain exact atomic leftovers for
durable replay.
- Add focused lifecycle, transaction, compatibility, replay, and
source-shape coverage while keeping the candidate provider inert.
- Preserve the donor heads under
`backup/podman-stack/pr8077-source-83e7fe53`,
`backup/podman-stack/pr8078-source-9d4dc59c`,
`backup/podman-stack/pr8080-source-9096a968`, and
`backup/podman-stack/pr8083-source-a2ae901b`.

The adapter contract is currently required by managed-bootstrap journal
and runtime construction consumers. A Docker-local change is
insufficient because later Podman and MXC-style providers must compare
the same durable receipts without central runtime switches. The
managed-bootstrap adapter, runtime, journal, shared-state, and
source-shape tests protect that boundary.

## Type of Change

- [ ] Code change (feature, bug fix, or refactor)
- [x] Code change with doc updates
- [ ] Doc only (prose changes, no code sample modifications)
- [ ] Doc only (includes code sample changes)

## Quality Gates

- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [ ] Docs updated for user-facing behavior changes
- [x] Docs not applicable — justification: No user-visible provider is
registered or activated in this additive slice; the internal
managed-bootstrap README documents the architecture change.
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [x] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification: Maintainer-authored
implementation scope under #7744; the provider remains inert and
repository advisors must still clear the exact head before merge.
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Documentation Writer Review

- [x] Documentation writer subagent reviewed the completed changes
- Result: `docs-updated`
- Evidence: Updated `src/lib/onboard/managed-bootstrap/README.md`. The
managed-bootstrap provider remains unregistered and unsupported in
production, so no user-facing `docs/` change is required.
- Agent: Codex Desktop
<!-- docs-review-head-sha: b3973ce -->
<!-- docs-review-agents-blob-sha: 3dd7c24 -->

## DGX Station Hardware Evidence

- [ ] Tested on DGX Station
- Tested commit:
- Station profile/scenario:
- Result:
- Supporting evidence:

## Verification

- [x] PR description includes a `Signed-off-by:` line and every commit
appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run validate:pr` passed after refreshing `origin/main` when hooks
were skipped or unavailable
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — command/result or justification:
Targeted Vitest run covering all 12 changed test files passed 175/175
tests at `b3973cebb50d`.
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result: Local `npm test` was
attempted and encountered widespread unrelated five-second timeouts
across existing installer, package-contract, rebuild, inference, and
policy tests; authoritative sharded CI is pending.
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [ ] `npm run docs` builds without warnings (doc changes only)
- [ ] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

---

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Commit and rollback failures now surface reliably instead of being
silently ignored.
* Improved recovery when runtime finalization or supervisor reconnection
fails.
  * Prevented mismatched container images from advancing through setup.
  * Strengthened rollback protection after a commit becomes durable.

* **Compatibility**
* Added support for valid legacy transaction manifests while rejecting
malformed or incomplete data.

* **Reliability**
* Repeated commit or rollback requests now produce consistent results,
including after acknowledgement failures.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@ericksoa

ericksoa commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by clean consolidated replacement #8225, now merged. The donor head remains preserved under backup/podman-stack/pr8080-source-9096a968.

@ericksoa ericksoa closed this Aug 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: onboarding Onboarding FSM, provider setup, sandbox launch, or first-run flow area: security Security controls, permissions, secrets, or hardening bug-fix PR fixes a bug or regression platform: container Affects Docker, containerd, Podman, or images

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants