Skip to content

test(TC-887): harness follow-ups: derived keys in mirrors, escrow-none, bounded generations, required mirrors (stacked on #335) - #338

Merged
samgbafa merged 1 commit into
mainfrom
skgbafa/tc-887-harness-followups2
Oct 17, 2026
Merged

samgbafa merged 1 commit into
mainfrom
skgbafa/tc-887-harness-followups2

Conversation

@samgbafa

@samgbafa samgbafa commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

TC-887 harness follow-ups from the #335 approval (review a7e06ef6), on main after #335 merged. No product code changes.

What changed (tests/at_rest_harness.rs, scripts/at-rest-harness/README.md, docs/at-rest/INTERFACES.md)

  1. Escrow and record contents:
    • In an escrow-none run (read from state.json), any escrow bundle or record object is RED.
    • In every run, mirrors are scanned for each secret the harness derives or unwraps: root, W, each ARK, KEK, chain, canary and record-MAC key, NK, the DEK-mirror tag key, and every DEK. The scan covers exempt fields too: shares[].commitment, holder names (singly, in pairs and all together) and the armored share text and payload.
    • Each secret is matched as hex, base64 or base64url text at any alignment, and inside hex, base64, base64url and base32 decodings.
  2. No false RED on holder names: shares[].holder no longer counts toward the 16+16 split check; the 32-byte and derived-secret checks still apply.
  3. Bounded generations: a generation above MAX_ARK_GENERATION = 9 is one finding. A gap is found by comparing counts, not by looping, and ARKs above 9 are never opened. ark-4294967295-… fails RED in under 2 s.
  4. Mirrors required in encrypt and strict modes:
    • an ARK mirror must exist;
    • every block must be named v1/<space tag>/…, with the space tag recomputed from the re-derived NK;
    • the tag must belong to a harness space whose DEK mirror authenticates.
      A missing DEK or ARK mirror, a foreign tag, or a plaintext-named block is RED.
  5. INTERFACES status note now mentions feat(TC-887): seal KV blocks in the S3 store (S3c, stacked on #333) #336 (the S3 store seals KV blocks).
  • Backstop scan: it now also decodes base32, strips any short label: prefix, and flags decodings longer than 32 bytes.

How it's tested

  • cargo test -p tinycloud-node --test at_rest_harness: 7 self-tests pass, 4 live checks ignored. New self-tests:
    • selftest_key_mirror_refuses_escrow_contents_and_derived_keys: escrow none refuses both objects. Six planted derived secrets are each RED, with the EFP, name and MAC recomputed so that only this rule can catch them. Valid holder names that look like encoded halves give no findings.
    • selftest_key_mirror_bounds_absurd_generations
    • selftest_key_mirror_requires_mirrors_in_encrypt_mode
    • plus 3 new cases in selftest_key_mirror_flags_every_bypass.
  • cargo clippy … --test at_rest_harness -- -D warnings, cargo fmt --check and bash -n harness.sh are clean.
  • Live, node from the S3 sealing stack (feat(TC-887): seal KV blocks in the S3 store (S3c, stacked on #333) #336), encrypt mode, escrow none:
    • the check covered 5 control objects and 8 sealed blocks: KV GREEN, SQL RED; the real mirrors passed every new rule unchanged;
    • with one DEK mirror deleted after the puts, KV is RED with exactly 2 findings, one per block of that space;
    • mode off on the same binary is RED (20 KV, 16 SQL), and main's node is RED (24 KV, 16 SQL). No false GREEN.

…e, bounded generations, required mirrors

Review a7e06ef6 on #335 (Naomi's round-5 rulings):
- Escrow-none runs: any escrow bundle or record object is RED. Every
  mirror string (exempt fields, commitments, holder names alone, in pairs
  and in order, the armored share text and its payload, record fields)
  must not carry a secret the harness derived or unwrapped (root, W,
  ARK_g, KEK_g, chain/canary/MAC keys, NK, the DEK tag key, any DEK) in
  hex, base64, base64url or base32, at any alignment.
- Escrow holder names are left out of the 16+16 split check (they are
  checked exactly by the schema).
- ARK generations above 9 are refused outright and a gap is one finding;
  no loop is bounded by a number read from a name.
- Encrypt/strict mode: an ARK mirror must exist and every block must be
  sealed-named, its NK space tag a harness space whose DEK mirror
  authenticates.
- Raw-key backstop also decodes base32 and any short label: prefix and
  flags anything decoding to more than 32 bytes.
- INTERFACES status note names #336.
Self-tests for each rule.
@samgbafa
samgbafa force-pushed the skgbafa/tc-887-harness-followups2 branch from a7a461e to cf546bb Compare October 17, 2026 11:46
@samgbafa
samgbafa changed the base branch from skgbafa/tc-887-harness-mirror to main October 17, 2026 11:46
@samgbafa
samgbafa marked this pull request as ready for review October 17, 2026 12:11
@samgbafa

Copy link
Copy Markdown
Contributor Author

APPROVE: see TC-887 (head cf546bbd71ea6ad07de6b927da2a1223bb9c09d9)

@samgbafa
samgbafa merged commit 3f85987 into main Oct 17, 2026
28 checks passed
samgbafa added a commit that referenced this pull request Oct 17, 2026
… their DEK, ARK sanity cap (#340)

* test(TC-887): harness follow-ups 3: secrets in blocks, blocks tied to their DEK, ARK sanity cap

Review 159550aa on #338 (Naomi's round-6 rulings):
- Every block's name and bytes are scanned for the harness-derived
  secrets (root, W, ARK_g, KEK_g, chain/canary/MAC keys, NK, tag key,
  every unwrapped DEK): raw bytes, and hex, base64 or base64url text at
  any alignment. A DEK in the TCE1 header salt or b64url(DEK/NK) as the
  object name is RED.
- Encrypt/strict mode ties each block to its mirrored DEK: name
  v1/<22>/<43>, NK tag of a harness space, TCE1 header dek_id among that
  space's authenticated DEKs, name equal to the sealed name of a logged
  put (puts.log), and the block opens under that DEK (main's
  at_rest::open, AAD space + content hash) to the put's content.
- ARK generations get a harness-only sanity cap of 1000 (they are
  unbounded in the node; 1..=9 is the TCE format generation); absurd
  names still fail fast, a chain of 10 passes.
- Cheap free-field bypasses closed: bech32 recipient data, hex/base64
  text inside the armor payload, holder splits with -/_ separators,
  shifts up to 7 chars and any order. The rest is listed as out of
  scope in the README.
Self-tests for each rule.

* test(TC-887): partial and split secrets in TCE1 salts; README matches the block scans
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