Skip to main content
Create a builder with design(name, options?). Every returned authoring handle is immutable and owned by that builder.

Document definitions

Primitive and profile nodes

Feature nodes

Backend support is checked during evaluation, not authoring. A document may be valid while a selected kernel lacks one of its features.

Product structure

Repository-only staged product authoring

The source tree contains:
This is a deliberately narrow facade for authoring bounded primitive/import/Boolean/transform solid DAGs, acyclic fixed-placement products with one external-document boundary per active path, and datum nodes admitted by the four staged geometry evaluators and the datum resolver. Its implementation lives in src/internal/document-v7-body-set-authoring.ts; it is not exported from the package root or any package subpath. The public design(...) builder, DesignDocument alias, evaluator, and migration target remain on frozen v6. This is repository-only work staged for 0.2, not public 0.1.1 authoring. The facade privately composes the v6 builder for admitted parameters and native primitives, then adds staged configuration, material, resource, imported-body, body-set, part, local assembly, external component, and datum records. Its complete admitted surface is: The relevant staged source signatures are:
Every staged reference is owned by the builder that created it. Resource IDs, parameter IDs, material IDs, configuration IDs, node IDs, output names, and body-member IDs must be valid and unique in their applicable namespace. The facade rejects foreign or forged geometry, material, part, assembly, external-component, resource, and output handles. External handles require an owned resource whose media type is application/vnd.invariantcad.document+json; they retain a valid requested output ID and publish no local feature node. The facade constructs canonical references from captured identity rather than dispatching through mutable handle methods. Datum authoring returns owner-bound, frozen handles reserved for later feature consumers; no method in this slice consumes one. A body-set member keeps its stable ID, authored position, optional name, and detached JSON metadata; multiple memberships may deliberately reference the same owned solid DAG root. Every listed member is active, and the facade neither selects nor infers a primary body. A staged part wraps either one owned primitive, imported-body, Boolean, or transformed-solid DAG root, or one owned body set. It cannot wrap another part or assembly, or use a body set, part, or assembly as a Boolean or transform input. material(...) authors a document-owned definition with an explicit mass-density expression. part(...) accepts the existing PartOptions contract: part number, description, detached metadata, optional explicit density, and either a legacy descriptive material string or an owned materialRef, never both. A configuration can substitute another owned material for an owned part. The selected material determines effective material identity and supplies density when needed; an explicit part density still wins. A legacy label and a material name never perform catalogue lookup. Length, angle, density, and scalar parameters may be specialized by a named configuration and then by bounded caller overrides during evaluation.

Staged solid Boolean and transform DAGs

StagedSolidRefV7 is the owner-bound handle shared by direct primitive leaves, imported-body leaves, Boolean results, and transform results. union(...), subtract(...), and intersect(...) require one target plus a dense, non-empty tool list. Every operand must be a solid handle issued by the same builder. A Boolean result can feed a later Boolean, transform, body-set membership, or part. The evaluator invokes exactly one kernel Boolean with the target plus a frozen tool array in authored order. Backend implementation strategy is kernel-owned, but it may not reorder operands or reinterpret the authored operation. transform(...) requires at least one operation and captures its dense ordered operation list as plain own data. translate(...), rotate(...), scale(...), and mirror(...) author one typed operation each; their vectors use length, angle, scalar, and scalar expressions respectively. A transform result can feed another transform, a Boolean, body-set membership, or a part’s single-solid geometry. The staged evaluator plans the selected closure iteratively, deduplicates shared nodes, and executes every dependency before its consuming Boolean or transform. maxDistinctSolids counts primitive and imported leaves. maxSolidGraphNodes counts all distinct admitted solid nodes, maxSolidDependencyLinks counts every transform input edge plus every Boolean target and tool edge, including repeated tool references, and maxTransformOperations counts the ordered operations stored on distinct transform nodes. Each defaults to 100,000 in the staged body-set, part, and product-assembly evaluators. Transform expressions must resolve to finite values. Scale components must be nonzero, and a mirror normal must be finite and nonzero. The selected kernel must advertise and implement transform; each transform must return a fresh, valid, positive-volume owned shape. Failure is transactional and releases all shapes created for the graph. The selected kernel must advertise the boolean feature and implement the Boolean method before resource resolution or shape acquisition. Every created node must return a fresh, valid owned shape. A subtraction or intersection that returns a null shape or exactly zero volume fails with EMPTY_RESULT; an impossible empty union, negative/non-finite volume, or any returned shape that aliases an owned operand or earlier result fails as a kernel protocol violation. Repeated authored operand references remain allowed and are charged as separate dependency edges. Staged evaluation has no allowEmpty option. Failure is transactional and releases every acquired intermediate exactly once. Stock OCCT evaluates this graph as exact B-Rep geometry and retains its normal per-solid topology/native-export capabilities. Its Boolean history remains partial unless an owned facade honestly advertises the existing feature-scoped exact indexed-evolution protocol for boolean. A present malformed exact-evolution envelope fails before resource or kernel work rather than silently downgrading history. That promise covers the current Boolean operation; it does not upgrade partial history already carried by an imported or otherwise partial operand, and exact: true describes geometry rather than complete persistent history. Manifold evaluates native primitive/Boolean/transform graphs as approximate mesh geometry and exposes no topology snapshots. The evaluator never retries an exact failure on Manifold or silently converts an exact graph to a mesh graph. Any imported leaf, transformed or Boolean-composed, additionally requires the strong exact B-Rep single-solid document-import capability, so it cannot fall back to Manifold’s weak or absent import path. This is not general shape algebra. A transform input must be an owned StagedSolidRefV7 created by a primitive, imported body, Boolean, or prior transform, and the same restriction applies to every Boolean operand. A body set, part, or assembly cannot be Boolean-composed or transformed. A generic Boolean or transformed solid also cannot be published directly by output(...): it must be retained by a body set or part. The one exception to generic-solid output is the narrower direct StagedImportedBodyRefV7 output already admitted by the import evaluator.

