identity: client-credentials grant (RFC 6749 §4.4, +9 tests)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 40s

oauth.sx now owns a client registry (loop/6) with register_client and the
client_credentials grant. A confidential client authenticates and gets a
token acting on its own behalf (subject = the client), no refresh token
(§4.4.3). A public client is unauthorized_client; any auth failure (unknown
client or wrong secret) is invalid_client — no client-existence oracle
(§5.2). identity-load-oauth! now pulls its deps. New tests/grants.sx.
158/158.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-07 02:22:26 +00:00
parent 9860582b4a
commit 3f3459d129
6 changed files with 139 additions and 25 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`**149/149** (4 phases + ext: scope, TTL, client registry)
`bash lib/identity/conformance.sh`**158/158** (4 phases + ext: scope, TTL, clients, client-creds)
## Ground rules
@@ -82,12 +82,20 @@ lib/identity/api.sx ── (identity/login) (identity/grant?) (identity/revoke)
- [x] access-token TTL / `expires_in` — logical-clock expiry, introspect honours it
- [x] scope as a set + scope narrowing on refresh (RFC 6749 §6)
- [x] client registry: public vs confidential clients, client authentication (RFC 6749 §2)
- [ ] client-credentials grant (RFC 6749 §4.4) and device grant (RFC 8628)
- [~] client-credentials grant (RFC 6749 §4.4) DONE; device grant (RFC 8628) pending
- [ ] acl-on-sx delegation: wire `verify`/membership projection → an acl decision, integration test
- [ ] OAuth `state` (CSRF) + OIDC `nonce` threaded through authorize→exchange
- [ ] unify `api.sx` over oauth + membership + audit (one facade, audited login/consent)
## Progress log
- 2026-06-07 — client-credentials grant (ext, RFC 6749 §4.4): `oauth.sx` now
owns a client registry (loop/6); `register_client` + `client_credentials`.
A confidential client authenticates and gets a token acting on its own
behalf (subject = the client), no refresh token (§4.4.3). A public client is
`unauthorized_client`; any auth failure (unknown client OR wrong secret) is
`invalid_client` — no client-existence oracle (§5.2). `identity-load-oauth!`
now pulls its deps (token/session/registry/clients). New tests/grants.sx (9).
149→158.
- 2026-06-07 — `clients.sx` (ext): OAuth client registry (RFC 6749 §2). public
vs confidential clients; confidential clients MUST present the right secret
(wrong → invalid_client), public clients are identified but not