Shared Primitives
Confidence, Attribution, Claim, evidence refs, and validation helpers — the primitives every part reuses
@disclosureos/records/shared is the shared primitive module: the definitions written once so that observables, origins, scoring, and your own code share one vocabulary for confidence, attribution, and validation.
import {
type Confidence, type Claim, type ValidationIssue,
evidenceRef, parseEvidenceRef, createEnumGuard,
} from '@disclosureos/records/shared';Confidence
A number in [0, 1]. 0 is no confidence, 1 is absolute.
import { isConfidence, assertConfidence, asConfidence } from '@disclosureos/records/shared';
isConfidence(0.85); // true — guard
assertConfidence(1.2); // throws — assertion
asConfidence(0.85); // 0.85, typed as Confidence — cast with checkA coarser five-step ConfidenceLevel enum also exists (with CONFIDENCE_LEVELS and isConfidenceLevel) for vocabularies that want named tiers instead of a continuous scale.
Attribution
The "who evaluated this, when, and why" mixin — every assessment surface in the standard composes these fields rather than inventing its own:
interface Attribution {
evaluatedAt?: string; // ISO datetime
evaluatedBy?: string; // person, institution, or pipeline
rationale?: string; // why this assessment was made
}Claim
A Claim is the unit of assessment in DisclosureOS: an Attribution plus the in-record evidence that justifies it.
interface Claim extends Attribution {
evidenceRefs?: string[]; // "sensor:<id>", "media:<id>", ...
}Every evaluative slot in the standard — observableAssessments, origin — holds lists of claims, so contested verdicts coexist with full attribution. Opinion aggregation lives in the scoring layer, never in the record.
Evidence references
Claims point at evidence inside the record using <kind>:<id> strings:
| Kind | Resolves to |
|---|---|
sensor | observation.sensorEvidence.sensors[].id |
media | observation.media[].id / featuredMedia.id |
testimony | observation.testimony[].statementId |
physical | observation.physicalEvidence[].id |
import { evidenceRef, isEvidenceRef, parseEvidenceRef } from '@disclosureos/records/shared';
const ref = evidenceRef('sensor', 'radar-01'); // "sensor:radar-01"
isEvidenceRef(ref); // true
parseEvidenceRef(ref); // { kind: 'sensor', id: 'radar-01' }Refs stay plain strings in the schema so they survive JSON Schema portability; the convention is enforced by the helpers and checked by disclosureos validate, which warns when a claim cites evidence the record doesn't contain.
ValidationIssue
The canonical error shape returned by every validator in every package:
interface ValidationIssue {
path: string; // 'temporal.date', 'origin[0].confidence'
message: string;
}The helpers issuesFrom (Zod error → issues) and validateWith (schema → validator function) let your own validators return the same shape.
Guard builders
import { createEnumGuard, makeGuard } from '@disclosureos/records/shared';
const isStatus = createEnumGuard(['open', 'closed'] as const);
const isPercent = makeGuard(z.number().min(0).max(100));These are the same builders the packages use for their own guards — see The Companion Pattern.
Brands
ObservationId is a branded string for code that wants nominal typing of record ids:
import { asObservationId, type ObservationId } from '@disclosureos/records/shared';
const id: ObservationId = asObservationId('nimitz-tic-tac-2004');