Introduction
prick stores secrets in a D1 database that only your Cloudflare account can reach, and hands them to processes at runtime.
The three parts
| Part | What it is |
|---|---|
prk |
The command-line client. One static Rust binary, published as @yashau/prick |
| The Worker | One Cloudflare Worker serving a JSON API at /api/* and a SvelteKit admin UI everywhere else |
| D1 | The database. Secret values are stored encrypted; key names are stored in plaintext |
That is the whole system. There is no separate control plane, no agent to run, and no service to sign up for.
How a request flows
prk / browser ──▶ Cloudflare Access ──▶ Worker ──▶ D1 (SSO / service (Hono + (values encrypted, tokens, at the edge) SvelteKit) AES-256-GCM + AAD)Cloudflare Access authenticates at the edge, before the Worker runs. The Worker
then verifies the signed JWT itself to learn who is calling, and consults its
own grants table to decide what they may do.
Authentication is Cloudflare’s. Authorization is prick’s. Getting through Access means you reached the Worker; it says nothing about what you can read.
How you use it
Organise secrets into projects and environments:
project "api"├── environment "production"│ ├── DATABASE_URL│ └── STRIPE_SECRET_KEY└── environment "staging" ├── DATABASE_URL └── STRIPE_SECRET_KEYWrite one:
prk secrets set DATABASE_URL --project api --env productionThen hand the whole environment to a process:
prk run --project api --env production -- npm startGrants are scoped to a project or one of its environments, so the same hierarchy that organises your secrets is what controls access to them.
Decisions worth knowing
- The CLI talks only to your Worker. It is a pure HTTP client: it presents your Access credential, and everything else — encryption, authorization, audit — happens server-side.
- Deployment is
wrangler deploy. Provisioning happens once per install, so it belongs to Cloudflare’s own tooling rather than to aprk initcommand. - Bulk writes are atomic. An environment-wide write is one D1
batch(), which is a real transaction, so an environment is never half-written. - Every mutation carries an audit row. The audit insert is the last statement inside the same transaction, so a failed audit fails the write with it.
- A decrypt failure is loud. A row that will not decrypt fails the request,
or is marked unreadable in a listing. A silently shorter
.envis how a deploy goes out withoutDATABASE_URL. MASTER_KEYis the whole ballgame. Lose it and the data is unrecoverable. Read Backup and recovery before you store anything.
What is built
The security-critical layers exist and are tested: the encryption envelope and
its additional authenticated data, Access JWT verification, grant resolution
including groups, and the bootstrap path. The domain layer is written —
projects, environments, secrets, identities, grants, groups and the audit query
— and the whole HTTP surface is mounted on top of it. The prk CLI signs in,
stores its token, sends service-token headers and runs every subcommand.
The rekey is operator-driven. GET /api/v1/admin/keyring and
POST /api/v1/admin/rekey answer for real, a rotation advances one page per
call, and it is finished when remaining reaches zero. The settings screen has
a button, and that is the whole mechanism — there is no cron. See
Key rotation.
Next steps
- Quickstart — deploy the Worker to your account.
- Install the CLI
- Architecture overview — how the pieces are wired.