Admin Console
What an operator controls from orochia-admin — creator verification, moderation, payouts, auctions, accounts, backups — and the four gates around it: IP allow-list, one account, a service token, armed confirmations.
The operator console (krizaka/orochia-admin) is a separate application
with its own database, its own single account and its own network gate. It never touches Orochia's database: every
decision goes through Orochia's admin API (/api/admin/*, listed in the API reference), server
side, with a service token the browser never sees. What an operator decides is recorded in the console's own log.
Select a module: who it calls and who calls it stay lit — requests (HTTP, SQL) solid, events (messages, webhooks, SSE, NOTIFY, push) dashed.
orochia-admin: calls 2, called by 0.
Clients3
orochia-admin
Clients · Orochia
Operator console for Orochia: 2257 creator verification, content reports, payouts and treasury
- Repository orochia-admin
- package @krizaka/orochia-admin
- version 1.0.0
Calls
Called by
NothingApplication1
Data stores2
External services10
Text version — 28 modules
| Module | Role | Repository | Version | Depends on | Used by |
|---|---|---|---|---|---|
orochia-admin | Clients | orochia-admin | 1.0.0 | krizaka-tailwind (2.0.0-beta.1), krizaka-tokens (2.0.0-beta.1), krizaka-ui (2.0.0-beta.1), orochia-design-system (3.0.0) | — |
orochia-mobile | Clients | orochia-mobile | 1.0.0 | krizaka-tokens (2.0.0-beta.4), krizaka-ui (2.0.0-beta.4), orochia-design-system (4.0.0) | — |
orochia-web | Clients | orochia | 1.0.0 | krizaka-i18n (0.1.0), krizaka-icons (0.1.0), krizaka-intl (0.1.0), krizaka-tailwind (2.0.0), krizaka-tokens (2.0.0), krizaka-ui (2.0.0), orochia-design-system (4.0.0) | — |
orochia-api | Application | orochia | 1.0.0 | orochia-db, orochia-media, orochia-payments, orochia-push | — |
orochia-config | Packages | orochia | 1.0.0 | — | — |
orochia-db | Packages | orochia | 1.0.0 | — | orochia-api, orochia-payments |
orochia-media | Packages | orochia | 1.0.0 | — | orochia-api |
orochia-payments | Packages | orochia | 1.0.0 | orochia-db | orochia-api |
orochia-push | Packages | orochia | 1.0.0 | — | orochia-api |
orochia-design-system | Design system | orochia-design-system | 4.1.0 | krizaka-tailwind (2.2.0), krizaka-tokens (2.2.0), krizaka-ui (2.2.0) | orochia-admin, orochia-mobile, orochia-web |
krizaka-i18n | Design system | krizaka-ui | 0.1.0 | — | orochia-web |
krizaka-icons | Design system | krizaka-ui | 0.1.0 | — | orochia-web |
krizaka-intl | Design system | krizaka-ui | 0.1.0 | — | orochia-web |
krizaka-tailwind | Design system | krizaka-ui | 2.0.0 | — | orochia-admin, orochia-design-system, orochia-web |
krizaka-tokens | Design system | krizaka-ui | 2.0.0 | — | orochia-admin, orochia-design-system, orochia-mobile, orochia-web |
krizaka-ui | Design system | krizaka-ui | 2.0.0 | — | orochia-admin, orochia-design-system, orochia-mobile, orochia-web |
admin-postgresql | Data stores | orochia-admin | — | — | — |
postgresql | Data stores | orochia | — | — | — |
bunny-stream | External services | Third party | — | — | — |
ccbill | External services | Third party | — | — | — |
expo-push | External services | Third party | — | — | — |
facebook-oauth | External services | Third party | — | — | — |
google-oauth | External services | Third party | — | — | — |
mailgun | External services | Third party | — | — | — |
nowpayments | External services | Third party | — | — | — |
resend | External services | Third party | — | — | — |
segpay | External services | Third party | — | — | — |
stripe | External services | Third party | — | — | — |
| From | To | Kind | Via |
|---|---|---|---|
orochia-admin | orochia-api | HTTP | /api/admin/* · service token |
orochia-api | bunny-stream | HTTP | create video · Tus signature |
orochia-api | expo-push | HTTP | @orochia/push · send |
orochia-api | facebook-oauth | HTTP | code exchange · user info |
orochia-api | google-oauth | HTTP | code exchange · user info |
orochia-api | mailgun | HTTP | send e-mail |
orochia-api | nowpayments | HTTP | checkout session over its API |
orochia-api | resend | HTTP | send e-mail |
orochia-api | stripe | HTTP | checkout session over its API |
orochia-mobile | bunny-stream | HTTP | HLS playback · signed URL |
orochia-mobile | orochia-api | HTTP | /api/* · Bearer session |
orochia-web | bunny-stream | HTTP | HLS playback · signed URL |
orochia-web | bunny-stream | HTTP | Tus upload (resumable) |
orochia-web | ccbill | HTTP | hosted checkout page |
orochia-web | facebook-oauth | HTTP | consent screen (redirect) |
orochia-web | google-oauth | HTTP | consent screen (redirect) |
orochia-web | nowpayments | HTTP | hosted checkout page |
orochia-web | orochia-api | HTTP | /api/* · session cookie |
orochia-web | segpay | HTTP | hosted checkout page |
orochia-web | stripe | HTTP | hosted checkout page |
postgresql | orochia-api | LISTEN/NOTIFY | LISTEN/NOTIFY orochia_events |
expo-push | orochia-mobile | push | notification |
orochia-admin | admin-postgresql | SQL | operator accounts · sessions |
orochia-api | postgresql | SQL | @orochia/db · Drizzle |
orochia-api | orochia-mobile | SSE | /api/conversations/stream |
orochia-api | orochia-web | SSE | /api/auctions/[id]/stream |
orochia-api | orochia-web | SSE | /api/challenges/[id]/stream |
orochia-api | orochia-web | SSE | /api/conversations/stream |
bunny-stream | orochia-api | webhook | /api/webhooks/bunny |
ccbill | orochia-api | webhook | /api/webhooks/payments/ccbill |
nowpayments | orochia-api | webhook | /api/webhooks/payments/crypto |
segpay | orochia-api | webhook | /api/webhooks/payments/segpay |
stripe | orochia-api | webhook | /api/webhooks/payments/stripe |
Journey — Playback
- Asks to play — The player holds no media URL: it asks Orochia for one. (orochia-web → orochia-api) ·
GET /api/videos/[id]/stream - Access check — Public, contacts, followers or paid unlock: visibility is checked against contacts, follows and access grants. (orochia-api → postgresql)
- Decision — No grant, no URL: the answer is a refusal or the paywall. (postgresql → orochia-api)
- Signed URL · 300 s — An HMAC-SHA256 token bound to the video and its expiry: a shared link dies in five minutes. (orochia-api → orochia-web)
- 4K HLS streaming — Segments come straight from Bunny's edge, never through the application servers. (orochia-web → bunny-stream)
Journey — Paid unlock
- Asks to unlock — The buyer picks an amount and a configured gateway. (orochia-web → orochia-api) ·
POST /api/videos/unlock-video - Payment intent — Buyer, creator, video and amount are recorded before any money moves. (orochia-api → postgresql)
- Checkout page — The buyer goes to the provider's hosted page: Orochia never sees a card. (orochia-api → orochia-web)
- Payment — Only gateways whose credentials are all configured are offered. (orochia-web → ccbill, orochia-web → segpay, orochia-web → nowpayments, orochia-web → stripe)
- Signed webhook — Signature verified in constant time over the raw body — no lenient mode. (ccbill → orochia-api, segpay → orochia-api, nowpayments → orochia-api, stripe → orochia-api) ·
POST /api/webhooks/payments/[gateway] - Settled exactly once — Ledger credit and access grant in one transaction; a replayed webhook changes nothing. (orochia-api → postgresql)
Journey — Upload
- Opens an upload — Only verified creators (18 U.S.C. § 2257 records) can open a session. (orochia-web → orochia-api) ·
POST /api/videos/create-upload-session - Creates the video — Orochia registers the video with Bunny Stream and signs a Tus session. (orochia-api → bunny-stream)
- Signed Tus session — The studio receives the upload address and its signature, valid for this video only. (orochia-api → orochia-web)
- Resumable upload — The file goes straight to Bunny and resumes after a cut. (orochia-web → bunny-stream)
- Encoding done — Bunny signals the end of transcoding with a signed webhook. (bunny-stream → orochia-api) ·
POST /api/webhooks/bunny - Ready to stream — The video becomes playable, under the visibility its creator chose. (orochia-api → postgresql)
The operator reaches the console from an allowed IP only, with its one account; the console keeps its account, sessions and operator log in its own PostgreSQL, and calls Orochia server-side on /api/admin/* with the service token — never the Orochia database.
What you control
| Screen | What an operator sees and decides | Orochia API |
|---|---|---|
| Overview | Ledger totals, catalogue state and the three queues that need a human | GET /api/admin/overview |
| 2257 Creator Verification | The review queue; open a creator's identity and age document, approve the creator — only verified creators can upload | GET/PATCH /api/admin/creators, GET /api/admin/documents |
| Content Reports | Triage: start a review, reopen, resolve with a recorded reason; suspected minors and non-consensual content first | GET/PATCH /api/admin/reports |
| Treasury & Payouts | Revenue from the ledger; put a payout under review, settle it with the transfer reference, or fail it with a reason (the balance is refunded) | GET /api/platform/treasury, GET/PATCH /api/admin/payouts |
| Catalogue | Every video by state with its open reports; take one down with a recorded reason (DMCA, terms, a confirmed report — its auction is cancelled) or restore it | GET/PATCH /api/admin/videos |
| Auctions | Open, awaiting and sold auctions and the credits held; cancel one with a reason — the leading bid's credits go back to its bidder | GET/DELETE /api/admin/auctions |
| Creator Registry | Every creator and their activity; suspend or restore their uploads | GET/PATCH /api/admin/creators |
| Accounts | Every account, filtered by role, suspension or search; suspend (sign-in blocked, open sessions refused on their next request, open auctions cancelled) with a reason shown to the account, reinstate, or change the role (member, creator, administrator) | GET/PATCH /api/admin/users |
| Platform & Database | Environment, database size and rows per table, migration history, backups (create, download, delete), the operator log and the factory reset | /api/admin/platform* |
Screens
Captured on a local development stack (e-mail addresses and the operator's name redacted).

Overview — the three queues that need a human, and the ledger.

Accounts — every account, its role, its checks and its state.

Platform & Database — deployment, migrations, backups and rows per table.

The factory reset — backup first by default, locked until the phrase is typed.
How it is secured
Four gates, each enforced in code:
- The network. Every request — the sign-in page included — is refused with
403unless the client address is inADMIN_ALLOWED_IPS(comma-separated). On DigitalOcean the address isdo-connecting-ip, set by the platform's edge, never by the client. In production the list is mandatory: empty, the console answers403to everyone. Only the liveness route/api/health(no data) is outside it. - One account. Nobody signs up. The single operator is defined by environment —
ADMIN_EMAIL,ADMIN_NAME,ADMIN_PASSWORD(12 characters or more) — and written to the console's database on first use. The password is stored as a salted scrypt hash and compared in constant time. Sessions are random tokens stored hashed, valid 8 hours, in anhttpOnly,SameSite=Strictcookie. Changing the password in the environment revokes every open session. - A service token. The console calls Orochia as a service:
Authorization: Bearer OROCHIA_ADMIN_API_TOKEN(32 characters or more, shared by the two deployments only), compared in constant time. Orochia accepts it on its ADMIN routes only, and acts as the platform owner (OROCHIA_OWNER_EMAIL), who must exist, be an administrator and not be suspended — otherwise every call is refused. Without the variable, no token is accepted. - Armed confirmations. Every decision opens a dialog that says what will happen before it does. A decision that affects someone requires a recorded reason (a takedown, a suspension, a failed payout, a cancelled auction) or the transfer reference (a settled payout). Irreversible operations are armed by a phrase: the operator types it before the button works. Benign, reversible steps (start a review, reopen a report) are one click.
Every decision — done or refused, with its target and detail — is written to the operator log, shown on Platform & Database.
Backups and factory reset
- Backup now writes the whole database (gzipped JSON of every table) to private storage; backups can be described, downloaded and deleted from the console.
- Factory reset deletes every account, video, payment, auction and setting and rebuilds the schema from the
release's migrations — the state of a fresh install. Orochia's owner account is kept; the console, its account
and its log live in their own database and are not affected; media files at Bunny are not deleted. It is
available only where
OROCHIA_ALLOW_DATABASE_RESET=trueand never on the public, indexed production, whatever the flag says. The operator must typereset <database name>; "back up first" is on by default, and if that backup fails nothing is deleted.
Run it locally
Start Orochia first, with the same OROCHIA_ADMIN_API_TOKEN in its .env, then:
git clone https://github.com/krizaka/orochia-admin.git && cd orochia-admin
cp .env.example .env.local # its database, the operator account, the token shared with Orochia
docker exec orochia-postgres-dev psql -U orochia_user -d orochia_db -c "CREATE DATABASE orochia_admin"
npm install
npm run dev # http://localhost:3001 — sign in with ADMIN_EMAIL / ADMIN_PASSWORDLocally (outside production) an empty ADMIN_ALLOWED_IPS lets every address in. On a deployment, deploy/Dockerfile
builds a standalone image (port 3001); ADMIN_PASSWORD and OROCHIA_ADMIN_API_TOKEN are app secrets, never in git.