Skip to content

T56 Encrypted Workspace Recovery Bundle Validation

T56 Encrypted Workspace Recovery Bundle Validation

Scope

  • Task: T56 — Implement encrypted Workspace recovery bundles and staged restore
  • Requirements: VES-SEC-004/005 and VES-HOF-005/006
  • Commit target: feat(recovery): add encrypted workspace bundles
  • Focused evidence: 39 cases (9 end-to-end, 9 fault injection, and 21 security)
  • Required minimum: 35 end-to-end/fault/security cases
  • Spec deviations: none

T56 creates an explicit, content-addressed recovery closure from one consistent runtime/memory snapshot barrier; signs its manifest with Ed25519; and encrypts one authenticated archive for one or more X25519 recipients using RFC 7516 General JWE JSON Serialization with ECDH-ES+A256KW and A256GCM. Restore authenticates and decrypts before staging, validates the staged closure, requires logical-secret rebinding, reevaluates policy/source/Approval/claim authority, reconciles uncertain effects, and only then calls the atomic activation port. Credential values, secret values, machine authentication, provider sessions, and derived vector indexes are mandatory exclusions.

Deterministic gates

Command Result
node --test tests/e2e/recovery-bundle-e2e.test.mjs tests/fault-injection/recovery-bundle-faults.test.mjs tests/security/recovery-bundle-security.test.mjs PASS — 39 passed, 0 failed/skipped
node scripts/gate.mjs security PASS — format, lint, typecheck/build, unit/property, architecture, qualification, 695 security, and 129 fault cases

Adequacy matrix

Done-when criterion / spec AC Exact assertion evidence Spec-defined outcome Result
Runtime and memory share one consistent snapshot barrier tests/e2e/recovery-bundle-e2e.test.mjs:43-75 Canonically ordered sources are captured only if every before/after state digest is unchanged inside the barrier PASS
Object closure is complete and content-addressed tests/e2e/recovery-bundle-e2e.test.mjs:97-105; tests/security/recovery-bundle-security.test.mjs:113-129 Every required object has exact identity, kind, byte size, and SHA-256 digest; missing, extra, or changed content fails before encryption/publication PASS
Inclusion and exclusion decisions are explicit tests/e2e/recovery-bundle-e2e.test.mjs:97-105; tests/security/recovery-bundle-security.test.mjs:71-95 Mandatory private-state exclusions are always present and no class may be simultaneously included and excluded PASS
One bundle supports multiple explicit recipients tests/e2e/recovery-bundle-e2e.test.mjs:17-27; tests/security/recovery-bundle-security.test.mjs:13-19,97-111 Each declared X25519 recipient opens the same signed closure; unknown or duplicate recipient identities fail closed PASS
Inspection cannot expose encrypted object bytes tests/e2e/recovery-bundle-e2e.test.mjs:29-41 Signature-verified metadata is inspectable without returning archive plaintext PASS
Time validity and Workspace binding precede staging tests/security/recovery-bundle-security.test.mjs:21-43 Expired, future-created, or foreign-Workspace bundles are rejected before any restore port is called PASS
Sensitive/private content cannot enter a plan tests/security/recovery-bundle-security.test.mjs:45-68 Credential, secret, token, session, transcript, environment, row, and local-path fields fail recursively PASS
Ciphertext and signed manifest tamper fail closed tests/security/recovery-bundle-security.test.mjs:70-77; tests/fault-injection/recovery-bundle-faults.test.mjs:62-74 Ed25519 envelope verification and AES-GCM authentication prevent semantic use or staging of modified bytes PASS
Restore order is safe and explicit tests/e2e/recovery-bundle-e2e.test.mjs:77-95 Stage, validate, rebind every logical secret, reevaluate authority, reconcile effects, then activate PASS
Wrong recipient, missing secret, or stale authority leaves active state unchanged tests/security/recovery-bundle-security.test.mjs:13-19,153-166; tests/fault-injection/recovery-bundle-faults.test.mjs:33-47 No rejected recovery can replace the active Workspace PASS
Unknown high-risk effects require reconciliation tests/fault-injection/recovery-bundle-faults.test.mjs:49-60 An unknown outcome remains fail-closed and cannot be interpreted as not applied PASS
Stage, validation, and activation faults preserve authority tests/fault-injection/recovery-bundle-faults.test.mjs:12-31 Every injected restore-boundary failure leaves the original active state untouched PASS
Publication is immutable, canonical, and retry-convergent tests/e2e/recovery-bundle-e2e.test.mjs:107-149 Repeating identical canonical bytes returns already-published; different randomized ciphertext cannot overwrite the first bundle; corrupt/noncanonical stored bytes fail integrity PASS

Necessary-test reverse map

Test group Maps to Keep
Snapshot and multi-recipient end-to-end cases Consistent cut, canonical closure, recipient interoperability, metadata-only inspection Yes
Restore sequence end-to-end case Staged validation, secret rebinding, authority refresh, effect reconciliation, atomic activation Yes
Publication end-to-end cases Idempotency, acknowledgement-loss convergence, no-clobber immutability Yes
Restore fault matrix Active-state preservation at every durable boundary and for every authority class Yes
Planner/closure security matrix Explicit exclusions, recursive sensitive-field denial, exact content closure Yes
Cryptographic security cases Wrong-recipient denial, expiry, Workspace isolation, signature and AEAD tamper detection Yes

Non-shallow checks

  • The plan identity is calculated from the normalized manifest material before encryption. Recipient order, object order, inclusion/exclusion order, logical-secret bindings, and uncertain-effect IDs are canonicalized, so the recovery intent is stable even though JWE ciphertext is deliberately randomized.
  • The signed outer envelope binds the full JWE and manifest. Authentication is evaluated before exposing inspection metadata, decrypting archive bytes, or invoking a staging port.
  • General JWE gives every recipient an independent X25519 key-wrap entry while sharing one A256GCM ciphertext. Adding recipients does not create divergent recovery archives.
  • The encrypted archive repeats the plan identity and exact object identity/kind/bytes. Decryption is not sufficient: the implementation recomputes every size and raw-byte SHA-256 digest against the signed manifest.
  • Restore never imports credential values. It imports only logical secret names and requires the destination machine’s secret broker to prove each one is locally bound.
  • Policy, source, Approvals, and claims are reevaluated in the destination environment. A valid historical signature is evidence of origin, not current execution authority.
  • An uncertain remote effect is reconciled to one of applied, not-applied, or already-applied. Any other result blocks activation instead of guessing or blindly retrying.
  • The store publishes through a same-filesystem hard link with no replacement semantics. Identical retries converge; a competing bundle for the same immutable plan remains untouched and raises a conflict.
  • Derived vector indexes are excluded because they can be rebuilt from authoritative memory. This reduces bundle size and prevents derived state from outranking restored lexical authority.

Cryptographic profile

  • Container: RFC 7516 General JWE JSON Serialization
  • Recipient algorithm: ECDH-ES+A256KW
  • Recipient keys: X25519 JWK thumbprints bound into the signed manifest
  • Content encryption: A256GCM
  • Outer artifact signature: Ed25519 through the Verchestra trust-root and purpose system
  • Protected binding: media type, schema version, and immutable recovery plan identity

Verdict

PASS for T56. A Workspace can now be captured as one explicit, signed, recipient-encrypted recovery closure and restored only through a fail-closed staged sequence. Wrong recipients, expiry, cross-Workspace replay, closure drift, missing secret bindings, stale authority, unknown effects, tamper, faults, and competing publication bytes cannot replace the active Workspace; retries converge without weakening authority.