An official website of the Disclosure Foundation

Introduction

Quick StartWhat is DisclosureOS?Installation

Concepts

Tour of the APIThe Companion PatternType Safety & Validation

API

API Reference

Guides

Data MigrationField Mapping ReferenceSupabase IntegrationBuilding on the StandardContributing

The Companion Pattern

Deep dive into the five companion exports: constants, guards, factories, formatters, and labels. One pattern across every layer.

Every vocabulary in DisclosureOS follows the same pattern: a type plus five kinds of companions. Learning this once lets you use the entire API — the pattern holds in records, observables, and origins alike.

The five companions

CompanionPurposeExample
ConstantsValid values as arraysTIMES_OF_DAY → ['dawn', 'morning', ...]
GuardsRuntime type narrowingisTimeOfDay(value) → value is TimeOfDay
FactoriesCreate with defaults + validationcreateTemporalData({ date: '2004-11-14' })
FormattersHuman-readable stringsformatTemporalData(temporal)
LabelsValue → display nameTIME_OF_DAY_LABELS['morning'] → "Morning"

Worked example: TimeOfDay

example.ts
import {
  TIMES_OF_DAY,
  TIME_OF_DAY_LABELS,
  isTimeOfDay,
  createTemporalData,
  formatTemporalData,
} from '@disclosureos/records';

// Constants — build a dropdown
const options = TIMES_OF_DAY.map((v) => ({
  value: v,
  label: TIME_OF_DAY_LABELS[v],
}));

// Guard — validate form or API input
const raw: unknown = formData.get('timeOfDay');
const timeOfDay = isTimeOfDay(raw) ? raw : undefined;

// Factory — create a validated temporal object
const temporal = createTemporalData('2004-11-14', 'exact', { timeOfDay });

// Formatter — display in UI
console.log(formatTemporalData(temporal));

The same pattern appears for source credibility, object shapes, location sensitivity, observable assessment levels, origin domains, and every other enum in the standard. Constants for options, guards for validation, factories for creation, formatters for display, labels for dropdowns and tables.

Claims have factories too

The pattern extends beyond enums. The evaluation layers ship claim factories that validate on construction:

import { createObservableClaim } from '@disclosureos/observables';
import { createOriginClaim } from '@disclosureos/origins';

const claim = createObservableClaim('measured', { confidence: 0.7 });
// throws if confidence is out of [0, 1]

const hypothesis = createOriginClaim('1.1.3', 0.4, {
  rationale: 'Performance exceeds known aerospace capability.',
});
// throws if the OCS node id is unknown

Factories parse their output against the schema — what they return is guaranteed valid.

Barrel vs. subpath imports

You can import from the barrel or from subpaths:

imports.ts
// Barrel
import { isTimeOfDay, TIMES_OF_DAY } from '@disclosureos/records';

// Subpaths
import { isTimeOfDay } from '@disclosureos/records/guards';
import { TIMES_OF_DAY } from '@disclosureos/records/constants';
import { TIME_OF_DAY_LABELS } from '@disclosureos/records/labels';

Use subpaths when you want tighter imports and only need a subset of the API.

Building custom guards

The shared primitives module exports the helpers the packages use internally, so your own vocabularies can follow the same pattern:

guards.ts
import { createEnumGuard, makeGuard } from '@disclosureos/records/shared';
import { z } from 'zod';

// From a values array
const REVIEW_STATES = ['queued', 'in_review', 'done'] as const;
const isReviewState = createEnumGuard(REVIEW_STATES);

// From any Zod schema
const isPercent = makeGuard(z.number().min(0).max(100));

Next steps

  • Type Safety & Validation — compile-time types, runtime guards, and where to validate
  • Records — Companions — the full companion reference for the core lexicon
  • Observables — assessment levels and their companions

Tour of the API

The mental model: one Observation, augmented slots, claims, and companions

Type Safety & Validation

Compile-time types, runtime validation, the extension point, and the strip hazard

On this page

The five companions
Worked example: TimeOfDay
Claims have factories too
Barrel vs. subpath imports
Building custom guards
Next steps