Cross-org, cross-user view of every relay on the platform.
1–8 of 18,442
Title
Code
Status
Org
User
Age
Size
Actions
Q3 onboarding handoff
HAVVPX
active
Northwind
usr_8f3a
4m
12.4K
Migration runbook v2
PMHUK3
claimed
Ravel
usr_2c19
1h
48.1K
Design review — v3.5-a
4TNE7K
active
Relay Context
usr_0001
2h
31.7K
Incident postmortem
A4K9R2
claimed
Lumen
usr_71bd
5h
9.8K
Sprint plan draft
QNHC2C
expired
Northwind
usr_8f3a
3d
6.2K
Client brief — Ravel
7HZQAX
claimed
Ravel
usr_2c19
3d
22.0K
Weekly sync context
FFFC90
active
Lumen
usr_71bd
4d
14.9K
Deprecated payload test
ZX01QP
deleted
Relay Context
usr_0001
6d
1.1K
Users
Every account across every org. Search, inspect, suspend.
1–7 of 1,284
Name
Email
Org
Role
Setup
Created
Actions
Erik Christensen
erik@relayctx.com
Relay Context
superadmin
100%
Feb 2026
Nadia Fournier
nadia@northwind.io
Northwind
member
60%
Jul 2026
Tunde Okafor
t.okafor@ravel.dev
Ravel
owner
100%
Jun 2026
Sam Ihejirika
sam@lumen.studio
Lumen
member
30%
Jul 2026
Priya Raman
priya@ravel.dev
Ravel
member
100%
May 2026
Marco Belli
marco@northwind.io
Northwind
owner
100%
Apr 2026
Lena Vos
lena@lumen.studio
Lumen
suspended
100%
Mar 2026
Account migrations
Merge one account into another, or split an address into a fresh one. Dual consent, journaled, tier-1 only — nothing executes until every required consent is in.
lena@lumen.studio − freelance@vos.dev → new account
address detaches · data stays with owner · fresh account invited
1 / 1
consented
1d
merge
sam@oldstudio.io → sam@lumen.studio
executed by usr_0001 · workspace admins notified (Lumen)
2 / 2
completed
6d
merge
nadia@personal.me → nadia@northwind.io
declined by source · everyone notified · nothing changed
0 / 2
cancelled
8d
state machinedraft → awaiting consent → consented → executing → completed · exits: cancelled / expired / failedtier-1· every action audit-logged · consent links are signed pointers, action requires sign-in as the party
Claim approvals
Cross-user claim requests waiting on an operator decision.
3 pending · 1 urgent
NF
Nadia Fournier requests HAVVPX
nadia@northwind.io → owned by usr_0001 (Relay Context)
4m ago
TO
Tunde Okafor requests PMHUK3
t.okafor@ravel.dev → owned by usr_71bd (Lumen)
1h ago
SI
Sam Ihejirika requests FFFC90
sam@lumen.studio → owned by usr_71bd (Lumen)
6h ago
Queue clear
No claim requests waiting. New cross-user requests land here for approval.
Access codes
Typed fast-tracks on the early-access form — the invite and referral classes, seen from the code side. Every code also mints its own tracked link at /x/{CODE}, which is why it shares the campaign handle space.
Its own column now — the label stays yours to write.
Server ceiling: 90.
Type a code — checked case-folded against the same space campaign slugs mint into.
5 codes · 2 active
Code
Label
Campaign
Share link
Uses
Status
Actions
Two columns, two jobs.label is the human name; campaign_slug is the attribution key. Today they are the same field — so a code called "Elevate Festival" drops out of its campaign's panel, and a campaign-scoped code cannot be given a name. Share link is the part that surprises people: minting a code also mints /x/{CODE}, so a code and a campaign slug spelled alike are one key in one space, and /x/ resolves campaigns first.
Roles & access
Who can do what, platform-wide. Capabilities are code-owned; roles group them. Org-scoped RBAC is delegated to org admins in the app.
Platform capabilities × platform roles. System roles are locked.
3 platform roles · system, locked
Capability
support
platform_admin
superadmin
Users · platform.users.manage
✓
✓
✓
Transfers (global) · platform.transfers.view
✓
✓
✓
Claim approvals · platform.approvals.manage
✓
✓
✓
Orgs admin · platform.orgs.manage
—
✓
✓
Finance · platform.finance
—
✓
✓
Flags · platform.flags
—
✓
✓
Maintenance · platform.maintenance
—
✓
✓
Roles & groups · platform.groups.manage
—
✓
✓
Force connect · platform.force_connect
—
—
✓
Tier-1 destructive · platform.tier1
—
—
✓+ELEV
Tier-1 capabilities require a short-lived elevation token (step-up re-auth) on top of the role — the same second factor the console uses today for destructive actions.
Support
support · reads users, transfers, approvals
AKRMJD3 members
Finance ops
custom · platform.finance only
ECLV2 members
On-call
custom · approvals + maintenance
ECTOMB3 members
Operator
Platform role
Groups
Effective caps
Actions
Erik Christensen
superadmin
Finance opsOn-call
all (10)
Ada Kensington
platform_admin
Support
8
Ravi Menon
support
Support
3
Jordan Diaz
support
SupportOn-call
5
Org-scoped RBAC is delegated. Org admins manage their own groups & roles self-service in the app (Team → Roles & Groups), bounded to their org and their own permission ceiling — they can never grant platform capabilities. One capability model, two planes. Spec: briefs/SPEC.rbac.md.
Investor track
Provision access, map packs to people, and evidence compliance — who holds what, under which signed version, and when they last looked. Pack IDs are opaque and never leave this screen or the Access policy.
Tier-1 surface. Guarded by check_tier1 — superadmin and platform_admin only, never general check_auth. Its web counterpart is founder-only; the console must not be looser. Signature status and version render here; the executed PDF is fetched only on explicit request, never inline in a list.
6 in the register · 1 flagged
Investor
Lens
Pack
NDA
ToS
Tier
Last access
Actions
Erik Christensen
productinvestor
QX7M4D
v1.2
Feb 2026
NDA
2h ago
A. Sorensen
investor
K4RZ7Q
v1.2
Jun 2026
NDA
Aug 5
M. Delacroix
investor
P9WX2M
v1.1 — stale
May 2026
access, no current signature
Aug 6
R. Nakamura
investor
H3JD8V
v1.2
Jul 2026
OPEN
Jul 31
L. Ferreira
investor
B6QT4N
unsigned
Jul 2026
OPEN
never
T. Abiodun
revoked
C2YL5S
v1.1
Mar 2026
—
Jul 12
Every name and pack ID on this screen is synthetic. This repo publishes — main is production, no build step — so a real pack ID beside a real name would put the exact mapping this screen exists to protect onto a static site. Prototypes get invented data; the register is the only place the real mapping lives.
Pack IDs stay opaque. Six characters, A–Z0–9 — never a name, initials, or firm, in a URL, page title, filename, or log line. The pack ↔ person mapping exists in the register and the Access policy, nowhere else. T. Abiodun shows the rule that exemption never rewrites history: access is revoked, the signed v1.1 acceptance row stays forever.
Who has access, under which signed version, and when they last looked
State
Who
Why it matters
Action
Flagged
M. Delacroix · P9WX2M
Holds NDA-tier access, but the signature on file is v1.1 and the current version is v1.2. A gate-mode version bump re-gates everyone who signed the prior version — this is a live state, not a hypothetical.
Watch
L. Ferreira · B6QT4N
Provisioned at OPEN tier, no NDA on file, never accessed. Correct today — becomes a flag the moment NDA-tier material is attached to the pack.
Clear
4 others
Current signature on the current version, access consistent with tier.
Residency. Executed NDA PDFs are user-owned bytes — fetched through storage.get_storage(region) with the region resolved from the owner's account, failing closed when a region isn't ready. Never a fallback to another region's bucket.
Every grant and revoke, actor and timestamp — following plan_features_audit
When
Actor
Action
Subject
Detail
Aug 7 · 09:14
erik@relayctx.com
grant
K4RZ7Q
Lens set to investor · tier NDA
Aug 6 · 16:02
erik@relayctx.com
tier
H3JD8V
NDA → OPEN (unlock held pending counsel)
Jul 12 · 11:47
erik@relayctx.com
revoke
C2YL5S
Lens cleared · Access policy emptied confirmed
Jul 2 · 08:30
system
re-gate
all NDA holders
NDA v1.2 published gate-mode — prior signatures no longer current
What the lens changes — and the trap it avoids
Document
Product lens
Investor lens
Both
EAPA · Early Access Program Agreement
required
not applicable
required
NDA · Non-Disclosure Agreement
required
required
required
Platform ToS · activation checkbox, not a gate document
already
already
already
No new document type is needed. The platform-side obligation is the Terms of Service, not an MSA — and every user already accepts it at activation (tos_accepted → registration_metadata, text at relayctx.com/terms). NDA already applies to everyone. So the entire change is one line of meaning: EAPA becomes product-lens only.
Two things follow. The ToS is a different mechanism — an unversioned checkbox, so a terms change re-consents nobody and the text signed isn't recoverable from the record, unlike legal_acceptances which is version-keyed and hashed. Real gap, whole user base, separate issue — not this one. And BPA is labelled "Platform Agreement" in DOC_LABELS while the signing flow says EAPA "Replaces Beta Participant Agreement (BPA)" — a retired type wearing the name of the live platform terms. Relabel and mark retired before that reading sticks.
Why this is not a switch in the gate component. The signing gate renders what GET /api/legal/pending returns — it decides nothing. Skipping EAPA client-side leaves gate_needed() returning true at seven server call sites (login, user API, MCP writes) while the screen meant to unblock the user shows nothing to sign. That is the gate loop the code already carries a warning comment about. Applicability belongs on the document version, resolved once, server-side, and read by every caller.
Fail posture splits by tier.gate_needed fails open today so a database blip can't lock everyone out of login — right for EAPA, wrong for an NDA guarding the room. NDA-tier applicability fails closed. · Onboarding takes the same lens. The curriculum is single-track today; an investor enrolled into it gets taught to claim Codes, plus EAP graduation sweeps and registration reminders. · Revocation is still two systems — clearing the lens does not empty the Cloudflare Access policy on that pack, so revoke surfaces it as an explicit, evidenced step.
Campaigns
One entity, four classes — every tracked acquisition surface, whichever door someone arrives through. Slugs and codes share one handle space, so a new one is refused at mint (DEC-030).
Personalized relay + OTP + trial.
Voice preset, not an audience. General leans on what the person tells the form.
Comma-separated. This is the sort axis.
Nothing granted. Nothing to expire.
Only tiers in grantable_trial_tiers().
Type a handle — it is checked against every campaign, access code, short link and relay Code before it can be minted.
Active campaigns
3
of 8 across 4 classes
Arrivals
0
clicks + code redemptions
Signups
0
— arrival → signup
First transfers
0
— of signups activate
8 campaigns · 3 live
Handle
Class
Access
Track
Tags
Status
Funnel
Conv
Signups
Actions
DEC-030 — what this screen now shows: the four things the word "campaign" named are one entity with a class column, not three screens sharing a name. A campaign is the thing tracked; a route is how someone arrives — so /i/ keeps its own door and beta_codes keeps its own table. Tags carry the grouping, which is what lets Track (formerly Angle) go optional behind a General default. Access is the third axis (§8): class is how someone arrives, Track is what voice the relay uses, Access is what they get — and a trial length exists only on a plan-aligned trial, because EAP's tier has nowhere to put one. Kill switch: pausing or expiring goes dark everywhere — /x/{handle}, personalize and verify all 410 (#1896).
One handle space— handles
Why this panel exists./x/{code} resolves campaign → short link → relay Code, in that order, so a campaign slug silently shadows an access code spelled the same way. On 2026-08-01 an audit found four access_code_share rows already colliding with live transfers, and the Elevate work order still mitigates it with a spelling convention — "not ELEVATE26 … the hyphen keeps them apart". Handles are compared case-folded: the card printed /x/elevate-2026 while the code minted /x/ELEVATE-2026, and only one of those resolved.
Live — accepting signupsexpires Sep 30, 2026 · Turnstile + rate limits on personalize & verify
Live
The handle is not editable. It is a minted pointer in the shared space — changing it would orphan every printed card, QR and link already carrying it. Retire and re-mint instead.
Scoped by the campaign_slug column, not by overloading label — so a code can be named and scoped at once. Today one field does both jobs and the console filters it with a Python string compare, so naming a code costs you the campaign link.
Access · what the signup gets
Handle · route
One campaign, several doors. Every row here is the same tracked thing — which is why they share attribution columns and why the class, not the prefix, says what it is.
Event loglast 100
Time
Event
Session
Detail
Screen
Specced in the console screen audit.
On the map, not yet skinned
This screen is part of the 36-screen console and is fully specced in AUDIT.console-v35.md. This prototype builds the shell plus the canonical screens (Dashboard, Transfers, Users, Claim Approvals, Access Codes, Roles & access, Campaigns) as the v3.5-a pattern-setters.
The re-skin of the remaining screens is tracked as Linear issues under the console epic (RCTX-705, batches RCTX-706–712).