Skip to content
Open
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
6 changes: 3 additions & 3 deletions docs/audit-log-hash-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ npm run migrate
### CLI (operations / CI)

```bash
npm run verify-audit-integrity
npm run verify:audit-integrity
```

- Exit `0` — chain valid
Expand All @@ -54,13 +54,13 @@ npm run verify-audit-integrity
Auditors can verify an exported audit log excerpt against a published cryptographic receipt without running the application server or accessing the database:

```bash
npx ts-node scripts/verify-audit-receipt.ts --receipt <path-or-url-to-receipt> --excerpt <path-or-url-to-excerpt>
npm run verify:audit-receipt -- --receipt <path-or-url-to-receipt> --excerpt <path-or-url-to-excerpt>
```

Or positional format:

```bash
npx ts-node scripts/verify-audit-receipt.ts <receipt.json> <excerpt.json-or-jsonl>
npm run verify:audit-receipt -- <receipt.json> <excerpt.json-or-jsonl>
```

#### Verification Receipt Schema (`AuditReceipt`)
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
"test:coverage": "jest --coverage --runInBand",
"test:coverage:backend-011": "jest --runInBand --coverage src/middleware/rateLimit.test.ts src/middleware/startupAuthRateTierPolicy.test.ts src/routes/health.test.ts --collectCoverageFrom='src/middleware/rateLimit.ts' --collectCoverageFrom='src/middleware/startupAuthRateTierPolicy.ts' --coverageThreshold='{\"global\":{\"statements\":95,\"lines\":95,\"functions\":95}}'",
"audit:ci": "ts-node scripts/audit-gate.ts",
"verify:audit-receipt": "ts-node scripts/verify-audit-receipt.ts",
"verify:audit-integrity": "ts-node src/cli/verifyAuditIntegrity.ts",
"validate:alert-mappings": "ts-node scripts/validate-alert-mappings.ts",
"drill:ttl-check": "ts-node scripts/failover-drill/ttl-check.ts",
"test:watch": "jest --watch",
Expand Down
27 changes: 27 additions & 0 deletions scripts/verify-audit-receipt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,33 @@ describe('verify-audit-receipt script', () => {
});
});

describe('package scripts and fixtures', () => {
it('exposes documented npm entry points for the audit verifier CLIs', () => {
const packageJson = JSON.parse(
fs.readFileSync(path.resolve(__dirname, '..', 'package.json'), 'utf8'),
);

expect(packageJson.scripts['verify:audit-receipt']).toBeDefined();
expect(packageJson.scripts['verify:audit-integrity']).toBeDefined();
});

it('verifies the checked-in audit fixtures as a valid receipt/excerpt pair', async () => {
const actualFs = jest.requireActual('fs') as typeof import('fs');
(fs.promises.readFile as jest.Mock).mockImplementation((filePath: fs.PathOrFileDescriptor) =>
actualFs.promises.readFile(filePath, 'utf8'),
);

const receiptPath = path.resolve(__dirname, 'fixtures', 'audit', 'valid-receipt.json');
const excerptPath = path.resolve(__dirname, 'fixtures', 'audit', 'valid-excerpt.json');

const spy = jest.spyOn(console, 'log').mockImplementation(() => {});
const code = await runCli([`--receipt=${receiptPath}`, `--excerpt=${excerptPath}`]);

expect(code).toBe(0);
expect(spy).toHaveBeenCalledWith(expect.stringContaining('PASS [VALID INTEGRITY PROOF]'));
});
});

describe('parseCliArgs and printHelp', () => {
it('parses flag options', () => {
const opts = parseCliArgs([
Expand Down
4 changes: 4 additions & 0 deletions scripts/verify-audit-receipt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -516,8 +516,12 @@ export function parseCliArgs(args: string[]): CliOptions {
const arg = args[i];
if (arg === '--receipt' || arg === '-r') {
options.receiptPathOrUrl = args[++i];
} else if (arg.startsWith('--receipt=')) {
options.receiptPathOrUrl = arg.slice('--receipt='.length);
} else if (arg === '--excerpt' || arg === '-e' || arg === '--entries') {
options.excerptPathOrUrl = args[++i];
} else if (arg.startsWith('--excerpt=')) {
options.excerptPathOrUrl = arg.slice('--excerpt='.length);
} else if (arg === '--json') {
options.jsonOutput = true;
} else if (arg === '--quiet' || arg === '-q') {
Expand Down
Loading