Skip to content

feat(TC-821): owner exact-CID revoke grants and canonical CID targets - #357

Merged
samgbafa merged 6 commits into
mainfrom
skgbafa/tc-821-owner-cid-revoke
Oct 19, 2026
Merged

samgbafa merged 6 commits into
mainfrom
skgbafa/tc-821-owner-cid-revoke

Conversation

@samgbafa

@samgbafa samgbafa commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Description

Owner exact-CID revoke grants and canonical CID targets. This PR is stacked on #353 (base skgbafa/tc-1436-revocation-authz) and follows its revoker rule.

  1. Owner-activatable urn:cid:<target> revoke grant.
    • /delegate admits a parentless grant whose non-root capabilities are all tinycloud.delegation/revoke on exactly urn:cid:<target>, when the stored target's abilities name a space the signer owns (revocation::owner_controls_target, used in delegation.rs validate).
    • Unknown targets, targets without abilities, and signers who are only the target's delegator or delegatee are still refused with Cannot find parent delegation.
    • This is the permission the js-sdk CLI requests in packages/cli/src/lib/revoke-delegation.ts:102-105.
  2. Revoke and status by a canonical CID with no stored row. revocation::target_for_cid resolves the stored historical encoding. The signed CID is kept as signed, and authorization and the revocation row use the stored delegation. target_condition also matches the alias canonical column.
  3. An exact-CID revoke or status grant covers every stored encoding of its target. control_proof_decision compares canonical identities, not resource strings. Space-scoped controls are unchanged; historical_alias_targets_cannot_widen_a_space_scoped_revoke_control still passes.

The grantor rule from #353 applies at use time: a control grant authorizes only when its grantor is the target's delegator or the owner of a space the target covers.

Commits:

  • fdbe687 adds the tests alone; on 1338d4f (fix(TC-1436): tighten revocation authorization #353) four historical_cacao_revocation tests and owner_activates_a_parentless_exact_cid_revoke_grant fail.
  • 248f419 makes the change.
  • siwe_issuer_identity::status_signed_invocation_cannot_revoke_but_revoke_signed_invocation_can previously expected 404 for a canonical CID; it now expects the resolved status. Its revoke assertions are unchanged.
  • 5c8175c adds siwe_issuer_identity::canonical_cid_revocations_are_sequenced_like_raw_ones. For both the owner-direct and the exact-CID grant path, a revocation naming the unstored canonical CID must append exactly one event_order row, in the target's space, at the same position as the raw-CID revocation. On 248f419 it fails on both paths (the event count does not change).
  • 794d101 makes sequence_spaces and event_spaces resolve each revocation target through revocation::target_for_cid before the event_order lookup. target_for_cid now picks the lowest stored alias ID deterministically.

Supersedes the remaining behaviours of #297.

Linear: TC-821 (TC-1436).

Type

  • New feature (non-breaking change which adds functionality)

Diligence Checklist

  • I have included unit tests: historical_cacao_revocation (owner CID control across historical encodings, unstored canonical status, owner direct revoke of an unstored canonical CID, control on canonical revoking raw and the reverse), revocation_scope (owner activation and use, plus refusal for unrelated signer, target delegatee, re-share delegatee, intermediate delegator, unknown target and target without abilities)
  • I have performed a self-review of my code
  • I have made corresponding changes to the documentation (CHANGELOG)
  • My changes generate no new warnings (cargo clippy --workspace --all-targets with -Dwarnings)

Local verification:

  • cargo test --workspace; Postgres tests skip without TINYCLOUD_TEST_POSTGRES_URL.
  • test/m1-realdata-e2e passes.
  • The CLI's raw-CID request was run against a real local node. It uses grantRuntimePermissions for {service: "tinycloud.delegation", space: "urn:cid:<cid>", actions: ["tinycloud.delegation/revoke"]}, then delegationManager.revoke(cid, { authorityCid }), as in ensureDelegationAuthority for local-key profiles.
    • On 1338d4f: refused, RAW_RECAP_RESOURCE_UNSUPPORTED: The host cannot activate a root raw-CID revoke authority without a parent delegation.
    • On this branch: activated, revoke {"revoked":true}, and the delegate's read then fails with AUTH_UNAUTHORIZED.

@samgbafa

Copy link
Copy Markdown
Contributor Author

REQUEST_CHANGES: see TC-821

sequence_spaces and event_spaces resolve each revocation's signed target through revocation::target_for_cid before the event_order lookup, so a revocation naming an unstored canonical CID takes the space sequence lock and appends to event_order like one naming the stored row. target_for_cid picks the lowest stored alias ID deterministically.
@samgbafa

Copy link
Copy Markdown
Contributor Author

APPROVE: see TC-821 (reviewed exact head 794d101)

@samgbafa

Copy link
Copy Markdown
Contributor Author

APPROVE: see TC-821 (reviewed exact head f9c5467; merge resolution with #356)

@samgbafa
samgbafa changed the base branch from skgbafa/tc-1436-revocation-authz to main October 19, 2026 13:52
@samgbafa

Copy link
Copy Markdown
Contributor Author

APPROVE: see TC-821 (main-merge only; PR change unchanged vs f9c5467: patch-ids and added/removed lines identical for db.rs, delegation.rs, revocation.rs, historical_cacao_revocation.rs, revocation_scope.rs, siwe_issuer_identity.rs; revocation.rs resolution untouched; head af8dafe)

@samgbafa
samgbafa merged commit c113eab into main Oct 19, 2026
16 of 22 checks passed
@samgbafa samgbafa mentioned this pull request Oct 19, 2026
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