AuthMiddleware.install(ctx, config, source) now owns the annotation processor and
the flash.auth.policy key, so a second credential source gets annotation-driven
authorization without copying the wiring. The key is public: an extension that
contributes middleware can order itself around authentication.
OidcSession becomes Session in auth-core, carrying claims, an expiry and an opaque
attribute map. OpenID Connect keeps its access, id and refresh tokens in that map
under its own keys, so renewal stays its business and core has no OAuth2 vocabulary
in it. isAccessTokenExpired() becomes isExpired(), with the 30s eager-renewal
window it always had and now a test for it.
flash-ext-oidc is renamed flash-ext-auth-oidc, matching cache-core/cache-caffeine
and data-core/data-hibernate.
First migration, chosen because it is the case that drove the harness design:
a Flash app plus a FakeOidcProvider, with tokens audience-bound to the app's
own port, so the port has to be readable after boot.
Drops the racy free-port dance, the hand-rolled HttpClient plumbing and the
per-test teardown; failures now report the response body. 120 to 106 code
lines, and what remains is tool-policy assertions rather than fixture code.
The two boot-rejection tests keep building their app directly — a harness whose
job is to boot an app is the wrong tool for asserting that booting fails — but
port(0) removes freePort() from those too.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Streamable HTTP transport (JSON-RPC 2.0 over POST), one-class-per-tool/resource/prompt
API mirroring RequestHandler, boot-time-precompiled schema/list payloads for a zero-alloc
hot path, and optional OAuth2 protection built on flash-ext-oidc (lazy-loaded, RFC 8707
audience binding, RFC 9728 Protected Resource Metadata). Registers the module in the
root and flash-extensions POMs and adds the ext-mcp commit scope to AGENTS.md.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>