At this level
app.tempomusic.staff · 20- app.tempomusic.staff.banAccount procedure Permanently ban an account: all of its content disappears from the public read surface and no surface can lift the state. Escalating an active suspension replaces it. Requires the `superAdmin` role. Writes an `accountBanned` audit row. Federation caveat: the ban blocks this DID — re-registration under a fresh DID is structurally possible in AT Protocol.
- app.tempomusic.staff.createInviteCode procedure Generate a batch of single-use PDS invite codes (TEM-502). Requires the caller to have the `superAdmin` role. Each call requests `quantity` codes from the PDS (`com.atproto.server.createInviteCode` with `useCount=1`), writes one `inviteCodeCreated` audit row per successfully-created code (payload = SHA-256 hash of the suffix + `use_count`, never the plain code), and returns the suffix-only codes. When the PDS returns a transient failure mid-batch the handler stops iterating and returns the succe
- app.tempomusic.staff.defs defs AppView projection of a moderation_audit row. The audit log is append-only and never purged; entries survive hard-deletion of the actor account.
- app.tempomusic.staff.disableInviteCodes procedure Disable one or more PDS invite codes (TEM-502). Requires the caller to have the `superAdmin` role. Codes are provided as suffix-only strings; the handler re-prepends the env prefix stored under `APPVIEW_PDS_INVITE_CODE_PREFIX` before calling `com.atproto.admin.disableInviteCodes`. On success, writes one `inviteCodeDisabled` audit row per code (payload = SHA-256 hash of the suffix, never the plain code).
- app.tempomusic.staff.dismissReport procedure Close a report without acting on the subject. Valid from `open` (fast-path obvious junk) and from `underReview`. Writes a single `reportDismissed` audit row. Fast-path dismissal directly from `open` does NOT emit a `reportTriaged` audit row first — only the dismissal entry is written.
- app.tempomusic.staff.getAccountModeration query Current account-level moderation state of a DID (suspension or ban), or an empty object when the account is unrestricted. A lapsed suspension is reported with its (past) `until` — interpretation is the caller's. Requires the `moderator` role.
- app.tempomusic.staff.getReport query Fetch a single report by id, including its subject snapshot as captured at intake. Requires the caller to be an active moderator.
- app.tempomusic.staff.getSubjectContent query Moderator-grade fetch of a report subject's stored record and lifecycle state, INCLUDING rows the public read surface hides: taken-down content, soft-deleted rows inside the 30-day evidence window, and tombstoned rows (record is then null — 'purged' — and the console shows a banner instead of content). ADR-009 future-work item 'expose retained content through the moderation surface'. Requires the caller to be an active moderator. When media attachments ship, CSAM-quarantined blobs are NEVER rend
- app.tempomusic.staff.getSubjectModerationHistory query Audit timeline for a single subject (post URI, reply URI, or account DID). Returns every moderation_audit row referencing the subject, in reverse-chronological order. Used by the moderator UI to answer 'what has ever happened to this content/account'. Requires the caller to be an active moderator.
- app.tempomusic.staff.grantStaffRole procedure Add a DID to the moderators allowlist with the given role. Requires the caller to have the `superAdmin` role. Writes a `moderatorGranted` audit row only when a new row is inserted or a revoked row is reactivated. Idempotent: granting a DID that already holds the same active role returns 200 with `granted: false` and no audit row.
- app.tempomusic.staff.listAuditEvents query Global audit journal browser for the moderation console. Returns moderation_audit rows in reverse-chronological (created_at, id) keyset order, optionally filtered by acting moderator, action type, or subject DID. Complements getSubjectModerationHistory (per-subject view) with the 'what has the team been doing' view. Requires the caller to be an active moderator.
- app.tempomusic.staff.listInviteCodes query List PDS invite codes on-demand via the PDS (`com.atproto.admin.getInviteCodes`). No local mirror — the source of truth is the PDS. Requires the caller to have the `superAdmin` role. Codes are returned as suffix-only strings (the env prefix stored under `APPVIEW_PDS_INVITE_CODE_PREFIX` has been stripped). Optional `createdBy` filter narrows the listing to codes emitted by a specific staff DID (applied server-side by the AppView — the admin endpoint has no such parameter); when omitted every code
- app.tempomusic.staff.listReports query Cursored listing of moderation reports for the queue view. Filterable by status, subject type, reason, reporter, and subject author. Sorted by (created_at DESC, id DESC). Requires the caller to be an active moderator (any role).
- app.tempomusic.staff.listStaff query List currently-active moderators. Audit transparency: any moderator may see who else holds privileges. Set `includeRevoked: true` to include historical (revoked) rows. Sorted by (granted_at DESC, did). Requires the caller to be an active moderator (any role).
- app.tempomusic.staff.restoreSubject procedure Flip `moderation_status` back to 0 on a previously taken-down subject row. Writes a `subjectRestore` audit row. Trivially symmetric with takedownSubject — both act on the subject row only; lifting an account-wide sanction is unsuspendAccount's job (bans are permanent). Requires the caller to be an active moderator.
- app.tempomusic.staff.revokeStaffRole procedure Mark a moderator row as revoked. The DID can no longer pass the moderator gate (latency = the moderator-cache TTL, default 30s). Requires the caller to have the `superAdmin` role. A super-admin cannot revoke themselves. Writes a `moderatorRevoked` audit row only when an active row was actually revoked. Idempotent: revoking a DID that is not currently an active moderator returns 200 with `revoked: false` and no audit row.
- app.tempomusic.staff.suspendAccount procedure Suspend an account: all of its content disappears from the public read surface (feeds, single fetches, threads, notifications) while the row is active. Reversible via unsuspendAccount; optionally time-boxed via `until` (evaluated at read time — a lapsed suspension readmits content with no further action). Re-suspending replaces the current suspension (new reason/expiry, new audit row). Requires the `moderator` role. Writes an `accountSuspended` audit row.
- app.tempomusic.staff.takedownSubject procedure Flip `moderation_status` on a subject row to a non-zero takedown class. Read paths immediately refuse to serve the subject (404 on getPost / getReply / actor reads). Re-takedown against an already-taken-down subject is permitted as a severity escalation (e.g. `reported` → `legalHold`) or to amend the reason; each call writes a new audit row. Scoped to the subject row ONLY: an account takedown flips the profile row (offensive avatar/bio case) and does not touch the account's content — hiding ever
- app.tempomusic.staff.triageReport procedure Claim a report for review. Transitions status `open` → `underReview` atomically; if the report has already been claimed by another moderator, returns `AlreadyTriaged`. Writes a `reportTriaged` audit row. Requires the caller to be an active moderator.
- app.tempomusic.staff.unsuspendAccount procedure Lift an account suspension: deletes the current state row (history stays in the audit log) and instantly readmits the account's content on the public surface. Also accepts a LAPSED suspension (removes the stale row). Cannot lift a ban. Requires the `moderator` role. Writes an `accountUnsuspended` audit row.