Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions .cursor/rules/base/env-files.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
description: Environment files — templates, naming, alignment with t3 createEnv
glob: "**/.env.*.example"
alwaysApply: false
---

## Source of truth

- Runtime vars: each app’s `createEnv` in `lib/env.ts` or `src/lib/env.ts` (t3-oss + Zod). Adding/removing a var **requires** updating that schema and the committed template(s) for that app.
- Do not document env vars only in README without a template line.

## Secrets and commits

- **Never** put real API keys, tokens, or production secrets in committed `.env.<qualifier>.example` templates, nor in `.env.development`, `.env.staging`, or `.env.production`. Use obvious placeholders (`sk-ant-xxx`, `your_dynamic_environment_id`).
- `.env`, `.env.local`, and secret-bearing `.env.test` stay gitignored per app; ship `.env.test.example` where tests need a template.

## Naming (templates) — pattern `.env.<qualifier>.example`

- **Canonical glob**: `**/.env.*.example` (Cursor: `@**/.env.*.example`). Filenames must be `.env.` + one qualifier + `.example` (e.g. `defaults`, `local`, `test`). Do **not** add `.env.sample`, `.env-example`, or bare `.env.example`.
- **Fastify API** (`apps/api`): `.env.defaults.example` (copy to `.env`); `.env.test.example` → `.env.test`.
- **Next.js** (`apps/web`, `apps/mathler`): `.env.local.example` (copy to `.env.local`); committed `.env.development` / `.env.staging` / `.env.production` only for non-sensitive defaults (`NEXT_PUBLIC_*`, etc.).
- **Expo** (`apps/mobile`): `.env.defaults.example` with `EXPO_PUBLIC_*`.
- **Docu**: committed `.env.development`; optional `.env.defaults.example` aligned with `lib/env.ts`.
- **Legacy**: `.env.schema` may remain; update `block-secret-files` / gitleaks when renaming templates.

## Next.js section order (web + mathler)

Use the same header order in `.env.local.example` and committed `.env.*`:

1. Short header (what is committed vs local-only).
2. Client / `NEXT_PUBLIC_*` (API URL, auth, logging, legal).
3. Server-only / local secrets (`JWT_SECRET`, etc.) — template only where applicable.
4. E2E / Playwright (`PLAYWRIGHT_APP_URL`, `PLAYWRIGHT_API_URL` on web; unify mathler on the same names; avoid duplicate `BASE_URL` / `PLAYWRIGHT_TEST_BASE_URL` without documented precedence).
5. Optional integrations (Sentry, …).

## Prefix discipline

- Browser-exposed: `NEXT_PUBLIC_*` (Next), `EXPO_PUBLIC_*` (Expo). Do not use unprefixed names for client-only config.
- If `createEnv` expects `NEXT_PUBLIC_LOG_*`, do not use `LOG_*` alone in Next env files.

## API template completeness

- `apps/api/.env.defaults.example` and `.env.test.example` share **the same section headings**; defaults template documents the full `env.ts` surface (optional blocks commented). Tests override a subset via `.env.test`.

## When editing

