Krizaka
Documentation
Operations

Admin Console

For decision-makers

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

Nothing

Application1

Data stores2

External services10

Text version — 28 modules
Modules and their build dependencies
ModuleRoleRepositoryVersionDepends onUsed by
orochia-adminClientsorochia-admin1.0.0krizaka-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-mobileClientsorochia-mobile1.0.0krizaka-tokens (2.0.0-beta.4), krizaka-ui (2.0.0-beta.4), orochia-design-system (4.0.0)—
orochia-webClientsorochia1.0.0krizaka-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-apiApplicationorochia1.0.0orochia-db, orochia-media, orochia-payments, orochia-push—
orochia-configPackagesorochia1.0.0——
orochia-dbPackagesorochia1.0.0—orochia-api, orochia-payments
orochia-mediaPackagesorochia1.0.0—orochia-api
orochia-paymentsPackagesorochia1.0.0orochia-dborochia-api
orochia-pushPackagesorochia1.0.0—orochia-api
orochia-design-systemDesign systemorochia-design-system4.1.0krizaka-tailwind (2.2.0), krizaka-tokens (2.2.0), krizaka-ui (2.2.0)orochia-admin, orochia-mobile, orochia-web
krizaka-i18nDesign systemkrizaka-ui0.1.0—orochia-web
krizaka-iconsDesign systemkrizaka-ui0.1.0—orochia-web
krizaka-intlDesign systemkrizaka-ui0.1.0—orochia-web
krizaka-tailwindDesign systemkrizaka-ui2.0.0—orochia-admin, orochia-design-system, orochia-web
krizaka-tokensDesign systemkrizaka-ui2.0.0—orochia-admin, orochia-design-system, orochia-mobile, orochia-web
krizaka-uiDesign systemkrizaka-ui2.0.0—orochia-admin, orochia-design-system, orochia-mobile, orochia-web
admin-postgresqlData storesorochia-admin———
postgresqlData storesorochia———
bunny-streamExternal servicesThird party———
ccbillExternal servicesThird party———
expo-pushExternal servicesThird party———
facebook-oauthExternal servicesThird party———
google-oauthExternal servicesThird party———
mailgunExternal servicesThird party———
nowpaymentsExternal servicesThird party———
resendExternal servicesThird party———
segpayExternal servicesThird party———
stripeExternal servicesThird party———
Runtime calls
FromToKindVia
orochia-adminorochia-apiHTTP/api/admin/* · service token
orochia-apibunny-streamHTTPcreate video · Tus signature
orochia-apiexpo-pushHTTP@orochia/push · send
orochia-apifacebook-oauthHTTPcode exchange · user info
orochia-apigoogle-oauthHTTPcode exchange · user info
orochia-apimailgunHTTPsend e-mail
orochia-apinowpaymentsHTTPcheckout session over its API
orochia-apiresendHTTPsend e-mail
orochia-apistripeHTTPcheckout session over its API
orochia-mobilebunny-streamHTTPHLS playback · signed URL
orochia-mobileorochia-apiHTTP/api/* · Bearer session
orochia-webbunny-streamHTTPHLS playback · signed URL
orochia-webbunny-streamHTTPTus upload (resumable)
orochia-webccbillHTTPhosted checkout page
orochia-webfacebook-oauthHTTPconsent screen (redirect)
orochia-webgoogle-oauthHTTPconsent screen (redirect)
orochia-webnowpaymentsHTTPhosted checkout page
orochia-weborochia-apiHTTP/api/* · session cookie
orochia-websegpayHTTPhosted checkout page
orochia-webstripeHTTPhosted checkout page
postgresqlorochia-apiLISTEN/NOTIFYLISTEN/NOTIFY orochia_events
expo-pushorochia-mobilepushnotification
orochia-adminadmin-postgresqlSQLoperator accounts · sessions
orochia-apipostgresqlSQL@orochia/db · Drizzle
orochia-apiorochia-mobileSSE/api/conversations/stream
orochia-apiorochia-webSSE/api/auctions/[id]/stream
orochia-apiorochia-webSSE/api/challenges/[id]/stream
orochia-apiorochia-webSSE/api/conversations/stream
bunny-streamorochia-apiwebhook/api/webhooks/bunny
ccbillorochia-apiwebhook/api/webhooks/payments/ccbill
nowpaymentsorochia-apiwebhook/api/webhooks/payments/crypto
segpayorochia-apiwebhook/api/webhooks/payments/segpay
stripeorochia-apiwebhook/api/webhooks/payments/stripe

Journey — Playback

  1. Asks to play — The player holds no media URL: it asks Orochia for one. (orochia-web → orochia-api) · GET /api/videos/[id]/stream
  2. Access check — Public, contacts, followers or paid unlock: visibility is checked against contacts, follows and access grants. (orochia-api → postgresql)
  3. Decision — No grant, no URL: the answer is a refusal or the paywall. (postgresql → orochia-api)
  4. 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)
  5. 4K HLS streaming — Segments come straight from Bunny's edge, never through the application servers. (orochia-web → bunny-stream)

Journey — Paid unlock

  1. Asks to unlock — The buyer picks an amount and a configured gateway. (orochia-web → orochia-api) · POST /api/videos/unlock-video
  2. Payment intent — Buyer, creator, video and amount are recorded before any money moves. (orochia-api → postgresql)
  3. Checkout page — The buyer goes to the provider's hosted page: Orochia never sees a card. (orochia-api → orochia-web)
  4. Payment — Only gateways whose credentials are all configured are offered. (orochia-web → ccbill, orochia-web → segpay, orochia-web → nowpayments, orochia-web → stripe)
  5. 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]
  6. Settled exactly once — Ledger credit and access grant in one transaction; a replayed webhook changes nothing. (orochia-api → postgresql)

Journey — Upload

  1. 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
  2. Creates the video — Orochia registers the video with Bunny Stream and signs a Tus session. (orochia-api → bunny-stream)
  3. Signed Tus session — The studio receives the upload address and its signature, valid for this video only. (orochia-api → orochia-web)
  4. Resumable upload — The file goes straight to Bunny and resumes after a cut. (orochia-web → bunny-stream)
  5. Encoding done — Bunny signals the end of transcoding with a signed webhook. (bunny-stream → orochia-api) · POST /api/webhooks/bunny
  6. 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

ScreenWhat an operator sees and decidesOrochia API
OverviewLedger totals, catalogue state and the three queues that need a humanGET /api/admin/overview
2257 Creator VerificationThe review queue; open a creator's identity and age document, approve the creator — only verified creators can uploadGET/PATCH /api/admin/creators, GET /api/admin/documents
Content ReportsTriage: start a review, reopen, resolve with a recorded reason; suspected minors and non-consensual content firstGET/PATCH /api/admin/reports
Treasury & PayoutsRevenue 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
CatalogueEvery 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 itGET/PATCH /api/admin/videos
AuctionsOpen, awaiting and sold auctions and the credits held; cancel one with a reason — the leading bid's credits go back to its bidderGET/DELETE /api/admin/auctions
Creator RegistryEvery creator and their activity; suspend or restore their uploadsGET/PATCH /api/admin/creators
AccountsEvery 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 & DatabaseEnvironment, 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

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

Accounts: role changes and suspensions, each behind a confirmation

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

Platform and database: deployment, migrations, backups and tables

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

The factory reset, armed by a typed phrase

The factory reset — backup first by default, locked until the phrase is typed.

How it is secured

Four gates, each enforced in code:

  1. The network. Every request — the sign-in page included — is refused with 403 unless the client address is in ADMIN_ALLOWED_IPS (comma-separated). On DigitalOcean the address is do-connecting-ip, set by the platform's edge, never by the client. In production the list is mandatory: empty, the console answers 403 to everyone. Only the liveness route /api/health (no data) is outside it.
  2. 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 an httpOnly, SameSite=Strict cookie. Changing the password in the environment revokes every open session.
  3. 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.
  4. 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=true and never on the public, indexed production, whatever the flag says. The operator must type reset <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_PASSWORD

Locally (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.

Product overview →

On this page