Repository navigation
Sealed-input gate: NAME=PATH arguments and a missing deployment key - #1777
Conversation
With no key configured, Flow generates a local key (0600) and encrypts web recordings, compiled and induced bundles (also from a plaintext recording) and durable checkpoints. OPENADAPT_FLOW_PLAINTEXT_AT_REST opts out, with a warning and a ledger line. OPENADAPT_FLOW_AT_REST=strict encrypts every run directory and refuses what can't be encrypted yet; outside strict mode those writes are named on stderr and in the ledger, and Desktop shows a notice. Compile-agent screenshots are redacted before they reach the model, and heal artifacts go through the sealed-set helpers. Remaining work: #1751.
…sections and check mark read sealed input Add openadapt_flow.artifacts (thin wrapper over the sealed_set path helpers) and route the artifact reads of these commands through it. for-each of a sealed body writes a sealed loop bundle; emit-skill copies a sealed bundle as ciphertext; record --with-check marks a check in an encrypted recording. A lint test fails when a converted function reads an artifact with pathlib or open(). Refs #1751.
…e read sealed children Route the composition, process-contract and variant-set reads (parent files, admission envelopes, child bundles, repair-candidate records) through openadapt_flow.artifacts. compose copies sealed children as ciphertext; process, variants and route read sealed children in place. Each command has a sealed-input test, and the lint in test_artifact_reads covers the converted functions. Refs #1751.
…g key under the local key
…s, deployment-key commands, ledger failures stop writes
…only; read-only key resolver; post-run reports survive a ledger failure
# Conflicts: # packages/desktop/CHANGELOG.md # packages/desktop/openadapt_desktop/__init__.py # packages/desktop/package-lock.json # packages/desktop/package.json # packages/desktop/pyproject.toml # packages/desktop/src-tauri/Cargo.lock # packages/desktop/src-tauri/Cargo.toml # packages/desktop/src-tauri/tauri.conf.json # packages/desktop/uv.lock
# Conflicts: # CAPABILITIES.md # llms-full.txt
# Conflicts: # CAPABILITIES.md # llms-full.txt # packages/flow/openadapt_flow/__main__.py
# Conflicts: # CAPABILITIES.md # llms-full.txt
# Conflicts: # CAPABILITIES.md # llms-full.txt # packages/flow/docs/phi_at_rest.md # packages/flow/openadapt_flow/__main__.py # packages/flow/tests/test_artifact_reads.py
Independent adversarial review: APPROVEFrom: Codex. Reviewed 88832e0 in a fresh detached worktree, against its stacked base 03b3f33. No blocking finding.
I instrumented the real CLI handlers. Missing-key child, admission and variant inputs each returned 2 with zero handler calls and no output. An unfinished set and a configured wrong key also refused before handlers. A valid recording-key fallback still succeeded, and source bytes stayed unchanged. Validation: 69 artifact/key/at-rest tests passed, with 2 fixture warnings; Flow Ruff and formatting passed (1311 files). Eight independent probes used temporary synthetic keys and artifacts. CI was complete and green on this exact head. I did not push to this branch. |
# Conflicts: # packages/flow/tests/test_artifact_reads.py
Part of #1751. Stacked on #1769.
The sealed-input gate (
__main__._sealed_paths_in) now reads the path after the first=inNAME=PATHarguments (--child,--admission,--variant). An encrypted child goes through the same checks as any other input._sealed_input_refusalalso opens each sealed input before the command runs. With no key configured the local key resolves, so opening the set is what reveals that it was sealed under a deployment key that isn't set. The command then stops with the "set the key" message before any work.Test:
test_name_path_arguments_go_through_the_missing_key_check. With no key set,composewith encrypted--childbundles stops with the key message and writes nothing.Tests:
test_artifact_reads.py,test_sealed_at_rest.pyandtest_at_rest_default.py, 54 passed (run with the in-tree packages).