Skip to main content

Module dashboard

Module dashboard 

Source
Expand description

The per-server homepage and operations dashboard: this server, reporting on itself. docs/web-surfaces.md calls this surface 3 of the project’s four websites, and draws the boundary this module keeps: it is served by didbot-serve, about the deployment serving it, one per deployment rather than one for the whole project, and it owns no policy — policy is written from a separate, statically-hosted origin (surface 2) and only ever read here, never edited.

It answers before anyone signs in: about says what this deployment is (its zone) and what it holds (bot.did.stats’s own numbers, reused rather than reread). Everything past that is the authenticated operations view.

plan/ops-dashboard.md sets one rule above everything else it asks for: never display invented data as if it were real. Every panel this module serves answers in exactly one of three states, carried in crate::surface::PanelState rather than left for a client to infer from shape:

  • Live — a real capability, read fresh from this process’s own state.
  • Not implemented — the epic it needs does not exist yet (write-policy, scope-policy, app-allowlist, oauth). Names what is missing and carries no numbers at all, because a plausible-looking zero is a lie this dashboard is built specifically not to tell.
  • Unreachable — a real capability whose read failed, which is a different fact from a real capability that read as zero.

panel_state_never_carries_numbers_without_a_backing_capability is the mechanical guard on that rule: it asserts, at the JSON level, that PanelState::NotImplemented and PanelState::Unreachable can never serialize a data field, so a future panel cannot regress into showing a number for a capability that is not there.

§What is public here, and what is not

Public: the static shell and its assets, about and capabilities, and the client metadata document — about is bot.did.stats’s own public numbers, capabilities names which epics are unbuilt, which plan/ already says out loud, and the metadata document’s own URL is the client_id, so the operator’s authorization server has to be able to fetch it before it will show them a consent screen.

Behind the operator sign-in: the e-stop’s status and its two controls, the bot.did.operator records the poll last read out of the operator’s own repository, and the relay announce. What authenticates them is crate::operator — atproto OAuth against the operator’s own server, requesting atproto and nothing else, with the verified sub compared against this deployment’s --operator. No operator credential reaches this server, which is what plan/handshake.md is protecting: the sign-in proves control of a DID, and this server then issues a session of its own.

An anonymous, internet-reachable halt would be a denial of service rather than an emergency stop, which is why throwing costs a sign-in too and not only releasing.

The session list still has no data behind it, and renders PanelState::NotImplemented naming the epic it waits on. That is the same honesty rule the rest of this module follows: a panel whose data this server does not have is a panel that says so, not one showing a plausible zero.

The per-app panels — live logins, refusals and writes — are crate::dashboard_apps’s, and the account list and detail are crate::dashboard_accounts’s, both merged into this module’s router.

Structs§

AboutView 🔒
What the unauthenticated homepage panel reports.
Acted 🔒
What one account route did, as it answers.
AnnounceBody
What /dashboard/api/relay/announce accepts.
CallbackQuery
What the authorization server sends back.
DeleteBody
What /dashboard/api/accounts/{did}/delete accepts.
LoginQuery
What /dashboard/login accepts.
OperatorRecordView 🔒
One bot.did.operator record in the operator’s own repository, as the panel shows it.
ThrowBody
What /dashboard/api/estop/throw accepts.

Constants§

DASHBOARD_CSS 🔒
DASHBOARD_JS 🔒
DASHBOARD_WASM 🔒
The dashboard’s wave field, as compiled in. Empty when the opt-in wasm build has not been run; see build.rs.
INDEX_HTML 🔒

Functions§

about 🔒
GET /dashboard/api/about
account_at 🔒
The account the path segment names, or the refusal to answer with.
account_credentials 🔒
POST /dashboard/api/accounts/{did}/credentials
account_delete 🔒
POST /dashboard/api/accounts/{did}/delete
account_erase 🔒
POST /dashboard/api/accounts/{did}/erase
account_lift_quarantine 🔒
POST /dashboard/api/accounts/{did}/lift-quarantine
account_lock 🔒
POST /dashboard/api/accounts/{did}/lock
account_revoke_tokens 🔒
POST /dashboard/api/accounts/{did}/revoke-tokens
account_unlock 🔒
POST /dashboard/api/accounts/{did}/unlock
acted 🔒
Acted for did, reading the entry the action just wrote.
as_the_operator 🔒
Moves the latch inside a span naming this deployment’s operator, so the line the latch logs for the throw or the release says who asked. The span carries the DID and nothing from the session.
callback 🔒
GET /dashboard/callback
capabilities 🔒
GET /dashboard/api/capabilities
client_metadata 🔒
GET /dashboard/oauth/client-metadata.json
css 🔒
GET /dashboard/dashboard.css
did_it 🔒
The envelope every account route answers with: what was asked for, and each account it reached.
estop_release 🔒
POST /dashboard/api/estop/release
estop_status 🔒
GET /dashboard/api/estop
estop_throw 🔒
POST /dashboard/api/estop/throw
index 🔒
GET /dashboard
js 🔒
GET /dashboard/dashboard.js
login 🔒
GET /dashboard/login
logout 🔒
POST /dashboard/logout
no_operator 🔒
The page login and callback answer on a deployment started with no --operator.
operator_records 🔒
GET /dashboard/api/operator-records
refused 🔒
A registry refusal, as the operator reads it.
refused_partway 🔒
A registry refusal that came after the action had already reached some accounts, with those accounts beside it: a caller that saw only the refusal would not know what had already happened.
relay_announce 🔒
POST /dashboard/api/relay/announce
routes
Builds the dashboard’s routes, to be merged into the main router.
subtree_of 🔒
did and everything beneath it, deepest first — the order a hard delete has to take them in.
wasm_asset 🔒
GET /dashboard/wasm/{file}