# Artifact Builders

Builder functions for top-level Paradoc artifacts

Canonical URL: https://docs.paradoc.dev/sdk/artifacts/

## Artifact Builders

Artifact builders create top-level schema types that can be validated, serialized, and rendered independently.

## Available Builders

| Builder                               | Description                               | Badge       |
| ------------------------------------- | ----------------------------------------- | ----------- |
| [document](/sdk/artifacts/document)   | Static content (disclosures, pamphlets)   | Design-time |
| [form](/sdk/artifacts/form)           | Interactive forms with fields and parties | Design-time |
| [checklist](/sdk/artifacts/checklist) | Task lists and verification items         | Design-time |
| [bundle](/sdk/artifacts/bundle)       | Collection of multiple artifacts          | Design-time |

## Common Features

All artifact builders share common functionality:

### Static Methods

* `.from(input)` - Parse unknown input, throws on error
* `.safeFrom(input)` - Parse unknown input, returns result object

### Instance Methods

* `.validate()` - Validate the schema definition
* `.isValid()` - Check if schema is valid
* `.toJSON()` - Serialize to JSON, with the current dated `$schema`
* `.toYAML()` - Serialize to YAML, with the current dated `$schema`
* `.clone()` - Deep clone the instance

### Validating templates

`validate(artifact)` checks every template expression in inline text layers along with the schema and logic. For a form, it also checks that each PDF layer binding value is a known Paradoc path, so an inverted binding (a field name in the value position) is an error naming the key. It also reports each layer reference that render or seal would fail on, naming the layer, slot, or role: a `defaultLayer` that names no layer, a signature slot for an undeclared party role, a `'flow'` slot on a PDF or DOCX layer or of a type other than `signature` or `initials`, a party whose signature is required but has no slot on a layer that declares `signatures`, and a `'flow'` slot that no directive in an inline template places. `fill()` does not run these reference checks, so a draft still fills and renders, and `seal()` rejects the same problems for the layer it seals. Files are read through a resolver, so they are checked by `validateLayers`. A file-backed layer, `instructions`, or `agentInstructions` file that cannot be read is an error:

```ts
import { validateLayers } from '@paradoc/sdk'
import { createFsResolver } from '@paradoc/resolvers/fs'

const result = await validateLayers(artifact, { resolver: createFsResolver({ root: '.' }) })
// result.issues: 'Template error at layer "markdown", line 12, column 7 in {{fields.amount}}: ...'
```

`validateLayers` also checks that each file-backed text template places its `'flow'` slots. For a form, `validateLayers` also checks that each PDF layer binding key is an AcroForm field of the template, and that values a PDF layer binding accepts can fill its PDF text field: a typical value at the field's `maxLength` or `pattern` length that is too wide for its box, an option value too wide for its box, or a value too long for its comb boxes is an error. A value that overflows only when made of the widest letters, and a bound text field with no length bound, are returned in `result.warnings`, which do not fail validation. See [Checking bindings before filling](/sdk/renderers/pdf#checking-bindings-before-filling).

### Schema versions

An artifact built with the SDK is always the current [schema version](/schemas#schema-versions). `load()`, `loadFromObject()`, each kind's constructor, `.from()` and `.safeFrom()`, and the builder's `.from()` refuse an artifact written for another version with a `SchemaVersionError`, and `validate()` reports it, as the [loading rules](/schemas#loading-rules) describe. To bring an artifact written for an earlier version up to date, use `migrateArtifact` for a parsed object or `migrateArtifactSource` for file content. Both apply the migration steps in order, validate the result, and fail with `SchemaMigrationError` instead of guessing. The [`paradoc migrate`](/cli/commands/migrate) command uses them.

```ts
import { migrateArtifactSource } from '@paradoc/sdk'

const result = migrateArtifactSource(yamlText, { format: 'yaml' })
if (result.status === 'migrated') {
  console.log(`${result.from} → ${result.to}`)
  // result.content is the rewritten YAML, comments kept
}
```

### Instance Properties

* `_data` - Raw artifact data
* `kind` - Artifact type discriminator
* `name` - Artifact name
* `version` - Semantic version
* `instructions` - Domain/compliance reference content ([ContentRef](/schemas/artifacts/shared/content-ref))
* `agentInstructions` - LLM/agent presentation guidance ([ContentRef](/schemas/artifacts/shared/content-ref))
