Changelog
What shipped.
- orgs
Orgs on anythink tenants, tenant and org delete, and a Sandboxes page
An org can move under another as a tenant subtree — tenants, clients, grants and settings in one step, with a dry run first, a flat move for orgs with their own tenant tree, and a way back out (PR latchkey#292). An owner can delete an archived tenant and staff can delete an org; a delete is final but recorded, and every delete takes
?dry_run=1(PRs latchkey#295, latchkey#296). In the console, Create organization starts from an anythink tenant you administer (PR ui#53), a Sandboxes page lists an org’s sandboxes and the admin view nests them under their org (PR ui#55), deleted orgs leave the org list and search (PR ui#52), and staff and site admins follow the configured house org (PR ui#51). - auth
One-click MCP sign-in, generated refs and confidential-client sign-in
MCP clients such as Claude Code, Cursor and Codex sign a person into a house MCP server in one click: every issuer host serves RFC 8414 metadata and open dynamic registration, Client ID Metadata Documents are accepted,
resource=binds the token’s audience, and people approve each app on a consent page and can revoke it later (PRs latchkey#170, latchkey#171, latchkey#172, latchkey#174, latchkey#175). An org lists the APIs it owns withPUT /org/{slug}/resources(PR latchkey#208). New orgs and tenants are named by a generated ref that never changes, so a rename no longer breaks a product’s authorization; existing orgs move onto refs with one call and can move back (PRs latchkey#155, latchkey#158, latchkey#159, latchkey#160). A server-side app holding a secret can run the browser authorization-code flow, authenticating at the token endpoint for the code and every refresh. - org api
Client scoping, the products claim and org rename
A confidential client can be scoped to a set of tenants and role prefixes (
POST /org/{slug}/clients/scope, orscopeon the client PUT), so a product’s backend manages only its own roles on its own tenants; refusals say why, andGET /org/{slug}/clients?unscoped=truelists the clients still unscoped (PR latchkey#117). A tenant records the products it has turned on (PUT /org/{slug}/tenants/{tenant}/products), every token for the tenant carries them in aproductsclaim, and atenant.products_setwebhook fires on change — so a product refuses a tenant that has not enabled it without calling anything (PR latchkey#116). An org’s owner can rename it withPOST /org/{slug}/rename; the old slug keeps resolving to the same org and no one else can claim it (PR latchkey#125). - machines
Machine credentials, and staying signed in
A person can register a machine for an org — a CLI signed in with the device flow,
terraform login, or a client-secret machine for scripts — and its tokens name the person who operates it, so a product authorizes a machine as its operator. The console’s org page lists an org’s machine credentials and revokes them (PR ui#50). Consoles built on the shared app shell refresh the access token ahead of expiry, once across tabs, so people are no longer signed out when the hour-long token lapses (PRs ui#40, ui#54). - auth
GitHub sign-in, passkey scope, fresh-login clients and tenant invitations
Settings → Sign-in offers GitHub as a sign-in method, with Settings → GitHub for the GitHub App and its proxy (PRs ui#38, ui#42, ui#43). An auth domain can set its passkey scope (
rp_id) (PR ui#41). A client can require a fresh login every time instead of riding an existing session (PR ui#44), and the store-review sign-in takes a test-identity domain (PR ui#47). Tenants have an Invitations tab and their owntenant_inviteemail template (PR ui#37). Publishable keys may be unrestricted, and the key list shows each key in full (PR ui#39). - console
Email deliverability, delivery webhooks, people tables and bulk invites
Settings → Email → Activity runs a deliverability check on the org’s sender, and delivery events can be sent to a webhook you configure, with an event feed in the console (PRs ui#29, ui#30). The People page has filterable people and event tables, each person has a detail page, and invites go out in bulk (PRs ui#31, ui#33, ui#34). Missing pages answer with a real 404 and errors with an error page instead of a blank screen, and empty lists say so plainly (PRs ui#32, ui#36).
- console
Sandboxes, role levels, secret rotation and browser keys
Orgs and tenants have a sandbox beside production, and a production/sandbox switch on the org and tenant pages flips between them (PRs ui#22, ui#23, ui#26). Settings → Roles lets a role extend a level (PR ui#25). A client can flip between public and confidential and rotate its secret from the console, clients can be deleted, and browser (publishable) API keys are issued per org (PRs ui#24, ui#27, ui#28). Clients that ship through an app store get a review-login setting with its own sign-in section, and the sign-in code email has its own template tab (PRs ui#16, ui#17, ui#18).
- auth
Session links, passkeys, and magic links hardened
Product-minted sign-in links redeem at
/oauth/goand are single-use, expiring and revocable (PR #45). Passkeys sign people in and enrol after a magic-link sign-in, with a hosted management page (PR #34). Magic-link tickets are hashed at rest, so nothing stored is a live link, and the confirm page consumes on POST so mail scanners cannot burn one (PR #44). Refused sign-ins are recorded and shown on the console’s Attempts page (PR #40). - org api
Org API indexes, paging and delivery visibility
Clients, members, sessions and users are single filtered queries with
?limit=&offset=instead of registry scans.GET /org/{slug}/mail/activityfolds the login-ticket log into per-email created / sent / consumed / expired rows, so “sent 2m ago — not used” is answerable without ticket ids. - mail
Per-org email templates
Login and invite emails are per organisation: a strict variable allowlist, the link injected by the service, and a console editor with a variable-aware preview. Sender credentials live in org settings, sealed under KMS, with the platform sender as the fallback.