Fake AS emits spec-required iss/sub; declare deferred verify checks
Two foundational fixes plus a pair of placeholder checks:
Fake AS compliance: the authorize redirect now always appends
`iss=<active_base>` (atproto's `authorization_response_iss_parameter_supported
= true` contract) and token responses now always include
`sub=<account DID>`. Without these, a spec-compliant client pointed
at the fake AS couldn't perform the mandatory issuer and subject
verifications — meaning our own fake AS was the reason those
verifications appeared to succeed. Driving real clients against the
fake AS now gives them the fields they're required to check.
Placeholder checks: add `ClientVerifiedIss` and `ClientVerifiedSub`
to the interactive `CHECK_ALL`, rendered on every report as
`Skipped` with reason "broken-AS sub-stage for client-side
iss/sub verification not yet implemented". The atproto OAuth
profile calls this verification *"critical (mandatory)"* for all
clients (<https://atproto.com/specs/oauth#authentication-and-subject>)
— the checks are visible so operators know the gap exists; fully
exercising them requires a broken-AS sub-stage (similar in shape to
`dpop_edges`) that emits bogus `iss` or wrong `sub` and observes
whether the client terminates the flow. That infrastructure is a
future phase.
Design plan updated with AC4.9 (fake AS compliance — Success) and
AC4.10 (Deferred) so the intent is recorded.
All 334 tests pass; all 16 real-world atproto OAuth clients still
pass statically.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>