feat: operator console with sponsored trial invites - #104
Open
pythonlearner1025 wants to merge 2 commits into
Open
feat: operator console with sponsored trial invites#104pythonlearner1025 wants to merge 2 commits into
pythonlearner1025 wants to merge 2 commits into
Conversation
Two platform-operator routes. GET /admin/orgs lists every organization with its members, invites, live workspaces, and entitlement state — the one deliberate exception to org-scoped queries, gated on the same users.platform_operator flag as /operator-tokens. POST /admin/trial-orgs seeds a sponsored trial: a fresh org with platform_compute = 1, a trial clock, and an admin invite link, so a prospect tries the product on the deployment's cloud credential with no BYOK setup. The trial clock is org_entitlements.trial_expires_at (migration 0040). A janitor sweep flips platform_compute off when it runs out — one flag, no provider calls, same downgrade contract as a billing cancellation. A billing write clears the clock: the body states the org's whole entitlement, and a paid org is not a trial. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One page behind the operator flag: every organization with members, invites, live workspaces, seats and VM slots against their limits, and the plan state (free, paid, trial until, trial ended) derived from the entitlement integers. A "Start a trial" form seeds a sponsored org and shows its admin invite link once, the same way InvitesPanel does. The rail entry renders only for platform operators; direct navigation by anyone else renders the server's 403 in place — one refusal source. A hard refresh on /admin gets the SPA shell because run_worker_first derives /admin/* and never the bare path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Member
Author
|
TODO - update after merging the workspace udpate |
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What this adds
Control plane
GET /admin/orgs— platform-operator route that lists every organization with members, invites, live workspaces, and entitlement state. This is the one deliberate exception to org-scoped queries; the gate isusers.platform_operator, the same flag as/operator-tokens. Read-only operator tokens cannot reach it.POST /admin/trial-orgs— seeds a sponsored trial: a fresh org withplatform_compute = 1, a trial clock, and an admin invite link. A prospect follows the link and lands with machines they can create on the deployment's cloud credential — no BYOK setup.org_entitlements.trial_expires_at. A janitor sweep flipsplatform_computeoff when the clock runs out (same downgrade contract as a billing cancellation: running workspaces stay alive, the next create is refused). A billing write clears the clock, so a converted trial becomes an ordinary paid org.Webapp
/adminconsole page, rail entry visible only to platform operators. Shows all orgs, members, invites, seats and VM slots against limits, and plan state (free / paid / trial until / trial ended). "Start a trial" form shows the invite link once, like InvitesPanel.Defaults
Trial: 14 days (max 90), 5 seats, 2 VMs. Override per trial in the form.
Not in scope (follow-ups)
Test plan
npm run typecheck— clean.npm run lint:gate— passes at baseline; max-lines warn list unchanged.test/admin-console.test.ts: operator gate, cross-org listing, trial seeding + redeemable invite, trial expiry sweep, billing write superseding the trial clock, trial length cap).test/admin-console.test.tsx: org rendering, trial post + one-time link, plan-state derivation, 403 refusal, rail gating).🤖 Generated with Claude Code