Paul HittandClaude Opus 5.5 03c8e4e4da Tell npm where the @extant2000 scope lives before installing
The package is on the GitLab registry, and a bare npm install looks on
npmjs.org and fails. The install section now sets the scope's registry
first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 16:44:36 -04:00
2026-09-28 14:46:17 -04:00
2026-09-28 14:46:17 -04:00
2026-09-28 14:46:17 -04:00
2026-09-28 14:46:17 -04:00
2026-09-28 14:46:17 -04:00
2026-09-28 14:46:17 -04:00
2026-09-28 14:46:17 -04:00
2026-09-28 14:46:17 -04:00
2026-09-28 14:46:17 -04:00
2026-09-28 14:46:17 -04:00
2026-09-28 14:46:17 -04:00

@extant2000/evidence-record

A small vocabulary for checks that have to show their work: four-way determinations, cited evidence, and reports that derive their own verdict.

Zero runtime dependencies. Pure functions. Ships ESM and CommonJS.

Why it exists

Automated checks tend to fail their readers in the same few ways. This package gives every check one shared way to avoid them.

  1. A boolean hides the case that matters most. passed: true can mean "we looked and it held" or "there was nothing to look at". Those need to stay apart, so a determination has four values, and three of them are not a pass.
  2. Findings that do not say where they came from ask the reader to take them on trust. Every finding here carries Evidence: a file and line, a database row, a command, a measurement, or a document.
  3. A measurement without its sample count is not evidence. An availability of 100% over zero samples and one over 8,640 samples are different claims, so the sample count travels with the number.
  4. A report with zero findings is not a pass unless something was examined. The verdict is computed from the report, and examined === 0 always gives not-assessed.

The unflattering outputs stay unflattering. A missing value is not a pass, and nothing in this package turns one into a pass.

Determinations

type Determination = 'pass' | 'fail' | 'not-applicable' | 'not-assessed'

rollUp combines several. Any fail wins. An empty list is not-assessed, because [].every(...) being true is the trap this type closes. One unassessed item keeps the roll-up at not-assessed, so healthy items cannot dilute it.

rollUp([])                          // 'not-assessed'
rollUp(['pass', 'not-assessed'])    // 'not-assessed'
rollUp(['pass', 'pass', 'fail'])    // 'fail'

label(d) gives a short badge (MET, NOT MET, N/A, NOT ASSESSED). describe(d, subject) gives a sentence that still makes sense when pasted into an email on its own.

Evidence

import { evidence, cite, describeMeasurement } from '@extant2000/evidence-record'

evidence.file('docker-compose.yml', 42, 'ports: ["2222:22"]')
evidence.record('requirements', 'a1b2c3', 'parent_id', 'null')
evidence.command('docker compose config', 0)
evidence.measurement('uptime', null, 0, { unit: '%', window: '2026-07' })
evidence.document('NIST SP 800-53 Rev 5', 'AC-2')

cite() renders each kind in the form people already read it in: path:line for source, table#id (field) for rows, $ command → exit 0 for commands. citeVerbose() adds the excerpt and note. describeMeasurement() reads the null case out loud: "No samples for Availability in 2026-07; it cannot be computed."

Reports

import { evidence, overall, validateReport, formatReport } from '@extant2000/evidence-record'

const report = {
  capability: 'PortCheck',
  scope: '12 compose services',
  examined: 12,
  findings: [
    { id: 'f1', summary: 'SSH published on a host port', determination: 'fail',
      severity: 'critical', evidence: [evidence.file('docker-compose.yml', 42, 'ports: ["2222:22"]')] },
    { id: 'f2', summary: 'Admin UI bound to loopback only', determination: 'pass',
      severity: 'info', evidence: [evidence.file('docker-compose.yml', 88)] },
  ],
}

overall(report)          // 'fail', computed from the findings
validateReport(report)   // [] when every conclusion carries a citation
formatReport(report)     // worst first, one citation per finding

Output of formatReport(report):

PortCheck — 12 compose services
  NOT MET  ·  12 items examined  ·  2 findings

✗ CRITICAL SSH published on a host port   [NOT MET]
             evidence: docker-compose.yml:42
◦ info     Admin UI bound to loopback only   [MET]
             evidence: docker-compose.yml:88

The same report with nothing examined:

PortCheck — no services found
  NOT ASSESSED  ·  0 items examined  ·  0 findings

  PortCheck's scope was not assessed. This is not a pass — an unassessed control is not an implemented control.

validateReport flags a finding that reaches pass, fail or not-applicable with no evidence, plus duplicate ids and empty summaries. A not-assessed finding may have no evidence, since having nothing to cite is what it reports. formatReport accepts { evidence: 'inline' | 'full' | 'none', minSeverity }. formatRollUp(reports) gives one line per report and a combined verdict, where an unrun report pulls the total to not-assessed.

Conformance

A check built on this package conforms when its own tests assert that:

  • validateReport(report) is empty for every report it can produce;
  • an empty input produces not-assessed, and the rendered output contains neither ✓ nor the word "clean";
  • every fail finding carries at least one Evidence;
  • the rendered output of a failure names a file, a row, or a command.

Install

The package is published to the GitLab package registry, so point the @extant2000 scope there first:

npm config set @extant2000:registry https://gitlab.com/api/v4/packages/npm/
npm install @extant2000/evidence-record

License

MIT. Copyright (c) 2026 Extant 2000 LLC.

S
Description
A shared format for checks that cite their evidence.
Readme MIT
53 KiB
Languages
TypeScript 100%