Skip to content

Shapes

Every boundary has a shape, built with t. Shapes exist at runtime, so the tool can check contracts across files without imports.

Shape Meaning
t.string, t.int, t.number, t.boolean, t.literal(v), t.enum(...) Primitives. t.int accepts only safe integers (Number.isSafeInteger).
t.text(64) A string of at most 64 chars; the issue never echoes the value. Use it for free text from callers.
t.object({...}), t.array(s), t.optional(s), t.nullable(s) Structure; objects strip unknown fields.
t.array(s, { max: 20 }) At most 20 items.
t.pattern(re, message, of?) A string matching the regex. Over caller input, bound it first: t.pattern(re, message, t.text(30)) (ATLAS028 warns otherwise: ReDoS).
t.record(t.string) String keys, every value of one shape (translations). The keys __proto__, constructor and prototype are rejected.
t.normalized(shape, fn) A pure, idempotent string transform applied before shape parses.
t.variant('kind', { physical: t.object({ lat: t.number }), virtual: t.object({}) }) A discriminated union; keeps the tag in the value.
t.sensitive(s) Parses like s; may live in records and command inputs, never in facts, sent commands or views.
t.fact(n, shape, ...steps) / t.versioned(...) A versioned fact or record with upcasters (see Facts).

Invalid input is a rejection with the exact path (invalid-input), never a crash.

atlas check ATLAS003 compares producer and consumer: every case the producer may produce must satisfy the consumer.

  • A consumer variant must handle each produced case (same tag; extra cases are fine) with the fields that case needs; a plain consumer may only require fields every case has.
  • A consumer t.pattern is satisfied only by the same pattern (or literals and enum values matching it).
  • A consumer max (t.text, t.array(s, { max })) is satisfied only by a producer with a max no larger; a producer without a max does not guarantee one.

JSON Schema (atlas schema) carries bounds as maxLength and maxItems.

Capabilities may import from the sibling shapes/ folder (../shapes/handle.ts), so one rule lives in one place. A shapes module imports only the runtime and other shapes modules, and exports only shapes (ATLAS018).