bloqr-admin Worker (admin.bloqr.dev)
bloqr-admin Worker
bloqr-admin is the dedicated Cloudflare Worker that serves the operator /
system-admin console at admin.bloqr.dev. It is deployed and versioned
independently from the main bloqr-backend Worker (its own script name, its
own wrangler.toml) and lives at worker/admin-app/ in the monorepo — the
same pattern the sibling bloqr-mail Worker uses.
Why a separate host and worker?
Bloqr has two distinct admin surfaces, intentionally separated by hostname so the blast radius of the more powerful one is fenced off.
| Surface | Host | Audience | Served by |
|---|---|---|---|
| User (tenant) admin | app.bloqr.dev/admin | An account’s own admins | Angular SPA + bloqr-backend /api/admin/* |
| Operator / system admin | admin.bloqr.dev | Bloqr operators (super-admin) | bloqr-admin (this worker) |
The user admin panel manages a single account. The operator console reaches across the whole platform (cross-tenant user management, role assignment, tier/scope/endpoint registries, feature flags, storage tools, Cloudflare audit). Putting the operator surface on its own host and worker means a bug or misconfiguration in one surface cannot expose the other, and the operator host can carry a tighter CORS + security-header policy.
Thin gateway, single source of truth
bloqr-admin is a thin operator gateway, not a second copy of the admin
API. All admin business logic — handlers, Zod schemas, D1 access — stays in the
bloqr-backend worker. The gateway’s job is narrow and security-critical:
- Terminate the host boundary. Strict CORS locked to the operator origin,
X-Frame-Options: DENY,Referrer-Policy: no-referrer, HSTS preload. - Enforce the operator gate.
requireOperator()verifies a Better Auth session and requires the resolved role to besuper-admin— before anything is forwarded. Holding an individual permission is not enough; this is a role gate, not a permission gate. It is the exact same guard the main worker exposes (worker/middleware/admin-role-middleware.ts), imported directly, so there is one operator-gate implementation. - Forward over a service binding. The now-authorized request is proxied to
bloqr-backend’s existing/api/admin/*routes via theAPICloudflare service binding — a Worker-to-Worker call with no public network hop. The downstream handlers re-authenticate and apply their own finer-grained permission checks, so the edge gate is defense in depth, not the only line.
sequenceDiagram
participant Op as Operator (browser)
participant Admin as bloqr-admin<br/>(admin.bloqr.dev)
participant Api as bloqr-backend<br/>(/api/admin/*)
Op->>Admin: GET /admin/system/roles (session cookie / Bearer)
Admin->>Admin: requireOperator() — Better Auth → super-admin?
alt not an operator
Admin-->>Op: 401 / 403 (API binding never called)
else operator
Admin->>Api: GET /api/admin/system/roles<br/>(service binding, headers preserved)
Api->>Api: re-auth + permission check
Api-->>Admin: 200 JSON
Admin-->>Op: 200 JSON
end
Routes served on admin.bloqr.dev
| Path | Behaviour |
|---|---|
GET / | Minimal dark-first operator console landing shell (noindex) |
GET /health | Liveness probe — { status: "ok", worker, time } |
GET /meta | Service descriptor: environment + which bindings are wired |
ALL /api/admin/* | Operator-gated, forwarded to bloqr-backend |
ALL /admin/* | Alias of the above (rewritten to /api/admin/*) |
| anything else | 404 — this host is not a general API mirror |
/health and /meta responses are validated with Zod
(AdminHealthSchema, AdminMetaSchema) before they leave the worker, so the
contract can never silently drift.
Bindings
Configured in worker/admin-app/wrangler.toml:
| Binding | Kind | Purpose |
|---|---|---|
API | Service | Forward target — the bloqr-backend Worker |
ADMIN_DB | D1 | Edge role resolution (admin_role_assignments / admin_roles). Migrations are owned by the main worker (admin-migrations/) — never migrate from here |
RATE_LIMIT | KV | Resolved-role cache, shared with the main worker so a role lookup is cached once and reused across both |
The operator gate verifies a Better Auth session at the edge, so the same auth secrets the main worker uses must be set on this worker:
cd worker/admin-appwrangler secret put BETTER_AUTH_SECRETwrangler secret put BETTER_AUTH_API_KEYwrangler secret put BETTER_AUTH_KV_URLNever commit secrets. For local development, put them in a gitignored
.dev.vars inside worker/admin-app/.
Routing (Cloudflare)
The worker claims the operator host via its wrangler.toml routes:
[[routes]]pattern = "admin.bloqr.dev"custom_domain = true
[[routes]]pattern = "*.admin.bloqr.dev/*"zone_name = "bloqr.dev"This matches the DNS record admin.bloqr.dev and the wildcard route
*.admin.bloqr.dev/*.
Develop, test & deploy
deno task wrangler:admin:dev # local dev server for bloqr-admindeno task wrangler:admin:deploy # deploy to admin.bloqr.devdeno task check:worker # typecheck (includes admin-worker.ts)deno test --allow-read --allow-write --allow-net --allow-env worker/admin-app/Security model
- Fail closed everywhere. Missing
ADMIN_DB⇒503; missing/invalid session ⇒401; authenticated non-operator ⇒403; missingAPIbinding ⇒503. There is no code path where an unauthorized request reaches the backend. - No secrets in
wrangler.toml. Only non-secret vars (ENVIRONMENT,ADMIN_ALLOWED_ORIGINS) live there; auth secrets are Worker Secrets. - Preserved credentials. The gateway forwards the original
Authorizationheader / session cookie unchanged so the downstream handler re-verifies the caller — the gateway never mints or elevates credentials. It adds audit headers (X-Bloqr-Admin-Gateway,X-Bloqr-Operator-Id,X-Forwarded-Host) for traceability only. - Tight CORS. Only
https://admin.bloqr.dev(plus any explicitly configuredADMIN_ALLOWED_ORIGINS) is reflected; localhost origins are trusted only outside production.
Design
The operator landing shell is dark-first and expresses its palette as
Filter design-system
CSS custom properties (--bg-base, --accent, --link, …), with the
canonical dark-first values as fallbacks only. The accent is Filter orange
(#FF5500), never white or a light background. See the design system’s
guidelines/OPERATOR_CONSOLE.md for the operator-console design contract that
both this shell and the Angular operator panels follow.
Bloqr AI™ — The privacy you didn't know you needed.
© 2026 Bloqr AI™, a trademark of Bloqr Systems™. Created by Bloqr Systems™, founded by Jayson Knight.
Internet Hygiene (n.) — the ongoing practices that keep your digital life clean, private, and safe.
Our product repos live in the BloqrAI org, part of the Bloqr Systems GitHub Enterprise. Product repos are internal-visibility — enterprise membership is required to view them.