identity: identity->acl delegation boundary — 401 gates before 403 (+8 tests)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 57s

delegation.sx makes the loop's central rule concrete: check() introspects
the token first — inactive → {error, unauthenticated} (401), acl never
consulted — and only an authenticated subject's request is delegated to
acl, which returns permit/deny ({error, forbidden} = 403). 401 strictly
precedes 403. acl-on-sx (Datalog) is a different SX guest wired at the
integration layer, so the decider here is a labelled stub (permits when
Action in Scope); swap the pid and the boundary is unchanged. New
tests/delegation.sx. 185/185 — extensions backlog clear.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-07 03:05:12 +00:00
parent d2f5b49d3f
commit db885e15bc
6 changed files with 158 additions and 6 deletions

View File

@@ -19,7 +19,7 @@ through the event log, all authorization questions delegated to `acl-on-sx`.
## Status (rolling)
`bash lib/identity/conformance.sh`**177/177** (4 phases + 7 ext incl unified facade)
`bash lib/identity/conformance.sh`**185/185** (4 phases + 8 ext; backlog clear)
## Ground rules
@@ -83,11 +83,20 @@ lib/identity/api.sx ── (identity/login) (identity/grant?) (identity/revoke)
- [x] scope as a set + scope narrowing on refresh (RFC 6749 §6)
- [x] client registry: public vs confidential clients, client authentication (RFC 6749 §2)
- [x] client-credentials grant (RFC 6749 §4.4) + device grant (RFC 8628)
- [ ] acl-on-sx delegation: wire `verify`/membership projection → an acl decision, integration test
- [x] acl-on-sx delegation: identity-gates-before-acl boundary (401 vs 403), stub decider (live Datalog bridge is cross-substrate)
- [ ] OAuth `state` (CSRF) + OIDC `nonce` threaded through authorize→exchange
- [x] unify `api.sx` over membership + audit (one facade, audited login/logout)
## Progress log
- 2026-06-07 — `delegation.sx` (ext): the identity→acl boundary made concrete.
`check` introspects the token first: inactive → `{error, unauthenticated}`
(401, acl never consulted); active → constructs {Subject, Scope, Action,
Resource} and hands off to acl, which returns permit/deny (`forbidden` =
403). 401 strictly precedes 403 (a revoked token with no scope is still
unauthenticated). acl-on-sx (Datalog) is a different SX guest language —
wired at the integration layer — so the decider here is a labelled stub
(permits when Action ∈ Scope); swap the pid, boundary unchanged. New
tests/delegation.sx (8). 177→185. **Extensions backlog clear.**
- 2026-06-07 — unified facade (ext): `api.sx` coordinator now owns an audit
ledger + a membership registry alongside its token table (started with the
ledger) and session registry. login/logout are audited; new ops