seekrit

Architecture

Resource model

seekrit is multi-tenant. Resources nest from organizations down to individual secrets:

organizations ─┬─ members (users, via org_memberships with a role)
               ├─ applications ── environments ─┬─ secrets (+ version history)
               │                                └─ key grants (wrapped DEKs)
               ├─ service tokens
               └─ audit log (append-only)
  • Organization — a tenant. Has members, applications, service tokens, and its own audit trail.
  • Application — a deployable (a service, site, or worker) within an org.
  • Environment — a named context under an application (production, staging, ci, ephemeral-agent-42, …). Each environment owns one data key.
  • Secret — a named, encrypted value in an environment. Every write appends a new version.
  • Key grant — a wrapped copy of an environment's data key for one principal.

Roles

Membership carries a role: owner > admin > member.

  • Admin and owner manage structure (apps, environments), service tokens, key grants, and can read the audit trail.
  • Members read and write secrets in environments they hold a key for.

The real access boundary is cryptographic: you can only decrypt an environment if you hold a key grant for it. Roles gate the management API on top of that. Non-members receive 404s for an org so its existence can't be probed.

Cloudflare building blocks

seekrit is designed to run entirely on a Cloudflare account.

ComponentCloudflare productRole
APIWorkersThe Hono API worker
DatabaseD1 (SQLite)Orgs, users, secrets (ciphertext), grants, audit
CacheKVCached identity-provider JWKS (and future session/rate-limit state)
Web dashboardWorkers (via OpenNext)Next.js app serving the browser client

The API and web app deploy as separate Workers. D1 and KV are provisioned as bindings; the CLI wrangler handles migrations and deploys.

Request lifecycle

  1. A request arrives at the API worker with a credential — a Stytch session JWT, a service token, or (locally) a dev-user header.
  2. Auth middleware resolves the actor (a user or a service token) and, for org-scoped routes, checks membership and role.
  3. The handler reads or writes ciphertext in D1. It never handles plaintext secrets.
  4. Any mutating action (and secret reads) writes an entry to the append-only audit log before the response returns.

Authentication

  • Web — Stytch B2B sign-in (Google/GitHub OAuth discovery). The browser holds the session; its JWT is sent as a bearer token and verified by the API against Stytch's JWKS (cached in KV).
  • CLI / machines — service tokens (skt_…) sent as bearer tokens.
  • Local dev — an x-seekrit-dev-user header, enabled only when the API runs with AUTH_MODE=dev.

The first time a valid session proves access to a Stytch organization, seekrit provisions the matching org and membership just-in-time.