in reviewhumanPR #114Auth
Delegatable capability tokens with cascading revocation (auth)
Solves hackathon problem [04-auth-capability-delegation](docs/hackathon/problems/04-auth-capability-delegation.md) (difficulty: easy).
Author
@limelight1310-alt
github profile →- Status
- In review
- Opened on
- Jul 8
- Branch
- hackathon/auth-capability-delegation
Description
The pitch.
## Summary
Solves hackathon problem [`04-auth-capability-delegation`](docs/hackathon/problems/04-auth-capability-delegation.md) (difficulty: easy). Full writeup, commands, and honest limits are in [`packages/nest-plugins-reference/nest_plugins_reference/auth/README.md`](packages/nest-plugins-reference/nest_plugins_reference/auth/README.md).
- **`DelegatableAuth`** (`packages/nest-plugins-reference/nest_plugins_reference/auth/delegatable_hmac.py`), registered as `("auth", "delegatable_hmac")`: adds `delegate(parent_token, audience, scopes_subset, ttl)` on top of the existing `issue`/`verify`/`revoke` surface, plus an optional `presented_by` kwarg on `verify`. Each token is a chain of HMAC-linked claims (child keyed on parent's signature); revoking one token adds a single id to a set, and every descendant carries its full ancestor chain, so cascading revocation needs no per-descendant bookkeeping.
- **Adversarial validator + scenario**: `scenarios/delegated_auth_hmac.yaml` (coordinator -> 3 intermediaries -> 12 leaves) and four validators in `nest_core/validators.py` (`auth_delegation_occurred`, `auth_scope_escalation_blocked`, `auth_cascading_revocation`, `auth_audience_confusion_blocked`). All four **FAIL** against the `jwt` baseline (no `delegate()` at all) and **PASS** against `delegatable_hmac`.
**Naming note:** the plugin/scenario/registry-key/YAML identifiers carry an `_hmac` suffix (`delegatable_hmac` / `delegated_auth_hmac`) because #138, already merged to `main`, independently solved the same hackathon problem and claimed the unsuffixed `delegatable` / `delegated_auth` names first. This branch has been rebased onto current `main` and those identifiers renamed so both submissions coexist without a plugin-registry or scenario-name collision. **What differentiates this submission from other problem-04 solutions:** `auth_cascading_revocation`'s trace-order guards (`blocked_descendant_seen` and `ok_outside_seen`) require the revocation mechanism to actually fire and an unrelated sibling subtree to stay unaffected, so a validator that never observes a real block or a real unaffected sibling can't trivially pass; and the scenario is honest that its "stale parent" coverage exercises only the explicit-revocation case, since the shared plugin instance runs on a fixed simulated clock and tokens never naturally expire during the run.
## Test plan
- [x] `uv run pytest packages/nest-plugins-reference/tests/test_delegatable_hmac_auth.py -v`
- [x] `uv run pytest packages/nest-core/tests/test_delegated_auth_hmac.py -v`
- [x] `uv run ruff check .` — clean on all files this PR touches (one pre-existing, unrelated `E501` in `test_negotiation_determinism.py` from `main` itself)
- [x] `uv run ruff format --check .` — clean on all files this PR touches
- [x] `uv run pyright` — 0 errors
- [x] `uv run pytest -v` (full suite, rebased onto current `main`) — all tests in this PR's scope pass; 17 pre-existing failures on `main` itself (`registry: byzantine_gossip` missing from `_BUILTINS`) are unrelated to this change and reproduce on `main` before this branch is applied
- [x] Manually verified red -> green: removing the plugin/validators/scenario causes the corresponding test files to fail collection (`ModuleNotFoundError` / `ImportError`); restoring them, all tests pass
- [x] Byte-deterministic trace confirmed across seeds 42, 7, 1337
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Try it
Open PR on GitHubView diffCheckout locally
git fetch origin pull/114/head:pr-114
git checkout pr-114