Tenants & Users
Tenants
A tenant is a workspace. The owner creates it via POST /v1/tenants
after signing up. One owner may have several workspaces; they all share
the owner’s Stripe customer.
On creation the platform writes the tenant row (tier=starter,
status=active), provisions a per-tenant KMS CMK, reuses or creates the
owner’s Stripe customer, creates a metered subscription, writes a
free-credit row (10,000 tokens), and writes the owner membership row.
Selected tenant fields:
| Field | Notes |
|---|---|
tenant_id | System-generated UUID |
name | Display name; the proxy slug is derived from it via slugify() |
slug | Stored for quick reference; renaming updates gsi1_pk |
owner_sub | Cognito sub of the creator |
stripe_subscription_id | One subscription per workspace |
tier | starter / pro / enterprise |
status | active / suspended / deleted |
has_payment_method | true after Stripe Checkout setup completes |
default_region | eu-central-1 / eu-central-2 / us-east-1 |
kms_cmk_arn | Per-tenant KMS CMK |
Deletion
- Soft delete (
DELETE /v1/tenants/{id}, owner): setsstatus=deleted,deleted_at=now, cancels the Stripe subscription immediately. - Hard delete / purge: automatic 14 days after soft delete via the
daily cleanup cron, or on demand via
DELETE /v1/tenants/{id}/purge(platform admin only). Removes GSI1 rows, membership rows, key rows, the Stripe customer (if it was the owner’s last workspace), and Cognito users.
Users & RBAC
| Role | Capabilities |
|---|---|
owner | Full access: billing, users, grants, keys, settings. One per tenant. |
developer | Invoke the proxy, view own usage, create own keys within their grant. |
service_account | Non-human; holds an ar_live_... key; proxy invoke only. Not a Cognito user. |
Roles are injected into the Cognito JWT (custom:tenant_role) by the
pre-token-generation Lambda from the DynamoDB user row.
Invite flow
- The owner calls
POST /v1/users/invite { "email": "dev@example.com" }. - The control plane calls Cognito
AdminCreateUser, sending an invite email. - The developer registers; the
post-confirmationtrigger fires. - Because an invited
USER#<sub>row already exists, the trigger sets itactiverather than creating a new tenant. - The owner creates a grant for the developer via
PUT /v1/grants/{dev_sub}.
Removing a user (DELETE /v1/users/{user_id}) sets status=removed on
the DynamoDB row and automatically revokes their grant. The Cognito
user is not deleted — they may belong to another tenant.