Admin guide
Infrastructure, secrets setup, database migrations, audit logs, deployment, and security best practices.
1. Infrastructure
Passflares runs entirely on the Cloudflare stack:
| Service | Purpose |
|---|---|
| Workers | API routing and request handling |
| D1 (SQLite) | User accounts, vault metadata, organisations, audit logs |
| R2 | Encrypted vault blobs (the actual password data) |
| KV | Rate limiting counters for failed login attempts |
| Turnstile | Bot protection on the login and register forms |
| Assets | Static frontend files (HTML, CSS, JS) |
2. Secrets
Two secrets must be set in Cloudflare Workers. Never commit these to the repository.
# Set via Wrangler CLI (prompts for value securely)
wrangler secret put JWT_SECRET
wrangler secret put TURNSTILE_KEY
JWT_SECRET— signs and verifies authentication tokens. Use at least 32 random characters. Generate one with:node -e "console.log(require('crypto').randomBytes(48).toString('base64url'))"TURNSTILE_KEY— the Turnstile secret key (not the site key) from your Cloudflare Turnstile dashboard. The site key is safe to embed in the frontend HTML; the secret key must never be exposed.
For local development, copy .dev.vars.example to .dev.vars and fill in local values. .dev.vars is gitignored and read automatically by wrangler dev.
3. Database migrations
Migrations live in migrations/ and are applied with Wrangler:
# Apply all pending migrations to the live database
npx wrangler d1 migrations apply secure-password-db --remote
# Apply to local development database only
npx wrangler d1 migrations apply secure-password-db
Current migrations:
0001_init.sql— initial schema (users, vaults, organisations, audit logs, access controls)0002_super_admin_role.sql— addssuper_adminto theuser_organizations.roleCHECK constraint; must be applied before deploying v1.1.0-beta0003_user_preferences.sql— adds theuser_preferencestable for cross-device UI prefs (theme, density, shape, accent); must be applied before deploying v2.0.0-beta
4. Deployment
# Deploy Worker + static assets
npx wrangler deploy --env=""
# Or via npm script
npm run deploy
The Cloudflare CI/CD pipeline (configured in the Cloudflare Workers dashboard) runs npx wrangler deploy automatically on push to main.
5. Local development
# Start local dev server (Worker + static assets)
npm run dev
# or
wrangler dev
wrangler dev simulates D1, R2, and KV locally. Set local secrets in .dev.vars. Use the Turnstile test site key 1x0000000000000000000000000000000AA in .dev.vars — it always passes validation.
6. Running tests
# Requires Node.js 20+
nvm use 23
npm test
The test suite covers:
- Backend: all API handlers (auth, vaults, organisations, middleware, utilities)
- Frontend: API call functions, vault list rendering, org card rendering, crypto encrypt/decrypt roundtrip, password utilities
7. Audit logs
Every sensitive action is recorded in the audit_logs D1 table:
-- View recent activity
SELECT * FROM audit_logs ORDER BY timestamp DESC LIMIT 100;
-- Failed logins in the last 24 hours
SELECT * FROM audit_logs
WHERE action LIKE '%FAILURE%'
AND timestamp > datetime('now', '-1 day')
ORDER BY timestamp DESC;
-- All actions by a specific user
SELECT * FROM audit_logs WHERE user_id = 42 ORDER BY timestamp DESC;
Logged actions include: REGISTER, LOGIN, GET_SALT, UPDATE_PASSWORD, DELETE_ACCOUNT, VAULT_CREATE, VAULT_LIST, VAULT_UPLOAD, VAULT_DOWNLOAD, VAULT_DELETE, ORG_CREATE, ORG_LIST, ORG_GET_MEMBERS, ORG_ADD_MEMBER, ORG_UPDATE_ROLE, ORG_REMOVE_MEMBER, ORG_DELETE, AUTH_FAILURE, VAULT_ACCESS_DENIED.
8. Security best practices
- Rotate
JWT_SECRETperiodically. All existing sessions will be invalidated — users will need to log in again. - Monitor audit logs for unusual patterns: repeated AUTH_FAILURE from the same IP, unexpected VAULT_DELETE events, etc.
- D1 and R2 are Cloudflare-managed. Keep the KV namespace ID, D1 database ID, and R2 bucket name confidential — they are in
wrangler.tomlbut not security-sensitive on their own since access requires a valid Cloudflare API token. - The rate limiter blocks IPs after 5 failed login attempts for 15 minutes. Failed attempts are stored in KV with TTL. KV entries are cleared on successful login and on account deletion.
- The Turnstile Permissions-Policy and CSP warnings you may see in browser console are from Cloudflare's own challenge infrastructure, not from app code — they are harmless.
9. Account deletion — admin notes
When a user deletes their account:
- All personal vault R2 objects are deleted.
- All personal vault D1 records are deleted (cascade removes access controls).
- The user's shared vault access control entries are removed.
- Organisation memberships are removed (cascade).
- Audit log entries are retained but the
user_idcolumn is set to NULL. - Organisation-owned vaults are not deleted.
If a deleted user was the sole Owner of an organisation, the organisation still exists but has no Owner — it will remain until a database admin manually assigns a new Owner or deletes the org.