feat(platform): declarative kernel OAuth broker (descriptor engine) — spec 005 core#325
Merged
Merged
Conversation
… spec 005 core
Finishes spec 004's deferred layer 3 (the kernel OAuth broker, Task C) as a
DECLARATIVE descriptor engine rather than hardcoded provider classes — so any
future "connect X" plugin acquires standard authorization-code credentials
through pure manifest data, with no bespoke core PR.
- Manifest: top-level `oauth_providers[]` descriptors + `type:oauth` field
provider/scopes parsing; `permissions_summary.acquires_oauth` signal (T21).
- Engine: generic RFC-6749 / PKCE / refresh from descriptor data
(`token_auth_style` body_form|body_json|basic, `{field}` URL interpolation).
Retires the bespoke MicrosoftGraphProvider class — it collapses into a
`body_form` + `{tenant_id}` descriptor regression fixture. No plugin code
runs in the OAuth dance; refresh tokens stay kernel-side (T22).
- pendingFlows + signed state gain a `pluginId` path for store-detail
re-connect without an install job (T23).
- Broker routes GET /api/v1/install/oauth/{start,callback}; start is
operator-authed, callback is public + state-verified (publicPaths). Tokens
persist to the plugin's own vault namespace under `oauth.<fieldKey>` (T24).
- ctx.oauthTokens.get(fieldKey): valid access token, lazy refresh under a
5-min margin, refresh-token rotation, never leaked; typed errors
(not_connected / refresh_failed) (T25).
- web-ui: `type:oauth` fields render a Connect button (store-detail
re-connect); store page shows the `?connected=ok|error` broker result (T26).
Spec: specs/005-declarative-oauth-broker-atlassian/spec.md. Validated by
engine units (MS fixture + Atlassian dialect), stub-IdP broker integration
tests, and the accessor's lazy-refresh tests. The Atlassian consumer plugin
(integration + agent, new repo) follows in T28–T31.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`validateValues` still carried the spec-004 stub that hard-rejected any
`type:oauth` field with `unsupported_type` ("erst in Slice 1.2c"). Slice 1.2c
is the broker shipped in this branch — so every broker plugin (e.g.
integration-atlassian) failed to install: configure rejected the declared
oauth field even though its value is supplied AFTER install by the broker
(Connect flow → token in the vault under `oauth.<key>`), never at the flyout.
configure now skips `type:oauth` fields entirely. Regression test:
configure with an oauth field present activates, and the oauth field is never
flagged (while a genuinely missing required non-oauth field still is).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…(spec 005) The integration sets its operator-facing status + resolves derived config (e.g. Atlassian cloud_id) only in activate() → resolveConnection(). But the broker callback persists the tokens AFTER activate, with nothing to re-run that resolution — so post-connect the plugin's ctx.status stayed needs_action and its derived config stayed empty until the next restart. The callback now calls an injected reactivatePlugin(pluginId) hook after the tokens persist (best-effort; wired to installService.reactivate, the same deactivate→activate the install flow uses). The plugin re-reads the stored token, resolves derived config, and clears its status — so the badge clears without a restart. Broker test asserts reactivation fires on success and not on deny. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Finishes spec 004's deferred layer 3 (the kernel OAuth broker, Task C) as a declarative descriptor engine rather than hardcoded provider classes — so any future "connect X" plugin acquires standard authorization-code credentials through pure manifest data, with no bespoke core PR.
Spec:
specs/005-declarative-oauth-broker-atlassian/spec.md.What's in this PR (core only)
oauth_providers[]descriptor schema +type:oauthfield provider/scopes parsing;permissions_summary.acquires_oauthsignaltoken_auth_style(body_form|body_json|basic),{field}URL interpolation. Retires the bespokeMicrosoftGraphProviderclass — it collapses into abody_form+{tenant_id}descriptor regression fixturependingFlows+ signed state carrypluginIdso the store-detail re-connect path works without an install jobGET /api/v1/install/oauth/{start,callback}— start is operator-authed, callback is public + signed-state-verified (publicPaths). Tokens persist to the plugin's own vault namespace underoauth.<fieldKey>ctx.oauthTokens.get(fieldKey)— valid access token, lazy refresh under a 5-min margin, refresh-token rotation, never leaked; typed errors (not_connected/refresh_failed)type:oauthfields render a Connect button (store-detail re-connect); store page surfaces the?connected=ok|errorbroker resultSecurity posture
extra_authorize_paramscannot override engine-owned params (redirect_uri, PKCE, etc.).Tests
Engine units (Microsoft fixture + Atlassian
body_jsondialect, error handling, reserved-param guard, interpolation), stub-IdP broker integration (round-trip, user-deny, bad-state, single-use replay, exchange-fail, missing-creds), and the accessor's lazy-refresh / rotation / failure-mode tests.tsc+eslintclean.The Atlassian consumer plugin (integration + agent, separate Hub repo) validates this end-to-end and follows in a separate change (spec 005 T28–T31).
🤖 Generated with Claude Code