- After changing any template, verify `pnpm` dev/test for that app still loads `createEnv` without missing/empty required vars.
- Update docs under `apps/docu/` if canonical filenames or copy instructions change.
7 changes: 1 addition & 6 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,7 @@ useDefault = true
description = "Allowlist for test fixtures and example files"
paths = [
'''apps/web/e2e/wallet-setup/.*\.(ts|js|mjs)$''',
'''\.env-example$''',
'''\.env\.example$''',
'''\.env\.test\.example$''',
'''\.env-sample$''',
'''^apps/web/\.env\.local\.example$''',
'''\.env\.sample$''',
'''\.env\.[^/]+\.example$''',
'''\.env\.schema$''',
'''\.env\.test$''',
'''\.github/workflows/.*\.yml$''',
Expand Down
9 changes: 3 additions & 6 deletions .trufflehogignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,10 @@
^\.cursor/skills/.*
^packages/.*/README\.md$

# Example and sample files
.*\.example$
.*\.sample$
.*\.env-example$
.*\.env\.example$
# Committed env templates and defaults (match scripts/block-secret-files.mjs allowlist)
.*\.env\.[^/]+\.example$
.*\.env\.schema$
.*\.env\.test$
.*\.env\.(development|staging|production|test)$

# Test files
.*\.test\.(ts|tsx|js|jsx|mjs)$
Expand Down
63 changes: 0 additions & 63 deletions apps/api/.env-sample

This file was deleted.

98 changes: 98 additions & 0 deletions apps/api/.env.defaults.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Copy to .env and adjust. Placeholders only — never commit real secrets.
# Schema: apps/api/src/lib/env.ts (t3 createEnv)

# -----------------------------------------------------------------------------
# Core
# -----------------------------------------------------------------------------
PORT=3001
HOST=0.0.0.0
# NODE_ENV=development
# CI=false

# -----------------------------------------------------------------------------
# Database (PGLITE=true uses in-memory DB; else DATABASE_URL required)
# -----------------------------------------------------------------------------
PGLITE=false
DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:54322/postgres

# -----------------------------------------------------------------------------
# Ops / limits / logging
# -----------------------------------------------------------------------------
# RATE_LIMIT_MAX=100
# RATE_LIMIT_TIME_WINDOW=60000
# TRUST_PROXY=true
# SECURITY_HEADERS_ENABLED=true
# BODY_LIMIT=1048576
# REQUEST_TIMEOUT=30000
# LOG_LEVEL=info

# -----------------------------------------------------------------------------
# Sentry (optional)
# -----------------------------------------------------------------------------
# SENTRY_DSN=
# SENTRY_ENVIRONMENT=

# -----------------------------------------------------------------------------
# AI (at least one provider path for chat features)
# -----------------------------------------------------------------------------
ANTHROPIC_API_KEY=sk-ant-xxx
# OPEN_ROUTER_API_KEY=sk-or-v1-xxxxxxxxxxxxxxxxxx
# OLLAMA_BASE_URL=http://localhost:11434
# AI_PROVIDER=anthropic
# AI_DEFAULT_MODEL=
# AI_UPSTREAM_TIMEOUT_MS=120000
# BRAVE_SEARCH_API_KEY=

# -----------------------------------------------------------------------------
# JWT / encryption (JWT_SECRET must match Next.js web app)
# -----------------------------------------------------------------------------
JWT_SECRET=default-jwt-secret-min-32-chars-for-dev
# 64 hex chars dev default; must not be all-zero in production
ENCRYPTION_KEY=0000000000000000000000000000000000000000000000000000000000000000
# ACCESS_JWT_EXPIRES_IN_SECONDS=900
# REFRESH_JWT_EXPIRES_IN_SECONDS=604800
# JWT_ISSUER=api.yourapp.com
# JWT_AUDIENCE=api.yourapp.com

# -----------------------------------------------------------------------------
# Email / app identity
# -----------------------------------------------------------------------------
# RESEND_API_KEY=re_placeholder
# EMAIL_FROM=noreply@localhost
# EMAIL_FROM_NAME=App
# APP_NAME=Your App

# -----------------------------------------------------------------------------
# Testing / features
# -----------------------------------------------------------------------------
# ALLOW_TEST=false

# -----------------------------------------------------------------------------
# OAuth — optional (routes return 503 when unset)
# -----------------------------------------------------------------------------
# GITHUB_CLIENT_ID=
# GITHUB_CLIENT_SECRET=
# OAUTH_GITHUB_CALLBACK_URL=http://localhost:3000/auth/callback/oauth/github
# OAUTH_GITHUB_CALLBACK_URLS=http://localhost:3000/auth/callback/oauth/github,yourapp://auth/callback

# GOOGLE_CLIENT_ID=
# GOOGLE_CLIENT_SECRET=
# OAUTH_GOOGLE_CALLBACK_URL=http://localhost:3000/auth/callback/oauth/google
# OAUTH_GOOGLE_CALLBACK_URLS=http://localhost:3000/auth/callback/oauth/google,yourapp://auth/callback

# FACEBOOK_CLIENT_ID=
# FACEBOOK_CLIENT_SECRET=
# OAUTH_FACEBOOK_CALLBACK_URL=http://localhost:3000/auth/callback/oauth/facebook
# OAUTH_FACEBOOK_CALLBACK_URLS=http://localhost:3000/auth/callback/oauth/facebook,yourapp://auth/callback

# TWITTER_CLIENT_ID=
# TWITTER_CLIENT_SECRET=
# OAUTH_TWITTER_CALLBACK_URL=http://localhost:3000/auth/callback/oauth/twitter
# OAUTH_TWITTER_CALLBACK_URLS=http://localhost:3000/auth/callback/oauth/twitter,yourapp://auth/callback

# -----------------------------------------------------------------------------
# CORS / app URLs / auth metadata
# -----------------------------------------------------------------------------
# ALLOWED_ORIGINS=*
# TOTP_ISSUER=
# WEBAUTHN_RP_NAME=
64 changes: 50 additions & 14 deletions apps/api/.env.test.example
Original file line number Diff line number Diff line change
@@ -1,29 +1,65 @@
# Test env - copy to .env.test (gitignored)
# Test env — copy to .env.test (gitignored under apps/api). Placeholders only.
# Section headers match apps/api/.env.defaults.example

# -----------------------------------------------------------------------------
# Core
# -----------------------------------------------------------------------------
NODE_ENV=test
# CI=false

# -----------------------------------------------------------------------------
# Database
# -----------------------------------------------------------------------------
PGLITE=true
DATABASE_URL=postgresql://localhost/test
JWT_SECRET=e2e-jwt-secret-min-32-chars-for-tests

# AI provider: Anthropic (default), Open Router, or Ollama (use .env.test, not committed)
# Unit/E2E tests use Anthropic Sonnet. Set ANTHROPIC_API_KEY for local and CI.
# -----------------------------------------------------------------------------
# Ops / limits / logging
# -----------------------------------------------------------------------------
# RATE_LIMIT_MAX=10000

# -----------------------------------------------------------------------------
# Sentry (optional)
# -----------------------------------------------------------------------------
# SENTRY_DSN=
# SENTRY_ENVIRONMENT=

# -----------------------------------------------------------------------------
# AI
# -----------------------------------------------------------------------------
ANTHROPIC_API_KEY=sk-ant-xxx
# OPEN_ROUTER_API_KEY=sk-or-v1-xxxxxxxxxxxxxxxxxx
# OPEN_ROUTER_API_KEY=
# OLLAMA_BASE_URL=http://localhost:11434

# Optional: Override default AI model (Claude Sonnet 4)
# AI_DEFAULT_MODEL=claude-sonnet-4-20250514

# Optional: GitHub OAuth (for OAuth route tests)
# -----------------------------------------------------------------------------
# JWT / encryption
# -----------------------------------------------------------------------------
JWT_SECRET=e2e-jwt-secret-min-32-chars-for-tests
# ENCRYPTION_KEY=0000000000000000000000000000000000000000000000000000000000000000

# -----------------------------------------------------------------------------
# Email / app identity
# -----------------------------------------------------------------------------
# RESEND_API_KEY=
# EMAIL_FROM=
# APP_NAME=

# -----------------------------------------------------------------------------
# Testing / features
# -----------------------------------------------------------------------------
# ALLOW_TEST=false

# -----------------------------------------------------------------------------
# OAuth (optional — for OAuth route tests)
# -----------------------------------------------------------------------------
# GITHUB_CLIENT_ID=
# GITHUB_CLIENT_SECRET=
# OAUTH_GITHUB_CALLBACK_URL=http://localhost:3000/auth/callback/oauth/github

# CORS + URL allowlist. Default: * (any). Comma-separated origins to restrict.
# -----------------------------------------------------------------------------
# CORS / app URLs / auth metadata
# -----------------------------------------------------------------------------
# ALLOWED_ORIGINS=https://app.example.com,https://localhost:3000

# Passkey and TOTP tests (unit tests)
WEBAUTHN_RP_NAME=Test App
TOTP_ISSUER=Test App

# Rate limit (unit tests make many requests; default 100 is too low)
# RATE_LIMIT_MAX=10000
2 changes: 1 addition & 1 deletion apps/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Type-safe REST API built with Fastify & OpenAPI. Routes in `src/routes/` are the

## Development

Start database first (`pnpm db:start`), then `pnpm dev`. Uses Supabase CLI for PostgreSQL, or `PGLITE=true` for in-memory. Dev server at [http://localhost:3000](http://localhost:3000).
Copy [`.env.defaults.example`](.env.defaults.example) to `.env` and set values (gitignored). Start database first (`pnpm db:start`), then `pnpm dev`. Uses Supabase CLI for PostgreSQL, or `PGLITE=true` for in-memory. Dev server at [http://localhost:3000](http://localhost:3000).

## Vercel

Expand Down
11 changes: 11 additions & 0 deletions apps/docu/.env.defaults.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Copy to .env.local if needed. Schema: apps/docu/lib/env.ts

# -----------------------------------------------------------------------------
# Client (NEXT_PUBLIC_*)
# -----------------------------------------------------------------------------
NEXT_PUBLIC_SITE_URL=https://docs.basilic.dev

# -----------------------------------------------------------------------------
# Server (local dev)
# -----------------------------------------------------------------------------
PORT=3002
4 changes: 3 additions & 1 deletion apps/docu/.env.development
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
PORT=3002
# Docu dev server — committed, non-sensitive. Schema: apps/docu/lib/env.ts
PORT=3002
NEXT_PUBLIC_SITE_URL=https://docs.basilic.dev
6 changes: 3 additions & 3 deletions apps/docu/content/docs/architecture/security.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Pre-commit hooks run automatically via `simple-git-hooks` when you attempt to co

The following file patterns are blocked from being committed:

- `.env` (but `.env-example`, `.env.schema`, `.env.development`, `.env.staging`, `.env.production`, `.env.test` are allowed)
- `.env` (but `.env.<qualifier>.example` templates such as `.env.defaults.example` / `.env.local.example`, `.env.schema`, `.env.development`, `.env.staging`, `.env.production`, `.env.test` are allowed)
- `*.pem`, `*.key`, `*.p12`, `*.pfx`, `*.jks`, `*.keystore`
- `id_rsa*` (SSH private keys)
- Certificate files: `*.crt`, `*.cer`, `*.der`, `*.p7b`, `*.p7c`, `*.p7m`, `*.p7s`
Expand Down Expand Up @@ -199,7 +199,7 @@ git reset HEAD~1
### 3. Prevent Future Incidents

- Use `.env` files for secrets (never commit them)
- Use `.env-example` or `.env.schema` for templates
- Use `.env.<qualifier>.example` (e.g. `.env.defaults.example`, `.env.local.example`) or `.env.schema` for templates
- Review staged files before committing: `git diff --cached`
- Run `pnpm security:secrets` before committing

Expand Down Expand Up @@ -268,7 +268,7 @@ If CI detects secrets:
## Best Practices

1. **Never commit secrets** - Use `.env` files and environment variables
2. **Use `.env-example`** - Provide templates for required environment variables
2. **Use `.env.<qualifier>.example`** - Provide templates for required environment variables (see `apps/api/.env.defaults.example`, `apps/web/.env.local.example`)
3. **Review before committing** - Check `git diff --cached` before committing
4. **Rotate secrets regularly** - Even if not exposed, rotate secrets periodically
5. **Use secret management** - Consider using tools like HashiCorp Vault, AWS Secrets Manager, etc. for production
Expand Down
2 changes: 1 addition & 1 deletion apps/docu/content/docs/development/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Setup runs install, git hooks, security tools, and database. See the root README

### 2. Environment variables

- copy fastify/.env-sample over to fastify/.env and update the values
- copy `apps/api/.env.defaults.example` to `apps/api/.env` and update the values

### 3. Explore the Running Apps

Expand Down
2 changes: 1 addition & 1 deletion apps/docu/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"fumadocs-ui": "16.6.0",
"lucide-react": "^0.564.0",
"mermaid": "^11.12.2",
"next": "16.1.6",
"next": "16.1.7",
"next-themes": "^0.4.6",
"react": "^19.2.4",
"react-dom": "^19.2.4",
Expand Down
Loading
Loading