- Register validates redirect_uris/grant_types/response_types/auth-method
in PHP's exact order, strips control characters and caps client_name at
255 runes, and generates client_id/secret via crypto/rand base64url
- confidential clients return the raw secret once; only its sha256 hex
persists (constant-time-comparable fixed transform)
- sweep-unconsented, the atomic cap check and the create all run inside one
wristband.Backend.WithinTx transaction (T-08-DCR-FLOOD)
- 64 KiB body bound via http.MaxBytesReader collapses to the endpoint's
native invalid_client_metadata body, matching D-21
- TestPhase8RedRegistration asserts the exact public-client DCR success
contract and fails while Server.Register is a 501 stub
- adds the Backend/Tx transaction-scoped store bundle (ClientStore,
AuthCodeStore, RefreshTokenStore, AccessTokenIssuer) and wristband's own
in-memory implementation for framework-level tests (D-07)
- adds crypto.go's fixed-transform helpers (random base64url, sha256 hex,
constant-time compare, S256) and Options/Server seams for the DCR
lifetimes, cap, sweep age and 64 KiB body bound (D-03/D-21)
- Server.Metadata now writes the unwrapped 11-field PHP-parity document
through a local no-envelope, no-trailing-newline JSON writer with the
PHP Cache-Control: no-cache, private header (D-06); response types,
grant types and PKCE method stay fixed protocol constants
- TestPhase8RedMetadata now passes; TestMetadataExactBytes and
TestMetadataUsesConfiguredOptions cover byte-exact output and the four
configurable Options fields
- wristband.Server.Metadata is a compiling 501 stub; TestPhase8RedMetadata
asserts the exact unwrapped PHP metadata document, headers and status and
fails with the PHASE8_RED:metadata sentinel (D-06)
- scripts/check-phase8-red.sh implements the shared go/shell RED contract
for the rest of Phase 8: exact selected test/package failure plus sentinel,
rejecting unrelated fail actions, compile/setup failures, panics,
malformed JSON, missing/duplicate sentinels and zero selection (D-04/D-18)