Tethra internal · Mission Control — not for client distribution. Do not screenshot into a shared thread.
Mission ControlTethra operations · every production, shallow, near-live
TETHRA INTERNAL
Mission Control
Two-step sign-in
QR code to add this account to your authenticator app
Can’t scan it? Add this key by hand:

Tethra Systems

Productions · every production in this deployment

—
Productions active
—
Captures
—
Assets registered
—
Need a look
ProductionStatusAssetsCaptures Last activityHealthTimezonePurge after
Loading…

Tethra operations · reachable here to a Tethra operator — the script remains the off-app fallback

Create production
The provisioning event (D33) — the production lands provisioned: units, stickers and PINs can be set up; nobody can sign in, nothing is billed. /api/show answers 501 with this pointer, deliberately.
set -a; source .secrets-pilot; set +a node scripts/create-show.mjs --name "Cold Harbor" --timezone America/Los_Angeles --execute

Studio and Tethra accounts · every membership in this deployment · read-only

PersonRoleScopeAdded (HST)Status
Loading…
Removing access ends data access at once, and every open page within a minute (docs/STUDIO-ACCOUNTS.md → Offboarding). The account itself isn’t deleted; it can still sign in, landing on Studio’s “not provisioned” screen. No in-app way to create an account or change a role — use the script below. node scripts/create-studio-user.mjs --email pat@studio.com --role studio_admin --execute
Every access change here lands in the audit trail — see Audit in the rail. Sign-in failures that happen before a token exists are counted there too, as daily totals rather than rows: the caller is still anon when they happen and cannot write to the trail at all.

Known future capability · not yet built

Restricting an account to SEVERAL productions. Every account here is deployment-wide by default: a show_members row with show_id = NULL and app_role = studio_admin sees every production, and the work then happens inside one production at a time. Restricting to one production is expressible today — set show_id. Restricting to several is a larger migration: the token claim would need to become a set, and every RLS policy reading private.jwt_show_id() changes with it, along with the custom access token hook and the production-scope branch in every function that reads tok.show_id. Recorded, not started.

Tethra operations · off-app — needs the service key, which no request path may hold

Studio and Tethra accounts
Owen still creates accounts and changes roles in the Supabase dashboard — no endpoint exists for either. Removing access no longer needs the dashboard: “Remove access…” on a live row above goes through /api/ops’s revoke_membership op, the same door Stop service uses.
node scripts/create-studio-user.mjs --email jo@studio.com --role coordinator --show cold-harbor --execute

Revenue · projected across every production, studio-wide

—
Weekly run-rate
—
Projected this month
—
Productions billing
—
Needs a look
Week starting (UTC) — the billing grid is epoch-anchored, not shown in any production's or Tethra's own zone.

Billing ledger · every started billing week, studio-wide

ProductionWeek (start–end)RateStatusInvoiceCreated (HST)
Loading…

Revenue projection · projected across every production

ProductionWeekly rateStartedEst. end Weeks to dateWeeks to comeRevenue to date Projected totalStatus
Loading…

Scenario planning · drafts, not financial records — never counted in the tiles or chart above

LabelWeekly rateEstimated weeksPlanned start Projected totalCreated byCreated (HST)
Loading…
Scenario subtotal: — — a draft total, never merged into the figures above.

Tethra operations · Run weekly billing is reachable here to a Tethra operator — Stop Service moved to each production's own Service card (I05); Change weekly rate remains off-app

