> ## Documentation Index
> Fetch the complete documentation index at: https://invariant-cad.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Documents and migrations

> Serialize, parse, validate, clone, hash, and migrate versioned InvariantCAD documents.

## Complete executable lifecycle

This canonical module migrates a frozen v1 document, serializes it
canonically, reparses the bytes through validation, proves the round trip is
stable, and computes its semantic SHA-256.

```ts theme={"system"}
import {
  DOCUMENT_SCHEMA_V1,
  DOCUMENT_VERSION,
  hashDocument,
  migrateDocument,
  parseDocument,
  stringifyDocument,
  type CadResult,
} from "invariantcad";

function valueOrThrow<T>(result: CadResult<T>): T {
  if (!result.ok) {
    throw new Error(
      result.diagnostics.map((item) => item.message).join("\n"),
    );
  }
  return result.value;
}

const legacyDocument = {
  schema: DOCUMENT_SCHEMA_V1,
  version: 1,
  name: "legacy-box",
  units: { length: "mm", angle: "rad" },
  parameters: {},
  nodes: {
    box: {
      kind: "box",
      size: [
        { op: "literal", dimension: "length", value: 10 },
        { op: "literal", dimension: "length", value: 20 },
        { op: "literal", dimension: "length", value: 30 },
      ],
      center: false,
    },
  },
  outputs: { box: { kind: "solid", node: "box" } },
} as const;

const migrated = valueOrThrow(migrateDocument(legacyDocument));
const canonicalJson = stringifyDocument(migrated);
const reparsed = valueOrThrow(parseDocument(canonicalJson));
const semanticHash = await hashDocument(reparsed);

export const documentLifecycleSummary = {
  sourceVersion: legacyDocument.version,
  targetVersion: migrated.version,
  currentVersion: DOCUMENT_VERSION,
  canonicalRoundTrip:
    stringifyDocument(reparsed) === canonicalJson,
  semanticHash,
};
console.log(documentLifecycleSummary);
```

The release gate compiles and executes the source module from
`examples/docs/document-canonicalization-and-migration.ts`.

## Serialize deterministically

```ts theme={"system"}
const compact = stringifyDocument(document);
const readable = stringifyDocument(document, { pretty: true });
```

Serialization canonicalizes topology query ordering and persistent-reference
variants. Equivalent commutative topology expressions therefore produce the
same document representation.

## Parse untrusted text

```ts theme={"system"}
const parsed = parseDocument(jsonText, {
  limits: {
    maxDocumentBytes: 8 * 1024 * 1024,
    maxNestingDepth: 64,
  },
});

if (!parsed.ok) {
  console.error(parsed.diagnostics);
  return;
}

const document = parsed.value;
```

`parseDocument` checks UTF-8 byte size before `JSON.parse`, captures a bounded
plain snapshot, validates the matching frozen version schema, validates graph
semantics, and deep-freezes the result.

Use `parseDocumentValue(value)` when another parser already produced an unknown
JavaScript value. It still performs the bounded snapshot and schema checks.

## Do not cast

```ts theme={"system"}
// Unsafe: bypasses every runtime invariant.
const document = JSON.parse(text) as DesignDocument;
```

Type assertions provide no runtime safety and can feed cycles, wrong versions,
invalid expressions, missing references, or resource bombs into code that
expects a validated document.

## Clone

```ts theme={"system"}
const detached = cloneDocument(document);
```

Cloning serializes and reparses through the public protocol. It is appropriate
when a detached frozen copy is needed; it is not a mutable editing API.

## Migrate

Migration preserves admitted authored data from versions 1 through 6 and moves
it to the current schema. It does not:

* invent information a prior version could not express
* recapture topology evidence
* upgrade a stored persistent-reference protocol
* rewrite kernel fingerprints
* execute geometry

Keep the original input when auditability requires proving exactly what was
received before migration.

## Hash a document

By default, root metadata is excluded so descriptive root changes do not alter
the semantic document hash. Node metadata and every modeled field follow the
protocol's canonical representation. Pass `{ includeMetadata: true }` when the
root metadata is intentionally part of the hash.

## Schema identifiers

The `schema` URI and integer `version` are protocol identifiers. Parsers do not
dereference the URI over the network. Treat both as exact values, not as a URL
from which runtime code should be downloaded.

## Editing strategy

InvariantCAD 0.1 exposes a builder for authoring and parsers for validated
documents. It does not expose an in-place mutable document editor. To revise a
stored document programmatically, use a reviewed transformation that produces
a new value, then pass it through `parseDocumentValue` before persistence or
evaluation.
