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.
Sélectionne un module : qui il appelle et qui l'appelle restent allumés — requêtes (HTTP, SQL) en trait plein, événements (messages, webhooks, SSE, NOTIFY, push) en pointillés.
orochia-admin : appelle 2, appelé par 0.
Clients3
orochia-admin
Clients · Orochia
Operator console for Orochia: 2257 creator verification, content reports, payouts and treasury
- Dépôt orochia-admin
- paquet @krizaka/orochia-admin
- version 1.0.0
Appelle
Appelé par
RienApplication1
Données2
Services externes10
Version texte — 28 modules
| Module | Rôle | Dépôt | Version | Dépend de | Utilisé par |
|---|---|---|---|---|---|
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 | Paquets | orochia | 1.0.0 | — | — |
orochia-db | Paquets | orochia | 1.0.0 | — | orochia-api, orochia-payments |
orochia-media | Paquets | orochia | 1.0.0 | — | orochia-api |
orochia-payments | Paquets | orochia | 1.0.0 | orochia-db | orochia-api |
orochia-push | Paquets | 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 | Données | orochia-admin | — | — | — |
postgresql | Données | orochia | — | — | — |
bunny-stream | Services externes | Tiers | — | — | — |
ccbill | Services externes | Tiers | — | — | — |
expo-push | Services externes | Tiers | — | — | — |
facebook-oauth | Services externes | Tiers | — | — | — |
google-oauth | Services externes | Tiers | — | — | — |
mailgun | Services externes | Tiers | — | — | — |
nowpayments | Services externes | Tiers | — | — | — |
resend | Services externes | Tiers | — | — | — |
segpay | Services externes | Tiers | — | — | — |
stripe | Services externes | Tiers | — | — | — |
| De | Vers | Type | 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 |
Parcours — Lecture
- Demande de lecture — Le lecteur ne détient aucune URL média : il en demande une à Orochia. (orochia-web → orochia-api) ·
GET /api/videos/[id]/stream - Contrôle d'accès — Publique, contacts, abonnés ou déblocage payant : la visibilité est vérifiée contre les contacts, abonnements et droits d'accès. (orochia-api → postgresql)
- Décision — Pas de droit, pas d'URL : la réponse est un refus ou le paywall. (postgresql → orochia-api)
- URL signée · 300 s — Un jeton HMAC-SHA256 lié à la vidéo et à son expiration : un lien partagé meurt en cinq minutes. (orochia-api → orochia-web)
- Diffusion 4K HLS — Les segments viennent directement du CDN de Bunny, jamais des serveurs applicatifs. (orochia-web → bunny-stream)
Parcours — Déblocage payant
- Demande de déblocage — L'acheteur choisit un montant et une passerelle configurée. (orochia-web → orochia-api) ·
POST /api/videos/unlock-video - Intention de paiement — Acheteur, créateur, vidéo et montant sont enregistrés avant tout mouvement d'argent. (orochia-api → postgresql)
- Page de paiement — L'acheteur part sur la page hébergée du prestataire : Orochia ne voit jamais de carte. (orochia-api → orochia-web)
- Paiement — Seules les passerelles dont tous les identifiants sont configurés sont proposées. (orochia-web → ccbill, orochia-web → segpay, orochia-web → nowpayments, orochia-web → stripe)
- Webhook signé — Signature vérifiée en temps constant sur le corps brut — aucun mode permissif. (ccbill → orochia-api, segpay → orochia-api, nowpayments → orochia-api, stripe → orochia-api) ·
POST /api/webhooks/payments/[gateway] - Règlement, une seule fois — Crédit au grand livre et droit d'accès dans une même transaction ; un webhook rejoué ne change rien. (orochia-api → postgresql)
Parcours — Téléversement
- Ouverture d'envoi — Seuls les créateurs vérifiés (registres 18 U.S.C. § 2257) peuvent ouvrir une session. (orochia-web → orochia-api) ·
POST /api/videos/create-upload-session - Création de la vidéo — Orochia enregistre la vidéo chez Bunny Stream et signe une session Tus. (orochia-api → bunny-stream)
- Session Tus signée — Le studio reçoit l'adresse d'envoi et sa signature, valables pour cette seule vidéo. (orochia-api → orochia-web)
- Envoi reprenable — Le fichier part directement vers Bunny et reprend après une coupure. (orochia-web → bunny-stream)
- Encodage terminé — Bunny signale la fin du transcodage par un webhook signé. (bunny-stream → orochia-api) ·
POST /api/webhooks/bunny - Prête à diffuser — La vidéo devient lisible, sous la visibilité choisie par son créateur. (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.