feat: introspection-mode token validation (CRAIG Plan F pattern)

Scope

Implement RFC 7662 introspection-based token validation as an alternative to local JWS validation. Unblocks IdPs that emit JWE-encrypted (kanidm), opaque (ZITADEL-opaque, Keycloak-lightweight-tokens), or encrypted-mode (authentik-encrypted) access tokens.

Acceptance

  • canopy_auth::IntrospectionClient posts bearer to issuer's introspection endpoint + caches claims
  • Per-service env var CANOPY_<SVC>__TOKEN_VALIDATION_MODE selects strategy: jws | introspect | auto
  • auto dispatches on token shape (3 segments → JWS, 5 → JWE-via-introspection, no dots → opaque-via-introspection)
  • Five per-service knobs per CRAIG Plan F: endpoint, auth method, cache TTL, cache max entries, serve-on-outage
  • CHANGELOG entry

References

  • Tracking: epic &51 #460
  • CRAIG ADR-029: ~/code/craig/docs/modules/ROOT/pages/adrs/adr-029-introspection-validation.adoc
  • CRAIG idp-integration.adoc lines 7-10, 136-165