Tenants, environments, keys, hostnames and suspension — the forms mirror the gateway's /admin/v1/* wire shapes exactly, down to the slug rule and the conflict codes. Mocked in this milestone: nothing here leaves the tab.
Tenant slug[a-z0-9-]{1,32} · immutable · becomes the tid claimDisplay name0/120
Environments
prod · fixed
Add non-prod environment
prod is created implicitly with the tenant. All non-prod environments together draw on a fixed 25% of the org’s allowances — the platform applies that rule itself, so there is nothing here to configure.
Mint publishable key
POST /admin/v1/…/publishable-keys
EnvironmentLabelfree text, so two keys can be told apartStage
Publishable keys are not secrets — they ship in app bundles — but the full value is returned exactly once, so rotation is mint-new, deploy, revoke-old. Several keys may be live for one environment at a time; there is no window where the app cannot reach the platform.
Attach hostname
Staff onlyPOST /admin/v1/…/hostnames
EnvironmentHostnameglobally unique across every tenant
A hostname resolves scope for hosted web apps, which is why a browser app can work without embedding a publishable key. Hostnames are globally unique across the platform; mapping stays staff-only until Karpo has a hosting story of its own.
A suspended tenant answers 403 E_TENANT_SUSPENDED platform-wide, through the flags: projection. Suspension, reactivation, quota lift-once and abuse actions never become self-serve — anything that touches another org's existence stays here. This is the same action the abuse queue offers, one implementation.
Actions this session
No actions yet. Every form on this page appends the request it would have sent.