73 lines
2.5 KiB
JavaScript
73 lines
2.5 KiB
JavaScript
import { readFile, stat } from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
import { fail, pass, repositoryRoot } from './lib.mjs';
|
|
|
|
const failures = [];
|
|
const requiredFiles = [
|
|
'src/app/api/demo/route.ts',
|
|
'src/components/integrations/DemoDialogHost.tsx',
|
|
'src/lib/demo/schema.ts',
|
|
'src/lib/demo/service.ts',
|
|
'src/lib/demo/idempotency.ts',
|
|
'src/lib/demo/adapters/types.ts',
|
|
'src/lib/demo/adapters/local.ts',
|
|
'src/lib/demo/adapters/blocked.ts',
|
|
'src/lib/integrations/destinations.ts',
|
|
'src/lib/integrations/environment.ts',
|
|
'src/lib/integrations/feature-flags.ts',
|
|
'src/lib/analytics/events.ts',
|
|
'src/lib/analytics/client.ts',
|
|
'docs/phase14/INTEGRATION_TRACEABILITY_MATRIX_v1.0.csv',
|
|
'docs/phase14/DATA_FLOW_INVENTORY_v1.0.csv',
|
|
'docs/phase14/RELEASE_GATE_MATRIX_v1.0.csv',
|
|
];
|
|
for (const file of requiredFiles) {
|
|
try {
|
|
const details = await stat(path.join(repositoryRoot, file));
|
|
if (!details.isFile()) failures.push(`${file}: not a file.`);
|
|
} catch {
|
|
failures.push(`${file}: missing.`);
|
|
}
|
|
}
|
|
|
|
const schema = await readFile(path.join(repositoryRoot, 'src/lib/demo/schema.ts'), 'utf8');
|
|
for (const field of ['fullName', 'workEmail', 'company', 'fleetSize', 'idempotencyKey', 'source']) {
|
|
if (!schema.includes(`${field}:`)) failures.push(`Demo schema is missing ${field}.`);
|
|
}
|
|
if (!schema.includes('.strict()'))
|
|
failures.push('Demo transport schemas must reject unknown fields.');
|
|
if (schema.includes('phone:'))
|
|
failures.push('Unapproved phone field was added to the demo contract.');
|
|
|
|
const destinations = await readFile(
|
|
path.join(repositoryRoot, 'src/lib/integrations/destinations.ts'),
|
|
'utf8',
|
|
);
|
|
for (const issue of ['P9-002', 'P9-003', 'P9-004', 'P9-008', 'P9-012', 'P9-014', 'P9-015']) {
|
|
if (!destinations.includes(issue))
|
|
failures.push(`Destination registry does not preserve ${issue}.`);
|
|
}
|
|
if (/href:\s*['"]https?:\/\//.test(destinations)) {
|
|
failures.push('Destination registry contains an unapproved hard-coded external URL.');
|
|
}
|
|
|
|
for (const locale of ['en', 'fr', 'ar']) {
|
|
const catalog = JSON.parse(
|
|
await readFile(
|
|
path.join(repositoryRoot, `src/content/locales/${locale}/homepage.json`),
|
|
'utf8',
|
|
),
|
|
);
|
|
if (!catalog.form || catalog.form.fleetOptions?.length !== 7) {
|
|
failures.push(
|
|
`${locale}: demo form fleet options do not match the approved six-value contract.`,
|
|
);
|
|
}
|
|
}
|
|
|
|
if (failures.length) fail(failures);
|
|
else
|
|
pass(
|
|
'Phase 14 integration structure, form contract, destinations, and locale resources are present.',
|
|
);
|