**RESOLVED 2026-07-12 (w6 follow-ups).** Hydra has no global PKCE toggle (verified), so PKCE is now required at the dashboard consent acceptor (dashboard/src/common/server-fn/hydra-consent.ts): a consent request whose authorize URL lacks a code_challenge is rejected with 400. Covered by a new vitest case.

# Enforce PKCE for all authorization_code clients — from w6/m6/t006 (OAuth audit)

PKCE is **not** enforced bex-side. The bootstrap client and bex-minted API keys
use `client_credentials` (PKCE does not apply). OAuth 2.1 agent clients
self-register via Hydra's public DCR (`deploy/gitops/base/values/hydra.values.yaml`,
`oidc.dynamic_client_registration.enabled: true`), and the only authorization_code
clients are those agent DCR clients — which are **public**, so Hydra mandates
PKCE per OAuth 2.1 conformance. The actual MCP-agent surface is therefore
covered.

The gap: nothing in bex or the committed Hydra values requires PKCE for **all**
authorization_code clients, so a future confidential (secret-bearing) DCR client
could run authorization_code without PKCE and Hydra would allow it.

**Fix:** set Hydra's `oauth2.pkce` enforcement in
`deploy/gitops/base/values/hydra.values.yaml` (Hydra 2.x supports requiring PKCE
for every authorization_code client), and/or have bex-api or the dashboard
consent route reject authorization_code clients lacking `require_pkce: true` at
DCR time. Low priority — the real attack surface (public agent clients) is
already PKCE-mandated by Hydra.

Source: w6/m6/t006 OAuth/OIDC audit, 2026-07-11.
