Skip to content

Generic vault context erase/verify and predecessor lineage - #177

Merged
censgate-coder merged 4 commits into
mainfrom
coderclient-file-review-5ee7
Sep 12, 2026
Merged

censgate-coder merged 4 commits into
mainfrom
coderclient-file-review-5ee7

Conversation

@censgate-coder

@censgate-coder censgate-coder commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Thank you for contributing to Redact. These checkboxes are acknowledgements;
the CLA bot enforces the Individual CLA signature.

  • I have read CLA.md and will sign the Individual CLA via the bot comment (or I have already signed). A Corporate CLA, if required, does not replace the Individual CLA.
  • All commits are DCO-signed (git commit -s)
  • I have read docs/PROJECT_SCOPE.md; this change is in scope

Employer time or equipment

  • Yes — my employer has authorised the contribution, or a Corporate CLA is on file

Summary

Additive, product-noun-free gateway APIs for platform ForgetMe(client):

  • Optional vault.context_id alias on redact/restore (session_id unchanged; mismatch → 400)
  • DELETE /v1/vault/context and POST /v1/vault/context/verify
  • KV2 purge (all versions + metadata)
  • POST /v1/credentials/predecessors with Authorization + X-Predecessor-Authorization
  • Erase/verify walk current subject + transitive predecessor closure; echo lineage_revision / predecessor_count
  • Default credential subject stays key:<sha256(api_key)> (no remapping)

No team/client/professional/ForgetMe types or docs.

Test plan

  • cargo test -p redact-gateway (vault context, purge, predecessor register, rotation forget)
  • Fixture names stay generic (caller-a, context-1)

…ssors

Optional vault.context_id aliases session_id on redact/restore without
changing storage keying. TokenMapStore::purge permanently deletes maps
(KV v2 metadata and all versions; memory hard-delete). New generic
erase/verify and predecessor-register routes walk the current subject
plus a durable predecessor closure.
Sol Medium review of PR 177: verify uses KV2 metadata presence, predecessor
register CAS-updates a tenant graph, subjects stay out of storage paths,
and new erase/verify/predecessor bodies reject unknown fields.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>
@censgate-coder

Copy link
Copy Markdown
Contributor Author

Sol Medium review (e6ed32b)

Verdict: CHANGES_REQUESTED (Important, no Critical)

  1. Verify used get() (empty live mappings), so expired/soft-deleted KV2 history could report verified: true while ciphertext remained.
  2. Predecessor register was a non-atomic read/compose/write; concurrent rotations could drop subjects or form cross-record cycles.
  3. Lineage paths included the raw credential subject (OIDC emails can land in OpenBao audit URLs).
  4. New erase/verify/predecessor bodies ignored unknown JSON fields (e.g. a foreign subject_id).

Addressed in 3dfc3d4 (DCO-signed): metadata exists(), tenant-graph CAS register, {prefix}/_lineage/{tenant} path, deny_unknown_fields on the new envelopes. Re-running Sol Medium on the new tip.

Store direct edges and recompute the bounded closure on erase/verify so a
later child rotation is visible to existing parents. Lineage records live
at {prefix}/_lineage/{tenant}/graph so they cannot collide with session maps.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>
@censgate-coder

Copy link
Copy Markdown
Contributor Author

Sol Medium re-review of 3dfc3d4 was still CHANGES_REQUESTED (2 Important):

  1. Cached closures went stale when a child rotated after a parent had already registered (A→B then B→C left erase-as-A missing C).
  2. {prefix}/_lineage/{tenant} collided with session_path(prefix, "_lineage", tenant).

4e372ac stores direct edges and walks the live closure on erase/verify, and moves lineage to {prefix}/_lineage/{tenant}/graph. Re-running Sol Medium.

Build a candidate graph and validate every subject's bounded closure before
committing, so a descendant rotation cannot make an existing ancestor's
forget path fail closed.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>
@censgate-coder

Copy link
Copy Markdown
Contributor Author

Sol Medium re-review of 4e372ac was still CHANGES_REQUESTED (1 Important): a descendant edge could expand an ancestor past the 32-subject bound, then erase/verify as that ancestor would 503. In-memory register could also keep the failed edge.

cf5a942 builds a candidate graph, validates every subject's closure, and commits only if all stay in bound / acyclic. Re-running Sol Medium.

@censgate-coder

Copy link
Copy Markdown
Contributor Author

Sol Medium APPROVE on tip cf5a942.

All previously identified privacy, durability, verification, closure, and namespace issues are fixed with regression coverage. Ready to merge to main (operator). First commit e6ed32b is still not DCO-signed; follow-ups 3dfc3d4, 4e372ac, and cf5a942 are signed.

@censgate-coder
censgate-coder merged commit cd92c8b into main Sep 12, 2026
32 checks passed
@censgate-coder
censgate-coder deleted the coderclient-file-review-5ee7 branch September 12, 2026 12:53
@github-actions github-actions Bot locked and limited conversation to collaborators Sep 12, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants