ASPM-lite catalog + quality gate. Catalog applications and services, reconcile scanner Issues with ownership, and enforce a CI quality gate — without replacing SonarQube. Scanners are inputs; Security Center owns catalog, Issues, scores, and the gate.
For a short quickstart, see below. For architecture and how CI, Issues, and the worker fit together, see documentation.md. Deferred work: TODO.md.
| Layer | Choice |
|---|---|
| App | Next.js (App Router) + TypeScript |
| Package manager | pnpm (Corepack-pinned in package.json) |
| UI | Tailwind + shadcn/ui |
| DB | PostgreSQL + Prisma |
| Auth | Auth.js OIDC + bootstrap admin |
| Worker | src/worker — export jobs only |
| Jobs | Postgres FOR UPDATE SKIP LOCKED (no Redis in V1) |
| CI | One curl | bash → GET /api/v1/ci/scan.sh with SC_TOKEN |
V1 tools (run on the CI runner, enabled per app/service in the UI): gitleaks, npm audit, pip-audit, Trivy (fs), semgrep.
No host agent. No server-side clone/scan. Teams replace prior scanner steps with the curl; which tools run is configured in the UI.
pnpm is pinned via Corepack in package.json (packageManager).
corepack enable
pnpm installCompose bind-mounts the repo and uses the Dockerfile dev stage. Dependencies install into a shared node_modules volume (pnpm install --frozen-lockfile).
cp .env.example .env # required — compose loads it via env_file for app + worker
docker compose up --buildApp: http://localhost:3000. Worker shares the same mount. Auth/OIDC come from .env; DATABASE_URL / STORAGE_PATH are overridden for the Compose network.
Dev Container (VS Code / Cursor): open the repo → “Reopen in Container”. That reuses this Compose stack (Postgres + worker), copies .env from .env.example if missing, installs deps, migrates, and seeds. Then in the container terminal:
pnpm run dev --hostname 0.0.0.0 --port 3000Production image (no host node_modules):
docker build --target runner -t security-center:app .
docker build --target worker -t security-center:worker .| Variable | Purpose |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
AUTH_* / OIDC |
Auth.js OIDC provider settings |
BOOTSTRAP_ADMIN_EMAIL |
First admin (matched on OIDC login) |
SC_URL |
Base URL of Security Center (used by CI) |
SC_TOKEN |
Service token for CI (Authorization: Bearer …) |
Exact names may match Auth.js conventions in the app config once scaffolded.
In your pipeline (after checkout), set SC_URL and SC_TOKEN, then:
curl -fsSL -H "Authorization: Bearer $SC_TOKEN" \
"$SC_URL/api/v1/ci/scan.sh" | bashInternally: probe → fetch enabled tools → install/run on the CI runner → ingest → quality gate (exit 0/1). Execution stays on the runner, never on the Security Center host.
| Process | Responsibility |
|---|---|
| App | Catalog, tool toggles, Issues, score/gate, scan.sh, reconcile ingest, enqueue exports |
| Worker | export.issues (CSV/JSON) |
| CI | scan.sh: probe → run enabled tools → ingest → gate |
See LICENSE.