TETHRA INTERNAL
Mission Control
Tethra Systems
Productions · every production in this deployment
—
Productions active
—
Captures
—
Assets registered
—
Need a look
| Production | Status | Assets | Captures | Last activity | Health | Timezone | Purge 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
set -a; source .secrets-pilot; set +a
node scripts/create-show.mjs --name "Cold Harbor" --timezone America/Los_Angeles --execute
provisioned: units, stickers and PINs can be set up; nobody can sign in, nothing is billed. /api/show answers 501 with this pointer, deliberately.Studio and Tethra accounts · every membership in this deployment · read-only
| Person | Role | Scope | Added (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
node scripts/create-studio-user.mjs --email jo@studio.com --role coordinator --show cold-harbor --execute
/api/ops’s
revoke_membership op, the same door Stop service uses.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
| Production | Week (start–end) | Rate | Status | Invoice | Created (HST) | |
|---|---|---|---|---|---|---|
| Loading… | ||||||
Revenue projection · projected across every production
| Production | Weekly rate | Started | Est. end | Weeks to date | Weeks to come | Revenue to date | Projected total | Status |
|---|---|---|---|---|---|---|---|---|
| Loading… | ||||||||
Scenario planning · drafts, not financial records — never counted in the tiles or chart above
| Label | Weekly rate | Estimated weeks | Planned start | Projected total | Created by | Created (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
| Ticket | When (HST) | Who | Role | Production | Kind | Title | Message | Status |
|---|---|---|---|---|---|---|---|---|
| Loading… | ||||||||
Audit · the trail, and the sign-in failures that happen before anyone has a token
| Event | Count | First (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.
| When (HST) | Event | Production | Who | Detail |
|---|---|---|---|---|
| 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.
| Day (UTC) | Event | Reason | Count | First (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.
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
set -a; source .secrets-pilot; set +a
node scripts/activate-show.mjs --show cold-harbor --weekly-rate 375 --execute
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.Stop service
I05: the other half of Activate Service. Records a real
set -a; source .secrets-pilot; set +a
node scripts/stop-service.mjs --show cold-harbor --reason "..." --execute
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.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.| Tag | Name | Type | Rated kW | Fuel | Status | |
|---|---|---|---|---|---|---|
| — | ||||||
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.
| Role | Name | Issued (HST) | Expires | Status | |
|---|---|---|---|---|---|
| — | |||||
Activity spot check · ten most recent, tombstones included · the ledger itself is Studio's
| When | Asset | Type | By | Excluded | Entry hash |
|---|---|---|---|---|---|
| — | |||||
Tethra internal