Skip to content

Apply a cart branch and fast-forward main onto it (#929 D6).

POST
/v1/metadata@{branchId}/publish
curl --request POST \
--url https://example.com/v1/metadata@example/publish \
--header 'Authorization: Bearer <token>'
branchId
required
string

First path segment: metadata@<branchId>. branchId must be an existing cart branch — main is rejected with 400 MAIN_IS_NOT_A_CART_BRANCH. Requires admin.metadata.apply; applies the branch and fast-forwards main onto it on success.

Top-level result returned by plan(), apply(), plan_branch(), and merge_branch_and_apply().

Media typeapplication/json

Top-level result returned by plan(), apply(), plan_branch(), and merge_branch_and_apply().

object
changes
required

Ordered list of individual changes with risk and SQL.

Array<object>
One of:

A new table is created with the given columns.

object
disposition
required

Whether this change executes, is skipped, or would make the whole run refuse under this result’s options. See [Disposition].

One of:

This change runs as part of the result.

Includes every change when the result was computed with destructive: true, and the managed Lookup->Junction FK drop even under destructive: false – the strategy migration that scheduled it already decided the drop is safe, independent of the destructive gate.

string
Allowed value: execute
risk
required

The highest risk among this change’s DDL statements.

One of:

No lock escalation, instant operation.

string
Allowed value: safe
sql

The DDL statements this change runs, in the order they execute. Views are rebuilt on every run and are listed under no change.

Array<string>
action
required
string
Allowed value: createTable
columns
required
Array<object>

Column metadata in a plan change report.

object
generatedMode

Generated column mode ("virtual" or "stored"), if applicable.

string | null
generationExpression

SQL expression for a generated column, if applicable.

string | null
name
required

Column name (snake_case).

string
notNull

Whether the column has a NOT NULL constraint.

boolean
primaryKey

Whether this column is the table’s primary key.

boolean
type
required

Bare PostgreSQL type, never including modifiers.

Examples: "TEXT", "UUID", "BIGINT", "TIMESTAMPTZ", "VARCHAR(255)". Modifier information is carried by the dedicated boolean fields (primary_key, not_null, unique) — it never appears inline here.

string
unique

Whether the column has a UNIQUE constraint.

boolean
table
required
string
diagnostics

Non-fatal warnings emitted during compilation or diffing.

Array<object>

A diagnostic message emitted during metadata compilation.

object
message
required

Human-readable description of the issue.

string
severity
required

How serious the diagnostic is.

One of:

Informational note, does not block compilation.

string
Allowed value: info
source
required

Source location, e.g. “core_Contact.account”

string
options
required

The [DiffOptions] this result was computed with, echoed back so the result is self-describing.

object
destructive
required

When true, destructive operations (drop column, narrow type) produce DDL. When false (default), they produce diagnostics only.

boolean
vault
required

When true (default), vault data before destructive operations.

boolean
source
required

Which tree (and, when knowable, which commit) this result was computed against.

object
One of:

The server’s own working-tree metadata directory (state.metadata_path).

object
commit

refs/heads/main’s HEAD commit, or None when metadata_path is not inside a git checkout (a bare hf apply against a filesystem path with no .git at all is a normal, non-erroring case – see crate::git::main_commit_for_metadata_path).

string | null
kind
required
string
Allowed value: main
status
required

Whether this result was planned or applied.

One of:

The changes have been computed and diffed but no DDL has run yet.

string
Allowed value: planned
summary
required

Aggregate change counts.

object
columnsAdded
required

Number of columns added to existing tables.

integer format: uint
columnsChanged
required

Number of columns whose definition changed (replace, generated expression).

integer format: uint
columnsDropped
required

Number of columns dropped.

integer format: uint
columnsTypeChanged
required

Number of columns whose SQL type changed.

integer format: uint
constraintsChanged
required

Number of constraint changes (foreign key, unique).

integer format: uint
indexesCreated
required

Number of new indexes created.

integer format: uint
indexesReplaced
required

Number of existing indexes replaced.

integer format: uint
tablesCreated
required

Number of new tables created.

integer format: uint
tablesDropped
required

Number of junction tables dropped (--destructive only).

integer format: uint
tablesRenamed
required

Number of junction tables renamed (OID-preserving; rows preserved).

integer format: uint
unchanged
required

Number of tables/columns that required no changes.

integer format: uint
Example
{
"changes": [
{
"disposition": "execute",
"risk": "safe",
"action": "createTable"
}
],
"diagnostics": [
{
"severity": "info"
}
],
"source": {
"kind": "main"
},
"status": "planned"
}

Structured error envelope (SPEC-DATA-0006): {"errors": [{"domain", "scope", "target", "code", "message"}, ...]}. domain (added #950 D9) names the subsystem that produced the entry (data, metadata, apply, git, auth, iam, hfx, or api for a transport-level failure with no domain error behind it) and is always present.

Media typeapplication/json

The top-level response body. Wraps a non-empty list of [ErrorEntry].

object
errors
required

The error entries making up the envelope. Always non-empty.

Array<object>

One entry in the error envelope.

Carries a [Domain] naming the subsystem that produced it, an anchoring [ErrorScope], an optional target that disambiguates within the scope, a stable SCREAMING_SNAKE_CASE code, and a human-readable English message. See SPEC-DATA-0006 for the full envelope contract.

object
code
required

Machine-readable, stable, SCREAMING_SNAKE_CASE identifier.

string
domain
required

Which subsystem produced this entry. Always serialized.

One of:

data::error::DataError – record CRUD, validation, queries.

string
Allowed value: data
location
Any of:

HFX source location for an HFX_PARSE entry.

Emitted as the extra location field on the entry JSON when present. The line/column are 1-based. The frame is the offending source line extracted verbatim from the input.

object
column
required

1-based column within the line, measured in UTF-16 code units of the prefix so browser-side editors can consume it directly.

integer format: uint32
frame

The offending source line text, when available.

string | null
line
required

1-based line number within the source text.

integer format: uint32
message
required

Server-authored English message. Not part of the API contract; may change across releases without notice.

string
rule

The key of the validation rule that failed, when the code is RULE_FAILED. None for all other codes. Skipped during serialization when absent so it does not appear on unrelated entries (same pattern as location).

string | null
scope
required

Anchoring category. Drives client-side rendering.

One of:

Attached to a specific request field. target is the field key.

string
Allowed value: field
target

Field key for field scope, record id for record scope, null otherwise. Always serialized, even when null.

string | null
Example
{
"errors": [
{
"domain": "data",
"scope": "field"
}
]
}