Scaffolds the project: Next.js 16 App Router with strict TypeScript, Prisma 7 on PostgreSQL 16, Tailwind 4, Vitest, Playwright, CI, and a standalone Docker image that applies migrations on boot. Makes the no-tracker rule of PLAN.md 3.7 enforceable rather than stated. A per-request nonce-based CSP names no external origin, a unit test fails if any network directive gains one, and a second test fails if a tracking package appears in package.json. The end-to-end test drives the standalone server the Docker image runs, not `next dev`, so a proxy matcher that stopped matching could not pass unnoticed. Environment is validated at import, so a missing DATABASE_URL fails at boot with a readable message instead of surfacing later as a driver error mid-export. ENCRYPTION_KEY is checked to be 32 bytes. Three deviations from the plan, recorded in PLAN.md and README: Next 16 rather than 15, `proxy.ts` rather than the now-deprecated `middleware.ts`, and database-backed sessions rather than Auth.js v5, which is still beta and whose JWTs would make the session revocation required by compliance item 23 awkward. Verified locally against PostgreSQL 16: migrations apply, extensions created, typecheck, lint, 9 unit tests and the end-to-end header test all pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Cr9dkEHwbDgkWPnyGj1Rjv
66 lines
1.6 KiB
TypeScript
66 lines
1.6 KiB
TypeScript
import { readFileSync } from 'node:fs';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
import { describe, expect, it } from 'vitest';
|
|
|
|
/**
|
|
* PLAN.md §3.7 bans analytics and advertising dependencies outright.
|
|
*
|
|
* The CSP stops such a package at runtime; this stops it at review time, with a
|
|
* message that says why. The audited product carried ten of these, so the
|
|
* failure mode is not hypothetical — it is what happens when nobody is looking.
|
|
*/
|
|
const BANNED = [
|
|
'segment',
|
|
'@segment/',
|
|
'analytics-node',
|
|
'react-ga',
|
|
'gtag',
|
|
'google-analytics',
|
|
'mixpanel',
|
|
'amplitude',
|
|
'hotjar',
|
|
'clarity-js',
|
|
'satismeter',
|
|
'fullstory',
|
|
'logrocket',
|
|
'bugsnag',
|
|
'sentry',
|
|
'datadog',
|
|
'posthog',
|
|
'heap-analytics',
|
|
'intercom',
|
|
];
|
|
|
|
interface PackageJson {
|
|
dependencies?: Record<string, string>;
|
|
devDependencies?: Record<string, string>;
|
|
}
|
|
|
|
describe('dépendances', () => {
|
|
const packageJson: PackageJson = JSON.parse(
|
|
readFileSync(
|
|
fileURLToPath(new URL('../../package.json', import.meta.url)),
|
|
'utf8',
|
|
),
|
|
);
|
|
|
|
const installed = [
|
|
...Object.keys(packageJson.dependencies ?? {}),
|
|
...Object.keys(packageJson.devDependencies ?? {}),
|
|
];
|
|
|
|
it('ne contient aucun traceur publicitaire ou analytique', () => {
|
|
const offenders = installed.filter((name) =>
|
|
BANNED.some((banned) => name.toLowerCase().includes(banned)),
|
|
);
|
|
|
|
expect(
|
|
offenders,
|
|
'PLAN.md §3.7 interdit les traceurs tiers dans une application RH. ' +
|
|
"Pour de la télémétrie technique, passer par l'interface abstraite " +
|
|
'auto-hébergée plutôt que par un service externe.',
|
|
).toEqual([]);
|
|
});
|
|
});
|