Repository navigation
[pull] main from UsefulSoftwareCo:main - #52
Merged
Merged
Conversation
* Add ID-JAG discovery, token exchange, and jwt-bearer redemption helpers
* Wire the enterprise-managed grant through connect and credential refresh
* Add ID-JAG protocol conformance fixtures and tests
* Cover the enterprise-managed credential lifecycle through the executor
* Declare the enterprise identity provider on MCP servers and carry it to connect
An MCP oauth2 method may now name the registered OAuth app that plays its
enterprise identity provider. The catalog projects that pointer so a client
knows which app to name on oauth.start, and the start handler forwards the
enterprise inputs it was already accepting. Declaring a provider only asks the
connect path to try the ID-JAG grant; the server still has to advertise the
profile, so an ordinary server keeps the interactive flow.
* Match enterprise-managed failures with tagged handlers
The refresh path switched on _tag by hand and the fallback rule lived in an
exported predicate nothing called. Use catchTags for the mapping, assert the
tags directly in the tests, and drop the predicate: the connect path's single
catchTag is where that rule is actually enforced.
* Cover enterprise-managed authorization against the Okta and MCP emulators
A selfhost scenario runs the whole ID-JAG chain through the product: Okta
issues the ID token, executor exchanges it for an ID-JAG and redeems it at the
MCP server, and a tool call rides the result with no consent step. Seeding one
DENY policy then proves a refusal surfaces as blocked-by-admin and does not
fall back to the interactive flow. Both emulator ledgers carry the assertions.
Needs emulate 0.14.0 for the Okta token exchange and its policy table.
* Classify token-endpoint error bodies in one place
The ID-JAG exchange had its own error-body machinery beside the existing
one, and it only understood a conform RFC 6749 envelope. An IdP answering
{"errors":["invalid_grant - ..."]} therefore read as a transport failure
and was retried forever instead of asking for a fresh sign-on.
Route it through toOAuth2ErrorWithHttpSummary, which now tries the conform
envelope first and falls back to the closed-set non-conform recovery. The
recovery only runs on 4xx, so a 5xx carrying an error code stays a
retryable transport verdict rather than becoming a permanent refusal.
Also hoist the body-reading helpers: a body-read failure on the exchange
response now fails distinctly instead of rendering as "did not match RFC
8693 2.2.1", and the read is passed as a thunk so a clone() on a consumed
body is caught rather than escaping as a defect.
* Give OAuthStartError its verdict fields, and declare the payloads once
A start failure carried only prose, so a console could not tell an
administrator refusal from a credential problem — and the two demand
opposite behaviour: blocked-by-admin must NOT offer the interactive
per-server flow, because that walks the user around the policy the
identity provider just enforced. Add blockedByAdmin and oauthErrorCode
alongside the pattern OAuthCompleteError already sets with
restartRequired.
Same file, second concern: { client, clientOwner } was written three times
(SDK interface, API Schema.Struct, MCP plugin Schema.Struct) and the
enterprise connect input twice. Each is now one Schema in the SDK that the
API and the MCP plugin reference.
SUBJECT_TOKEN_TYPES goes back to module-local: it is only ever an argument
to Schema.Literals.
* Keep the enterprise-managed taxonomy structural through connect and refresh
The connect boundary flattened every EMA failure to a message string, so
the taxonomy the module argues for at length stopped at the service edge.
Translate per tag instead: a policy denial reaches the caller as
blockedByAdmin with the identity providers own error code.
Split the error union so minting cannot claim a verdict it never reaches.
mintEnterpriseManagedAccessToken never inspects metadata, so
EmaGrantProfileUnsupported belongs only to the discovery entry point; the
refresh path loses its unreachable arm.
Also: the connect paths authorization-server discovery was unbounded,
because it was copied from scope discovery without the timeout. Both now
share one capped, bounded probe loop. The inert Effect.provide on the EMA
chain is gone — oauth4webapi drives the configured fetch, not HttpClient,
and the layer read as a claim the chain did not honour.
* Assert the enterprise-managed verdict, not its wording
Substring-matching the rendered prose let the tests pass on any error that
happened to say the right thing, and left blockedByAdmin with no coverage
at all. Assert the tag and the fields instead, at the unit, lifecycle, and
e2e tiers.
Cover the case that only exists over time: an administrator withdrawing
access AFTER a connection was made, which the credential-refresh path
meets with no user present. That is the only producer of blockedByAdmin on
a credential failure, and it was untested. The OAuth fixture grows a
policy control for it, since a denial that is fixed at construction cannot
express the change.
Decode the fixtures metadata through the production schema, so a decoder
that stopped retaining authorization_grant_profiles_supported would fail
the gate that reads it.
* Gate enterprise-managed authorization behind a host-owned rollout seam * Carry the rollout gate through to the cloud executor * Evaluate the enterprise-managed rollout flag in PostHog * Re-run CI after rebase onto main
This branch was successfully deployed
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )