Skip to content

feat(features): let org admins enforce preemptive session refresh - #5066

Draft
speakeasyforgebot wants to merge 5 commits into
mainfrom
cursor/org-default-preemptive-session-refresh-4b7e
Draft

feat(features): let org admins enforce preemptive session refresh#5066
speakeasyforgebot wants to merge 5 commits into
mainfrom
cursor/org-default-preemptive-session-refresh-4b7e

Conversation

@speakeasyforgebot

@speakeasyforgebot speakeasyforgebot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds an organization-wide policy for automatic remote-session refresh (AIS-493), managed by customer organization admins from the MCP Connections page, and makes that policy legible to end users on the OAuth consent screen.

The policy has three explicit states:

  • Disabled — refresh never runs; the consent screen states this read-only so users know idle connections will lapse.
  • User controlled — the consent screen shows an editable control, defaulting new connections on.
  • Required — refresh always runs; the consent screen shows it locked as managed by the organization.

Changes

Organization policy (admin)

  • Adds an atomic setRemoteSessionAutoRefreshPolicy endpoint authorized with org:admin, so the two underlying product-feature flags cannot be left partially updated.
  • Adds the three-state policy card to the customer-facing MCP Connections page. Organization readers see the effective policy; only organization admins can change it.
  • Removes both automatic-refresh controls from the internal Developer Toolkit.

Consent screen (end user)

  • Replaces the previous show/hide behavior with an explicit policy model, so a managed policy is always visible instead of silently absent. Disabled previously rendered nothing at all, which left users unable to tell that refresh was off.
  • Renders the value read-only under both managed policies (Off · Managed by your organization / On · Managed by your organization) and editable only under User controlled. Off is styled neutrally rather than as a feedback color, since it is a policy choice and not a failure.
  • Ignores the posted form value under both managed policies, so a crafted request can neither disable a required connection nor opt into refresh the organization disabled. Only the Disabled direction was previously unguarded.

Keepalive

  • Eligibility is now the organization policy applied to the session's own preference: Required refreshes every eligible session, User controlled honors the stored preference, and Disabled refreshes nothing. Previously a stored auto_refresh = true kept renewing connections after an organization turned refresh off, which would have made the new "Off" label untrue.
  • Stored preferences are read, never rewritten, so restoring User controlled restores each user's original choice.

Testing

  • mise run test:server ./internal/productfeatures/... ./internal/mcp/... ./internal/remotesessions/... — passes, including new coverage for all three policies on the consent template, the required and disabled keepalive paths (and that a restored opt-in policy honors the stored preference again), and org:admin enforcement on the new endpoint.
  • mise run lint:server, mise run build:server, pnpm -F dashboard lint, pnpm -F dashboard type-check, pnpm -F dashboard build — pass.
  • Manual end-to-end verification of the admin policy change, including persistence across reload.

Admin policy on MCP Connections

mcp_connections_refresh_policy.mp4

Consent screen, one state per policy

Rendered from the production consent template (a live capture would require real upstream OAuth providers).

Disabled:

Consent screen showing Auto refresh Off, managed by your organization

User controlled:

Consent screen showing an editable Auto refresh control set to On

Required:

Consent screen showing Auto refresh On, managed by your organization

Linear Issue: AIS-493

Open in Web Open in Cursor 

Summary by cubic

Adds an org-level policy for preemptive remote session refresh with Disabled, User controlled, and Enforced states so admins can set and lock the default. This improves session reliability and aligns consent UX with org policy (AIS-493).

  • New Features

    • Policy endpoint: new RPC productFeatures.setRemoteSessionAutoRefreshPolicy with enum values disabled, user_controlled, enforced; maps to visibility + enforced flags.
    • Consent flow: the consent page now always shows refresh status when remote sessions exist; Enforced shows “On · Managed by your organization” and is pinned on, Disabled shows “Off · Managed by your organization”; posted values are ignored under managed policies and both connect and set_auto_refresh force the managed value.
    • Keepalive: refresh candidates include sessions when the user opted in or the org enforces; the stored per-session preference is unchanged.
    • Dashboard: added “Remote Session Refresh Policy” control with three options on Org → User Sessions; removed the old admin-panel toggle; non-admins see read-only.
    • API/SDK: GetProductFeatures includes remote_session_auto_refresh_enforced_enabled; new @gram/client function featuresSetRemoteSessionAutoRefreshPolicy and React Query hook useSetRemoteSessionAutoRefreshPolicyMutation; OpenAPI and CLI updated.
  • Bug Fixes

    • Hardened read-only policy guard and resolved UI lint issues in the new policy controls.

Written for commit 79c3926. Summary will update on new commits.

Review in cubic

Introduce a new remote_session_auto_refresh_enforced product feature so
org admins can make preemptive session refresh the organization default
rather than relying only on per-user settings.

- productfeatures: new feature constant, Goa design attribute + enum, and
  GetProductFeatures result field (regenerated Goa + TS SDK).
- consent flow: when enforced, the auto-refresh control renders locked
  ('On · Managed by your organization'), the value is pinned on, and the
  posted form value is never trusted (connect/set_auto_refresh forced on).
- keepalive: ClaimDue/GetDue candidate queries treat every eligible
  session as due when the org enforces refresh, regardless of the persisted
  per-session preference (opt-in visibility feature stays UI-only).
- dashboard: admin panel toggle for the enforced feature.
- tests: consent template locked-state test + refresh sweep enforced-org test.

Co-authored-by: Forge Bot <speakeasyforgebot@users.noreply.github.com>
@linear-code

linear-code Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

AIS-493

@changeset-bot

changeset-bot Bot commented Aug 7, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 79c3926

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

cursoragent and others added 3 commits August 9, 2026 15:36
Co-authored-by: Sagar Batchu <simplesagar@users.noreply.github.com>
Co-authored-by: Sagar Batchu <simplesagar@users.noreply.github.com>
Co-authored-by: Sagar Batchu <simplesagar@users.noreply.github.com>
Co-authored-by: Sagar Batchu <simplesagar@users.noreply.github.com>
@blacksmith-sh

blacksmith-sh Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Found 1 test failure on Blacksmith runners:

Failure

Test View Logs
github.com/speakeasy-api/gram/server/cmd/tools/migrations/riskfindings/
TestPipelineRespectsFromBound
View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@simplesagar simplesagar self-assigned this Aug 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants