Repository navigation
Sync upstream while preserving external OIDC login - #6
Conversation
…o#1626) * Bind span header redaction to the hosted HTTP client Live verification after the telemetry-layer redaction shipped showed post-deploy http.client spans still recording non-allowlisted headers: consumers capture the client value at construction and execute requests on fibers a host telemetry layer never reaches, so providing the redaction reference by layer was not enough. Bind it to the client itself so every request effect carries it, and keep the cloud layer as the server-side half. Regression test drives a request through the real client and asserts on the recorded span attributes. * Add DOM.Iterable to the mcp plugin tsconfig The package's tsc build failed on Headers.entries() and the iterable protocol: its lib had DOM without DOM.Iterable, so the fetch Headers type lacked both. Latent on main; every CI run served the package build from the turbo cache until the sdk change invalidated it. Same lib pairing hosts/cloudflare already uses.
* Add first-party OAuth clients (host-operated GitHub/Google apps) * Allow endpoint overrides for the first-party GitHub app in tests/dev * Launch built-in Google OAuth for Calendar and Sheets
…uting (UsefulSoftwareCo#1632) * Send keepalive comments on rotated MCP SSE streams * Route drained Last-Event-ID reconnects to the standalone listener * Resume reconnects for streams with in-flight requests
* Speed up selfhost e2e: tunable sandbox deadline + 3-way sharding * Fix the local e2e suite: toolkit MCP DB lock, Bun-only spawn, stale auth selector * Stabilize CI process lifecycle
* Cut CI toward two minutes * Bring CI under two minutes * Make approval lease test deterministic * Stabilize E2E dependency setup * Harden CI regression coverage
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…sefulSoftwareCo#1656) * Fix two CI e2e flakes: stylesheet-count race and dev-db queue wedge * Raise sandbox-heavy discovery-shape test to the file's 10s ceiling
UTM-tagged landings on executor.sh produced no $pageview, so campaigns read as zero traffic in PostHog. The params only reached $web_vitals, which no funnel or web-analytics view uses. Autocapture stays off.
…finity (UsefulSoftwareCo#1658) * Retry reveal-style clicks that race console hydration * Repair dev-db queue affinity abandoned by mid-execution disconnects
* run independent tool-call reads concurrently * add e2e coverage for the tool-call contract * interrupt speculative reads on branches that never consume them * launch the dominant read before the speculative forks start * make dominant-first read launch structural, not scheduling-dependent * Accept the rare budget-yield launch reversal instead of suppressing yields * State the real launch-order guarantee in the fork comment
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* desktop publish: blacksmith runners, bun/electron caches, dry-run input * desktop publish: parallelize release asset uploads * desktop publish: drop caches, cold install is faster on these runners
* Overlap desktop build with npm publishes and parallelize package publishing * Gate desktop promote on the exact publish run; validate variant set from wrapper optionalDependencies
* Support raw OAuth Basic credentials * Fix OAuth app E2E selector * Stabilize cloud session cap E2E
* Restrict workspace writes to admins Co-authored-by: Max schwenk <maschwenk@gmail.com> * Fix self-host MCP request forwarding * Update file secrets durability invariant * Fix versioned cloud credentials * Fix self-host live-role scenario * Update cloud principal contract tests * Remove stray audit history assertions * Fix no-auth credential classification * fix(mcp): project legacy stdio as no-auth * fix(graphql): classify empty auth templates as no-auth * fix(sdk): defer no-auth classification to engine * fix(sdk): ignore placements on no-auth methods * test(mcp): make reconcile cleanup infallible * test(graphql): use empty no-auth timeout input * test(e2e): remove no-auth placeholder credentials * test(e2e): use empty no-auth credential shapes * Project legacy stdio credentials truthfully * Reject invalid no-auth placements * Reject MCP no-auth credential input * Propagate MCP test cleanup failures * Honor projected legacy stdio credentials * Deduplicate invalid auth method warnings --------- Co-authored-by: Max schwenk <maschwenk@gmail.com>
* feat(host-selfhost): Google sign-in with domain-allowlist admission * feat(host-selfhost): generic OIDC SSO sign-in with verified-domain admission * refactor(host-selfhost): extract SSO admission helpers, trim comments
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fa485591b7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| return { | ||
| context: { | ||
| context: { | ||
| options: { account: { accountLinking: { disableImplicitLinking: false } } }, |
There was a problem hiding this comment.
Provide a usable path for verified SSO linking
When SSO is enabled on an existing instance, users created through setup or invite-based email signup cannot use this implicit-linking branch: emailAndPassword configures no email-verification flow, so those users remain unverified, while Better Auth requires the local email to be verified before linking. The added test only succeeds after manually setting emailVerified = 1 in SQLite, and the UI exposes explicit linking only for external-oidc, not the configured SSO provider. Consequently, a normal existing user with a matching IdP email cannot adopt SSO without an operator editing the database; add an authenticated SSO-link flow or a reachable local email-verification path.
Useful? React with 👍 / 👎.
| // way it does for the email form's post-login navigation. | ||
| const result = await authClient.signIn.oauth2({ | ||
| providerId, | ||
| callbackURL: postLogin, |
There was a problem hiding this comment.
Return failed SSO callbacks to the login page
When the IdP denies authorization or the callback rejects a user outside EXECUTOR_SSO_ALLOWED_DOMAINS, this request stores no errorCallbackURL, so Better Auth sends the browser to its default auth-error endpoint instead of returning to the self-host login UI. The external-OIDC paths in this component explicitly supply an error callback for exactly this case, while the SSO test only checks that the resulting redirect contains error and never follows it. Supply a login-page error callback that also preserves postLogin so users can recover or choose local sign-in without landing on a raw auth endpoint.
Useful? React with 👍 / 👎.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
When an operator changes EXECUTOR_OIDC_ISSUER, this fixed provider ID causes Better Auth to look up both the old and new providers' accounts under the same (providerId, sub) namespace. If the new issuer returns a subject already linked under the previous issuer, an account at the new IdP can sign in as that existing Executor user without going through the email-matching link flow. Include the issuer in the persisted account identity or invalidate existing links when the issuer changes.
executor/apps/host-selfhost/web/login.tsx
Line 82 in 69c2e48
When this page is serving an interrupted MCP authorization, postLogin is /api/auth/mcp/authorize?..., so this new error URL nests that value inside returnTo. After an SSO or external-OIDC failure returns to /login, postLoginTarget rejects the nested target because safeReturnTo excludes /api/*; retrying local or provider sign-in therefore goes to / while the MCP client remains waiting. The fresh evidence beyond the handled ordinary deep-link case is this MCP-specific target produced by mcpAuthorizeResumeTarget; preserve the original top-level authorization parameters or explicitly validate and resume this internal endpoint.
executor/apps/host-selfhost/src/config.ts
Lines 191 to 194 in 69c2e48
When an IdP issues an opaque client secret that is not exactly 64 base64url characters, enabling external OIDC now throws during boot even though the credential is valid for that provider. OIDC providers control this value and commonly vary its length and character set, so operators cannot necessarily regenerate it in this imposed format; the tests conceal the incompatibility by using "A".repeat(64). Treat the nonempty provider-issued secret as opaque rather than enforcing a locally generated-key format.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const idp = await createEmulator({ | ||
| service: "okta", | ||
| port: ports.E2E_SELFHOST_SSO_IDP_PORT!, | ||
| }); |
There was a problem hiding this comment.
Close the emulator when setup aborts
If client registration, user seeding, or bootSelfhost fails after this acquisition, the callback never returns its teardown, and the later Effect.ensuring is never installed because booted was not produced. The emulator therefore retains its listening port and can keep the failing e2e worker alive; wrap the entire acquisition sequence in cleanup that closes idp on every setup failure.
AGENTS.md reference: e2e/AGENTS.md:L16-L17
Useful? React with 👍 / 👎.
| const clientId = process.env.EXECUTOR_SSO_CLIENT_ID?.trim(); | ||
| const clientSecret = process.env.EXECUTOR_SSO_CLIENT_SECRET?.trim(); | ||
| if (!clientId && !clientSecret) return undefined; |
There was a problem hiding this comment.
Reject all partial SSO configurations
When an operator sets SSO metadata such as EXECUTOR_SSO_PROVIDER_ID, EXECUTOR_SSO_DISCOVERY_URL, or EXECUTOR_SSO_ALLOWED_DOMAINS but the client credential injection is missing, this early return silently disables SSO instead of reporting the incomplete deployment configuration. That contradicts the surrounding fail-at-boot contract and leaves the instance running local-only with no indication beyond the missing login button; determine whether any SSO variable is present before returning undefined.
Useful? React with 👍 / 👎.
|
@codex review |
|
Codex Review: Didn't find any major issues. 🎉 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Merge UsefulSoftwareCo/executor at
38915a32cfa0fa1fd0012ee12a8c21716710dbc1into this fork, retaining opt-in external OIDC alongside upstream SSO. This includes 328 upstream commits; dependency manifests, all seven patches, and bun.lock remain identical to upstream.Upgrade requirement: existing external OIDC links must be relinked. Old records contain only a subject and cannot establish which issuer owned it. They remain stored but cannot authenticate automatically. Users sign in with their local password and explicitly relink with a matching verified provider email. New links bind issuer and subject; switching issuers cannot reuse another issuer's account. No automatic database rewrite or deletion is performed. Qualify local account access before upgrading. A source downgrade can reactivate legacy links and cannot safely be combined with an issuer change without separate rollback qualification.
Both providers share one generic OAuth plugin. External OIDC retains explicit local-account proof and rejects signup or implicit email matching. SSO retains verified-domain admission and offers authenticated linking for existing setup/invite accounts without database edits or relaxed provider/email checks. Provider failures return to usable login with ordinary deep links and MCP authorization parameters intact. Partial SSO configuration fails at boot; external client secrets accept opaque provider-issued values while retaining secret-file ownership and permission checks.
The selfhost Vite HTTP adapter now preserves every Set-Cookie header. Its inherited overwrite behavior dropped the session cookie during interrupted MCP login. Emulator/browser setup releases resources on acquisition failures as well as normal completion.
Validation:
e2e/runs/selfhost/external-oidc-coexistence-explicit-linking-and-deep-link-return/.Merge with a merge commit to retain upstream ancestry; do not squash or rebase.