Run weekly billing
Inserts every started, unrecorded billing week for every commercial service, at the rate that opened it — idempotent, running it again before the next week starts inserts nothing new. Run it weekly so each newly-started week gets recorded. Wires straight into the Billing ledger above. Previews first; recording needs the typed word BILL.
set -a; source .secrets-pilot; set +a node scripts/run-weekly-billing.mjs --execute
Create Final Invoice Draft
Stopping a service (a production's own Service card) already bills its final started week like any other — there is no separate "final" billing step. What is still unbuilt is the invoice itself: there is no invoices table yet, so a stopped service's last billable week sits in the Billing ledger, due, same as every week before it.
Change weekly rate
A rate change is stop-current-period + open-new-period at the new rate, never an edit — commercial_services is immutable once written.

Feedback · every note, feedback, feature request and problem, studio-wide

TicketWhen (HST)WhoRoleProductionKindTitleMessageStatus
Loading…

Audit · the trail, and the sign-in failures that happen before anyone has a token

Trail
EventCountFirst (HST)Last (HST)
Loading…
Pick an event to read its rows. Times are Honolulu, the support desk’s zone — a production’s own ledger is shown in the production’s zone, and this is not that.
Rows
When (HST)EventProductionWhoDetail
Pick an event above.
Detail stays closed until you open it. Some rows carry the caller’s IP address, and a column that shows one at rest is a column that ends up in a screenshot.
Sign-in failures, before a token exists
Day (UTC)EventReasonCountFirst (HST)Last (HST)
Loading…
Counts, not records — no IP address, no code that was typed, nothing that identifies a person. What this answers is the shape: one person mistyping a PIN is a handful a day, and every access code in the field failing inside one hour is what a botched pepper rotation looks like. An empty table is the normal state. Days are UTC, not Honolulu, because that is the day the counter keys on. A throttle row counts trips, not refused requests: only the first refusal in each hour is recorded, so a blocked caller never costs a write. The test suite writes here too. The live sign-in suites run the real refusal paths against this database, so a full run.sh — which is also gate 1 of every deploy — adds roughly ten to no_match in a burst a minute wide. Before reading a spike as a rotation gone wrong, check whether a deploy or a test run happened that day. The same has always been true of the trail above, where the suites are a large share of capture_submit and auth_success.
THIS PRODUCTION

 

Identity · this production, as /api/shows reports it

—
—
—
—
—
Captures
—
Assets
—
Last activity
Service start and the weekly rate aren’t readable back — set off-app, by Activate Service below.

Service · reachable here to a Tethra operator — the script remains the off-app fallback

Activate Service
The billing event (D33). One transaction: the production goes active, its commercial service opens with a real service_start_at and the weekly rate, an audit row is written. Idempotent. Refused from the app plane by the lifecycle guard, by name.
set -a; source .secrets-pilot; set +a node scripts/activate-show.mjs --show cold-harbor --weekly-rate 375 --execute
Stop service
I05: the other half of Activate Service. Records a real service_stop_at and flips the commercial service to stopped — a week only bills if it started before the stop, so stopping exactly one week after activation bills that one week, never two. Does NOT wrap the production; wrap and stopping service are two different decisions. Previews first (the effective stop, the weeks that would still bill, any conflict); stopping needs a reason and the typed word STOP. Refuses rather than overriding if billing is already recorded for a week at or after the stop.
set -a; source .secrets-pilot; set +a node scripts/stop-service.mjs --show cold-harbor --reason "..." --execute

Retention · nothing is deleted on a timer

Purge after: — — never set. We keep the data; a purge is a deliberate, off-app action on the client’s request, not a scheduled date (commercial call D, 2026-09-07).
Purge
On request only — nothing is deleted on a timer (retention is open-ended since 2026-09-01). Deletes captures, the asset registry, and photos, retaining a receipt. Purge is reachable here to a Tethra operator once this production is wrapped.
node scripts/purge-show.mjs --show cold-harbor node scripts/purge-show.mjs --show cold-harbor --execute --confirm-hash=<hash> --confirm=PURGE --confirm-id=cold-harbor

Assets · this production's registry · the equipment CATALOG is separate and stays Tethra-side

Registering, editing and retiring units on this show are closed — this show is neither provisioned nor active. The registry below stays readable.
TagNameTypeRated kWFuelStatus
—
Equipment catalog: methodology IP. Studio consumes it, never edits it. No table in this deployment yet.

Access · crew and coordinator

Neither role opens a back office.
RoleNameIssued (HST)ExpiresStatus
—

Activity spot check · ten most recent, tombstones included · the ledger itself is Studio's

WhenAssetTypeByExcludedEntry hash
—