- Next.js 15 app (App Router) written in TypeScript
- PostgreSQL database accessed via Drizzle ORM
- OC images stored in MinIO (S3-compatible)
- Backend APIs live under
/api/v1
- Node.js ≥ 20 (check with
node -v) - pnpm ≥ 9 (check with
pnpm -v) - Docker (for Postgres/MinIO)
macOS/Linux:
git clone https://github.com/your-org/e-dossier.git
cd e-dossierWindows (PowerShell):
git clone https://github.com/your-org/e-dossier.git
cd e-dossier
⚠️ Git hooks may not be configured automatically on every machine after clone. After cloning, runpnpm install(this repository runs apostinstallthat configures hooks), or runpnpm run setup:git-hooksmanually to enable the hooks.
pnpm installmacOS/Linux/Windows (All Terminals):
# Verify hooks are configured (if not, run the setup command below)
git config core.hooksPath
# If configured, output should be: .githooks
# List the hooks
ls -la .githooks/
# Should show: pre-push, post-checkout, .gitkeepWindows (PowerShell alternative):
git config core.hooksPath
# Should output: .githooks
dir .\.githooks\
# Should show: pre-push, post-checkout, .gitkeepgit checkout -b feature/my-feature
# Make your changes...
git add .
git commit -m "feat: add something"
git push origin feature/my-feature
# ✅ Hooks automatically run: lint → typecheck → build
# If any checks fail, fix errors and push againIf you're already working on this project, pull master to get the updated hooks:
git pull origin master
# → post-checkout hook runs
# → Hooks are ready for your next push
git checkout -b feature/whatever
git push origin feature/whatever
# ✅ Hooks automatically enforce qualityIf hooks don't trigger on push, the quickest fixes are:
- Run the setup script installed by
postinstall:
pnpm install
# or run the setup directly:
pnpm run setup:git-hooks- Manual commands (if you prefer not to run the script):
# macOS / Linux
git config core.hooksPath .githooks
chmod +x .githooks/pre-push .githooks/post-checkout || true
# Windows (PowerShell)
git config core.hooksPath .githooks
git update-index --add --chmod=+x .githooks/pre-push .githooks/post-checkoutFor more details, see CONTRIBUTING.md. For token-based UI color rules, see THEMING_GUIDE.md.
This repository enforces automatic quality checks on every git push to ensure code quality across all branches.
When you run git push, the pre-push hook automatically:
- ✓ Verifies dependencies are locked (
pnpm-lock.yamlexists) - ✓ Checks Node.js and pnpm versions meet requirements
- ✓ Runs
pnpm run lint(ESLint) - ✓ Runs
pnpm run typecheck(TypeScript type checking) - ✓ Runs
pnpm run build(production build validation)
If any check fails, the push is blocked and errors are shown. Fix issues locally and push again.
Git hooks auto-configure automatically:
- After
git clone(viapost-checkouthook) - Before first
git push(viapre-pushhook auto-setup)
Just clone and push—no manual setup needed!
git clone https://github.com/your-org/e-dossier.git
cd e-dossier
pnpm install
git checkout -b feature/my-feature
git push origin feature/my-feature # Hook auto-configures and runs verificationIf hooks don't run:
# macOS/Linux
bash scripts/setup-git-hooks.sh
# Windows (PowerShell)
powershell -ExecutionPolicy Bypass -File scripts/setup-git-hooks.ps1For detailed setup and troubleshooting, see CONTRIBUTING.md.
- App env:
.env.development.example.env.qa.example.env.production.example
- Data VM env:
deploy/.env.data.dev.exampledeploy/.env.data.qa.exampledeploy/.env.data.production.example
- Base template:
.env.example
- Dev: Next app + Postgres + MinIO on one machine
- QA: Next app on VM-1, Postgres + MinIO on VM-2 (private network)
- Production: Same as QA with production secrets, backups, and monitoring
- Install dependencies:
pnpm install. - Configure app env:
cp .env.development.example .envand update secrets. - Start Postgres + MinIO:
cp deploy/.env.data.dev.example deploy/.env.datadocker compose -f deploy/docker-compose.data.yml --env-file deploy/.env.data up -d
- Run migrations:
pnpm db:migrate. - (Optional) Seed admins:
pnpm seed:admins. - Verify services:
pnpm run check. - Start dev server:
pnpm devand openhttp://localhost:3000.
Note: If you want to use a hosted DB in dev, update DATABASE_URL in .env.
VM-2 (Data: Postgres + MinIO)
cp deploy/.env.data.qa.example deploy/.env.dataand set strong credentials.- Start services:
docker compose -f deploy/docker-compose.data.yml --env-file deploy/.env.data up -d. - Firewall: allow only VM-1 to reach ports 5432/9000. Do not expose MinIO console (9001).
VM-1 (App)
pnpm install.cp .env.qa.example .envand set:DATABASE_URL=postgresql://...@<VM-2-IP>:5432/...MINIO_ENDPOINT=<VM-2-IP>MINIO_PUBLIC_URL=https://qa.example.com/media(or CDN URL)
pnpm db:migrate.- Start app:
pnpm start(or your QA process manager).
VM-2 (Data: Postgres + MinIO)
cp deploy/.env.data.production.example deploy/.env.dataand set production secrets.- Start services:
docker compose -f deploy/docker-compose.data.yml --env-file deploy/.env.data up -d. - Backups:
- Postgres: nightly
pg_dump+ WAL archiving. - MinIO:
mc mirrorto a separate disk or off-site target.
- Postgres: nightly
- Firewall: allow only VM-1 to reach ports 5432/9000. Do not expose MinIO console (9001).
VM-1 (App) Recommended for air-gapped / customer-hosted installs:
- Build a runtime-only artifact on your trusted build machine:
pnpm install --frozen-lockfilepnpm buildpnpm run package:runtime
- Transfer
.artifacts/runtime/e-dossier-runtime.tar.gzto the App VM. - Follow AIRGAP_RUNTIME_DEPLOYMENT.md.
Legacy source-checkout flow:
pnpm install.cp .env.production.example .envand set:DATABASE_URL=postgresql://...@<VM-2-IP>:5432/...MINIO_ENDPOINT=<VM-2-IP>MINIO_PUBLIC_URL=https://your-domain.example/media(or CDN URL)
pnpm db:migrate.- Build and run:
pnpm buildpnpm start(or run via systemd/pm2)
- Proxy
/media/on VM-1 tohttp://<VM-2-IP>:9000/. - If images are served from a different domain, add it to CSP
img-srcinnext.config.ts.
- Kinds:
CIVIL_DRESS,UNIFORM - Flow: presign -> upload -> complete
- Size limits: 20 KB to 200 KB
- Detailed API notes:
docs/oc-images.md
pnpm run checkverifies Postgres and MinIO connectivity.- If schema changes:
pnpm db:generatethenpnpm db:migrate.
Use this when db:migrate fails due to migration-history mismatch (for example, already exists errors).
- List migration tags:
pnpm run db:baseline:list
- Run safe auto-repair baseline:
pnpm run db:baseline
- Apply pending migrations:
pnpm run db:migrate
If auto-repair finds nothing, use explicit baseline and rerun migrate:
pnpm run db:baseline -- --tag 0019_same_meteoritepnpm run db:migrate
Use this flow after RBAC/action-map changes and after pnpm db:push.
- Seed permissions from parsed matrix:
pnpm seed:permissions
- Optional alternative import command (use if you want explicit parsed-matrix path control):
pnpm import:permissions- Example with explicit path:
pnpm import:permissions docs/rbac/permission-matrix.parsed.json
- Seed admins only if this environment needs admin bootstrap:
pnpm seed:admins
- Validate action-map coverage:
pnpm run validate:action-map
- Full verification:
pnpm lint && pnpm typecheck && pnpm test && pnpm build
Use this to initialize Physical Training and Camp template defaults in a new environment.
Recommended sequence on fresh setup:
pnpm db:migratepnpm seed:rbacpnpm seed:permissionspnpm seed:adminspnpm seed:org-template -- --module=ptpnpm seed:org-template -- --module=camp
Preview without writing:
pnpm seed:org-template -- --module=pt --dry-runpnpm seed:org-template -- --module=camp --dry-run