Skip to content

Support mission_id-indexed cascade for whole-mission revocation #173

@saucam

Description

@saucam

Context

The cascade-revocation functions (revoke_credential_cascade, revoke_credentials_cascade, migration 007; RETURNS TABLE in 029) find affected credentials by recursively walking parent_jti downward from an anchor. mission_id (migration 022) is a denormalized delegation-tree-root id that every credential in a tree shares, with its own btree index (idx_issued_credentials_mission_id).

The distinction

  • parent_jti walk = the anchor node + its descendants (a downward subtree). Excludes the anchor's ancestors and siblings.
  • WHERE mission_id = ? = the entire delegation tree in one indexed equality (no recursion).

They return the same set only when the anchor is the tree root. For a mid-tree anchor they differ — mission_id also sweeps the anchor's ancestors and sibling branches.

Why not just switch the existing functions

The current subtree semantics are the correct, least-surprising behaviour for token revocation: revoking a delegated child must not revoke the parent that delegated to it, nor unrelated sibling delegations. So mission_id is not a drop-in replacement for:

  • revoke_credential_cascade (RFC 7009 single-token revoke, auth-code replay) — anchor is often mid-tree; mission_id would over-revoke.
  • revoke_credentials_cascade (identity deactivation) — an identity may merely participate mid-tree in another tree; mission_id would sweep the whole foreign tree.

Proposal

Add a separate mission_id-indexed operation for the legitimate "revoke an entire mission in one shot" use case (e.g. tear down a whole delegation tree by its root), as a single indexed UPDATE ... WHERE mission_id = ? RETURNING ... — no recursion, faster than the walk. Keep the existing parent_jti subtree functions unchanged for per-token / per-identity revocation.

Scope / acceptance

  • New repo function + DB statement keyed on mission_id (indexed), returning affected rows for the RevocationNotifier fan-out (same RevokedCredential projection).
  • Tenant guards (account_id/project_id) on the anchor, consistent with the existing functions.
  • Tests covering: whole-mission revoke returns every tree member exactly once; tenant isolation; no effect on the existing subtree functions.
  • Decide the API surface (service method + whether it's exposed via an endpoint).

Spun out of the RevocationNotifier PR (#172) review — deliberately kept separate since it's a new operation with different semantics, not a change to the established cascade.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions