Skip to content

feat(api): a deployment can serve mainnet only - #2875

Merged
Windscar merged 6 commits into
mainfrom
claude/prod-sandbox-switch
Nov 13, 2026
Merged

Windscar merged 6 commits into
mainfrom
claude/prod-sandbox-switch

Conversation

@Windscar

@Windscar Windscar commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

SDP_ALLOW_SANDBOX_PROJECTS=false (the mirror of SDP_ALLOW_PRODUCTION_PROJECTS) makes a deployment mainnet-only. Unset keeps today's behavior, so this changes nothing on any deployment until infra sets it.

  • Sandbox projects are hidden and refused at the edge and in money admission. New orgs get no sandbox project, and no sandbox cron work is registered.
  • An org without mainnet access may only read its organization, projects and members and request mainnet access. Every other action answers 403 reason: "organization_not_admitted", checked in requireAction. Invitations are refused too, so unapproved orgs can't send prod Clerk invitations.
  • On a deployment that admits no production project (beta), mainnet requests are refused. The mainnet-access read adds sandboxOnly and mainnetOnly for the dashboard, and every signed-in member may read it (organizations.read; requests stay admin-only), since the dashboard decides from it where a member lands. Its parse defaults both to false for older API revisions.
  • Both settings false fails at boot.
  • "Mainnet enabled" reads as a welcome and is sent even with alert emails off (so is "Mainnet disabled"); the request page promises it.
  • Runbook: docs/ops/beta-cutover.md.
  • Docs: the new 403 is in the authentication guide's error table.

Verification: API typecheck; API suite 9216 passed, plus the 2 files edited mid-run, 44/44 on rerun; new mainnet-only-deployment.test.ts sweeps every project route with a sandbox project; web typecheck and mainnet-access tests 74/74; docs check:prose and check:links pass. Local QA on a mainnet-only stack (results in the release test plan): lock, refusals, request and approval pass.

Part of PRO-2436 and PRO-2477.

🤖 Generated with Claude Code

`SDP_ALLOW_SANDBOX_PROJECTS=false` is the mirror of `SDP_ALLOW_PRODUCTION_PROJECTS`. The
deployment hides and refuses every sandbox project (edge and money admission), creates none
for a new organization, registers no sandbox cron work, and admits only organizations with
mainnet access: the others may read their organization, projects and members and request
mainnet access, and every other action answers 403 `organization_not_admitted`.

A deployment that admits no production project (the sandbox) takes no mainnet requests: the
mainnet-access read says `sandboxOnly`, and a request is refused. The read also says
`mainnetOnly` for the dashboard. Unset keeps today's behavior; both settings false fails at boot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
sdp-docs Ready Ready Preview Nov 13, 2026 4:36am UTC
sdp-web Ready Ready Preview Nov 13, 2026 4:36am UTC
2 Skipped Deployments
Project Deployment Actions Updated
sdp-docs-beta Ignored Ignored Preview Nov 13, 2026 4:36am UTC
sdp-web-beta Ignored Ignored Preview Nov 13, 2026 4:36am UTC

Request Review

@github-actions

github-actions Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

React Doctor found no new issues. 🎉

Reviewed by React Doctor for commit 4918cdd.

…ting

The "Mainnet enabled" email answers the organization's own request, and the
mainnet request page promises it. It now reads as a welcome (open the
dashboard, start with the production project) instead of a change to review,
and it and "Mainnet disabled" are sent even when the organization turned alert
emails off, like the alert about that setting itself.

Also: a test that an organization without mainnet access on a mainnet-only
deployment cannot send feedback, and the cutover runbook
(docs/ops/beta-cutover.md).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[High impact] The reviewed changes appear safe to merge, with no new actionable issues established.

Summary

Adds SDP_ALLOW_SANDBOX_PROJECTS=false so a deployment can serve mainnet only.

  • A deployment can hide sandbox projects and serve mainnet only.
  • Unapproved organizations can only read basic details and request mainnet access.
  • Mainnet-access status tells callers which project environments a deployment serves.
  • Mainnet entitlement emails reach admins even when alert emails are off.

Reviews (4) · Last reviewed commit: "docs(ops): grant the canary org mainnet ..." · Reviewed by Greptile

Comment thread apps/sdp-api/src/cron/runner.ts Resolved
On a deployment that serves mainnet only, the dashboard decides from this read
where a member lands: their Production project, or the mainnet request page.
It required organizations.manage, so members and viewers got a refusal and
waited on the loading page. The read now takes organizations.read, checked
before the human-session check so an API key holding it is still refused;
requesting and resending stay admin-only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ocked orgs

Review on the mainnet-only organization lock:

- An organization that lost mainnet access kept its Earn reads and exits at
  project scope (ADR 0002), but the lock then refused them. The project check
  that admits the exit now marks the request exempt, and requireAction honors
  that one mark.
- The lock exempted every organizations.manage route, so a locked organization
  could still rename itself or change its IP allowlist and alert setting. Only
  the mainnet-access request and resend now mark themselves exempt.
- The Earn catalogue sync fetched and wrote the sandbox shelf on a deployment
  that serves mainnet only; it now skips the sandbox lanes there.
- The lock tests parse responses with schemas and cover all three.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…owner notice

Clerk CAPTCHA is not required: Vercel bot protection covers both dashboards.
The README names the hosted sandbox on platform-beta.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@linear

linear Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

PRO-2436

PRO-2477

@Windscar
Windscar merged commit edf7b8e into main Nov 13, 2026
63 checks passed
@Windscar
Windscar deleted the claude/prod-sandbox-switch branch November 13, 2026 06:13

This branch was successfully deployed

2 active deployments
Preview – sdp-docs — 4918cddd Deployed Nov 13, 2026 by vercel[bot]
Preview – sdp-web — 4918cddd Deployed Nov 13, 2026 by vercel[bot]
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.

2 participants