Skip to content

feat(remotesessions): explicitly configure upstream OAuth scope + audience#2941

Merged
qstearns merged 11 commits into
mainfrom
quinn/age-2331-app
May 20, 2026
Merged

feat(remotesessions): explicitly configure upstream OAuth scope + audience#2941
qstearns merged 11 commits into
mainfrom
quinn/age-2331-app

Conversation

@qstearns
Copy link
Copy Markdown
Contributor

Summary

Wires the new scope and audience columns introduced in #2940 through the management API, model view, and OAuth dance.

  • Management API: optional scope (array) and audience (string) attributes on remoteSessionClients.{create,clone,update} forms and the RemoteSessionClient result. Goa enforces RFC 6749 §3.3 scope-token regex (^[!#-[\]-~]+$, MaxLength 128 per element) and audience pattern (^[!-~]+$, MaxLength 512) at the request boundary.
  • OAuth dance:
    • Scope: BuildAuthorizationUrl prefers client.scope over issuer.scopes_supported, falling back when unset.
    • Audience: when configured, attached to the authorize redirect, the authorization-code → token exchange, and every refresh-token request.
  • Tests: round-trip create/update + end-to-end authorize-URL + httptest refresh-form assertions for both fields.
  • Changesets: server: minor for both scope and audience.

Stacked on #2940 — base will retarget to main after the migration PR merges.

Linear: https://linear.app/speakeasy/issue/AGE-2331

Test plan

  • CI green
  • mise run test:server ./internal/remotesessions/... (62 tests)
  • mise run lint:server
  • Manually exercise the dashboard create/edit flow for a remote_session_client with scope + audience set

🤖 Generated with Claude Code

@qstearns qstearns requested a review from a team as a code owner May 20, 2026 02:51
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 20, 2026

AGE-2331

Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 20, 2026

🦋 Changeset detected

Latest commit: ceba4e4

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
server Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link
Copy Markdown

vercel Bot commented May 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
gram-docs-redirect Ready Ready Preview, Comment May 20, 2026 5:44pm

Request Review

@disintegrator
Copy link
Copy Markdown
Contributor

@claude review once

Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Code review skipped — your organization's overage spend limit has been reached.

Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit at claude.ai/admin-settings/claude-code.

Once credits are available, comment @claude review on this pull request to trigger a review.

@claude
Copy link
Copy Markdown

claude Bot commented May 20, 2026

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

@qstearns qstearns force-pushed the quinn/age-2331-migration branch from 9196ebc to 1bd9658 Compare May 20, 2026 16:57
Base automatically changed from quinn/age-2331-migration to main May 20, 2026 17:30
Wire scope through CreateRemoteSessionClient and UpdateRemoteSessionClient
params, and expose c.scope alongside i.scopes_supported on the two joined
client+issuer views the runtime uses to drive the OAuth dance.
@qstearns
Copy link
Copy Markdown
Contributor Author

@codex can you review?

@qstearns
Copy link
Copy Markdown
Contributor Author

@claude can you review?

qstearns added 3 commits May 20, 2026 10:37
Add an optional scope attribute to the create, clone, and update forms on
remoteSessionClients and surface it on the RemoteSessionClient result so
operators can override the upstream OAuth scope set the dance requests.
Pass payload.Scope through to the repo layer in CreateRemoteSessionClient,
CloneClientFromOAuthProxyProvider, and UpdateRemoteSessionClient, and
surface the stored value on the RemoteSessionClient model view.
Resolve the upstream scope set from the remote_session_client's stored
scope first, falling back to remote_session_issuers.scopes_supported when
unset. Applies to both the authorize URL minted by BuildAuthorizationUrl
and the outbound RFC 7591 DCR call fired by CreateRemoteSessionClient.
@claude
Copy link
Copy Markdown

claude Bot commented May 20, 2026

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

qstearns added 4 commits May 20, 2026 10:39
Adds:
- Unit coverage for Client.resolveScopes prefer-then-fallback semantics.
- An end-to-end test that drives ListClients → BuildAuthorizationUrl and
  asserts the upstream authorize URL's `scope` query parameter is sourced
  from the client override when set and the issuer's scopes_supported
  when absent.
- Round-trip assertions on create/update of the new RemoteSessionClient
  scope field.

Also explicitly initialises Scope on the issuer-driven DCR insert path
for exhaustruct, regenerates the TypeScript SDK from the updated OpenAPI,
and adds the AGE-2331 changeset.
Wire audience through CreateRemoteSessionClient and UpdateRemoteSessionClient
params, and expose c.audience alongside c.scope on the two joined
client+issuer views the runtime uses to drive the OAuth dance.
Add an optional audience attribute to the create, clone, and update forms
on remoteSessionClients and surface it on the RemoteSessionClient result.
… view

Pass payload.Audience through to the repo layer in CreateRemoteSessionClient,
CloneClientFromOAuthProxyProvider, and UpdateRemoteSessionClient, and
surface the stored value on the RemoteSessionClient model view.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e38695d587

ℹ️ 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".

Comment thread server/internal/remotesessions/queries.sql
When a remote_session_client has audience configured, attach it as the
upstream OAuth `audience` parameter on the authorize redirect, the
authorization-code → token exchange, and every refresh-token request.
Empty audience omits the parameter entirely.
qstearns added 2 commits May 20, 2026 10:42
Adds:
- Round-trip assertions on create/update of the RemoteSessionClient
  audience field.
- An end-to-end test that drives ListClients → BuildAuthorizationUrl and
  asserts the upstream authorize URL's `audience` query parameter is
  emitted when client.audience is set and omitted otherwise.
- Refresh-path tests that drive ResolveAccessToken against an httptest
  token endpoint and assert the POST body echoes audience iff configured.

Also regenerates the TypeScript SDK from the updated OpenAPI and adds
the AGE-2331 audience changeset.
…rings

Code-review cleanup over the AGE-2331 scope/audience commits:

- Replace three call sites of `conv.PtrValOr(conv.FromPGText[string](x), "")`
  with the equivalent `conv.FromPGTextOrEmpty[string](x)` helper that
  already exists in the conv package.
- Trim the new Client struct field docstrings down to the one non-obvious
  invariant (ClientScope overrides IssuerScopesSupported); the rest just
  restated the field names.
@qstearns qstearns force-pushed the quinn/age-2331-app branch from e38695d to ceba4e4 Compare May 20, 2026 17:44
@github-actions github-actions Bot added the preview Spawn a preview environment label May 20, 2026
@speakeasybot
Copy link
Copy Markdown
Collaborator

speakeasybot commented May 20, 2026

🚀 Preview Environment (PR #2941)

Preview URL: https://pr-2941.dev.getgram.ai

Component Status Details Updated (UTC)
✅ Database Ready Created and validated 2026-05-20 17:52:17.
✅ Images Available Container images ready 2026-05-20 17:51:35.

Gram Preview Bot

@qstearns qstearns added this pull request to the merge queue May 20, 2026
Merged via the queue into main with commit 3531836 May 20, 2026
33 checks passed
@qstearns qstearns deleted the quinn/age-2331-app branch May 20, 2026 18:04
@github-actions github-actions Bot locked and limited conversation to collaborators May 20, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

preview Spawn a preview environment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants