Security here means baseline hygiene the scaffold encodes—not a certification.
Input and API
- tRPC procedures use Zod (or shared validators) at boundaries
- Prefer policy checks for authorization—not “security by obscurity” routes
- Keep server-only code out of client bundles via package exports
Secrets and env
.env.examplelists required keys;serverEnvvalidates at boot inpackages/backend-common- Never commit
.envwith production secrets - Rotate
BETTER_AUTH_SECRETif leaked
Transport
- Production: HTTPS everywhere; align
FRONTEND_URLandBETTER_AUTH_URLwith real origins - CORS is configured on the API for the web origin—update when adding staging domains
Dependencies
- Run your package manager’s audit in CI (
bun run ciincludes lint/typecheck; add audit if your team requires it) - Pin catalogs via workspace catalog files when using Bun/pnpm
Agents
Generated repos include agent maps—not extra attack surface, but do not paste production secrets into agent chats. Use .env locally and platform secret stores in deploy hosts.
Reporting
This is a personal/template project. For production apps you ship, follow your own disclosure process.
Demo endpoints (/live)
The live sandbox (proof run, chat, posts) is intentionally public for evaluation. Treat it as demo-only.
| Procedure | Auth | Public data | Notes |
|---|---|---|---|
hello | No | Greeting string | Harmless contract check |
post.list | No | Published posts only | Drafts filtered server-side |
post.create | Yes | — | Draft only; max title/content lengths |
chat.list | No | Messages + redacted sender (id, name, image) | No email in JSON |
chat.stats | No | Message count + latest timestamp | Activity strip metadata |
chat.send | Yes | — | Max 280 chars; visible to all readers |
GET /api/chat/stream | No | SSE message events | Heartbeat every 30s; rate limited |
auth.getSession | No | Session user or null | No secrets |
auth.getSecretMessage | Yes | Protected string | Proof-run only |
user.findUserByEmail | Yes | Self email only | Returns public user shape |
SSE: One-way push from the API after chat.send. Clients invalidate chat.list on events; polling is the fallback when the stream drops (e.g. cold starts).
Before production: remove /live, demo auth pages, and seed chat messages—or restrict these procedures behind admin policy. Run template-cleanup --remove=live on generated projects.