Fixed-placement products

The staged assembly(id, build) method passes one StagedLocalAssemblyBuilderV7 to its callback. Each instance(...) in this slice references an owned local part, an already-completed owned local assembly, or an owned external-part or external-assembly handle. A local assembly handle is published only after its callback succeeds, so the facade can reference earlier local definitions but cannot author a local cycle. Foreign or forged handles are rejected. externalPart(resource, output) and externalAssembly(resource, output) require a committed InvariantCAD-document resource owned by the same staged builder. They select a valid named part or assembly output without publishing a local feature node. Product evaluation admits the committed child document before child geometry work. A selected external assembly may contain child-local parts and bounded nested local assemblies; each active occurrence path may cross only one external-document boundary. An instance ID is stable within its containing assembly. Evaluation joins those IDs into a full root-to-leaf path for each emitted part occurrence. Its placement is an ordered list of translate, rotate, scale, or mirror operations, and its configuration selector is exactly one of:
  • inherit, which evaluates a local component in the containing assembly’s context and maps root base to child base or a root named ID to the same ID in an external document;
  • base, which evaluates a local component in the root base context or an external component in the child base context; or
  • named, which selects the referenced configuration in the applicable root or child document.
Omitted instance options mean an empty placement, suppressed: false, and { mode: "inherit" }. The configuration active for every containing assembly controls its definition-scoped instance suppression and placement expressions. configuration.instanceSuppressed(...) can target any owned assembly definition. Passing false explicitly unsuppresses an instance authored with suppressed: true; omission retains the authored value. Suppression is resolved before component support is checked, so suppressing an assembly edge prunes its entire subtree, including external or otherwise unsupported descendants. A suppressed nested external component therefore performs no descendant resolution or kernel work. An active direct external part or fixed subassembly is supported, but an active external descendant inside the admitted child would cross a second document boundary and is rejected before nested resolution or child geometry/kernel work. Occurrence IDs are unique only within their containing assembly. Repeating one part or subassembly in several instances is expected and does not copy its document definition. Iterative evaluation expands active assemblies in authored depth-first leaf order and composes edge placements parent first. Bounded caller parameter overrides apply to root-document contexts only and never cross an external boundary. Per-occurrence inherit, base, and named selection can therefore produce different geometry, material, or density from a shared part definition. Evaluation reuses local parts for equal (part, effective configuration) states and direct external parts for equal (resource, output, child configuration) states. Fixed-subassembly leaves share geometry by resource, child part node, and child configuration; distinct assembly output aliases retain separate component, diagnostic, and BOM identity. Direct part evaluation may additionally deduplicate solid-DAG acquisition within a configuration batch. Authoring does not create a persistent or cross-run cache commitment. Product evaluation separately bounds nesting with maxAssemblyDepth and the aggregate stored leaf-path length with maxOccurrencePathSegments, in addition to its external-document, instance, occurrence, placement, contextual-part, solid, material, document, and resource ceilings. Solid-graph nodes, all solid dependency edges, and transform operations are counted globally across the active product. Repeated occurrences in the same effective context reuse that work, different contexts are charged independently, and suppressed subtrees are pruned before these counters advance. Hand-authored cyclic local dependencies fail strict document admission, and evaluation also rejects a recursive path rather than looping. The four datum methods author ordinary Document v7 nodes with stable node IDs. A point carries a length-valued position. An axis adds one scalar direction. A plane adds scalar positive-X and normal directions, while a coordinate system adds scalar positive-X and positive-Y directions. Their owned handles establish builder identity, but datums are not admitted by output(...): callers pass datum node IDs to the separate source-only datum resolver. That resolver is kernel-independent, normalizes admitted directions, and returns deterministic orthonormal right-handed frames. It rejects non-finite or zero directions and requires each normalized authored direction pair to have an absolute dot product no greater than 1e-12 before deterministic re-orthonormalization. Authoring a datum does not yet make it usable as a sketch plane or shape-algebra input. A resource commitment describes bytes that an application resolver may later supply. Its ordered locations are hints only: authoring and evaluation never dereference them. The facade does not read bytes or compute a digest or byte length; the caller supplies those commitments. The imported-body method, rather than mediaType, chooses the reader. STEP always uses { mode: "from-file" }. Text and binary BREP require { mode: "declared", length: "mm" | "cm" | "m" | "in" }. All staged imports emit { healing: { mode: "none" } } and expected: "single-solid"; there is no healing switch, weak-import fallback, or automatic exact-to-mesh conversion. build({ limits }) accepts a partial DesignDocumentLimits override and strictly parses the completed document. A failed strict result is raised as a CadError; no invalid document escapes. During authoring, resources also use the current default ceilings of 10,000 definitions, 100,000 aggregate location hints, and 16 MiB of aggregate UTF-8 location text. One bodySet(...) call is additionally rejected before copying if it exceeds the default 1,000,000 structural-value ceiling, and one instance placement cannot contain more operations than that ceiling. The completed assembly instance list is charged to maxStructuralValues during build. Final build limits can be stricter; they do not raise these immediate safeguards. Authoring methods fail immediately when a handle comes from another builder, a namespace is duplicated, a required collection is sparse or empty, member IDs repeat, a commitment is malformed, a configuration references foreign definitions, an immediate authoring ceiling is exceeded, or a parameter, configuration, material, part, assembly instance, placement, resource, import, unit-policy, datum, or body-member option record contains an accessor or unknown field. Those inputs must be plain own-data records; required arrays must be dense own-data arrays. Accessors are not invoked and unsupported semantics are rejected rather than silently discarded. Build then applies caller-selected document limits and strict v7 validation before returning the detached, recursively frozen document. This facade does not author generic solid or direct primitive outputs, recursive external-document graphs, cyclic local assembly graphs, datum-backed sketches, Booleans over body sets/parts/assemblies, transforms over body sets/parts/assemblies, other body-consuming features, per-body materials, or general solid graphs beyond primitive/import/Boolean/transform DAGs. It also does not add datum design outputs, CLI support, location I/O, reader inference, healing, a primary-body rule, cross-body or assembly topology, aggregate geometric measurement, mates, motion, interference/collision, or exact aggregate STEP/BREP export. Part- and product-level STL/OBJ export is an aggregate tessellation view and is explicitly approximate/lossy; exact native export and topology remain per-solid or per-body capabilities. These omissions are product boundaries, not implicit fallbacks. The staged facade remains repository-only work for 0.2, and the public 0.1.1 document alias remains v6.

ID rules

All IDs use the shared stable ID grammar and must be unique in their namespace. Avoid generated array positions or user-facing labels that may change. Prefer IDs such as housing-side-a, left-bearing-seat, and manufacturing-assembly.

Programmer errors

Methods throw TypeError or RangeError for invalid direct calls, including:
  • duplicate or malformed IDs
  • references from another builder
  • wrong-dimensional expressions
  • wrong topology kind
  • invalid option enum/literal values
  • empty required lists
  • non-positive tolerances
  • references targeting the wrong direct solid
These failures indicate an invalid model definition or unvalidated UI input, not a geometry-kernel failure.