Skip to main content
← Back to list
01Issue
FeatureShippedSwamp CLIPublic
Assigneeszack

Relationships

#3558 typed-secrets 2.2: VaultSecretBag entries hold references, one registry per run, 128-bit sentinels

Opened by zack · 10/16/2026· Shipped 10/16/2026

Outcome

Every VaultSecretBag entry carries its reference, its encoding and its data-origin flag beside the value it holds today. Every pass of a run issues sentinels into one run-scoped registry, of which a step's bag is a view. The sentinel prefix is 128 random bits. The persisted form is derived from entries, not from a value search. Values are still read eagerly, so behavior is unchanged.

Why now

This is the structural half of Phase 2 in design/enablers/typed-secrets.md Section 11, specified in Section 3.2. Doing it while values are still eager means every existing suite proves the refactor preserved behavior before 2.3, not yet filed, changes what a bag holds. It does not depend on 2.1 (swamp-club#3557), and 2.3 depends on both.

Scope

  • VaultSecretBag entries hold a reference (vault name and key), an encoding and a data-origin flag, beside the value. Data-origin entries record the source that RunSensitiveValues already holds for each value.
  • The run-scoped bag registry: the run-start pass, workflow-level evaluation and every step pass issue sentinels into it, and a step's bag is a view of it, so a sentinel from an earlier pass is never delivered as literal text. Rehoming between bags (SanitizedTaskOverlay.forStep) covers vault-origin entries as well as data-origin ones.
  • The sentinel prefix grows from 32 to 128 random bits in src/domain/vaults/vault_secret_bag.ts. A sentinel-shaped string with another prefix stays ordinary text.
  • toPersistedForm takes its entries from sentinels, and its callers pass the registry. The value search stays only for plaintext that data reads still bring into CEL, and the code says so.
  • alignProvenance and SplicePair compare sentinels, not values.
  • Tests: property tests for the sentinel format and the persisted-form round trip (fast-check, beside the source); an integration test in integration/ that a sentinel issued in the run-start pass resolves from a later step's bag and through a child workflow's rehoming.
  • The design doc's source map (Section 13) if a seam moves.

Follow the repository conventions: no subprocesses or env mutation in tests, withMockedEnv for env values, and deno run license-headers for new files.

Exit

  • Existing suites pass unchanged.
  • A sentinel issued by any pass of a run resolves from any step's bag of that run, including after rehoming into a child workflow.
  • The persisted form of a run with vault-origin and data-origin secrets is the same as today's apart from the longer prefix, and no value search is needed for a vault-origin entry.
  • Each entry answers its reference, encoding and data origin without reading its value.

Out of scope

  • Stopping the eager read, the load step, the inline resolutions as loads, and the existence check (2.3).
  • Removing sentinelResolverOf, which still has a value to resolve until 2.3.
  • VaultExistenceProvider and has (2.1).
  • Any Secret value or refusal in CEL (Phase 3).
02Bog Flow
✓OPEN✓TRIAGED✓IN PROGRESS✓SHIPPED+ 1 MOREASSIGNED+ 6 MOREFINDINGS+ 12 MOREPR_MERGED+ 2 MORESESSION_SUMMARIZED

Shipped

10/16/2026, 9:56:54 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
zack assigned zack10/16/2026, 8:07:36 PM

Sign in to post a ripple.