An official website of the Disclosure Foundation

Introduction

Overview

Modules

ObservationShared PrimitivesExtension SlotsCompanions

Guides

Composing an ObservationValidating at Boundaries

Composing an Observation

Build a complete record step by step — from minimal facts to citable evidence

This guide builds a real record from the ground up. The principle throughout: record what you know, omit what you don't. A sparse record is valid; certainty you don't have should never be invented to fill fields.

Start minimal

Only temporal and location are required as input — the factory supplies id, status, and timestamps:

import { createObservation } from '@disclosureos/records/factories';

const obs = createObservation({
  temporal: { date: '1986-11-17', dateCertainty: 'exact' },
  location: {
    name: 'Eastern Alaska airspace',
    country: 'United States',
    latitude: 64.0,
    longitude: -145.0,
    siteType: 'wilderness',
  },
});
// obs.status === 'draft', obs.id is a UUID

Express uncertainty honestly

The temporal model supports the reality of historical data — dates that are approximate, known only to a month or decade, or relative to another event:

temporal: {
  date: '1947-07-01',          // always a full YYYY-MM-DD anchor (sortable)
  dateCertainty: 'approximate',
  dateGranularity: 'month',    // the real precision: "July 1947"
}

The same applies to location (coordinatePrecision, locationSensitivity) and witnesses. dateCertainty: 'exact' is an assertion; make it only when the record supports it.

Add descriptive domains

const obs = createObservation({
  temporal: { date: '1986-11-17', time: '17:11', dateCertainty: 'exact' },
  location: { /* ... */ },
  summary: 'JAL 1628 crew reported two objects and a larger craft shadowing the 747.',
  objectCharacteristics: { shape: 'other', numberObserved: 3 },
  movement: { maneuvers: ['instant_acceleration', 'appear'], radarData: true },
  witnesses: {
    count: 3,
    categories: ['commercial_pilot'],
    aviationWitnesses: true,
  },
  sourceData: {
    primarySource: {
      sourceId: 'faa-jal1628-report',
      type: 'official_report',
      title: 'FAA report on JAL 1628 incident',
      credibility: 'official',
    },
  },
});

Use guards when the values come from outside:

import { isObjectShape } from '@disclosureos/records/guards';

const shape = isObjectShape(row.shape) ? row.shape : undefined;

Attach evidence with citable ids

Sensor readings and media get ids so that claims — yours or another institution's — can cite them later:

import { createSensorReading, createMediaAttachment } from '@disclosureos/records/factories';
import { evidenceRef } from '@disclosureos/records/shared';

const radar = createSensorReading('ground_radar', 'radar_primary', {
  id: 'faa-anchorage-radar',
  operator: 'FAA Anchorage Center',
});

const obs = createObservation({
  // ...
  sensorEvidence: { sensors: [radar] },
});

const RADAR = evidenceRef('sensor', radar.id); // ready for claims

Prefer explicit, stable ids ('faa-anchorage-radar') over generated UUIDs when the record will be published — refs survive better when humans can read them.

Relate records, don't merge them

The same event reported in two catalogs stays two records, linked:

relations: {
  edges: [
    { kind: 'duplicate_of', targetId: 'nuforc-1986-11-17-jal' },
    { kind: 'corroborates', targetId: 'faa-anchorage-radar-1986-11-17' },
  ],
},

The edge vocabulary is typed: corroborates, contradicts, duplicate_of, same_object, supersedes, superseded_by, re_analysis_of, part_of. External catalog ids belong in the identifiers extension slot.

Validate before storing

import { validateObservation } from '@disclosureos/records';

const issues = validateObservation(obs);
if (issues.length > 0) throw new Error(JSON.stringify(issues, null, 2));

When the record gains observable or origin claims, switch to parseEnrichedObservation — see Validating at Boundaries.

Next steps

  • Claim anomalous characteristics on the record
  • Classify origin hypotheses
  • Score the case for completeness and compellingness

Companions

Constants, guards, factories, formatters, and labels for the record lexicon

Validating at Boundaries

Where to validate, which validator to use, and how to handle issues

On this page

Start minimal
Express uncertainty honestly
Add descriptive domains
Attach evidence with citable ids
Relate records, don't merge them
Validate before storing
Next steps