┌─────────────────────────────────────────────────────────────────┐ │ Your Machine │ │ │ │ sigillo run -- next dev │ │ │ │ │ │ device flow login (RFC 8628) │ │ │ or bearer token │ │ ▼ │ │ ┌──────────┐ │ │ │ Sigillo │ │ │ │ CLI │ │ │ └────┬─────┘ │ │ │ │ └───────┼─────────────────────────────────────────────────────────┘ │ REST API ▼ ┌──────────────────────┐ ┌──────────────────────┐ │ App Worker │ │ Provider Worker │ │ (self-hosted) │────────▶│ (self-hosted) │ │ │ OAuth │ │ │ • Secrets CRUD │ PKCE │ • Google login │ │ • AES-256-GCM │ │ • OAuth2 / OIDC │ │ • Audit log │◀────────│ • Dynamic client │ │ • API tokens │ token │ registration │ │ • Device flow │ │ │ │ ┌────────────┐ │ │ ┌────────────┐ │ │ │ D1 (app) │ │ │ │ D1 (auth) │ │ │ └────────────┘ │ │ └────────────┘ │ └──────────────────────┘ └──────────────────────┘
<name>-auth. People sign in with Google through it. The app registers itself with it on its first request via RFC 7591 dynamic client registration, as a public PKCE client that needs no client secret.| Who | What they can do | What limits it |
| Anyone who can edit Workers on the Cloudflare account | Deploy code that reads every secret | A dedicated account |
| Anyone who can edit the D1 databases | Make any account that can sign in an org admin, change the history | A dedicated account, protected environments, the signed history |
Anyone with ~/.sigillo/selfhost.json and its passphrase | Decrypt a database export or backup and use the sessions in an export, sign history rows, and with a saved login deploy to the account | The passphrase |
| Anyone who can sign in | What their org role and project access allow | The sign-in allowlist |
| A CI job or pod that a trust rule accepts | What the rule grants, with a token of one hour | Narrow trust rules |
| Anyone with a stolen browser session or CLI login | What that person can read and change, except protected environments, and admin actions in an org that has one | Passkeys |
| Org admins | Every project and environment of their org | Few admins |
ENCRYPTION_KEY, 32 random bytes. Deployments made before there was one derive it from BETTER_AUTH_SECRET with SHA-256.ENCRYPTION_KEYS holds the newer keys and names the current one. Every value names the key it was encrypted with.~/.sigillo/selfhost.json.CLI/Agent App (self-hosted) Provider (self-hosted) │ │ │ │ POST /api/auth/device/code │ │ │─────────────────────────────▶│ │ │ { user_code, device_code } │ │ │◀─────────────────────────────│ │ │ │ │ │ User opens /device │ │ │ and enters user_code │ │ │ ┌────────────────────┼────── redirect ───────────────▶│ │ │ │ │ │ │ │ Google sign-in ──▶│ Google │ │ │ ◀── callback ─────│ │ │ │ │ │ │ │◀── auth code (PKCE) ───────────│ │ └────────────────────┼────── approved ───────────────▶│ │ │ │ │ Poll /api/auth/device/token │ │ │─────────────────────────────▶│ │ │ { access_token } │ │ │◀─────────────────────────────│ │
self-host turns them on again with every deploy. A request's log holds its method, URL and headers: the name of a secret fetched on its own, and the client's IP address. Cloudflare replaces credentials such as the Authorization header with REDACTED, as wrangler tail shows. Logs are kept for 3 days on the Free plan or 7 on Workers Paid, and anyone who can read logs on the account can see them.workers.dev. Both workers keep their workers.dev URLs, also with a custom domain (--domain): self-host uses them, and the login provider only has that one.