| name | bondery-security |
| description | Bondery security patterns โ tenant isolation, auth areas, sessions, secrets, input validation, uploads, webhooks, client trust boundaries, and deployment hardening. Use when adding authentication, authorization, API routes, secrets, uploads, webhooks, payments, sensitive data, extension bridges, or reviewing security-sensitive changes.
|
| metadata | {"version":"1.0.0","namespace":"bondery"} |
Bondery Security
When to use
- Implementing authentication, authorization, or session handling
- Adding or changing API routes, webhooks, or internal service calls
- Handling user input, file uploads, or HTML/markdown rendering
- Working with secrets, env vars, or client token storage
- Integrating payments (Stripe), AI tools, sync WebSockets, or third-party APIs
- Reviewing changes that touch tenant data, cookies, CORS, or extension bridges
- Planning self-hosted deployment or production hardening
Do not activate for routine UI refactors, copy changes, or non-security API contract work โ use bondery-api / bondery-ux instead.
Trust-boundary workflow
- Identify which trust boundary the change crosses (browser, BFF, API, DB, extension, webhook).
- Read the matching reference file from the decision tree below.
- Verify auth is wired through route shells โ never ad-hoc in route handlers.
- Confirm tenant-owned Prisma queries scope by authenticated
userId, not request input.
- Run contextual verification commands (see below).
- Complete the security checklist before merge.
Non-negotiables (ranked)
- Tenant isolation โ
getAuth(request).client is unscoped Prisma. Every tenant-owned query must filter by where: { userId: user.id } (or equivalent join). There is no RLS on the current API path. Foreign and nonexistent resources should normally be indistinguishable (404, not 403).
- Route shell auth โ Auth hooks live only in
apps/api/src/lib/platform/route-areas.ts, mounted via routes/register-all.ts. Custom-auth routes (webhooks, WS tickets) must implement their own verification.
- JWT vs opaque bearer โ JWT-shaped bearer tokens route exclusively to OAuth JWT verification. On failure, return
null โ never fall back to auth.api.getSession.
- Secrets in env only โ Use
packages/helpers/src/env/manifest.ts (BONDERY_PRIVATE_*, secret: true). No hardcoded keys, tokens, or passwords.
- Public clients never get secrets โ Webapp OAuth client secrets stay server-only. Mobile and extension use PKCE + state validation.
- CORS is not authorization โ Trusted origins (
lib/platform/trusted-origins.ts) control browser cross-origin access, not who can read data.
- Webhooks verify raw bytes โ HMAC/signature validation on the exact request body before parsing (Stripe pattern in
routes/webhooks/stripe.ts).
- 5xx errors are sanitized โ Client sees generic message; details only in server logs (
map-to-response.ts).
- AI tool arguments are untrusted โ Zod-validate and scope to user-owned domain context; model output never grants authority.
- No secrets or PII in logs or client bundles โ Redact tokens, cookies, passwords, and contact PII from structured logs.
Decision tree
| Task | Read |
|---|
| Trust boundaries, route shells, tenant isolation | references/security-architecture.md |
| Better Auth, sessions, API keys, OAuth, client tokens | references/auth-and-sessions.md |
| Input validation, uploads, XSS, errors, public files | references/input-storage-and-output.md |
| Webhooks, WS, AI tools, extension/mobile bridges | references/integrations-and-clients.md |
| Secrets, env, deploy, Redis, supply chain | references/secrets-deployment-and-supply-chain.md |
| Security review process, severity, false positives | references/review-playbook.md |
Full index: references/README.md.
Cross-skill owners: API contracts โ bondery-api; UI error display โ bondery-ux; Prisma schema/migrations (classic) โ bondery-database (Prisma Next โ prisma-next-* via bondery-database/references/prisma-skills.md); generic Postgres indexes/RLS (legacy stack) โ supabase-postgres-best-practices; E2E auth flows โ bondery-e2e-tests; policy/subprocessor disclosure accuracy โ bondery-legal.
Verification commands
Run only what applies to the change:
pnpm run check:types -w api
pnpm run test:auth -w api
pnpm run env -- --check
node deploy/bondery/scripts/check-compose.mjs
pnpm run check:types -w chrome-extension
Known-safe patterns (not bugs)
- API Helmet with CSP disabled โ JSON API, not HTML (
build-app.ts)
- Webapp session cookies use
SameSite=Lax โ required for OAuth redirect flows
- CORS allows requests with no
Origin header โ non-browser clients (trusted-origins.ts)
GET /files/:bucket/* is intentionally unauthenticated โ public avatars/logos by UUID path
- Global rate limit with Redis required in production (
rate-limit.ts)
- Legacy
apps/supabase-db RLS migrations apply only to Supabase stacks โ not the current Prisma API
Security checklist (before merge)