globalThis.process ??= {};
globalThis.process.env ??= {};
import { r as __exportAll$1 } from "./rolldown-runtime_-UtK6b3T.mjs";
import { B as uuid, E as eq, F as or, G as text, I as primaryKey, R as pgTable, T as and, Tt as sql, U as timestamp, Y as jsonb, Z as integer, c as uniqueIndex, d as assertTransactionIdentity, et as boolean, f as getTransactionIdentity, j as isNull, n as d1AssertPreviousChanges, p as isTransactionCapabilityError, q as numeric, s as index, tt as bigserial, u as check } from "./d1_DTqC4o_t.mjs";
//#region ../../packages/fields/dist/schema.js
var FieldDefinitionVersionError = class extends Error {
	field;
	detail;
	name = "FieldDefinitionVersionError";
	code = "invalid-definition-version";
	constructor(field, detail) {
		super(`field definition version ${field}: ${detail}`);
		this.field = field;
		this.detail = detail;
	}
};
var MAX_DEPTH = 12;
var MAX_NODES = 1e3;
var MAX_INPUT_NODES = 1e4;
var MAX_STRING = 4096;
var MAX_BYTES = 262144;
var MAX_ITEMS = 1e3;
var forbidden = /* @__PURE__ */ new Set([
	"__proto__",
	"prototype",
	"constructor"
]);
function fail$4(field, detail) {
	throw new FieldDefinitionVersionError(field, detail);
}
function preflight$1(value, budget, depth = 0, seen = /* @__PURE__ */ new Set()) {
	if (depth > 64) fail$4("fieldDefinitionVersion", "exceeds maximum depth");
	if (value === null || typeof value === "boolean") {
		budget.bytes += 5;
		return;
	}
	if (typeof value === "string") {
		budget.bytes += new TextEncoder().encode(value).byteLength;
		if (value.length > MAX_STRING) fail$4("fieldDefinitionVersion", "contains an oversized string");
		return;
	}
	if (typeof value === "number") {
		if (!Number.isFinite(value)) fail$4("fieldDefinitionVersion", "contains a non-finite number");
		budget.bytes += 8;
		return;
	}
	if (value instanceof Date) {
		if (Object.getOwnPropertyNames(value).length !== 0 || Object.getOwnPropertySymbols(value).length !== 0 || Number.isNaN(Date.prototype.getTime.call(value))) fail$4("fieldDefinitionVersion", "contains an invalid Date");
		budget.bytes += 24;
		return;
	}
	if (typeof value !== "object" || value === null || seen.has(value)) fail$4("fieldDefinitionVersion", "must be an acyclic data graph");
	if (++budget.nodes > MAX_INPUT_NODES || budget.bytes > MAX_BYTES) fail$4("fieldDefinitionVersion", "exceeds maximum input size");
	seen.add(value);
	if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype || Object.getOwnPropertySymbols(value).length) fail$4("fieldDefinitionVersion", "must contain only plain data objects and arrays");
	const descriptors = Object.getOwnPropertyDescriptors(value);
	const keys = Object.keys(value);
	if (keys.length > MAX_ITEMS) fail$4("fieldDefinitionVersion", "contains an oversized collection");
	for (const key of keys) {
		const d = descriptors[key];
		if (forbidden.has(key) || !d.enumerable || !("value" in d)) fail$4(`fieldDefinitionVersion.${key}`, "contains a forbidden key or accessor");
		budget.bytes += new TextEncoder().encode(key).byteLength;
		preflight$1(d.value, budget, depth + 1, seen);
	}
	seen.delete(value);
	if (budget.bytes > MAX_BYTES) fail$4("fieldDefinitionVersion", "exceeds maximum input size");
}
function cloneData(value) {
	if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
	if (Array.isArray(value)) return Object.freeze(value.map(cloneData));
	const source = obj$1(value, "defaultValue");
	const output = {};
	for (const key of Object.keys(source)) output[key] = cloneData(source[key]);
	return Object.freeze(output);
}
function obj$1(value, path) {
	if (typeof value !== "object" || value === null || Array.isArray(value) || Object.getPrototypeOf(value) !== Object.prototype) fail$4(path, "must be a plain object");
	return value;
}
function keys(v, allowed, path) {
	for (const k of Object.keys(v)) if (!allowed.includes(k)) fail$4(`${path}.${k}`, "is not allowed");
}
function str$1(v, path) {
	if (typeof v !== "string" || !v.length || v.length > MAX_STRING) fail$4(path, "must be a bounded non-empty string");
	return v;
}
function bool$1(v, p) {
	if (v === void 0) return;
	if (typeof v !== "boolean") fail$4(p, "must be a boolean");
	return v;
}
function num(v, p, integer = false, positive = false) {
	if (v === void 0) return;
	if (typeof v !== "number" || !Number.isFinite(v) || integer && !Number.isInteger(v) || positive && v <= 0) fail$4(p, `must be a ${positive ? "positive " : ""}${integer ? "integer" : "finite number"}`);
	return v;
}
function enumValue(v, values, p) {
	if (typeof v !== "string" || !values.includes(v)) fail$4(p, "has an invalid value");
	return v;
}
function array$1(v, p, max = MAX_ITEMS) {
	if (!Array.isArray(v) || v.length > max) fail$4(p, "must be a bounded array");
	return v;
}
function strings(v, p, required = false) {
	if (v === void 0 && !required) return;
	return Object.freeze(array$1(v, p).map((x, i) => str$1(x, `${p}.${i}`)));
}
function boundedMap(v, p) {
	const x = obj$1(v, p);
	const out = {};
	for (const k of Object.keys(x)) {
		if (!k || k.length > MAX_STRING) fail$4(p, "has invalid key");
		out[k] = str$1(x[k], `${p}.${k}`);
	}
	return Object.freeze(out);
}
function pair(min, max, p) {
	if (min !== void 0 && max !== void 0 && min > max) fail$4(p, "minimum exceeds maximum");
}
function safePattern(v, p) {
	const x = obj$1(v, p);
	keys(x, ["source", "flags"], p);
	const source = str$1(x.source, `${p}.source`);
	const flags = x.flags === void 0 ? void 0 : str$1(x.flags, `${p}.flags`);
	if (flags !== void 0 && !/^[dgimsuvy]*$/.test(flags)) fail$4(`${p}.flags`, "has invalid flags");
	return Object.freeze({
		source,
		...flags === void 0 ? {} : { flags }
	});
}
function fieldPath$2(v, p) {
	const a = array$1(v, p, 64);
	if (!a.length) fail$4(p, "must not be empty");
	return Object.freeze(a.map((x, i) => typeof x === "number" && Number.isSafeInteger(x) && x >= 0 ? x : str$1(x, `${p}.${i}`)));
}
function conditional(v, p) {
	if (v === void 0) return;
	return Object.freeze(array$1(v, p, 64).map((group, i) => Object.freeze(array$1(group, `${p}.${i}`, 64).map((raw, j) => {
		const x = obj$1(raw, `${p}.${i}.${j}`);
		keys(x, [
			"fieldPath",
			"operator",
			"value",
			"quantifier"
		], `${p}.${i}.${j}`);
		const operator = enumValue(x.operator, [
			"eq",
			"neq",
			"contains",
			"notContains",
			"gt",
			"gte",
			"lt",
			"lte",
			"empty",
			"notEmpty",
			"matches"
		], `${p}.${i}.${j}.operator`);
		const fp = fieldPath$2(x.fieldPath, `${p}.${i}.${j}.fieldPath`);
		const q = x.quantifier === void 0 ? void 0 : enumValue(x.quantifier, ["any", "all"], `${p}.${i}.${j}.quantifier`);
		let value = x.value;
		if (["empty", "notEmpty"].includes(operator)) {
			if (value !== void 0) fail$4(`${p}.${i}.${j}.value`, "is not allowed");
		} else if (operator === "matches") value = safePattern(value, `${p}.${i}.${j}.value`);
		else if ([
			"gt",
			"gte",
			"lt",
			"lte"
		].includes(operator)) {
			if (typeof value !== "number" || !Number.isFinite(value)) fail$4(`${p}.${i}.${j}.value`, "must be finite number");
		} else if (operator === "contains" || operator === "notContains") {
			if (typeof value !== "string" && typeof value !== "number") fail$4(`${p}.${i}.${j}.value`, "has invalid value");
		} else if (!(value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean")) fail$4(`${p}.${i}.${j}.value`, "has invalid value");
		return Object.freeze({
			fieldPath: fp,
			operator,
			...value === void 0 ? {} : { value },
			...q === void 0 ? {} : { quantifier: q }
		});
	}))));
}
function location(v, p) {
	return Object.freeze(array$1(v, p, 64).map((group, i) => Object.freeze(array$1(group, `${p}.${i}`, 64).map((raw, j) => {
		const x = obj$1(raw, `${p}.${i}.${j}`);
		keys(x, [
			"parameter",
			"operator",
			"value"
		], `${p}.${i}.${j}`);
		const op = enumValue(x.operator, [
			"eq",
			"neq",
			"in",
			"notIn",
			"contains"
		], `${p}.${i}.${j}.operator`);
		const value = x.value;
		const isList = Array.isArray(value);
		if (op === "in" || op === "notIn" ? !isList : isList || !(typeof value === "string" || typeof value === "number" || typeof value === "boolean")) fail$4(`${p}.${i}.${j}.value`, "has invalid operator/value combination");
		const copied = isList ? Object.freeze(array$1(value, `${p}.${i}.${j}.value`, MAX_ITEMS).map((item, k) => typeof item === "string" || typeof item === "number" ? item : fail$4(`${p}.${i}.${j}.value.${k}`, "must be string or number"))) : value;
		return Object.freeze({
			parameter: str$1(x.parameter, `${p}.${i}.${j}.parameter`),
			operator: op,
			value: copied
		});
	}))));
}
var builtin = /* @__PURE__ */ new Set([
	"text",
	"textarea",
	"number",
	"range",
	"email",
	"url",
	"password",
	"boolean",
	"select",
	"checkbox",
	"radio",
	"buttonGroup",
	"richText",
	"oembed",
	"link",
	"message",
	"image",
	"file",
	"gallery",
	"entity",
	"entityLink",
	"relationship",
	"taxonomy",
	"user",
	"date",
	"dateTime",
	"time",
	"color",
	"icon",
	"map",
	"accordion",
	"tab",
	"group",
	"repeater",
	"flexible",
	"clone"
]);
function settings$1(value, type, p, depth, b) {
	const x = obj$1(value, p);
	const common = (allowed) => keys(x, allowed, p);
	const copy = (allowed) => {
		common(allowed);
		const out = {};
		for (const k of allowed) if (x[k] !== void 0) out[k] = x[k];
		return out;
	};
	if (type === "text" || type === "email") {
		const o = copy([
			"placeholder",
			"prepend",
			"append",
			"maxLength",
			"pattern"
		]);
		for (const k of [
			"placeholder",
			"prepend",
			"append"
		]) if (o[k] !== void 0) o[k] = str$1(o[k], `${p}.${k}`);
		o.maxLength = num(o.maxLength, `${p}.maxLength`, true);
		if (o.maxLength !== void 0 && o.maxLength < 0) fail$4(`${p}.maxLength`, "must be non-negative");
		if (o.pattern !== void 0) o.pattern = safePattern(o.pattern, `${p}.pattern`);
		return Object.freeze(o);
	}
	if (type === "textarea") {
		const o = copy([
			"placeholder",
			"prepend",
			"append",
			"maxLength",
			"pattern",
			"rows",
			"newline"
		]);
		for (const k of [
			"placeholder",
			"prepend",
			"append"
		]) if (o[k] !== void 0) o[k] = str$1(o[k], `${p}.${k}`);
		o.maxLength = num(o.maxLength, `${p}.maxLength`, true);
		if (o.maxLength !== void 0 && o.maxLength < 0) fail$4(`${p}.maxLength`, "must be non-negative");
		o.rows = num(o.rows, `${p}.rows`, true, true);
		o.newline = enumValue(o.newline, [
			"preserve",
			"br",
			"paragraph"
		], `${p}.newline`);
		if (o.pattern !== void 0) o.pattern = safePattern(o.pattern, `${p}.pattern`);
		return Object.freeze(o);
	}
	if (type === "number" || type === "range") {
		const o = copy([
			"min",
			"max",
			"step",
			"integer",
			"prepend",
			"append"
		]);
		o.min = num(o.min, `${p}.min`);
		o.max = num(o.max, `${p}.max`);
		o.step = num(o.step, `${p}.step`, false, true);
		pair(o.min, o.max, p);
		o.integer = bool$1(o.integer, `${p}.integer`);
		for (const k of ["prepend", "append"]) if (o[k] !== void 0) o[k] = str$1(o[k], `${p}.${k}`);
		return Object.freeze(o);
	}
	if (type === "url") {
		const o = copy([
			"placeholder",
			"prepend",
			"append",
			"maxLength",
			"pattern",
			"schemes",
			"allowRelative"
		]);
		for (const k of [
			"placeholder",
			"prepend",
			"append"
		]) if (o[k] !== void 0) o[k] = str$1(o[k], `${p}.${k}`);
		o.maxLength = num(o.maxLength, `${p}.maxLength`, true);
		if (o.maxLength !== void 0 && o.maxLength < 0) fail$4(`${p}.maxLength`, "must be non-negative");
		o.schemes = strings(o.schemes, `${p}.schemes`, true);
		o.allowRelative = bool$1(o.allowRelative, `${p}.allowRelative`);
		if (o.pattern !== void 0) o.pattern = safePattern(o.pattern, `${p}.pattern`);
		return Object.freeze(o);
	}
	if (type === "password") {
		const o = copy([
			"hasherKey",
			"minLength",
			"maxLength"
		]);
		o.hasherKey = str$1(o.hasherKey, `${p}.hasherKey`);
		o.minLength = num(o.minLength, `${p}.minLength`, true);
		o.maxLength = num(o.maxLength, `${p}.maxLength`, true);
		pair(o.minLength, o.maxLength, p);
		return Object.freeze(o);
	}
	if (type === "boolean") {
		const o = copy([
			"style",
			"onLabel",
			"offLabel"
		]);
		if (o.style !== void 0) o.style = enumValue(o.style, ["switch", "checkbox"], `${p}.style`);
		for (const k of ["onLabel", "offLabel"]) if (o[k] !== void 0) o[k] = str$1(o[k], `${p}.${k}`);
		return Object.freeze(o);
	}
	if ([
		"select",
		"checkbox",
		"radio",
		"buttonGroup"
	].includes(type)) {
		const o = copy([
			"choices",
			"multiple",
			"allowNull",
			"allowCustom",
			"min",
			"max",
			"searchable",
			"orientation"
		]);
		o.choices = boundedMap(o.choices, `${p}.choices`);
		for (const k of [
			"multiple",
			"allowNull",
			"allowCustom",
			"searchable"
		]) o[k] = bool$1(o[k], `${p}.${k}`);
		o.min = num(o.min, `${p}.min`, true);
		o.max = num(o.max, `${p}.max`, true);
		pair(o.min, o.max, p);
		if (o.min !== void 0 && o.min < 0) fail$4(`${p}.min`, "must be non-negative");
		if (o.orientation !== void 0) o.orientation = enumValue(o.orientation, ["vertical", "horizontal"], `${p}.orientation`);
		return Object.freeze(o);
	}
	if (type === "richText") {
		const o = copy([
			"toolbar",
			"media",
			"tabs",
			"delayedInit"
		]);
		if (o.toolbar !== void 0) o.toolbar = str$1(o.toolbar, `${p}.toolbar`);
		o.media = bool$1(o.media, `${p}.media`);
		if (o.tabs !== void 0) o.tabs = Object.freeze(array$1(o.tabs, `${p}.tabs`).map((v, i) => enumValue(v, ["visual", "source"], `${p}.tabs.${i}`)));
		o.delayedInit = bool$1(o.delayedInit, `${p}.delayedInit`);
		return Object.freeze(o);
	}
	if (type === "oembed") {
		const o = copy([
			"providers",
			"width",
			"height"
		]);
		o.providers = strings(o.providers, `${p}.providers`);
		o.width = num(o.width, `${p}.width`, true, true);
		o.height = num(o.height, `${p}.height`, true, true);
		return Object.freeze(o);
	}
	if (type === "link") {
		const o = copy(["schemes", "targets"]);
		o.schemes = strings(o.schemes, `${p}.schemes`, true);
		if (o.targets !== void 0) o.targets = Object.freeze(array$1(o.targets, `${p}.targets`).map((v, i) => enumValue(v, ["_self", "_blank"], `${p}.targets.${i}`)));
		return Object.freeze(o);
	}
	if ([
		"message",
		"accordion",
		"tab"
	].includes(type)) {
		const o = copy([
			"text",
			"open",
			"endpoint"
		]);
		if (o.text !== void 0) o.text = str$1(o.text, `${p}.text`);
		o.open = bool$1(o.open, `${p}.open`);
		o.endpoint = bool$1(o.endpoint, `${p}.endpoint`);
		return Object.freeze(o);
	}
	if ([
		"image",
		"file",
		"gallery"
	].includes(type)) {
		const o = copy([
			"mimeTypes",
			"minBytes",
			"maxBytes",
			"source",
			"return",
			...type !== "file" ? [
				"minWidth",
				"maxWidth",
				"minHeight",
				"maxHeight"
			] : [],
			...type === "gallery" ? [
				"min",
				"max",
				"previewSize"
			] : []
		]);
		o.mimeTypes = strings(o.mimeTypes, `${p}.mimeTypes`);
		for (const k of [
			"minBytes",
			"maxBytes",
			"minWidth",
			"maxWidth",
			"minHeight",
			"maxHeight",
			"min",
			"max"
		]) o[k] = num(o[k], `${p}.${k}`, true);
		pair(o.minBytes, o.maxBytes, p);
		pair(o.minWidth, o.maxWidth, p);
		pair(o.minHeight, o.maxHeight, p);
		pair(o.min, o.max, p);
		if (o.min !== void 0 && o.min < 0) fail$4(`${p}.min`, "must be non-negative");
		if (o.source !== void 0) o.source = enumValue(o.source, ["all", "uploadedToEntity"], `${p}.source`);
		o.return = enumValue(o.return, [
			"ref",
			"id",
			"url"
		], `${p}.return`);
		if (o.previewSize !== void 0) o.previewSize = str$1(o.previewSize, `${p}.previewSize`);
		return Object.freeze(o);
	}
	if ([
		"entity",
		"entityLink",
		"relationship"
	].includes(type)) {
		const o = copy([
			"entityTypes",
			"statuses",
			"taxonomies",
			"return",
			...type === "relationship" ? [
				"min",
				"max",
				"bidirectional"
			] : []
		]);
		o.entityTypes = strings(o.entityTypes, `${p}.entityTypes`);
		o.statuses = strings(o.statuses, `${p}.statuses`);
		if (o.taxonomies !== void 0) {
			const tax = obj$1(o.taxonomies, `${p}.taxonomies`), out = {};
			for (const k of Object.keys(tax)) out[k] = strings(tax[k], `${p}.taxonomies.${k}`, true);
			o.taxonomies = Object.freeze(out);
		}
		o.return = enumValue(o.return, [
			"ref",
			"id",
			"object"
		], `${p}.return`);
		o.min = num(o.min, `${p}.min`, true);
		o.max = num(o.max, `${p}.max`, true);
		pair(o.min, o.max, p);
		if (o.min !== void 0 && o.min < 0) fail$4(`${p}.min`, "must be non-negative");
		if (o.bidirectional !== void 0) {
			const q = obj$1(o.bidirectional, `${p}.bidirectional`);
			keys(q, ["targetFieldKey"], `${p}.bidirectional`);
			o.bidirectional = Object.freeze({ targetFieldKey: str$1(q.targetFieldKey, `${p}.bidirectional.targetFieldKey`) });
		}
		return Object.freeze(o);
	}
	if (type === "taxonomy") {
		const o = copy([
			"taxonomies",
			"multiple",
			"allowCreate",
			"saveTerms",
			"loadTerms",
			"return"
		]);
		o.taxonomies = strings(o.taxonomies, `${p}.taxonomies`, true);
		for (const k of [
			"multiple",
			"allowCreate",
			"saveTerms",
			"loadTerms"
		]) o[k] = bool$1(o[k], `${p}.${k}`);
		o.return = enumValue(o.return, [
			"ref",
			"id",
			"object"
		], `${p}.return`);
		return Object.freeze(o);
	}
	if (type === "user") {
		const o = copy([
			"roles",
			"multiple",
			"return"
		]);
		o.roles = strings(o.roles, `${p}.roles`);
		o.multiple = bool$1(o.multiple, `${p}.multiple`);
		o.return = enumValue(o.return, [
			"ref",
			"id",
			"object"
		], `${p}.return`);
		return Object.freeze(o);
	}
	if ([
		"date",
		"dateTime",
		"time"
	].includes(type)) {
		const o = copy([
			"inputFormat",
			"displayFormat",
			"returnFormat",
			...type !== "time" ? ["firstWeekday"] : [],
			...type === "dateTime" ? ["timezone"] : []
		]);
		for (const k of [
			"inputFormat",
			"displayFormat",
			"returnFormat"
		]) o[k] = str$1(o[k], `${p}.${k}`);
		o.firstWeekday = num(o.firstWeekday, `${p}.firstWeekday`, true);
		if (o.firstWeekday !== void 0 && (o.firstWeekday < 0 || o.firstWeekday > 6)) fail$4(`${p}.firstWeekday`, "must be between 0 and 6");
		if (o.timezone !== void 0) o.timezone = enumValue(o.timezone, [
			"site",
			"user",
			"utc"
		], `${p}.timezone`);
		return Object.freeze(o);
	}
	if (type === "color") {
		const o = copy(["alpha", "palette"]);
		o.alpha = bool$1(o.alpha, `${p}.alpha`);
		o.palette = strings(o.palette, `${p}.palette`);
		return Object.freeze(o);
	}
	if (type === "icon") {
		const o = copy(["sets", "allowNull"]);
		o.sets = strings(o.sets, `${p}.sets`);
		o.allowNull = bool$1(o.allowNull, `${p}.allowNull`);
		return Object.freeze(o);
	}
	if (type === "map") {
		const o = copy([
			"providerKey",
			"center",
			"zoom",
			"height"
		]);
		o.providerKey = str$1(o.providerKey, `${p}.providerKey`);
		if (o.center !== void 0) {
			const c = obj$1(o.center, `${p}.center`);
			keys(c, ["latitude", "longitude"], `${p}.center`);
			o.center = Object.freeze({
				latitude: num(c.latitude, `${p}.center.latitude`),
				longitude: num(c.longitude, `${p}.center.longitude`)
			});
		}
		o.zoom = num(o.zoom, `${p}.zoom`);
		o.height = num(o.height, `${p}.height`, true, true);
		return Object.freeze(o);
	}
	if (type === "group" || type === "repeater") {
		const o = copy(type === "group" ? ["fields", "layout"] : [
			"fields",
			"layout",
			"min",
			"max",
			"collapsedBy",
			"pagination"
		]);
		o.fields = parseFields(o.fields, `${p}.fields`, depth + 1, b);
		if (o.layout !== void 0) o.layout = enumValue(o.layout, [
			"block",
			"table",
			"row"
		], `${p}.layout`);
		o.min = num(o.min, `${p}.min`, true);
		o.max = num(o.max, `${p}.max`, true);
		pair(o.min, o.max, p);
		if (o.collapsedBy !== void 0) o.collapsedBy = str$1(o.collapsedBy, `${p}.collapsedBy`);
		if (o.pagination !== void 0) {
			const q = obj$1(o.pagination, `${p}.pagination`);
			keys(q, ["pageSize"], `${p}.pagination`);
			o.pagination = Object.freeze({ pageSize: num(q.pageSize, `${p}.pagination.pageSize`, true, true) });
		}
		return Object.freeze(o);
	}
	if (type === "flexible") {
		const o = copy([
			"layouts",
			"min",
			"max"
		]);
		o.layouts = Object.freeze(array$1(o.layouts, `${p}.layouts`).map((raw, i) => {
			const q = obj$1(raw, `${p}.layouts.${i}`);
			keys(q, [
				"key",
				"name",
				"label",
				"fields"
			], `${p}.layouts.${i}`);
			return Object.freeze({
				key: str$1(q.key, `${p}.layouts.${i}.key`),
				name: str$1(q.name, `${p}.layouts.${i}.name`),
				label: str$1(q.label, `${p}.layouts.${i}.label`),
				fields: parseFields(q.fields, `${p}.layouts.${i}.fields`, depth + 1, b)
			});
		}));
		const ls = o.layouts;
		if (new Set(ls.map((l) => l.key)).size !== ls.length) fail$4(`${p}.layouts`, "contains duplicate layout keys");
		o.min = num(o.min, `${p}.min`, true);
		o.max = num(o.max, `${p}.max`, true);
		pair(o.min, o.max, p);
		return Object.freeze(o);
	}
	const o = copy([
		"sourceGroupKeys",
		"sourceFieldKeys",
		"display",
		"prefixNames"
	]);
	o.sourceGroupKeys = strings(o.sourceGroupKeys, `${p}.sourceGroupKeys`);
	o.sourceFieldKeys = strings(o.sourceFieldKeys, `${p}.sourceFieldKeys`);
	if (o.sourceGroupKeys === void 0 && o.sourceFieldKeys === void 0) fail$4(p, "must name a clone source");
	if (o.display !== void 0) o.display = enumValue(o.display, ["seamless", "group"], `${p}.display`);
	o.prefixNames = bool$1(o.prefixNames, `${p}.prefixNames`);
	return Object.freeze(o);
}
function parseField(raw, p, depth, b) {
	if (depth > MAX_DEPTH) fail$4(p, "exceeds maximum recursive definition depth");
	if (++b.nodes > MAX_NODES) fail$4(p, "exceeds maximum field count");
	const x = obj$1(raw, p);
	keys(x, [
		"key",
		"name",
		"label",
		"type",
		"instructions",
		"required",
		"defaultValue",
		"settings",
		"wrapper",
		"conditionalLogic",
		"disabled",
		"readOnly",
		"presentation"
	], p);
	const type = enumValue(x.type, [...builtin], `${p}.type`);
	const key = str$1(x.key, `${p}.key`);
	if (!/^[a-z][a-z0-9_]*$/.test(key)) fail$4(`${p}.key`, "must be a normalized field key");
	if ([
		"password",
		"message",
		"accordion",
		"tab"
	].includes(type) && x.defaultValue !== void 0) fail$4(`${p}.defaultValue`, "is not permitted for this field type");
	const out = {
		key,
		name: str$1(x.name, `${p}.name`),
		label: str$1(x.label, `${p}.label`),
		type,
		settings: settings$1(x.settings, type, `${p}.settings`, depth, b)
	};
	for (const k of ["instructions"]) if (x[k] !== void 0) out[k] = str$1(x[k], `${p}.${k}`);
	for (const k of [
		"required",
		"disabled",
		"readOnly"
	]) if (x[k] !== void 0) out[k] = bool$1(x[k], `${p}.${k}`);
	if (x.defaultValue !== void 0) out.defaultValue = cloneData(x.defaultValue);
	if (x.wrapper !== void 0) {
		const q = obj$1(x.wrapper, `${p}.wrapper`);
		keys(q, [
			"width",
			"className",
			"data"
		], `${p}.wrapper`);
		const w = {};
		w.width = num(q.width, `${p}.wrapper.width`);
		if (w.width !== void 0 && (w.width < 0 || w.width > 100)) fail$4(`${p}.wrapper.width`, "must be between 0 and 100");
		if (q.className !== void 0) w.className = str$1(q.className, `${p}.wrapper.className`);
		if (q.data !== void 0) w.data = boundedMap(q.data, `${p}.wrapper.data`);
		out.wrapper = Object.freeze(w);
	}
	const c = conditional(x.conditionalLogic, `${p}.conditionalLogic`);
	if (c !== void 0) out.conditionalLogic = c;
	if (x.presentation !== void 0) {
		const q = obj$1(x.presentation, `${p}.presentation`);
		keys(q, ["labelPlacement", "instructionPlacement"], `${p}.presentation`);
		out.presentation = Object.freeze({
			...q.labelPlacement === void 0 ? {} : { labelPlacement: enumValue(q.labelPlacement, ["top", "left"], `${p}.presentation.labelPlacement`) },
			...q.instructionPlacement === void 0 ? {} : { instructionPlacement: enumValue(q.instructionPlacement, ["label", "field"], `${p}.presentation.instructionPlacement`) }
		});
	}
	return Object.freeze(out);
}
function parseFields(v, p, depth, b) {
	const fs = Object.freeze(array$1(v, p).map((f, i) => parseField(f, `${p}.${i}`, depth, b)));
	if (new Set(fs.map((f) => f.key)).size !== fs.length) fail$4(p, "contains duplicate sibling field keys");
	return fs;
}
/** Parses one built-in field definition through the same bounded trust boundary as immutable group snapshots. */
function parseFieldDefinition(value) {
	preflight$1(value, {
		nodes: 0,
		bytes: 0
	});
	return parseField(value, "definition", 1, {
		nodes: 0,
		bytes: 0
	});
}
function parseFieldGroup(value) {
	const x = obj$1(value, "definition");
	keys(x, [
		"key",
		"title",
		"fields",
		"location",
		"order",
		"position",
		"style",
		"labelPlacement",
		"instructionPlacement",
		"hideOnScreen",
		"active",
		"description"
	], "definition");
	const key = str$1(x.key, "definition.key");
	if (!/^[a-z][a-z0-9_]*$/.test(key)) fail$4("definition.key", "must be a normalized group key");
	const out = {
		key,
		title: str$1(x.title, "definition.title"),
		fields: parseFields(x.fields, "definition.fields", 1, {
			nodes: 0,
			bytes: 0
		}),
		location: location(x.location, "definition.location"),
		active: bool$1(x.active, "definition.active")
	};
	if (out.active === void 0) fail$4("definition.active", "is required");
	out.order = num(x.order, "definition.order", true);
	if (x.position !== void 0) out.position = enumValue(x.position, [
		"normal",
		"side",
		"afterTitle"
	], "definition.position");
	if (x.style !== void 0) out.style = enumValue(x.style, ["default", "seamless"], "definition.style");
	if (x.labelPlacement !== void 0) out.labelPlacement = enumValue(x.labelPlacement, ["top", "left"], "definition.labelPlacement");
	if (x.instructionPlacement !== void 0) out.instructionPlacement = enumValue(x.instructionPlacement, ["label", "field"], "definition.instructionPlacement");
	out.hideOnScreen = strings(x.hideOnScreen, "definition.hideOnScreen");
	if (x.description !== void 0) out.description = str$1(x.description, "definition.description");
	for (const k of Object.keys(out)) if (out[k] === void 0) delete out[k];
	return Object.freeze(out);
}
/** Parses one complete field-group definition at an untrusted runtime boundary. */
function parseFieldGroupDefinition(value) {
	preflight$1(value, {
		nodes: 0,
		bytes: 0
	});
	return parseFieldGroup(value);
}
/** Parses a persisted/imported immutable snapshot before hashing or storage. */
async function parseFieldDefinitionVersion(value) {
	preflight$1(value, {
		nodes: 0,
		bytes: 0
	});
	const x = obj$1(value, "fieldDefinitionVersion");
	keys(x, [
		"groupKey",
		"revision",
		"canonicalHash",
		"definition",
		"createdAt",
		"origin"
	], "fieldDefinitionVersion");
	const groupKey = str$1(x.groupKey, "fieldDefinitionVersion.groupKey");
	if (!/^[a-z][a-z0-9_]*$/.test(groupKey)) fail$4("fieldDefinitionVersion.groupKey", "must be a normalized group key");
	if (typeof x.revision !== "number" || !Number.isSafeInteger(x.revision) || x.revision < 1) fail$4("fieldDefinitionVersion.revision", "must be a positive safe integer");
	const canonicalHash = str$1(x.canonicalHash, "fieldDefinitionVersion.canonicalHash");
	if (!/^[a-f0-9]{64}$/i.test(canonicalHash)) fail$4("fieldDefinitionVersion.canonicalHash", "must be a SHA-256 hex digest");
	const origin = enumValue(x.origin, [
		"code",
		"db",
		"import"
	], "fieldDefinitionVersion.origin");
	const created = x.createdAt instanceof Date ? new Date(Date.prototype.getTime.call(x.createdAt)) : typeof x.createdAt === "string" ? new Date(x.createdAt) : /* @__PURE__ */ new Date("");
	if (Number.isNaN(created.getTime())) fail$4("fieldDefinitionVersion.createdAt", "must be a valid Date or ISO timestamp");
	const definition = parseFieldGroup(x.definition);
	if (definition.key !== groupKey) fail$4("fieldDefinitionVersion.definition.key", "must match groupKey");
	const normalizedHash = await canonicalFieldGroupHash(definition);
	if (canonicalHash.toLowerCase() !== normalizedHash) fail$4("fieldDefinitionVersion.canonicalHash", "does not match the canonical definition bytes");
	return Object.freeze({
		groupKey,
		revision: x.revision,
		canonicalHash: normalizedHash,
		definition,
		createdAt: Object.freeze(created),
		origin
	});
}
function canonicalJson$1(value) {
	if (value === void 0) return "null";
	if (value === null) return "null";
	if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return JSON.stringify(value);
	if (Array.isArray(value)) return `[${value.map(canonicalJson$1).join(",")}]`;
	const record = value;
	return `{${Object.keys(record).filter((key) => record[key] !== void 0).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson$1(record[key])}`).join(",")}}`;
}
/** Computes the canonical immutable FieldGroup digest with the web-standard SHA-256 API. */
async function canonicalFieldGroupHash(definition) {
	const bytes = new TextEncoder().encode(canonicalJson$1(definition));
	const digest = await crypto.subtle.digest("SHA-256", bytes);
	return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
}
/** Current immutable group registry state; historical bytes live in fieldDefinitionVersions. */
var fieldGroupDefinitions = pgTable("field_group_definitions", {
	key: text("key").primaryKey(),
	origin: text("origin").$type().notNull(),
	version: integer("version").notNull().default(1),
	active: boolean("active").notNull().default(true),
	currentRevision: integer("current_revision").notNull().default(1),
	canonicalHash: text("canonical_hash").notNull(),
	definition: jsonb("definition").$type().notNull(),
	shadowedDbVersion: integer("shadowed_db_version"),
	hostSessionId: text("host_session_id"),
	createdAt: timestamp("created_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date()),
	updatedAt: timestamp("updated_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
}, (t) => [
	check("field_group_definitions_version_positive", sql`${t.version} > 0`),
	check("field_group_definitions_revision_positive", sql`${t.currentRevision} > 0`),
	index("field_group_definitions_active_idx").on(t.active, t.key)
]);
var fieldDefinitionVersions = pgTable("field_definition_versions", {
	groupKey: text("group_key").notNull(),
	revision: integer("revision").notNull(),
	canonicalHash: text("canonical_hash").notNull(),
	definition: jsonb("definition").$type().notNull(),
	origin: text("origin").$type().notNull(),
	hostSessionId: text("host_session_id"),
	createdAt: timestamp("created_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
}, (t) => [
	primaryKey({ columns: [t.groupKey, t.revision] }),
	check("field_definition_versions_revision_positive", sql`${t.revision} > 0`),
	index("field_definition_versions_hash_idx").on(t.canonicalHash)
]);
var fieldOptionsDefinitions = pgTable("field_options_definitions", {
	key: text("key").primaryKey(),
	origin: text("origin").$type().notNull(),
	version: integer("version").notNull().default(1),
	active: boolean("active").notNull().default(true),
	currentRevision: integer("current_revision").notNull().default(1),
	canonicalHash: text("canonical_hash").notNull(),
	definition: jsonb("definition").$type().notNull(),
	shadowedDbVersion: integer("shadowed_db_version"),
	hostSessionId: text("host_session_id"),
	createdAt: timestamp("created_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date()),
	updatedAt: timestamp("updated_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
}, (t) => [index("field_options_definitions_active_idx").on(t.active, t.key)]);
var fieldOptionsDefinitionVersions = pgTable("field_options_definition_versions", {
	optionsKey: text("options_key").notNull(),
	revision: integer("revision").notNull(),
	canonicalHash: text("canonical_hash").notNull(),
	definition: jsonb("definition").$type().notNull(),
	origin: text("origin").$type().notNull(),
	hostSessionId: text("host_session_id"),
	createdAt: timestamp("created_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
}, (t) => [primaryKey({ columns: [t.optionsKey, t.revision] }), check("field_options_definition_versions_revision_positive", sql`${t.revision} > 0`)]);
var fieldBlockDefinitions = pgTable("field_block_definitions", {
	key: text("key").primaryKey(),
	origin: text("origin").$type().notNull(),
	version: integer("version").notNull().default(1),
	active: boolean("active").notNull().default(true),
	currentRevision: integer("current_revision").notNull().default(1),
	canonicalHash: text("canonical_hash").notNull(),
	definition: jsonb("definition").$type().notNull(),
	shadowedDbVersion: integer("shadowed_db_version"),
	hostSessionId: text("host_session_id"),
	createdAt: timestamp("created_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date()),
	updatedAt: timestamp("updated_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
}, (t) => [index("field_block_definitions_active_idx").on(t.active, t.key)]);
var fieldBlockDefinitionVersions = pgTable("field_block_definition_versions", {
	blockKey: text("block_key").notNull(),
	revision: integer("revision").notNull(),
	canonicalHash: text("canonical_hash").notNull(),
	definition: jsonb("definition").$type().notNull(),
	origin: text("origin").$type().notNull(),
	hostSessionId: text("host_session_id"),
	createdAt: timestamp("created_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
}, (t) => [primaryKey({ columns: [t.blockKey, t.revision] }), check("field_block_definition_versions_revision_positive", sql`${t.revision} > 0`)]);
var fieldBlockDocuments = pgTable("field_block_documents", {
	entityType: text("entity_type").notNull(),
	entityId: text("entity_id").notNull(),
	version: integer("version").notNull().default(1),
	document: jsonb("document").$type().notNull(),
	definitionVersions: jsonb("definition_versions").$type().notNull(),
	parentRevisionId: text("parent_revision_id").notNull(),
	hostSessionId: text("host_session_id"),
	updatedBy: text("updated_by").notNull(),
	updatedAt: timestamp("updated_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
}, (t) => [primaryKey({ columns: [t.entityType, t.entityId] }), check("field_block_documents_version_positive", sql`${t.version} > 0`)]);
var fieldReusableBlocks = pgTable("field_reusable_blocks", {
	id: text("id").primaryKey(),
	version: integer("version").notNull().default(1),
	document: jsonb("document").$type().notNull(),
	definitionVersions: jsonb("definition_versions").$type().notNull(),
	deletedAt: timestamp("deleted_at", {
		withTimezone: true,
		precision: 3
	}),
	hostSessionId: text("host_session_id"),
	updatedBy: text("updated_by").notNull(),
	updatedAt: timestamp("updated_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
}, (t) => [check("field_reusable_blocks_version_positive", sql`${t.version} > 0`)]);
var fieldRevisions = pgTable("field_revisions", {
	id: uuid("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
	entityType: text("entity_type").notNull(),
	entityId: text("entity_id").notNull(),
	parentRevisionId: text("parent_revision_id").notNull(),
	parentAutosaveId: text("parent_autosave_id"),
	kind: text("kind").$type().notNull(),
	retentionClass: text("retention_class"),
	definitionVersions: jsonb("definition_versions").$type().notNull(),
	values: jsonb("values").$type().notNull(),
	blockDocument: jsonb("block_document").$type(),
	createdAt: timestamp("created_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date()),
	createdBy: text("created_by").notNull(),
	sourceVersion: text("source_version").notNull(),
	hostSessionId: text("host_session_id")
}, (t) => [index("field_revisions_entity_created_idx").on(t.entityType, t.entityId, t.createdAt, t.id), index("field_revisions_parent_idx").on(t.parentRevisionId, t.kind)]);
var fieldsOperationReceipts = pgTable("fields_operation_receipts", {
	operationId: text("operation_id").primaryKey(),
	kind: text("kind").notNull(),
	principalScope: text("principal_scope").notNull(),
	requestHash: text("request_hash").notNull(),
	result: jsonb("result").$type().notNull(),
	createdAt: timestamp("created_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
}, (t) => [index("fields_operation_receipts_kind_idx").on(t.kind, t.createdAt)]);
/** Final recursive typed EAV source of truth. */
var fieldValueNodes = pgTable("field_value_nodes", {
	nodeId: uuid("node_id").primaryKey().$defaultFn(() => crypto.randomUUID()),
	entityType: text("entity_type").notNull(),
	entityId: text("entity_id").notNull(),
	groupKey: text("group_key").notNull(),
	definitionRevision: integer("definition_revision").notNull(),
	fieldKey: text("field_key").notNull(),
	path: text("path").notNull(),
	parentNodeId: uuid("parent_node_id").references(() => fieldValueNodes.nodeId, { onDelete: "cascade" }),
	rowId: text("row_id"),
	layoutKey: text("layout_key"),
	nodeKind: text("node_kind").$type().notNull(),
	ordinal: integer("ordinal").notNull().default(0),
	isNull: boolean("is_null").notNull().default(false),
	valueText: text("value_text"),
	valueNumber: numeric("value_number"),
	valueBoolean: boolean("value_boolean"),
	valueDateTime: text("value_date_time"),
	valueRef: text("value_ref"),
	valueJson: text("value_json"),
	legacySourceIds: jsonb("legacy_source_ids").$type(),
	legacySourceHash: text("legacy_source_hash"),
	hostSessionId: text("host_session_id"),
	createdAt: timestamp("created_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date()),
	updatedAt: timestamp("updated_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
}, (t) => [
	uniqueIndex("field_value_nodes_entity_group_path_uq").on(t.entityType, t.entityId, t.groupKey, t.path),
	uniqueIndex("field_value_nodes_sibling_ordinal_uq").on(t.entityType, t.entityId, t.groupKey, sql`COALESCE(${t.parentNodeId}, '00000000-0000-0000-0000-000000000000'::uuid)`, t.ordinal),
	index("field_value_nodes_entity_idx").on(t.entityType, t.entityId, t.groupKey),
	index("field_value_nodes_definition_idx").on(t.groupKey, t.definitionRevision),
	index("field_value_nodes_text_idx").on(t.entityType, t.fieldKey, t.valueText),
	index("field_value_nodes_number_idx").on(t.entityType, t.fieldKey, t.valueNumber),
	index("field_value_nodes_ref_idx").on(t.entityType, t.fieldKey, t.valueRef),
	check("field_value_nodes_ordinal_nonnegative", sql`${t.ordinal} >= 0`),
	check("field_value_nodes_revision_positive", sql`${t.definitionRevision} > 0`),
	check("field_value_nodes_row_shape", sql`
      (${t.nodeKind} IN ('repeaterRow','flexibleRow') AND ${t.rowId} IS NOT NULL)
      OR (${t.nodeKind} NOT IN ('repeaterRow','flexibleRow') AND ${t.rowId} IS NULL)
    `),
	check("field_value_nodes_layout_shape", sql`
      (${t.nodeKind} = 'flexibleRow' AND ${t.layoutKey} IS NOT NULL)
      OR (${t.nodeKind} <> 'flexibleRow' AND ${t.layoutKey} IS NULL)
    `),
	check("field_value_nodes_lane_shape", sql`
      CASE
        WHEN ${t.nodeKind} <> 'leaf' THEN
          ${t.isNull} = false AND ${t.valueText} IS NULL AND ${t.valueNumber} IS NULL AND ${t.valueBoolean} IS NULL
          AND ${t.valueDateTime} IS NULL AND ${t.valueRef} IS NULL AND ${t.valueJson} IS NULL
        WHEN ${t.isNull} = true THEN
          ${t.valueText} IS NULL AND ${t.valueNumber} IS NULL AND ${t.valueBoolean} IS NULL
          AND ${t.valueDateTime} IS NULL AND ${t.valueRef} IS NULL AND ${t.valueJson} IS NULL
        ELSE
          (CASE WHEN ${t.valueText} IS NOT NULL THEN 1 ELSE 0 END
           + CASE WHEN ${t.valueNumber} IS NOT NULL THEN 1 ELSE 0 END
           + CASE WHEN ${t.valueBoolean} IS NOT NULL THEN 1 ELSE 0 END
           + CASE WHEN ${t.valueDateTime} IS NOT NULL THEN 1 ELSE 0 END
           + CASE WHEN ${t.valueRef} IS NOT NULL THEN 1 ELSE 0 END
           + CASE WHEN ${t.valueJson} IS NOT NULL THEN 1 ELSE 0 END) = 1
      END
    `)
]);
var fieldsImportStaging = pgTable("fields_import_staging", {
	hostSessionId: text("host_session_id").notNull(),
	section: text("section").notNull(),
	ordinal: integer("ordinal").notNull(),
	canonicalHash: text("canonical_hash").notNull(),
	payload: jsonb("payload").$type().notNull(),
	createdAt: timestamp("created_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
}, (t) => [primaryKey({ columns: [
	t.hostSessionId,
	t.section,
	t.ordinal
] }), check("fields_import_staging_ordinal_nonnegative", sql`${t.ordinal} >= 0`)]);
var fieldsImportJournal = pgTable("fields_import_journal", {
	importId: uuid("import_id").primaryKey().$defaultFn(() => crypto.randomUUID()),
	hostSessionId: text("host_session_id").notNull(),
	manifestHash: text("manifest_hash").notNull(),
	planHash: text("plan_hash").notNull(),
	state: text("state").notNull(),
	version: integer("version").notNull().default(0),
	nextSection: text("next_section"),
	nextOffset: integer("next_offset"),
	highWaterMark: text("high_water_mark"),
	payload: jsonb("payload").$type(),
	createdAt: timestamp("created_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date()),
	updatedAt: timestamp("updated_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
}, (t) => [uniqueIndex("fields_import_journal_session_uq").on(t.hostSessionId), check("fields_import_journal_version_nonnegative", sql`${t.version} >= 0`)]);
var fieldsMigrationCheckpoints = pgTable("fields_migration_checkpoints", {
	migrationId: text("migration_id").notNull(),
	adapter: text("adapter").$type().notNull(),
	phase: text("phase").$type().notNull(),
	batchOrdinal: integer("batch_ordinal").notNull().default(0),
	version: integer("version").notNull().default(0),
	lastKey: text("last_key"),
	sourceCount: integer("source_count").notNull(),
	targetCount: integer("target_count"),
	sourceHash: text("source_hash").notNull(),
	targetHash: text("target_hash"),
	highWaterMark: text("high_water_mark"),
	createdAt: timestamp("created_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date()),
	updatedAt: timestamp("updated_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
}, (t) => [primaryKey({ columns: [
	t.migrationId,
	t.adapter,
	t.phase,
	t.batchOrdinal
] })]);
var fieldsMigrationWriteJournal = pgTable("fields_migration_write_journal", {
	seq: bigserial("seq", { mode: "number" }).primaryKey(),
	migrationId: text("migration_id").notNull(),
	operation: text("operation").$type().notNull(),
	valueId: text("value_id").notNull(),
	beforeValue: jsonb("before_value").$type(),
	afterValue: jsonb("after_value").$type(),
	createdAt: timestamp("created_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
}, (t) => [index("fields_migration_write_journal_migration_seq_idx").on(t.migrationId, t.seq)]);
var fieldValues = pgTable("field_values", {
	id: uuid("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
	entityType: text("entity_type").notNull(),
	entityId: text("entity_id").notNull(),
	groupId: text("group_id").notNull(),
	fieldKey: text("field_key").notNull(),
	ordinal: integer("ordinal").notNull().default(0),
	valueText: text("value_text"),
	valueNum: numeric("value_num"),
	valueBool: boolean("value_bool"),
	valueDate: timestamp("value_date", {
		withTimezone: true,
		precision: 3
	}),
	refType: text("ref_type"),
	refId: text("ref_id"),
	refMeta: jsonb("ref_meta"),
	createdAt: timestamp("created_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date()),
	updatedAt: timestamp("updated_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
}, (t) => [
	uniqueIndex("field_values_entity_group_field_ord_uq").on(t.entityType, t.entityId, t.groupId, t.fieldKey, t.ordinal),
	index("field_values_entity_idx").on(t.entityType, t.entityId),
	index("field_values_facet_text_idx").on(t.entityType, t.fieldKey, t.valueText),
	index("field_values_facet_num_idx").on(t.entityType, t.fieldKey, t.valueNum),
	index("field_values_facet_date_idx").on(t.entityType, t.fieldKey, t.valueDate),
	index("field_values_ref_idx").on(t.entityType, t.refType, t.refId),
	check("field_values_one_lane", sql`
      (CASE WHEN ${t.valueText} IS NOT NULL THEN 1 ELSE 0 END
     + CASE WHEN ${t.valueNum} IS NOT NULL THEN 1 ELSE 0 END
     + CASE WHEN ${t.valueBool} IS NOT NULL THEN 1 ELSE 0 END
     + CASE WHEN ${t.valueDate} IS NOT NULL THEN 1 ELSE 0 END
     + CASE WHEN ${t.refId} IS NOT NULL THEN 1 ELSE 0 END) = 1`)
]);
var fieldGroups = pgTable("field_groups", {
	id: uuid("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
	entityType: text("entity_type").notNull(),
	subType: text("sub_type"),
	key: text("key").notNull(),
	label: text("label").notNull(),
	fields: jsonb("fields").notNull(),
	position: integer("position").notNull().default(0),
	createdAt: timestamp("created_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date()),
	updatedAt: timestamp("updated_at", {
		withTimezone: true,
		precision: 3
	}).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
}, (t) => [uniqueIndex("field_groups_entity_key_uq").on(t.entityType, t.key)]);
var fieldsSchema = {
	fieldValues,
	fieldGroups,
	fieldGroupDefinitions,
	fieldDefinitionVersions,
	fieldOptionsDefinitions,
	fieldOptionsDefinitionVersions,
	fieldBlockDefinitions,
	fieldBlockDefinitionVersions,
	fieldBlockDocuments,
	fieldReusableBlocks,
	fieldRevisions,
	fieldsOperationReceipts,
	fieldValueNodes,
	fieldsImportStaging,
	fieldsImportJournal,
	fieldsMigrationCheckpoints,
	fieldsMigrationWriteJournal
};
//#endregion
//#region ../../packages/fields/dist/migrate-EWZxeEIR.js
function plainDefault(value) {
	if (value === void 0) return void 0;
	if (value instanceof Date) return value.toISOString();
	if (Array.isArray(value)) return value.map((item) => plainDefault(item));
	if (typeof value === "object" && value !== null) {
		const output = {};
		for (const [key, child] of Object.entries(value)) output[key] = child instanceof Date ? child.toISOString() : child;
		return output;
	}
	return value;
}
function sharedField(field) {
	const defaultValue = plainDefault(field.defaultValue);
	return {
		key: field.key,
		name: field.key,
		label: field.label,
		...field.help ? { instructions: field.help } : {},
		...field.required === void 0 ? {} : { required: field.required },
		...defaultValue === void 0 ? {} : { defaultValue }
	};
}
function legacyFieldToFinalDefinition(field) {
	const shared = sharedField(field);
	switch (field.type) {
		case "text": return {
			...shared,
			type: "text",
			settings: {
				...field.maxLength === void 0 ? {} : { maxLength: field.maxLength },
				...field.pattern === void 0 ? {} : { pattern: { source: field.pattern } }
			}
		};
		case "textarea": return {
			...shared,
			type: "textarea",
			settings: {
				newline: "preserve",
				...field.maxLength === void 0 ? {} : { maxLength: field.maxLength }
			}
		};
		case "number": return {
			...shared,
			type: "number",
			settings: {
				...field.min === void 0 ? {} : { min: field.min },
				...field.max === void 0 ? {} : { max: field.max },
				...field.integer === void 0 ? {} : { integer: field.integer }
			}
		};
		case "boolean": return {
			...shared,
			type: "boolean",
			settings: {}
		};
		case "select": {
			const choices = Object.fromEntries(field.options.map((option) => [option.value, option.label]));
			return {
				...shared,
				type: "select",
				settings: {
					choices,
					...field.multiple === void 0 ? {} : { multiple: field.multiple }
				}
			};
		}
		case "date": return {
			...shared,
			type: "date",
			settings: {
				inputFormat: "yyyy-MM-dd",
				displayFormat: "yyyy-MM-dd",
				returnFormat: "yyyy-MM-dd"
			}
		};
		case "color": return {
			...shared,
			type: "color",
			settings: {}
		};
		case "url": return {
			...shared,
			type: "url",
			settings: { schemes: ["http", "https"] }
		};
		case "email": return {
			...shared,
			type: "email",
			settings: {}
		};
		case "media": {
			const settings = {
				...field.accept?.length ? { mimeTypes: [...field.accept] } : {},
				return: "ref"
			};
			return field.multiple ? {
				...shared,
				type: "gallery",
				settings
			} : {
				...shared,
				type: "file",
				settings
			};
		}
		case "relationship": return {
			...shared,
			type: "relationship",
			settings: {
				entityTypes: [field.targetEntityType],
				return: "ref",
				...field.multiple === false ? { max: 1 } : {}
			}
		};
	}
}
function legacyFieldGroupToFinalDefinition(group) {
	const location = [[{
		parameter: "entityType",
		operator: "eq",
		value: group.location.entityType
	}, ...group.location.subType === void 0 ? [] : [{
		parameter: "subType",
		operator: "eq",
		value: group.location.subType
	}]]];
	return Object.freeze({
		key: group.key,
		title: group.label,
		fields: Object.freeze(group.fields.map(legacyFieldToFinalDefinition)),
		location: Object.freeze(location.map((rules) => Object.freeze(rules))),
		...group.position === void 0 ? {} : { order: group.position },
		active: true
	});
}
async function materializeLegacyFieldDefinitionVersion(group, origin = "db") {
	const definition = legacyFieldGroupToFinalDefinition(group);
	const canonicalHash = await canonicalFieldGroupHash(definition);
	return parseFieldDefinitionVersion({
		groupKey: definition.key,
		revision: 1,
		canonicalHash,
		definition,
		createdAt: /* @__PURE__ */ new Date(0),
		origin
	});
}
var FIELDS_RECURSIVE_EAV_MIGRATION_ID = "fields-recursive-eav-v1";
function canonicalJson(value) {
	if (value === null) return "null";
	if (value instanceof Date) return JSON.stringify(value.toISOString());
	if (typeof value === "string" || typeof value === "boolean") return JSON.stringify(value);
	if (typeof value === "number") {
		if (!Number.isFinite(value)) throw new TypeError("fields migration data cannot contain non-finite numbers");
		return JSON.stringify(value);
	}
	if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
	if (typeof value === "object" && value !== null) {
		const record = value;
		return `{${Object.keys(record).filter((key) => record[key] !== void 0).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(record[key])}`).join(",")}}`;
	}
	throw new TypeError(`unsupported fields migration value: ${typeof value}`);
}
async function canonicalFieldsMigrationHash(value) {
	const bytes = new TextEncoder().encode(canonicalJson(value));
	const digest = await crypto.subtle.digest("SHA-256", bytes);
	return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
}
function plainFlatRow(row) {
	return {
		id: row.id,
		entityType: row.entityType,
		entityId: row.entityId,
		groupId: row.groupId,
		fieldKey: row.fieldKey,
		ordinal: row.ordinal,
		valueText: row.valueText,
		valueNum: row.valueNum,
		valueBool: row.valueBool,
		valueDate: row.valueDate?.toISOString() ?? null,
		refType: row.refType,
		refId: row.refId,
		refMeta: row.refMeta,
		createdAt: row.createdAt.toISOString(),
		updatedAt: row.updatedAt.toISOString()
	};
}
async function snapshotFlatFieldsCorpus(values) {
	const sorted = [...values].sort((left, right) => left.id.localeCompare(right.id));
	return Object.freeze({
		count: sorted.length,
		hash: await canonicalFieldsMigrationHash(sorted.map(plainFlatRow)),
		lastKey: sorted.at(-1)?.id ?? null
	});
}
function escapeFieldPathSegment(value) {
	return value.replaceAll("~", "~0").replaceAll("/", "~1");
}
function fieldPath(fieldKey) {
	return `/f:${escapeFieldPathSegment(fieldKey)}`;
}
async function deterministicUuid(seed) {
	const bytes = new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(seed))).slice(0, 16);
	bytes[6] = bytes[6] & 15 | 80;
	bytes[8] = bytes[8] & 63 | 128;
	const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
	return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
}
function legacyFieldMap(groups) {
	const map = /* @__PURE__ */ new Map();
	for (const group of groups) for (const field of group.fields) map.set(`${group.key}\u0000${field.key}`, field);
	return map;
}
function oneLane(row) {
	if (row.valueText !== null) return {
		lane: "text",
		value: row.valueText
	};
	if (row.valueNum !== null) return {
		lane: "number",
		value: row.valueNum
	};
	if (row.valueBool !== null) return {
		lane: "boolean",
		value: row.valueBool
	};
	if (row.valueDate !== null) return {
		lane: "dateTime",
		value: row.valueDate.toISOString()
	};
	if (row.refType !== null && row.refId !== null) return {
		lane: "ref",
		value: canonicalJson({
			entityType: row.refType,
			entityId: row.refId,
			meta: row.refMeta
		})
	};
	throw new TypeError(`flat field value ${row.id} does not contain exactly one legacy lane`);
}
function isLegacyMultiple(field) {
	if (!field) return false;
	return (field.type === "select" || field.type === "media" || field.type === "relationship") && field.multiple === true;
}
function valueJsonForRows(rows) {
	return canonicalJson(rows.map((row) => {
		const lane = oneLane(row);
		return {
			legacyId: row.id,
			ordinal: row.ordinal,
			lane: lane.lane,
			value: lane.value
		};
	}));
}
async function projectNode(rows, siblingOrdinal, field) {
	const first = rows[0];
	if (!first) throw new TypeError("cannot project an empty field-value group");
	const sorted = [...rows].sort((left, right) => left.ordinal - right.ordinal || left.id.localeCompare(right.id));
	const legacySourceIds = Object.freeze(sorted.map((row) => row.id));
	const legacySourceHash = await canonicalFieldsMigrationHash(sorted.map(plainFlatRow));
	const path = fieldPath(first.fieldKey);
	const base = {
		nodeId: await deterministicUuid([
			FIELDS_RECURSIVE_EAV_MIGRATION_ID,
			first.entityType,
			first.entityId,
			first.groupId,
			path
		].join("\0")),
		entityType: first.entityType,
		entityId: first.entityId,
		groupKey: first.groupId,
		definitionRevision: 1,
		fieldKey: first.fieldKey,
		path,
		parentNodeId: null,
		rowId: null,
		layoutKey: null,
		nodeKind: "leaf",
		ordinal: siblingOrdinal,
		isNull: false,
		valueText: null,
		valueNumber: null,
		valueBoolean: null,
		valueDateTime: null,
		valueRef: null,
		valueJson: null,
		legacySourceIds,
		legacySourceHash
	};
	if (sorted.length > 1 || isLegacyMultiple(field)) return Object.freeze({
		...base,
		valueJson: valueJsonForRows(sorted)
	});
	const lane = oneLane(sorted[0]);
	switch (lane.lane) {
		case "text": return Object.freeze({
			...base,
			valueText: lane.value
		});
		case "number": {
			const valueNumber = Number(lane.value);
			if (!Number.isFinite(valueNumber)) throw new TypeError(`flat numeric field value ${sorted[0].id} is not finite`);
			return Object.freeze({
				...base,
				valueNumber
			});
		}
		case "boolean": return Object.freeze({
			...base,
			valueBoolean: lane.value
		});
		case "dateTime": return Object.freeze({
			...base,
			valueDateTime: lane.value
		});
		case "ref": return Object.freeze({
			...base,
			valueRef: lane.value
		});
	}
}
function assertCompleteLegacyGroups(groups, values) {
	const groupFields = new Map(groups.map((group) => [group.key, new Set(group.fields.map((field) => field.key))]));
	for (const value of values) {
		const fields = groupFields.get(value.groupId);
		if (!fields) throw new TypeError(`flat field value ${value.id} references missing group ${value.groupId}`);
		if (!fields.has(value.fieldKey)) throw new TypeError(`flat field value ${value.id} references missing historical field ${value.groupId}.${value.fieldKey}`);
	}
}
async function planFieldsRecursiveEavMigration(values, groups) {
	assertCompleteLegacyGroups(groups, values);
	const source = await snapshotFlatFieldsCorpus(values);
	const definitions = Object.freeze(await Promise.all([...groups].sort((left, right) => left.key.localeCompare(right.key)).map((group) => materializeLegacyFieldDefinitionVersion(group, "db"))));
	const fields = legacyFieldMap(groups);
	const fieldOrder = /* @__PURE__ */ new Map();
	for (const group of groups) group.fields.forEach((field, index) => fieldOrder.set(`${group.key}\u0000${field.key}`, index));
	const grouped = /* @__PURE__ */ new Map();
	for (const value of values) {
		const key = [
			value.entityType,
			value.entityId,
			value.groupId,
			value.fieldKey
		].join("\0");
		const bucket = grouped.get(key) ?? [];
		bucket.push(value);
		grouped.set(key, bucket);
	}
	const buckets = [...grouped.values()].sort((left, right) => {
		const a = left[0];
		const b = right[0];
		return a.entityType.localeCompare(b.entityType) || a.entityId.localeCompare(b.entityId) || a.groupId.localeCompare(b.groupId) || fieldOrder.get(`${a.groupId}\u0000${a.fieldKey}`) - fieldOrder.get(`${b.groupId}\u0000${b.fieldKey}`) || a.fieldKey.localeCompare(b.fieldKey);
	});
	const nodes = [];
	for (const bucket of buckets) {
		const first = bucket[0];
		const siblingOrdinal = fieldOrder.get(`${first.groupId}\u0000${first.fieldKey}`);
		nodes.push(await projectNode(bucket, siblingOrdinal, fields.get(`${first.groupId}\u0000${first.fieldKey}`)));
	}
	const definitionRefs = Object.freeze(definitions.map((definition) => Object.freeze({
		groupKey: definition.groupKey,
		revision: definition.revision
	})));
	const target = Object.freeze({
		count: nodes.length,
		hash: await canonicalFieldsMigrationHash(nodes),
		lastKey: nodes.at(-1)?.nodeId ?? null
	});
	return Object.freeze({
		migrationId: FIELDS_RECURSIVE_EAV_MIGRATION_ID,
		source,
		target,
		definitions,
		definitionRefs,
		nodes: Object.freeze(nodes)
	});
}
function postgresDefinitionTables() {
	return [
		`CREATE TABLE IF NOT EXISTS field_group_definitions (
      key text PRIMARY KEY, origin text NOT NULL, version integer NOT NULL DEFAULT 1 CHECK (version > 0),
      active boolean NOT NULL DEFAULT true, current_revision integer NOT NULL DEFAULT 1 CHECK (current_revision > 0),
      canonical_hash text NOT NULL, definition jsonb NOT NULL, shadowed_db_version integer, host_session_id text,
      created_at timestamptz(3) NOT NULL DEFAULT NOW(), updated_at timestamptz(3) NOT NULL DEFAULT NOW()
    )`,
		`CREATE TABLE IF NOT EXISTS field_definition_versions (
      group_key text NOT NULL, revision integer NOT NULL CHECK (revision > 0), canonical_hash text NOT NULL,
      definition jsonb NOT NULL, origin text NOT NULL, host_session_id text,
      created_at timestamptz(3) NOT NULL DEFAULT NOW(), PRIMARY KEY (group_key, revision)
    )`,
		`CREATE TABLE IF NOT EXISTS field_options_definitions (
      key text PRIMARY KEY, origin text NOT NULL, version integer NOT NULL DEFAULT 1 CHECK (version > 0),
      active boolean NOT NULL DEFAULT true, current_revision integer NOT NULL DEFAULT 1 CHECK (current_revision > 0),
      canonical_hash text NOT NULL, definition jsonb NOT NULL, shadowed_db_version integer, host_session_id text,
      created_at timestamptz(3) NOT NULL DEFAULT NOW(), updated_at timestamptz(3) NOT NULL DEFAULT NOW()
    )`,
		`CREATE TABLE IF NOT EXISTS field_options_definition_versions (
      options_key text NOT NULL, revision integer NOT NULL CHECK (revision > 0), canonical_hash text NOT NULL,
      definition jsonb NOT NULL, origin text NOT NULL, host_session_id text,
      created_at timestamptz(3) NOT NULL DEFAULT NOW(), PRIMARY KEY (options_key, revision)
    )`,
		`CREATE TABLE IF NOT EXISTS field_block_definitions (
      key text PRIMARY KEY, origin text NOT NULL, version integer NOT NULL DEFAULT 1 CHECK (version > 0),
      active boolean NOT NULL DEFAULT true, current_revision integer NOT NULL DEFAULT 1 CHECK (current_revision > 0),
      canonical_hash text NOT NULL, definition jsonb NOT NULL, shadowed_db_version integer, host_session_id text,
      created_at timestamptz(3) NOT NULL DEFAULT NOW(), updated_at timestamptz(3) NOT NULL DEFAULT NOW()
    )`,
		`CREATE TABLE IF NOT EXISTS field_block_definition_versions (
      block_key text NOT NULL, revision integer NOT NULL CHECK (revision > 0), canonical_hash text NOT NULL,
      definition jsonb NOT NULL, origin text NOT NULL, host_session_id text,
      created_at timestamptz(3) NOT NULL DEFAULT NOW(), PRIMARY KEY (block_key, revision)
    )`
	];
}
function d1DefinitionTables() {
	const current = (table) => `CREATE TABLE IF NOT EXISTS ${table} (
    key TEXT PRIMARY KEY, origin TEXT NOT NULL, version INTEGER NOT NULL DEFAULT 1 CHECK (version > 0),
    active INTEGER NOT NULL DEFAULT 1 CHECK (active IN (0,1)), current_revision INTEGER NOT NULL DEFAULT 1 CHECK (current_revision > 0),
    canonical_hash TEXT NOT NULL, definition TEXT NOT NULL, shadowed_db_version INTEGER, host_session_id TEXT,
    created_at TEXT NOT NULL, updated_at TEXT NOT NULL
  )`;
	const version = (table, key) => `CREATE TABLE IF NOT EXISTS ${table} (
    ${key} TEXT NOT NULL, revision INTEGER NOT NULL CHECK (revision > 0), canonical_hash TEXT NOT NULL,
    definition TEXT NOT NULL, origin TEXT NOT NULL, host_session_id TEXT, created_at TEXT NOT NULL,
    PRIMARY KEY (${key}, revision)
  )`;
	return [
		current("field_group_definitions"),
		version("field_definition_versions", "group_key"),
		current("field_options_definitions"),
		version("field_options_definition_versions", "options_key"),
		current("field_block_definitions"),
		version("field_block_definition_versions", "block_key")
	];
}
function postgresForwardSql() {
	return Object.freeze([
		...postgresDefinitionTables(),
		`CREATE TABLE IF NOT EXISTS field_value_nodes (
      node_id uuid PRIMARY KEY, entity_type text NOT NULL, entity_id text NOT NULL, group_key text NOT NULL,
      definition_revision integer NOT NULL CHECK (definition_revision > 0), field_key text NOT NULL, path text NOT NULL,
      parent_node_id uuid REFERENCES field_value_nodes(node_id) ON DELETE CASCADE, row_id text, layout_key text,
      node_kind text NOT NULL CHECK (node_kind IN ('group','repeaterRow','flexibleRow','leaf')),
      ordinal integer NOT NULL CHECK (ordinal >= 0), is_null boolean NOT NULL DEFAULT false,
      value_text text, value_number numeric, value_boolean boolean, value_date_time text, value_ref text, value_json text,
      legacy_source_ids jsonb, legacy_source_hash text, host_session_id text,
      created_at timestamptz(3) NOT NULL DEFAULT NOW(), updated_at timestamptz(3) NOT NULL DEFAULT NOW(),
      CONSTRAINT field_value_nodes_row_shape CHECK (
        (node_kind IN ('repeaterRow','flexibleRow') AND row_id IS NOT NULL)
        OR (node_kind NOT IN ('repeaterRow','flexibleRow') AND row_id IS NULL)
      ),
      CONSTRAINT field_value_nodes_layout_shape CHECK (
        (node_kind = 'flexibleRow' AND layout_key IS NOT NULL)
        OR (node_kind <> 'flexibleRow' AND layout_key IS NULL)
      ),
      CONSTRAINT field_value_nodes_lane_shape CHECK (
        CASE
          WHEN node_kind <> 'leaf' THEN is_null = false AND value_text IS NULL AND value_number IS NULL
            AND value_boolean IS NULL AND value_date_time IS NULL AND value_ref IS NULL AND value_json IS NULL
          WHEN is_null = true THEN value_text IS NULL AND value_number IS NULL AND value_boolean IS NULL
            AND value_date_time IS NULL AND value_ref IS NULL AND value_json IS NULL
          ELSE (CASE WHEN value_text IS NOT NULL THEN 1 ELSE 0 END
              + CASE WHEN value_number IS NOT NULL THEN 1 ELSE 0 END
              + CASE WHEN value_boolean IS NOT NULL THEN 1 ELSE 0 END
              + CASE WHEN value_date_time IS NOT NULL THEN 1 ELSE 0 END
              + CASE WHEN value_ref IS NOT NULL THEN 1 ELSE 0 END
              + CASE WHEN value_json IS NOT NULL THEN 1 ELSE 0 END) = 1
        END
      )
    )`,
		`CREATE UNIQUE INDEX IF NOT EXISTS field_value_nodes_entity_group_path_uq
      ON field_value_nodes (entity_type, entity_id, group_key, path)`,
		`CREATE UNIQUE INDEX IF NOT EXISTS field_value_nodes_sibling_ordinal_uq
      ON field_value_nodes (entity_type, entity_id, group_key, COALESCE(parent_node_id, '00000000-0000-0000-0000-000000000000'::uuid), ordinal)`,
		`CREATE INDEX IF NOT EXISTS field_value_nodes_entity_idx ON field_value_nodes (entity_type, entity_id, group_key)`,
		`CREATE INDEX IF NOT EXISTS field_value_nodes_definition_idx ON field_value_nodes (group_key, definition_revision)`,
		`CREATE INDEX IF NOT EXISTS field_value_nodes_text_idx ON field_value_nodes (entity_type, field_key, value_text)`,
		`CREATE INDEX IF NOT EXISTS field_value_nodes_number_idx ON field_value_nodes (entity_type, field_key, value_number)`,
		`CREATE INDEX IF NOT EXISTS field_value_nodes_ref_idx ON field_value_nodes (entity_type, field_key, value_ref)`,
		`CREATE TABLE IF NOT EXISTS fields_import_staging (
      host_session_id text NOT NULL, section text NOT NULL, ordinal integer NOT NULL CHECK (ordinal >= 0),
      canonical_hash text NOT NULL, payload jsonb NOT NULL, created_at timestamptz(3) NOT NULL DEFAULT NOW(),
      PRIMARY KEY (host_session_id, section, ordinal)
    )`,
		`CREATE TABLE IF NOT EXISTS fields_import_journal (
      import_id uuid PRIMARY KEY DEFAULT gen_random_uuid(), host_session_id text NOT NULL UNIQUE,
      manifest_hash text NOT NULL, plan_hash text NOT NULL, state text NOT NULL, version integer NOT NULL DEFAULT 0 CHECK (version >= 0),
      next_section text, next_offset integer, high_water_mark text, payload jsonb,
      created_at timestamptz(3) NOT NULL DEFAULT NOW(), updated_at timestamptz(3) NOT NULL DEFAULT NOW()
    )`,
		`CREATE TABLE IF NOT EXISTS fields_migration_checkpoints (
      migration_id text NOT NULL, adapter text NOT NULL, phase text NOT NULL, batch_ordinal integer NOT NULL DEFAULT 0,
      version integer NOT NULL DEFAULT 0, last_key text, source_count integer NOT NULL, target_count integer,
      source_hash text NOT NULL, target_hash text, high_water_mark text,
      created_at timestamptz(3) NOT NULL DEFAULT NOW(), updated_at timestamptz(3) NOT NULL DEFAULT NOW(),
      PRIMARY KEY (migration_id, adapter, phase, batch_ordinal)
    )`,
		`CREATE TABLE IF NOT EXISTS fields_migration_write_journal (
      seq bigserial PRIMARY KEY, migration_id text NOT NULL, operation text NOT NULL, value_id text NOT NULL,
      before_value jsonb, after_value jsonb, created_at timestamptz(3) NOT NULL DEFAULT NOW()
    )`,
		`CREATE OR REPLACE FUNCTION fields_recursive_eav_journal_fn() RETURNS trigger AS $$
      BEGIN
        INSERT INTO fields_migration_write_journal (migration_id, operation, value_id, before_value, after_value)
        VALUES (
          '${FIELDS_RECURSIVE_EAV_MIGRATION_ID}', lower(TG_OP),
          CASE WHEN TG_OP = 'DELETE' THEN OLD.id::text ELSE NEW.id::text END,
          CASE WHEN TG_OP = 'INSERT' THEN NULL ELSE to_jsonb(OLD) END,
          CASE WHEN TG_OP = 'DELETE' THEN NULL ELSE to_jsonb(NEW) END
        );
        RETURN NULL;
      END;
    $$ LANGUAGE plpgsql`,
		`DROP TRIGGER IF EXISTS fields_recursive_eav_write_trigger ON field_values`,
		`CREATE TRIGGER fields_recursive_eav_write_trigger AFTER INSERT OR UPDATE OR DELETE ON field_values
      FOR EACH ROW EXECUTE FUNCTION fields_recursive_eav_journal_fn()`
	]);
}
function d1JsonRow(prefix) {
	return `json_object(
    'id', ${prefix}.id, 'entity_type', ${prefix}.entity_type, 'entity_id', ${prefix}.entity_id,
    'group_id', ${prefix}.group_id, 'field_key', ${prefix}.field_key, 'ordinal', ${prefix}.ordinal,
    'value_text', ${prefix}.value_text, 'value_num', ${prefix}.value_num, 'value_bool', ${prefix}.value_bool,
    'value_date', ${prefix}.value_date, 'ref_type', ${prefix}.ref_type, 'ref_id', ${prefix}.ref_id,
    'ref_meta', ${prefix}.ref_meta, 'created_at', ${prefix}.created_at, 'updated_at', ${prefix}.updated_at
  )`;
}
function d1ForwardSql() {
	const now = "strftime('%Y-%m-%dT%H:%M:%fZ','now')";
	return Object.freeze([
		...d1DefinitionTables(),
		`CREATE TABLE IF NOT EXISTS field_value_nodes (
      node_id TEXT PRIMARY KEY, entity_type TEXT NOT NULL, entity_id TEXT NOT NULL, group_key TEXT NOT NULL,
      definition_revision INTEGER NOT NULL CHECK (definition_revision > 0), field_key TEXT NOT NULL, path TEXT NOT NULL,
      parent_node_id TEXT REFERENCES field_value_nodes(node_id) ON DELETE CASCADE, row_id TEXT, layout_key TEXT,
      node_kind TEXT NOT NULL CHECK (node_kind IN ('group','repeaterRow','flexibleRow','leaf')),
      ordinal INTEGER NOT NULL CHECK (ordinal >= 0), is_null INTEGER NOT NULL DEFAULT 0 CHECK (is_null IN (0,1)),
      value_text TEXT, value_number TEXT, value_boolean INTEGER, value_date_time TEXT, value_ref TEXT, value_json TEXT,
      legacy_source_ids TEXT, legacy_source_hash TEXT, host_session_id TEXT, created_at TEXT NOT NULL, updated_at TEXT NOT NULL,
      CHECK ((node_kind IN ('repeaterRow','flexibleRow') AND row_id IS NOT NULL)
        OR (node_kind NOT IN ('repeaterRow','flexibleRow') AND row_id IS NULL)),
      CHECK ((node_kind = 'flexibleRow' AND layout_key IS NOT NULL) OR (node_kind <> 'flexibleRow' AND layout_key IS NULL)),
      CHECK (CASE
        WHEN node_kind <> 'leaf' THEN is_null = 0 AND value_text IS NULL AND value_number IS NULL
          AND value_boolean IS NULL AND value_date_time IS NULL AND value_ref IS NULL AND value_json IS NULL
        WHEN is_null = 1 THEN value_text IS NULL AND value_number IS NULL AND value_boolean IS NULL
          AND value_date_time IS NULL AND value_ref IS NULL AND value_json IS NULL
        ELSE (CASE WHEN value_text IS NOT NULL THEN 1 ELSE 0 END
          + CASE WHEN value_number IS NOT NULL THEN 1 ELSE 0 END
          + CASE WHEN value_boolean IS NOT NULL THEN 1 ELSE 0 END
          + CASE WHEN value_date_time IS NOT NULL THEN 1 ELSE 0 END
          + CASE WHEN value_ref IS NOT NULL THEN 1 ELSE 0 END
          + CASE WHEN value_json IS NOT NULL THEN 1 ELSE 0 END) = 1
      END)
    )`,
		`CREATE UNIQUE INDEX IF NOT EXISTS field_value_nodes_entity_group_path_uq
      ON field_value_nodes (entity_type, entity_id, group_key, path)`,
		`CREATE UNIQUE INDEX IF NOT EXISTS field_value_nodes_sibling_ordinal_uq
      ON field_value_nodes (entity_type, entity_id, group_key, COALESCE(parent_node_id, ''), ordinal)`,
		`CREATE INDEX IF NOT EXISTS field_value_nodes_entity_idx ON field_value_nodes (entity_type, entity_id, group_key)`,
		`CREATE INDEX IF NOT EXISTS field_value_nodes_definition_idx ON field_value_nodes (group_key, definition_revision)`,
		`CREATE INDEX IF NOT EXISTS field_value_nodes_text_idx ON field_value_nodes (entity_type, field_key, value_text)`,
		`CREATE INDEX IF NOT EXISTS field_value_nodes_number_idx ON field_value_nodes (entity_type, field_key, value_number)`,
		`CREATE INDEX IF NOT EXISTS field_value_nodes_ref_idx ON field_value_nodes (entity_type, field_key, value_ref)`,
		`CREATE TABLE IF NOT EXISTS fields_import_staging (
      host_session_id TEXT NOT NULL, section TEXT NOT NULL, ordinal INTEGER NOT NULL CHECK (ordinal >= 0),
      canonical_hash TEXT NOT NULL, payload TEXT NOT NULL, created_at TEXT NOT NULL,
      PRIMARY KEY (host_session_id, section, ordinal)
    )`,
		`CREATE TABLE IF NOT EXISTS fields_import_journal (
      import_id TEXT PRIMARY KEY, host_session_id TEXT NOT NULL UNIQUE, manifest_hash TEXT NOT NULL,
      plan_hash TEXT NOT NULL, state TEXT NOT NULL, version INTEGER NOT NULL DEFAULT 0 CHECK (version >= 0),
      next_section TEXT, next_offset INTEGER, high_water_mark TEXT, payload TEXT, created_at TEXT NOT NULL, updated_at TEXT NOT NULL
    )`,
		`CREATE TABLE IF NOT EXISTS fields_migration_checkpoints (
      migration_id TEXT NOT NULL, adapter TEXT NOT NULL, phase TEXT NOT NULL, batch_ordinal INTEGER NOT NULL DEFAULT 0,
      version INTEGER NOT NULL DEFAULT 0, last_key TEXT, source_count INTEGER NOT NULL, target_count INTEGER,
      source_hash TEXT NOT NULL, target_hash TEXT, high_water_mark TEXT, created_at TEXT NOT NULL, updated_at TEXT NOT NULL,
      PRIMARY KEY (migration_id, adapter, phase, batch_ordinal)
    )`,
		`CREATE TABLE IF NOT EXISTS fields_migration_write_journal (
      seq INTEGER PRIMARY KEY AUTOINCREMENT, migration_id TEXT NOT NULL, operation TEXT NOT NULL, value_id TEXT NOT NULL,
      before_value TEXT, after_value TEXT, created_at TEXT NOT NULL DEFAULT (${now})
    )`,
		`DROP TRIGGER IF EXISTS fields_recursive_eav_write_insert`,
		`DROP TRIGGER IF EXISTS fields_recursive_eav_write_update`,
		`DROP TRIGGER IF EXISTS fields_recursive_eav_write_delete`,
		`CREATE TRIGGER fields_recursive_eav_write_insert AFTER INSERT ON field_values BEGIN
      INSERT INTO fields_migration_write_journal (migration_id, operation, value_id, before_value, after_value)
      VALUES ('${FIELDS_RECURSIVE_EAV_MIGRATION_ID}', 'insert', NEW.id, NULL, ${d1JsonRow("NEW")});
    END`,
		`CREATE TRIGGER fields_recursive_eav_write_update AFTER UPDATE ON field_values BEGIN
      INSERT INTO fields_migration_write_journal (migration_id, operation, value_id, before_value, after_value)
      VALUES ('${FIELDS_RECURSIVE_EAV_MIGRATION_ID}', 'update', NEW.id, ${d1JsonRow("OLD")}, ${d1JsonRow("NEW")});
    END`,
		`CREATE TRIGGER fields_recursive_eav_write_delete AFTER DELETE ON field_values BEGIN
      INSERT INTO fields_migration_write_journal (migration_id, operation, value_id, before_value, after_value)
      VALUES ('${FIELDS_RECURSIVE_EAV_MIGRATION_ID}', 'delete', OLD.id, ${d1JsonRow("OLD")}, NULL);
    END`
	]);
}
function fieldsRecursiveEavForwardMigrationSql(adapter) {
	return adapter === "postgres" ? postgresForwardSql() : d1ForwardSql();
}
//#endregion
//#region ../../packages/fields/dist/definition-lifecycle-BMuLY0qV.js
var FieldValidationError = class extends Error {
	field;
	detail;
	name = "FieldValidationError";
	constructor(field, detail) {
		super(`field invalid: ${field} — ${detail}`);
		this.field = field;
		this.detail = detail;
	}
};
var FieldGroupConflictError = class extends Error {
	key;
	detail;
	name = "FieldGroupConflictError";
	constructor(key, detail) {
		super(`group conflict: ${key} — ${detail}`);
		this.key = key;
		this.detail = detail;
	}
};
var FieldAuthorizationError = class extends Error {
	actorId;
	action;
	name = "FieldAuthorizationError";
	constructor(actorId, action) {
		super(`actor ${actorId} cannot ${action}`);
		this.actorId = actorId;
		this.action = action;
	}
};
var FieldStoreError = class extends Error {
	detail;
	name = "FieldStoreError";
	constructor(detail) {
		super(`store error: ${detail}`);
		this.detail = detail;
	}
};
var hasName = (e, n) => typeof e === "object" && e !== null && e.name === n;
var isFieldValidationError = (e) => hasName(e, "FieldValidationError") && "field" in e && "detail" in e;
var isFieldGroupConflictError = (e) => hasName(e, "FieldGroupConflictError") && "key" in e;
var isFieldAuthorizationError = (e) => hasName(e, "FieldAuthorizationError") && "actorId" in e;
var isFieldStoreError = (e) => hasName(e, "FieldStoreError") && "detail" in e;
var FieldDefinitionIntegrityError = class extends Error {
	code;
	groupKey;
	revision;
	detail;
	name = "FieldDefinitionIntegrityError";
	constructor(code, groupKey, revision, detail) {
		super(`field definition ${code}: ${groupKey}@${revision} — ${detail}`);
		this.code = code;
		this.groupKey = groupKey;
		this.revision = revision;
		this.detail = detail;
	}
};
function definitionPayload(value) {
	if (typeof value !== "string") return value;
	try {
		return JSON.parse(value);
	} catch {
		throw new TypeError("definition payload is not valid JSON");
	}
}
async function resolveFieldDefinitionVersion(db, groupKey, revision) {
	const result = await db.execute(sql`
    SELECT
      group_key AS "groupKey",
      revision,
      canonical_hash AS "canonicalHash",
      definition,
      created_at AS "createdAt",
      origin
    FROM field_definition_versions
    WHERE group_key = ${groupKey} AND revision = ${revision}
    LIMIT 1
  `);
	const row = (Array.isArray(result) ? result : typeof result === "object" && result !== null && Array.isArray(result.rows) ? result.rows : [])[0];
	if (!row) throw new FieldDefinitionIntegrityError("definition-not-found", groupKey, revision, "immutable definition version is missing");
	try {
		return await parseFieldDefinitionVersion({
			groupKey: row.groupKey,
			revision: Number(row.revision),
			canonicalHash: row.canonicalHash,
			definition: definitionPayload(row.definition),
			createdAt: row.createdAt,
			origin: row.origin
		});
	} catch {
		throw new FieldDefinitionIntegrityError("definition-corrupt", groupKey, revision, "persisted definition bytes do not match their canonical hash");
	}
}
var DEFAULT_LIMITS = Object.freeze({
	maxBytes: 1048576,
	maxDepth: 12,
	maxNodes: 1e3
});
var PRESENTATION_TYPES = /* @__PURE__ */ new Set([
	"message",
	"accordion",
	"tab"
]);
function fail$1(field, detail) {
	throw new FieldValidationError(field, detail);
}
function obj(value, field) {
	if (typeof value !== "object" || value === null || Array.isArray(value) || Object.getPrototypeOf(value) !== Object.prototype) fail$1(field, "must be a plain object");
	return value;
}
function str(value, field, max = 8192) {
	if (typeof value !== "string" || value.length > max) fail$1(field, `must be a string up to ${max} characters`);
	return value;
}
function nonempty(value, field, max = 4096) {
	const s = str(value, field, max);
	if (!s.length) fail$1(field, "must not be empty");
	return s;
}
function finite(value, field) {
	if (typeof value !== "number" || !Number.isFinite(value)) fail$1(field, "must be a finite number");
	return value;
}
function serializable$1(value, limits = DEFAULT_LIMITS, field = "value", depth = 0, budget = {
	nodes: 0,
	bytes: 0
}) {
	if (depth > limits.maxDepth) fail$1(field, `exceeds maximum depth ${limits.maxDepth}`);
	if (value === null || typeof value === "boolean") return value;
	if (typeof value === "number") {
		if (!Number.isFinite(value)) fail$1(field, "contains non-finite number");
		budget.bytes += 8;
		return value;
	}
	if (typeof value === "string") {
		budget.bytes += new TextEncoder().encode(value).byteLength;
		if (budget.bytes > limits.maxBytes) fail$1(field, `exceeds maximum size ${limits.maxBytes}`);
		return value;
	}
	if (++budget.nodes > limits.maxNodes) fail$1(field, `exceeds maximum node count ${limits.maxNodes}`);
	if (Array.isArray(value)) return Object.freeze(value.map((item, i) => serializable$1(item, limits, `${field}.${i}`, depth + 1, budget)));
	const source = obj(value, field), out = {};
	for (const key of Object.keys(source).sort()) {
		if ([
			"__proto__",
			"prototype",
			"constructor"
		].includes(key)) fail$1(`${field}.${key}`, "is forbidden");
		out[key] = serializable$1(source[key], limits, `${field}.${key}`, depth + 1, budget);
	}
	return Object.freeze(out);
}
function settings(value) {
	return obj(value ?? {}, "settings");
}
function pattern(value, setting, field) {
	if (setting === void 0) return;
	const p = obj(setting, "settings.pattern"), source = nonempty(p.source, "settings.pattern.source", 512), flags = p.flags === void 0 ? "" : str(p.flags, "settings.pattern.flags", 16);
	let rx;
	try {
		rx = new RegExp(source, flags);
	} catch {
		fail$1("settings.pattern", "is invalid");
	}
	if (!rx.test(value)) fail$1(field, "does not match the required pattern");
}
function parseUrl(value, s, field = "value") {
	const raw = nonempty(value, field, 8192);
	if (s.allowRelative === true && /^(?:\/|\.\/|\.\.\/)/.test(raw)) return raw;
	let url;
	try {
		url = new URL(raw);
	} catch {
		fail$1(field, "must be a valid URL");
	}
	const schemes = Array.isArray(s.schemes) ? s.schemes.map(String) : [];
	if (schemes.length && !schemes.includes(url.protocol.replace(/:$/, ""))) fail$1(field, "uses a disallowed URL scheme");
	return url.toString();
}
function choice(value, field) {
	if (typeof value !== "string" && typeof value !== "number") fail$1(field, "must be string or number");
	if (typeof value === "number" && !Number.isFinite(value)) fail$1(field, "must be finite");
	return value;
}
function assertChoiceAllowed(value, s, field) {
	const choices = obj(s.choices ?? {}, "settings.choices");
	if (s.allowCustom !== true && !Object.prototype.hasOwnProperty.call(choices, String(value))) fail$1(field, "is not an allowed choice");
}
function ref$1(value, field) {
	const v = obj(value, field), allowed = /* @__PURE__ */ new Set([
		"entityType",
		"id",
		"taxonomy",
		"kind",
		"mimeType"
	]), out = {};
	for (const key of Object.keys(v)) {
		if (!allowed.has(key)) fail$1(`${field}.${key}`, "is not allowed");
		out[key] = nonempty(v[key], `${field}.${key}`, 256);
	}
	if (!out.id) fail$1(`${field}.id`, "is required");
	return Object.freeze(out);
}
function bounds(length, s, field, defaultMax = 100) {
	const min = typeof s.min === "number" ? s.min : 0, max = typeof s.max === "number" ? Math.min(s.max, defaultMax) : defaultMax;
	if (length < min || length > max) fail$1(field, `must contain ${min}..${max} items`);
}
function parseMap(fields, input, limits, write, depth) {
	if (depth > limits.maxDepth) fail$1("value", `exceeds maximum depth ${limits.maxDepth}`);
	const value = obj(input, "value"), byKey = new Map(fields.map((field) => [field.key, field])), out = {};
	for (const key of Object.keys(value)) if (!byKey.has(key)) fail$1(`value.${key}`, "is not defined");
	for (const field of fields) {
		if (PRESENTATION_TYPES.has(field.type)) continue;
		if (!Object.prototype.hasOwnProperty.call(value, field.key)) {
			if (field.required) fail$1(`value.${field.key}`, "is required");
			continue;
		}
		out[field.key] = parseBuiltin(field.type, value[field.key], field.settings, limits, write, depth + 1);
	}
	return Object.freeze(out);
}
function parseBuiltin(type, input, settingsValue, limits, write, depth = 0) {
	const s = settings(settingsValue);
	if (PRESENTATION_TYPES.has(type)) fail$1("value", `${type} is presentation-only`);
	if (type === "password") {
		const v = obj(input, "value");
		if (!write) {
			if (typeof v.configured !== "boolean" || Object.keys(v).length !== 1) fail$1("value", "password reads expose only configured:boolean");
			return Object.freeze({ configured: v.configured });
		}
		if (v.operation === "clear" || v.operation === "unchanged") {
			if (Object.keys(v).length !== 1) fail$1("value", "password clear/unchanged contain no value");
			return Object.freeze({ operation: v.operation });
		}
		if (v.operation !== "set") fail$1("value.operation", "must be set, clear, or unchanged");
		const raw = nonempty(v.value, "value.value", typeof s.maxLength === "number" ? s.maxLength : 4096);
		if (typeof s.minLength === "number" && raw.length < s.minLength) fail$1("value.value", `must contain at least ${s.minLength} characters`);
		return Object.freeze({
			operation: "set",
			value: raw
		});
	}
	if (type === "text" || type === "textarea" || type === "richText") {
		const value = str(input, "value", typeof s.maxLength === "number" ? s.maxLength : 1e6);
		pattern(value, s.pattern, "value");
		return value;
	}
	if (type === "email") {
		const value = nonempty(input, "value", 320);
		if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) fail$1("value", "must be an email address");
		return value.toLowerCase();
	}
	if (type === "url") return parseUrl(input, s);
	if (type === "number" || type === "range") {
		const value = finite(input, "value");
		if (s.integer === true && !Number.isSafeInteger(value)) fail$1("value", "must be a safe integer");
		if (typeof s.min === "number" && value < s.min) fail$1("value", `must be >= ${s.min}`);
		if (typeof s.max === "number" && value > s.max) fail$1("value", `must be <= ${s.max}`);
		if (typeof s.step === "number" && s.step > 0) {
			const ratio = (value - (typeof s.min === "number" ? s.min : 0)) / s.step;
			if (Math.abs(ratio - Math.round(ratio)) > 1e-9) fail$1("value", `must align to step ${s.step}`);
		}
		return value;
	}
	if (type === "boolean") {
		if (typeof input !== "boolean") fail$1("value", "must be boolean");
		return input;
	}
	if (type === "select" || type === "radio" || type === "buttonGroup") {
		if (input === null && s.allowNull === true) return null;
		if (s.multiple === true) {
			if (!Array.isArray(input)) fail$1("value", "must be an array");
			const values = [...new Set(input.map((v, i) => choice(v, `value.${i}`)))];
			values.forEach((v) => assertChoiceAllowed(v, s, "value"));
			bounds(values.length, s, "value", 1e3);
			return Object.freeze(values);
		}
		const value = choice(input, "value");
		assertChoiceAllowed(value, s, "value");
		return value;
	}
	if (type === "checkbox") {
		if (!Array.isArray(input)) fail$1("value", "must be an array");
		const values = [...new Set(input.map((v, i) => choice(v, `value.${i}`)))];
		values.forEach((v) => assertChoiceAllowed(v, s, "value"));
		bounds(values.length, s, "value", 1e3);
		return Object.freeze(values);
	}
	if (type === "oembed") {
		const v = obj(input, "value"), url = parseUrl(v.url, { schemes: ["http", "https"] }, "value.url"), metadata = v.metadata === void 0 ? void 0 : serializable$1(v.metadata, limits, "value.metadata");
		return Object.freeze({
			url,
			...metadata === void 0 ? {} : { metadata }
		});
	}
	if (type === "link") {
		if (input === null) return null;
		const v = obj(input, "value"), url = parseUrl(v.url, { schemes: s.schemes ?? ["http", "https"] }, "value.url"), title = str(v.title, "value.title", 4096), target = v.target;
		if (target !== void 0 && target !== "_self" && target !== "_blank") fail$1("value.target", "must be _self or _blank");
		return Object.freeze({
			url,
			title,
			...target === void 0 ? {} : { target }
		});
	}
	if (type === "image" || type === "file") {
		if (input === null) return null;
		const r = ref$1(input, "value");
		if (r.kind !== type) fail$1("value.kind", `must be ${type}`);
		return r;
	}
	if (type === "gallery") {
		if (!Array.isArray(input)) fail$1("value", "must be an array");
		const refs = input.map((item, i) => {
			const r = ref$1(item, `value.${i}`);
			if (r.kind !== "image") fail$1(`value.${i}.kind`, "must be image");
			return r;
		});
		bounds(refs.length, s, "value");
		return Object.freeze(refs);
	}
	if (type === "entity" || type === "entityLink") {
		if (input === null) return null;
		const r = ref$1(input, "value");
		if (!r.entityType) fail$1("value.entityType", "is required");
		const allowed = Array.isArray(s.entityTypes) ? s.entityTypes.map(String) : [];
		if (allowed.length && !allowed.includes(r.entityType)) fail$1("value.entityType", "is not allowed");
		return r;
	}
	if (type === "relationship") {
		if (!Array.isArray(input)) fail$1("value", "must be an array");
		const refs = input.map((item, i) => {
			const r = ref$1(item, `value.${i}`);
			if (!r.entityType) fail$1(`value.${i}.entityType`, "is required");
			const allowed = Array.isArray(s.entityTypes) ? s.entityTypes.map(String) : [];
			if (allowed.length && !allowed.includes(r.entityType)) fail$1(`value.${i}.entityType`, "is not allowed");
			return r;
		});
		const seen = /* @__PURE__ */ new Set();
		for (const r of refs) {
			const key = `${r.entityType}:${r.id}`;
			if (seen.has(key)) fail$1("value", "contains duplicate relationship target");
			seen.add(key);
		}
		bounds(refs.length, s, "value");
		return Object.freeze(refs);
	}
	if (type === "taxonomy") {
		if (input === null) return null;
		const one = (item, field) => {
			const r = ref$1(item, field);
			if (!r.taxonomy) fail$1(`${field}.taxonomy`, "is required");
			const allowed = Array.isArray(s.taxonomies) ? s.taxonomies.map(String) : [];
			if (allowed.length && !allowed.includes(r.taxonomy)) fail$1(`${field}.taxonomy`, "is not allowed");
			return r;
		};
		if (s.multiple === true) {
			if (!Array.isArray(input)) fail$1("value", "must be an array");
			return Object.freeze(input.map((item, i) => one(item, `value.${i}`)));
		}
		return one(input, "value");
	}
	if (type === "user") {
		if (input === null) return null;
		const one = (item, field) => Object.freeze({ id: nonempty(obj(item, field).id, `${field}.id`, 256) });
		if (s.multiple === true) {
			if (!Array.isArray(input)) fail$1("value", "must be an array");
			return Object.freeze(input.map((item, i) => one(item, `value.${i}`)));
		}
		return one(input, "value");
	}
	if (type === "date") {
		if (input === null) return null;
		const value = str(input, "value", 64);
		if (!/^\d{4}-\d{2}-\d{2}$/.test(value) || Number.isNaN(Date.parse(`${value}T00:00:00Z`))) fail$1("value", "must be YYYY-MM-DD");
		return value;
	}
	if (type === "time") {
		if (input === null) return null;
		const value = str(input, "value", 64);
		if (!/^(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d{1,3})?)?$/.test(value)) fail$1("value", "must be canonical local time");
		return value;
	}
	if (type === "dateTime") {
		if (input === null) return null;
		const value = str(input, "value", 128), date = new Date(value);
		if (Number.isNaN(date.getTime())) fail$1("value", "must be valid date-time");
		return date.toISOString();
	}
	if (type === "color") {
		if (input === null) return null;
		const value = str(input, "value", 32).toLowerCase();
		if (!(s.alpha === true ? /^#(?:[0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/ : /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/).test(value)) fail$1("value", "must be canonical hex color");
		return value;
	}
	if (type === "icon") {
		if (input === null && s.allowNull === true) return null;
		const v = obj(input, "value"), set = nonempty(v.set, "value.set", 128), name = nonempty(v.name, "value.name", 256), allowed = Array.isArray(s.sets) ? s.sets.map(String) : [];
		if (allowed.length && !allowed.includes(set)) fail$1("value.set", "is not allowed");
		return Object.freeze({
			set,
			name
		});
	}
	if (type === "map") {
		if (input === null) return null;
		const v = obj(input, "value"), latitude = finite(v.latitude, "value.latitude"), longitude = finite(v.longitude, "value.longitude");
		if (latitude < -90 || latitude > 90) fail$1("value.latitude", "must be between -90 and 90");
		if (longitude < -180 || longitude > 180) fail$1("value.longitude", "must be between -180 and 180");
		const address = v.address === void 0 ? void 0 : str(v.address, "value.address", 4096), zoom = v.zoom === void 0 ? void 0 : finite(v.zoom, "value.zoom"), metadata = v.metadata === void 0 ? void 0 : serializable$1(v.metadata, limits, "value.metadata");
		return Object.freeze({
			latitude,
			longitude,
			...address === void 0 ? {} : { address },
			...zoom === void 0 ? {} : { zoom },
			...metadata === void 0 ? {} : { metadata }
		});
	}
	if (type === "group") return parseMap(Array.isArray(s.fields) ? s.fields : [], input, limits, write, depth + 1);
	if (type === "repeater") {
		if (!Array.isArray(input)) fail$1("value", "must be array");
		bounds(input.length, s, "value");
		const fields = Array.isArray(s.fields) ? s.fields : [], ids = /* @__PURE__ */ new Set();
		return Object.freeze(input.map((raw, i) => {
			const row = obj(raw, `value.${i}`), rowId = nonempty(row.rowId, `value.${i}.rowId`, 256);
			if (ids.has(rowId)) fail$1(`value.${i}.rowId`, "must be unique");
			ids.add(rowId);
			return Object.freeze({
				rowId,
				values: parseMap(fields, row.values, limits, write, depth + 1)
			});
		}));
	}
	if (type === "flexible") {
		if (!Array.isArray(input)) fail$1("value", "must be array");
		bounds(input.length, s, "value");
		const layouts = Array.isArray(s.layouts) ? s.layouts : [], layoutMap = new Map(layouts.map((l) => [String(l.key), l])), ids = /* @__PURE__ */ new Set();
		return Object.freeze(input.map((raw, i) => {
			const row = obj(raw, `value.${i}`), rowId = nonempty(row.rowId, `value.${i}.rowId`, 256), layoutKey = nonempty(row.layoutKey, `value.${i}.layoutKey`, 256);
			if (ids.has(rowId)) fail$1(`value.${i}.rowId`, "must be unique");
			ids.add(rowId);
			const layout = layoutMap.get(layoutKey);
			if (!layout) fail$1(`value.${i}.layoutKey`, "is not registered");
			return Object.freeze({
				rowId,
				layoutKey,
				values: parseMap(Array.isArray(layout.fields) ? layout.fields : [], row.values, limits, write, depth + 1)
			});
		}));
	}
	if (type === "clone") return serializable$1(input, limits);
	fail$1("type", `unsupported field type ${type}`);
}
var BUILTIN_TYPES = Object.freeze([
	"text",
	"textarea",
	"number",
	"range",
	"email",
	"url",
	"password",
	"boolean",
	"select",
	"checkbox",
	"radio",
	"buttonGroup",
	"richText",
	"oembed",
	"link",
	"message",
	"image",
	"file",
	"gallery",
	"entity",
	"entityLink",
	"relationship",
	"taxonomy",
	"user",
	"date",
	"dateTime",
	"time",
	"color",
	"icon",
	"map",
	"accordion",
	"tab",
	"group",
	"repeater",
	"flexible",
	"clone"
]);
function digest(seed) {
	let a = 2166136261, b = 2654435769;
	for (let round = 0; round < 8; round++) {
		for (let i = 0; i < seed.length; i++) {
			a = Math.imul(a ^ seed.charCodeAt(i) + round, 16777619);
			b = Math.imul(b ^ (seed.charCodeAt(i) << i % 8) + round, 2246822507);
		}
		seed = `${seed}:${(a >>> 0).toString(16)}:${(b >>> 0).toString(16)}`;
	}
	return `${(a >>> 0).toString(16).padStart(8, "0")}${(b >>> 0).toString(16).padStart(8, "0")}`.repeat(4).slice(0, 64);
}
function parseDefinitionFor(type, input) {
	const parsed = parseFieldDefinition(input);
	if (parsed.type !== type) fail$1("definition.type", `must be ${type}`);
	return Object.freeze({
		key: parsed.key,
		name: parsed.name,
		label: parsed.label,
		type,
		settings: parsed.settings,
		...parsed.required === void 0 ? {} : { required: parsed.required },
		...parsed.readOnly === void 0 ? {} : { readOnly: parsed.readOnly }
	});
}
function builtinSchema(type, s) {
	const nullable = [
		"link",
		"image",
		"file",
		"entity",
		"entityLink",
		"taxonomy",
		"user",
		"date",
		"dateTime",
		"time",
		"color",
		"icon",
		"map"
	].includes(type);
	return Object.freeze({
		type,
		nullable,
		readOnly: PRESENTATION_TYPES.has(type),
		constraints: serializable$1(s ?? {}, DEFAULT_LIMITS, "settings")
	});
}
async function builtinFormat(type, value, context) {
	if (type === "richText") {
		if (typeof value !== "string") fail$1("value", "richText formatter requires a string");
		return Object.freeze({
			kind: "sanitizedHtml",
			value: await sanitizeFieldHtml(value, context)
		});
	}
	if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null) return Object.freeze({
		kind: "text",
		value: value === null ? "" : String(value)
	});
	return Object.freeze({
		kind: "structured",
		value: serializable$1(value)
	});
}
function createBuiltinFieldTypeDescriptors() {
	return Object.freeze(BUILTIN_TYPES.map((type) => Object.freeze({
		type,
		contractVersion: "1",
		schemaHash: digest(`schema:${type}:1`),
		codecHash: digest(`codec:${type}:1`),
		parseDefinition: (input) => parseDefinitionFor(type, input),
		parseValue: (input, s, limits) => parseBuiltin(type, input, s, limits, false),
		parseWrite: (input, s, limits) => parseBuiltin(type, input, s, limits, true),
		serialize: (value) => serializable$1(value),
		deserialize: (value, s) => parseBuiltin(type, value, s, DEFAULT_LIMITS, false),
		format: (value, _s, context) => builtinFormat(type, value, context),
		schema: (s) => builtinSchema(type, s),
		redactForRevision: (value) => type === "password" ? Object.freeze({ configured: Boolean(value?.configured) }) : PRESENTATION_TYPES.has(type) ? "omit" : serializable$1(value)
	})));
}
function descriptorFor(definition, registry) {
	const descriptor = registry.resolve(definition.type);
	if (!descriptor) fail$1("definition.type", `unregistered field type ${definition.type}`);
	return descriptor;
}
function fieldSettings(definition) {
	return definition.settings;
}
function refsFromValue(definition, value) {
	if (definition.type === "entity" || definition.type === "entityLink") return value === null ? [] : [value];
	if (definition.type === "relationship") return value;
	return [];
}
async function validateMedia(definition, value, resolver) {
	if (![
		"image",
		"file",
		"gallery"
	].includes(definition.type) || value === null) return;
	if (!resolver) fail$1("mediaMetadata", "is required to validate media values");
	const s = settings(definition.settings), refs = definition.type === "gallery" ? value : [value];
	for (const r of refs) {
		const meta = await resolver.resolve(r);
		if (!meta) fail$1("mediaMetadata", "is unavailable for a referenced item");
		const mimes = Array.isArray(s.mimeTypes) ? s.mimeTypes.map(String) : [];
		if (mimes.length && !mimes.some((allowed) => allowed.endsWith("/*") ? meta.mimeType.startsWith(allowed.slice(0, -1)) : meta.mimeType === allowed)) fail$1("value", "uses disallowed media MIME type");
		if (typeof s.minBytes === "number" && meta.bytes < s.minBytes) fail$1("value", "media is below minimum byte size");
		if (typeof s.maxBytes === "number" && meta.bytes > s.maxBytes) fail$1("value", "media exceeds maximum byte size");
		if (definition.type !== "file") for (const [key, actual] of [
			["minWidth", meta.width],
			["maxWidth", meta.width],
			["minHeight", meta.height],
			["maxHeight", meta.height]
		]) {
			const bound = s[key];
			if (typeof bound === "number" && actual === void 0) fail$1("mediaMetadata", `missing ${key.includes("Width") ? "width" : "height"}`);
			if (typeof bound === "number" && key.startsWith("min") && actual < bound) fail$1("value", `media violates ${key}`);
			if (typeof bound === "number" && key.startsWith("max") && actual > bound) fail$1("value", `media violates ${key}`);
		}
	}
}
async function validateFieldValue(definition, input, registry, context = {}, limits = DEFAULT_LIMITS) {
	let value;
	if (definition.type === "clone" && context.cloneResolver) value = parseMap(context.cloneResolver.resolve(definition), input, limits, true, 0);
	else value = descriptorFor(definition, registry).parseWrite(input, fieldSettings(definition), limits);
	if (definition.type === "richText") {
		if (!context.sanitizer) fail$1("sanitizer", "is required to validate richText");
		const sanitized = await context.sanitizer.sanitizeHtml(String(value));
		if (typeof sanitized !== "string") fail$1("sanitizer", "must return a string");
		value = sanitized;
	}
	await validateMedia(definition, value, context.mediaMetadata);
	const auth = context.authorization;
	if (auth) for (const r of refsFromValue(definition, value)) await auth.assertTarget(r, "readTarget");
	return value;
}
function redactFieldValueForRevision(definition, value, registry) {
	return descriptorFor(definition, registry).redactForRevision(value, fieldSettings(definition));
}
function pathField(parent, key) {
	return `${parent}/f:${escapeFieldPathSegment(key)}`;
}
function pathRow(parent, rowId) {
	return `${parent}/r:${escapeFieldPathSegment(rowId)}`;
}
function pathLayout(parent, layoutKey) {
	return `${parent}/l:${escapeFieldPathSegment(layoutKey)}`;
}
function leafLane(value) {
	const empty = {
		valueText: null,
		valueNumber: null,
		valueBoolean: null,
		valueDateTime: null,
		valueRef: null,
		valueJson: null
	};
	if (value === null) return {
		isNull: true,
		...empty
	};
	if (typeof value === "string") return {
		isNull: false,
		...empty,
		valueText: value
	};
	if (typeof value === "number") return {
		isNull: false,
		...empty,
		valueNumber: value
	};
	if (typeof value === "boolean") return {
		isNull: false,
		...empty,
		valueBoolean: value
	};
	return {
		isNull: false,
		...empty,
		valueJson: JSON.stringify(serializable$1(value))
	};
}
function encodeFieldValueNodes(group, values, options) {
	const nodes = [];
	const seenPaths = /* @__PURE__ */ new Set();
	const add = (row) => {
		if (seenPaths.has(row.path)) fail$1(row.path, "resolves to a duplicate materialized path");
		seenPaths.add(row.path);
		nodes.push(Object.freeze(row));
	};
	const structural = (field, path, parent, kind, ordinal, rowId = null, layoutKey = null) => add({
		nodeId: options.nodeIdForPath(path),
		entityType: options.entityType,
		entityId: options.entityId,
		groupKey: group.key,
		definitionRevision: options.definitionRevision,
		fieldKey: field.key,
		path,
		parentNodeId: parent,
		rowId,
		layoutKey,
		nodeKind: kind,
		ordinal,
		isNull: false,
		valueText: null,
		valueNumber: null,
		valueBoolean: null,
		valueDateTime: null,
		valueRef: null,
		valueJson: null
	});
	const walkFields = (fields, map, parentPath, parentId) => {
		fields.forEach((field, ordinal) => {
			if (PRESENTATION_TYPES.has(field.type)) return;
			const value = map[field.key], path = pathField(parentPath, field.key);
			if (field.type === "group") {
				structural(field, path, parentId, "group", ordinal);
				walkFields(field.settings.fields, value ?? {}, path, options.nodeIdForPath(path));
				return;
			}
			if (field.type === "repeater") {
				structural(field, path, parentId, "group", ordinal);
				const baseId = options.nodeIdForPath(path);
				for (const [rowOrdinal, row] of (value ?? []).entries()) {
					const rp = pathRow(path, row.rowId);
					structural(field, rp, baseId, "repeaterRow", rowOrdinal, row.rowId);
					walkFields(field.settings.fields, row.values, rp, options.nodeIdForPath(rp));
				}
				return;
			}
			if (field.type === "flexible") {
				structural(field, path, parentId, "group", ordinal);
				const baseId = options.nodeIdForPath(path);
				for (const [rowOrdinal, row] of (value ?? []).entries()) {
					const rp = pathLayout(pathRow(path, row.rowId), row.layoutKey), layout = field.settings.layouts.find((item) => item.key === row.layoutKey);
					if (!layout) fail$1(path, "contains unknown layout");
					structural(field, rp, baseId, "flexibleRow", rowOrdinal, row.rowId, row.layoutKey);
					walkFields(layout.fields, row.values, rp, options.nodeIdForPath(rp));
				}
				return;
			}
			if (field.type === "clone") {
				if (!options.cloneResolver) fail$1(path, "clone resolver is required");
				structural(field, path, parentId, "group", ordinal);
				walkFields(options.cloneResolver.resolve(field), value, path, options.nodeIdForPath(path));
				return;
			}
			const lane = leafLane(value === void 0 ? null : value);
			add({
				nodeId: options.nodeIdForPath(path),
				entityType: options.entityType,
				entityId: options.entityId,
				groupKey: group.key,
				definitionRevision: options.definitionRevision,
				fieldKey: field.key,
				path,
				parentNodeId: parentId,
				rowId: null,
				layoutKey: null,
				nodeKind: "leaf",
				ordinal,
				...lane
			});
		});
	};
	walkFields(group.fields, values, "", null);
	if (nodes.length > 1e3) fail$1("values", "exceeds maximum materialized node count 1000");
	return Object.freeze(nodes);
}
function decodeLane(node) {
	if (node.nodeKind !== "leaf") fail$1(node.path, "is not a leaf node");
	const lanes = [
		node.valueText !== null,
		node.valueNumber !== null,
		node.valueBoolean !== null,
		node.valueDateTime !== null,
		node.valueRef !== null,
		node.valueJson !== null
	].filter(Boolean).length;
	if (node.isNull) {
		if (lanes !== 0) fail$1(node.path, "null leaf contains a value lane");
		return null;
	}
	if (lanes !== 1) fail$1(node.path, "leaf must contain exactly one value lane");
	if (node.valueText !== null) return node.valueText;
	if (node.valueNumber !== null) return node.valueNumber;
	if (node.valueBoolean !== null) return node.valueBoolean;
	if (node.valueDateTime !== null) return node.valueDateTime;
	if (node.valueRef !== null) try {
		return JSON.parse(node.valueRef);
	} catch {
		return node.valueRef;
	}
	try {
		return JSON.parse(node.valueJson);
	} catch {
		fail$1(node.path, "contains invalid JSON lane");
	}
}
function assertNodeShape(node, group, revision) {
	if (node.groupKey !== group.key) fail$1(node.path, "belongs to another field group");
	if (node.definitionRevision !== revision) fail$1(node.path, "mixes immutable definition revisions");
	if (node.ordinal < 0 || !Number.isSafeInteger(node.ordinal)) fail$1(node.path, "has invalid ordinal");
	if (node.nodeKind === "flexibleRow" && (!node.rowId || !node.layoutKey)) fail$1(node.path, "flexible row requires row/layout identity");
	if (node.nodeKind === "repeaterRow" && !node.rowId) fail$1(node.path, "repeater row requires row identity");
	if ((node.nodeKind === "leaf" || node.nodeKind === "group") && (node.rowId !== null || node.layoutKey !== null)) fail$1(node.path, "non-row node carries row/layout identity");
}
function isCanonicalFieldValuePath(path) {
	return path.length > 0 && /^(?:\/(?:f|r|l):(?:[^~/]|~[01])+)+$/.test(path);
}
function decodeFieldValueNodes(group, nodes, options) {
	const byId = /* @__PURE__ */ new Map(), children = /* @__PURE__ */ new Map(), paths = /* @__PURE__ */ new Set();
	for (const node of nodes) {
		assertNodeShape(node, group, options.definitionRevision);
		if (!isCanonicalFieldValuePath(node.path)) fail$1(node.path, "is not a canonical typed field path");
		if (byId.has(node.nodeId)) fail$1(node.path, "duplicates node id");
		if (paths.has(node.path)) fail$1(node.path, "duplicates materialized path");
		byId.set(node.nodeId, node);
		paths.add(node.path);
		const list = children.get(node.parentNodeId) ?? [];
		list.push(node);
		children.set(node.parentNodeId, list);
	}
	for (const list of children.values()) {
		list.sort((a, b) => a.ordinal - b.ordinal || a.path.localeCompare(b.path));
		for (let i = 1; i < list.length; i++) if (list[i - 1].ordinal === list[i].ordinal) fail$1(list[i].path, "duplicates sibling ordinal");
	}
	for (const node of nodes) if (node.parentNodeId !== null && !byId.has(node.parentNodeId)) fail$1(node.path, "references missing parent");
	const fieldsByKey = (fields) => new Map(fields.map((field) => [field.key, field]));
	const readFields = (fields, parentId, parentPath) => {
		const out = {}, defs = fieldsByKey(fields);
		for (const node of children.get(parentId) ?? []) {
			const definition = defs.get(node.fieldKey);
			if (!definition) fail$1(node.path, "references a field absent from the pinned definition");
			const expected = pathField(parentPath, definition.key);
			if (definition.type === "group") {
				if (node.nodeKind !== "group" || node.path !== expected) fail$1(node.path, "has invalid group path/kind");
				out[definition.key] = readFields(definition.settings.fields, node.nodeId, node.path);
				continue;
			}
			if (definition.type === "repeater") {
				if (node.nodeKind !== "group" || node.path !== expected) fail$1(node.path, "has invalid repeater root");
				const rows = [];
				for (const rowNode of children.get(node.nodeId) ?? []) {
					if (rowNode.nodeKind !== "repeaterRow" || !rowNode.rowId || rowNode.path !== pathRow(node.path, rowNode.rowId)) fail$1(rowNode.path, "has invalid repeater row path");
					rows.push(Object.freeze({
						rowId: rowNode.rowId,
						values: readFields(definition.settings.fields, rowNode.nodeId, rowNode.path)
					}));
				}
				out[definition.key] = Object.freeze(rows);
				continue;
			}
			if (definition.type === "flexible") {
				if (node.nodeKind !== "group" || node.path !== expected) fail$1(node.path, "has invalid flexible root");
				const rows = [];
				for (const rowNode of children.get(node.nodeId) ?? []) {
					if (rowNode.nodeKind !== "flexibleRow" || !rowNode.rowId || !rowNode.layoutKey || rowNode.path !== pathLayout(pathRow(node.path, rowNode.rowId), rowNode.layoutKey)) fail$1(rowNode.path, "has invalid flexible row path");
					const layout = definition.settings.layouts.find((item) => item.key === rowNode.layoutKey);
					if (!layout) fail$1(rowNode.path, "references unknown flexible layout");
					rows.push(Object.freeze({
						rowId: rowNode.rowId,
						layoutKey: rowNode.layoutKey,
						values: readFields(layout.fields, rowNode.nodeId, rowNode.path)
					}));
				}
				out[definition.key] = Object.freeze(rows);
				continue;
			}
			if (definition.type === "clone") {
				if (node.nodeKind !== "group" || node.path !== expected) fail$1(node.path, "has invalid clone root");
				if (!options.cloneResolver) fail$1(node.path, "clone resolver is required");
				out[definition.key] = readFields(options.cloneResolver.resolve(definition), node.nodeId, node.path);
				continue;
			}
			if (node.nodeKind !== "leaf" || node.path !== expected) fail$1(node.path, "has invalid leaf path/kind");
			out[definition.key] = decodeLane(node);
		}
		return Object.freeze(out);
	};
	const result = readFields(group.fields, null, "");
	const consumed = /* @__PURE__ */ new Set();
	const mark = (parent) => {
		for (const child of children.get(parent) ?? []) {
			consumed.add(child.nodeId);
			mark(child.nodeId);
		}
	};
	mark(null);
	if (consumed.size !== nodes.length) fail$1("values", "contains unreachable nodes");
	return result;
}
async function authorizeRelationshipReplacement(definition, before, after, authorization) {
	if (definition.type !== "relationship") return;
	const key = (ref) => `${ref.entityType}:${ref.id}`, beforeMap = new Map(before.map((ref) => [key(ref), ref])), afterMap = new Map(after.map((ref) => [key(ref), ref]));
	for (const ref of after) await authorization.assertTarget(ref, "readTarget");
	if (typeof definition.settings === "object" && definition.settings !== null && "bidirectional" in definition.settings && definition.settings.bidirectional !== void 0) {
		for (const [id, ref] of beforeMap) if (!afterMap.has(id)) await authorization.assertTarget(ref, "writeReverseTarget");
		for (const [id, ref] of afterMap) if (!beforeMap.has(id)) await authorization.assertTarget(ref, "writeReverseTarget");
	}
}
var sanitizedFieldHtmlBrand = Symbol("sanitized-field-html");
function requireAuthorizedFieldsContext(context) {
	const authorization = context.authorization;
	if (!context.principal || !authorization || typeof authorization.assert !== "function" || typeof authorization.assertDefinitionMigration !== "function") throw new FieldValidationError("context", "principal and authorization are required");
	return context;
}
var CUSTOM_TYPE_RE = /^[a-z][a-z0-9-]*:[a-z][a-z0-9._-]*$/;
var HEX64 = /^[a-f0-9]{64}$/i;
var FIELD_DEFINITION_LIMITS = Object.freeze({
	maxBytes: 262144,
	maxDepth: 12,
	maxChildren: 1e3
});
var FIELD_VALUE_LIMITS = Object.freeze({
	maxBytes: 1048576,
	maxDepth: 12,
	maxNodes: 1e3
});
function fail$3(field, detail) {
	throw new FieldValidationError(field, detail);
}
function object$1(input, field) {
	if (typeof input !== "object" || input === null || Array.isArray(input) || Object.getPrototypeOf(input) !== Object.prototype) fail$3(field, "must be a plain object");
	return input;
}
function string$1(input, field, max = 4096) {
	if (typeof input !== "string" || input.length === 0 || input.length > max) fail$3(field, `must be a non-empty string up to ${max} characters`);
	return input;
}
function json(value, limits, field = "value", depth = 0, budget = {
	nodes: 0,
	bytes: 0
}) {
	if (depth > limits.maxDepth) fail$3(field, `exceeds maximum depth ${limits.maxDepth}`);
	if (value === null || typeof value === "boolean") return value;
	if (typeof value === "number") {
		if (!Number.isFinite(value)) fail$3(field, "contains a non-finite number");
		budget.bytes += 8;
		return value;
	}
	if (typeof value === "string") {
		budget.bytes += new TextEncoder().encode(value).byteLength;
		if (budget.bytes > limits.maxBytes) fail$3(field, `exceeds maximum size ${limits.maxBytes}`);
		return value;
	}
	if (++budget.nodes > limits.maxNodes) fail$3(field, `exceeds maximum node count ${limits.maxNodes}`);
	if (Array.isArray(value)) return Object.freeze(value.map((item, index) => json(item, limits, `${field}.${index}`, depth + 1, budget)));
	const source = object$1(value, field), out = {};
	for (const key of Object.keys(source).sort()) {
		if (key === "__proto__" || key === "prototype" || key === "constructor") fail$3(`${field}.${key}`, "contains a forbidden key");
		out[key] = json(source[key], limits, `${field}.${key}`, depth + 1, budget);
	}
	return Object.freeze(out);
}
function validateDescriptor(descriptor) {
	if (!CUSTOM_TYPE_RE.test(descriptor.type)) fail$3("descriptor.type", "extension type must use an adopter-owned namespace such as vendor:field");
	if (!descriptor.contractVersion || descriptor.contractVersion.length > 128) fail$3("descriptor.contractVersion", "must be a bounded non-empty string");
	if (!HEX64.test(descriptor.schemaHash)) fail$3("descriptor.schemaHash", "must be a 64-character hexadecimal digest");
	if (!HEX64.test(descriptor.codecHash)) fail$3("descriptor.codecHash", "must be a 64-character hexadecimal digest");
	for (const method of [
		"parseDefinition",
		"parseValue",
		"parseWrite",
		"serialize",
		"deserialize",
		"format",
		"schema",
		"redactForRevision"
	]) if (typeof descriptor[method] !== "function") fail$3(`descriptor.${method}`, "must be a function");
	json(descriptor.schema({}), FIELD_VALUE_LIMITS, "descriptor.schema");
}
function descriptorHash(seed) {
	let a = 2166136261, b = 2654435769;
	for (let round = 0; round < 8; round++) {
		for (let i = 0; i < seed.length; i++) {
			a = Math.imul(a ^ seed.charCodeAt(i) + round, 16777619);
			b = Math.imul(b ^ (seed.charCodeAt(i) << i % 8) + round, 2246822507);
		}
		seed = `${seed}:${(a >>> 0).toString(16)}:${(b >>> 0).toString(16)}`;
	}
	return `${(a >>> 0).toString(16).padStart(8, "0")}${(b >>> 0).toString(16).padStart(8, "0")}`.repeat(4).slice(0, 64);
}
function version(descriptors) {
	return `fields-registry-v1:${descriptorHash(descriptors.map((d) => `${d.type}:${d.contractVersion}:${d.schemaHash}:${d.codecHash}`).join("|"))}`;
}
function createFieldTypeRegistry(input = {}) {
	const builtIns = createBuiltinFieldTypeDescriptors();
	const builtInTypes = new Set(builtIns.map((descriptor) => descriptor.type));
	const extensions = [...input.extensions ?? []];
	const seen = new Set(builtInTypes);
	for (const descriptor of extensions) {
		validateDescriptor(descriptor);
		if (seen.has(descriptor.type)) fail$3("descriptor.type", `duplicate or reserved field type ${descriptor.type}`);
		seen.add(descriptor.type);
	}
	extensions.sort((left, right) => left.type.localeCompare(right.type));
	const ordered = Object.freeze([...builtIns, ...extensions.map((descriptor) => Object.freeze(descriptor))]);
	const map = new Map(ordered.map((descriptor) => [descriptor.type, descriptor]));
	return Object.freeze({
		version: version(ordered),
		builtInTypes,
		has: (type) => map.has(type),
		resolve: (type) => map.get(type),
		parseDefinition(input, limits) {
			const type = string$1(object$1(input, "definition").type, "definition.type", 256), descriptor = map.get(type);
			if (!descriptor) fail$3("definition.type", `unregistered field type ${type}`);
			return descriptor.parseDefinition(input, limits);
		}
	});
}
async function sanitizeFieldHtml(input, context) {
	if (!context.sanitizer) fail$3("sanitizer", "is required for sanitized HTML output");
	const html = await context.sanitizer.sanitizeHtml(input);
	if (typeof html !== "string") fail$3("sanitizer", "must return a string");
	return Object.freeze({
		html,
		[sanitizedFieldHtmlBrand]: true
	});
}
var FieldsLifecycleError = class extends Error {
	code;
	detail;
	field;
	name = "FieldsLifecycleError";
	constructor(code, detail, field) {
		super(`fields lifecycle ${code}: ${detail}${field ? ` (${field})` : ""}`);
		this.code = code;
		this.detail = detail;
		this.field = field;
	}
};
function freezeStorage(value, field = "result", depth = 0) {
	if (depth > 20) throw new FieldsLifecycleError("integrity", "stored payload exceeds maximum depth", field);
	if (value === null || typeof value === "string" || typeof value === "boolean") return value;
	if (typeof value === "number") {
		if (!Number.isFinite(value)) throw new FieldsLifecycleError("integrity", "stored payload contains a non-finite number", field);
		return value;
	}
	if (Array.isArray(value)) return Object.freeze(value.map((item, index) => freezeStorage(item, `${field}.${index}`, depth + 1)));
	if (typeof value === "object") {
		const output = {};
		for (const key of Object.keys(value).sort()) {
			if (key === "__proto__" || key === "prototype" || key === "constructor") throw new FieldsLifecycleError("integrity", "stored payload contains a forbidden key", `${field}.${key}`);
			const child = value[key];
			if (child !== void 0) output[key] = freezeStorage(child, `${field}.${key}`, depth + 1);
		}
		return Object.freeze(output);
	}
	throw new FieldsLifecycleError("integrity", `stored payload contains unsupported ${typeof value}`, field);
}
function assertActiveFieldsTransaction(tx, expectedIdentity) {
	try {
		const identity = getTransactionIdentity(tx);
		if (expectedIdentity !== void 0 && identity !== expectedIdentity) throw new FieldsLifecycleError("transaction-capability", "transaction identity does not match the parent composite");
		return identity;
	} catch (error) {
		if (error instanceof FieldsLifecycleError) throw error;
		if (isTransactionCapabilityError(error)) throw new FieldsLifecycleError("transaction-capability", error.reason);
		throw error;
	}
}
function authorizedFieldsContext(context) {
	try {
		return requireAuthorizedFieldsContext(context);
	} catch {
		throw new FieldsLifecycleError("access-denied", "fields operation is unavailable");
	}
}
async function assertFieldsAuthorized(context, action, ref) {
	const authorized = authorizedFieldsContext(context);
	try {
		await authorized.authorization.assert(authorized.principal, action, ref);
	} catch {
		throw new FieldsLifecycleError("access-denied", "fields operation is unavailable");
	}
	return authorized;
}
function assertPrincipalCapability(context, capability) {
	if (!context.principal.capabilities.has(capability)) throw new FieldsLifecycleError("access-denied", "fields operation is unavailable");
}
async function assertDefinitionMigration(context, entityTypes) {
	const authorized = authorizedFieldsContext(context);
	try {
		await authorized.authorization.assert(authorized.principal, "manageDefinitions", {
			entityType: "fields-definition",
			entityId: "*"
		});
		const result = await authorized.authorization.assertDefinitionMigration(authorized.principal, Object.freeze([...new Set(entityTypes)].sort()));
		if (!result || typeof result.policyVersion !== "string" || result.policyVersion.length === 0) throw new Error("invalid policy version");
		return {
			context: authorized,
			policyVersion: result.policyVersion
		};
	} catch {
		throw new FieldsLifecycleError("access-denied", "fields operation is unavailable");
	}
}
function principalScope(context) {
	return `${context.principal.system === true ? "system" : "principal"}:${context.principal.id}`;
}
async function fieldsRequestHash(value) {
	return canonicalFieldsMigrationHash(value);
}
async function readFieldsReceipt(db, operationId) {
	const row = lifecycleRows(await db.execute(sql`SELECT kind, principal_scope AS "principalScope", request_hash AS "requestHash", result
    FROM fields_operation_receipts WHERE operation_id = ${operationId}`))[0];
	if (!row) return null;
	const result = typeof row.result === "string" ? (() => {
		try {
			return JSON.parse(row.result);
		} catch {
			return row.result;
		}
	})() : row.result;
	return Object.freeze({
		kind: row.kind,
		principalScope: row.principalScope,
		requestHash: row.requestHash,
		result: freezeStorage(result)
	});
}
async function writeFieldsReceipt(tx, input) {
	await tx.execute(sql`INSERT INTO fields_operation_receipts (operation_id, kind, principal_scope, request_hash, result, created_at)
    VALUES (${input.operationId}, ${input.kind}, ${principalScope(input.context)}, ${input.requestHash}, ${JSON.stringify(input.result)}, ${(/* @__PURE__ */ new Date()).toISOString()})`);
}
function assertReceiptReplay(receipt, input) {
	if (receipt.kind !== input.kind || receipt.principalScope !== principalScope(input.context) || receipt.requestHash !== input.requestHash) throw new FieldsLifecycleError("operation-conflict", "operation id was already used with different input or scope");
}
async function verifyFieldsBackup(tx, input, backups) {
	let manifest;
	try {
		manifest = await backups.verify(tx, input.backupId, input.expectedScopeHash, input.corpusVersion, input.corpusHash, input.counts);
	} catch {
		throw new FieldsLifecycleError("backup-invalid", "backup manifest does not match the destructive scope");
	}
	if (!manifest || manifest.immutable !== true || manifest.id !== input.backupId || manifest.scopeHash !== input.expectedScopeHash || manifest.corpusVersion !== input.corpusVersion || manifest.corpusHash !== input.corpusHash || !Number.isSafeInteger(manifest.byteCount) || manifest.byteCount < 0) throw new FieldsLifecycleError("backup-invalid", "backup manifest does not match the destructive scope");
	if (JSON.stringify(Object.entries(input.counts).sort()) !== JSON.stringify(Object.entries(manifest.itemCounts).sort())) throw new FieldsLifecycleError("backup-invalid", "backup counts do not cover the complete corpus");
	return Object.freeze({
		...manifest,
		itemCounts: Object.freeze({ ...manifest.itemCounts })
	});
}
function lifecycleRows(value) {
	if (Array.isArray(value)) return value;
	if (typeof value === "object" && value !== null && Array.isArray(value.rows)) return value.rows;
	throw new FieldsLifecycleError("integrity", "database adapter returned an invalid row result");
}
async function lifecycleExecute(db, query) {
	return lifecycleRows(await db.execute(query));
}
function lifecycleJson(value, field) {
	if (typeof value !== "string") return value;
	try {
		return JSON.parse(value);
	} catch {
		throw new FieldsLifecycleError("integrity", `${field} contains invalid JSON`);
	}
}
function lifecycleBool(value) {
	return value === true || value === 1;
}
function lifecycleRecord(value, field) {
	const parsed = lifecycleJson(value, field);
	if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new FieldsLifecycleError("integrity", `${field} is malformed`);
	return parsed;
}
async function normalizeFinalGroup(value) {
	return parseFieldGroupDefinition(value);
}
function resolvedFinalGroup(row) {
	const definition = parseFieldGroupDefinition(lifecycleJson(row.definition, "field group definition"));
	if (definition.key !== row.key) throw new FieldsLifecycleError("integrity", "field group definition key mismatch");
	return Object.freeze({
		...definition,
		active: lifecycleBool(row.active),
		origin: row.origin === "code" ? "code" : "db",
		version: Number(row.version),
		revision: Number(row.currentRevision),
		...row.shadowedDbVersion === null ? {} : { shadowedDbVersion: Number(row.shadowedDbVersion) }
	});
}
async function finalGroupRows(db) {
	return lifecycleExecute(db, sql`SELECT key,origin,version,active,current_revision AS "currentRevision",canonical_hash AS "canonicalHash",definition,shadowed_db_version AS "shadowedDbVersion" FROM field_group_definitions ORDER BY key`);
}
async function finalGroupRow(db, key) {
	return (await lifecycleExecute(db, sql`SELECT key,origin,version,active,current_revision AS "currentRevision",canonical_hash AS "canonicalHash",definition,shadowed_db_version AS "shadowedDbVersion" FROM field_group_definitions WHERE key=${key} LIMIT 1`))[0] ?? null;
}
function normalizedGroupKey$1(value) {
	if (typeof value !== "string" || !/^[a-z][a-z0-9_]*$/.test(value)) throw new FieldsLifecycleError("validation", "group key must be normalized", "key");
	return value;
}
function codeGroupDefinition(value) {
	const { origin: _origin, version: _version, revision: _revision, shadowedDbVersion: _shadowedDbVersion, ...definition } = value;
	return parseFieldGroupDefinition(definition);
}
async function resolveFinalFieldGroups(db, input = {}) {
	const rows = await finalGroupRows(db), output = /* @__PURE__ */ new Map();
	for (const row of rows) output.set(row.key, resolvedFinalGroup(row));
	const seen = /* @__PURE__ */ new Set();
	for (const raw of input.codeGroups ?? []) {
		const definition = parseFieldGroupDefinition(raw);
		if (seen.has(definition.key)) throw new FieldsLifecycleError("validation", "duplicate code field-group key", definition.key);
		seen.add(definition.key);
		const previous = output.get(definition.key);
		output.set(definition.key, Object.freeze({
			...definition,
			origin: "code",
			version: previous?.version ?? 1,
			revision: previous?.revision ?? 1,
			active: true,
			...previous?.origin === "db" ? { shadowedDbVersion: previous.version } : previous?.shadowedDbVersion === void 0 ? {} : { shadowedDbVersion: previous.shadowedDbVersion }
		}));
	}
	return Object.freeze([...output.values()].sort((left, right) => (left.order ?? 0) - (right.order ?? 0) || left.key.localeCompare(right.key)));
}
function objectMentionsGroup(value, groupKey) {
	const parsed = lifecycleJson(value, "document");
	const visit = (item) => {
		if (Array.isArray(item)) return item.some(visit);
		if (typeof item !== "object" || item === null) return false;
		const record = item;
		if (record.groupKey === groupKey) return true;
		return Object.values(record).some(visit);
	};
	return visit(parsed);
}
async function groupCorpus(db, groupKey) {
	const nodes = await lifecycleExecute(db, sql`SELECT node_id AS "nodeId",entity_type AS "entityType",entity_id AS "entityId",group_key AS "groupKey",definition_revision AS "definitionRevision",field_key AS "fieldKey",path,parent_node_id AS "parentNodeId",row_id AS "rowId",layout_key AS "layoutKey",node_kind AS "nodeKind",ordinal,is_null AS "isNull",value_text AS "valueText",value_number AS "valueNumber",value_boolean AS "valueBoolean",value_date_time AS "valueDateTime",value_ref AS "valueRef",value_json AS "valueJson" FROM field_value_nodes WHERE group_key=${groupKey} ORDER BY entity_type,entity_id,path`);
	const revisions = (await lifecycleExecute(db, sql`SELECT id,entity_type AS "entityType",entity_id AS "entityId",definition_versions AS "definitionVersions","values" AS "values",block_document AS "blockDocument" FROM field_revisions ORDER BY entity_type,entity_id,id`)).filter((row) => {
		const versions = lifecycleRecord(row.definitionVersions, "revision definitionVersions");
		return Object.prototype.hasOwnProperty.call(versions, groupKey) || objectMentionsGroup(row.blockDocument, groupKey);
	});
	const currentDocuments = await lifecycleExecute(db, sql`SELECT entity_type AS "entityType",entity_id AS "entityId",version,document,definition_versions AS "definitionVersions" FROM field_block_documents ORDER BY entity_type,entity_id`);
	const reusableDocuments = await lifecycleExecute(db, sql`SELECT id,version,document,definition_versions AS "definitionVersions" FROM field_reusable_blocks ORDER BY id`);
	const documents = [];
	for (const row of currentDocuments) if (objectMentionsGroup(row.document, groupKey) || Object.prototype.hasOwnProperty.call(lifecycleRecord(row.definitionVersions, "block definitionVersions"), `group:${groupKey}`)) documents.push({
		section: "current",
		identity: `${String(row.entityType)}:${String(row.entityId)}`,
		entityType: String(row.entityType),
		entityId: String(row.entityId),
		version: row.version,
		document: lifecycleJson(row.document, "block document"),
		definitionVersions: lifecycleJson(row.definitionVersions, "block definitionVersions")
	});
	for (const row of reusableDocuments) if (objectMentionsGroup(row.document, groupKey) || Object.prototype.hasOwnProperty.call(lifecycleRecord(row.definitionVersions, "reusable definitionVersions"), `group:${groupKey}`)) documents.push({
		section: "reusable",
		identity: String(row.id),
		entityType: "reusableBlock",
		entityId: null,
		version: row.version,
		document: lifecycleJson(row.document, "reusable document"),
		definitionVersions: lifecycleJson(row.definitionVersions, "reusable definitionVersions")
	});
	documents.sort((a, b) => a.section.localeCompare(b.section) || a.identity.localeCompare(b.identity));
	const entityTypes = new Set(nodes.map((row) => row.entityType));
	for (const row of revisions) entityTypes.add(row.entityType);
	for (const row of documents) entityTypes.add(row.entityType);
	const entities = new Set(nodes.map((row) => `${row.entityType}\u0000${row.entityId}`));
	const counts = Object.freeze({
		nodes: nodes.length,
		entities: entities.size,
		revisions: revisions.length,
		documents: documents.length
	});
	const version = await fieldsRequestHash({
		nodes: nodes.map((row) => ({
			nodeId: row.nodeId,
			entityType: row.entityType,
			entityId: row.entityId,
			path: row.path,
			revision: Number(row.definitionRevision)
		})),
		revisions: revisions.map((row) => row.id),
		documents: documents.map((row) => ({
			section: row.section,
			identity: row.identity,
			version: row.version
		}))
	});
	const hash = await fieldsRequestHash({
		nodes,
		revisions,
		documents
	});
	return Object.freeze({
		version,
		hash,
		nodes: Object.freeze(nodes),
		revisions: Object.freeze(revisions),
		documents: Object.freeze(documents),
		entityTypes: Object.freeze([...entityTypes].sort()),
		counts
	});
}
function groupPaths(fields, prefix = []) {
	const output = /* @__PURE__ */ new Map();
	const visit = (definitions, parent) => {
		for (const definition of definitions) {
			const path = [...parent, definition.key];
			output.set(JSON.stringify(path), definition);
			if (definition.type === "group" || definition.type === "repeater") visit(definition.settings.fields, path);
			if (definition.type === "flexible") for (const layout of definition.settings.layouts) visit(layout.fields, [...path, layout.key]);
		}
	};
	visit(fields, prefix);
	return output;
}
async function groupIncompatibilities(current, next, corpus) {
	if (corpus.nodes.length === 0 && corpus.documents.length === 0 && corpus.revisions.length === 0) return Object.freeze([]);
	const before = groupPaths(current.fields), after = groupPaths(next.fields), output = [];
	if (current.active && !next.active) output.push("deactivate-with-data");
	for (const [path, definition] of before) {
		const replacement = after.get(path);
		if (!replacement) output.push(`removed:${path}`);
		else if (await fieldsRequestHash(definition) !== await fieldsRequestHash(replacement)) output.push(`changed:${path}`);
	}
	return Object.freeze([...new Set(output)].sort());
}
function groupTokenEncode(payload) {
	const bytes = new TextEncoder().encode(JSON.stringify(payload)), hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
	return fieldsRequestHash(payload).then((hash) => `${hex}.${hash}`);
}
async function groupTokenDecode(token) {
	const match = /^([a-f0-9]+)\.([a-f0-9]{64})$/i.exec(token);
	if (!match || match[1].length % 2 || match[1].length > 128e3) throw new FieldsLifecycleError("validation", "field-group impact token is invalid");
	let value;
	try {
		value = JSON.parse(new TextDecoder().decode(new Uint8Array(match[1].match(/../g).map((pair) => Number.parseInt(pair, 16)))));
	} catch {
		throw new FieldsLifecycleError("validation", "field-group impact token is invalid");
	}
	if (typeof value !== "object" || value === null || Array.isArray(value) || await fieldsRequestHash(value) !== match[2].toLowerCase()) throw new FieldsLifecycleError("validation", "field-group impact token integrity check failed");
	return value;
}
function normalizeGroupStrategy(strategy) {
	if (strategy.kind === "reject" || strategy.kind === "deactivate" || strategy.kind === "retainValues") return Object.freeze({ kind: strategy.kind });
	if (strategy.kind === "purgeValues") {
		if (!strategy.backupId || strategy.backupId.length > 512) throw new FieldsLifecycleError("validation", "backupId is required", "strategy.backupId");
		return Object.freeze({
			kind: "purgeValues",
			backupId: strategy.backupId
		});
	}
	if (strategy.kind === "migrateValues") {
		if (!Array.isArray(strategy.mappings) || strategy.mappings.length > 500) throw new FieldsLifecycleError("validation", "field mappings must be bounded", "strategy.mappings");
		const seen = /* @__PURE__ */ new Set(), mappings = strategy.mappings.map((mapping, index) => {
			if (!Array.isArray(mapping.from) || mapping.from.length === 0 || mapping.from.length > 64) throw new FieldsLifecycleError("validation", "mapping source path is invalid", `strategy.mappings.${index}.from`);
			if (mapping.to !== null && (!Array.isArray(mapping.to) || mapping.to.length === 0 || mapping.to.length > 64)) throw new FieldsLifecycleError("validation", "mapping destination path is invalid", `strategy.mappings.${index}.to`);
			const identity = JSON.stringify(mapping.from);
			if (seen.has(identity)) throw new FieldsLifecycleError("validation", "mapping source path is duplicated", `strategy.mappings.${index}.from`);
			seen.add(identity);
			return Object.freeze({
				from: Object.freeze([...mapping.from]),
				to: mapping.to === null ? null : Object.freeze([...mapping.to])
			});
		});
		return Object.freeze({
			kind: "migrateValues",
			mappings: Object.freeze(mappings)
		});
	}
	throw new FieldsLifecycleError("validation", "unknown field-group change strategy");
}
function groupDefinitionRef(key) {
	return Object.freeze({
		entityType: "fields-group-definition",
		entityId: key
	});
}
async function createFieldGroup(tx, definition, context, input) {
	assertActiveFieldsTransaction(tx);
	const normalized = await normalizeFinalGroup(definition), key = normalizedGroupKey$1(normalized.key);
	const authorized = await assertFieldsAuthorized(context, "manageDefinitions", groupDefinitionRef(key));
	if ((input.codeGroups ?? []).some((group) => group.key === key)) throw new FieldsLifecycleError("validation", "effective field-group key is owned by code", key);
	const canonicalHash = await canonicalFieldGroupHash(normalized);
	const requestHash = await fieldsRequestHash({
		kind: "create-field-group",
		canonicalHash,
		codeKeys: (input.codeGroups ?? []).map((group) => group.key).sort()
	});
	const replay = await readFieldsReceipt(tx, input.operationId);
	if (replay) {
		assertReceiptReplay(replay, {
			kind: "fields:create-field-group",
			context: authorized,
			requestHash
		});
		const row = await finalGroupRow(tx, key);
		if (!row) throw new FieldsLifecycleError("integrity", "committed group receipt has no definition");
		return resolvedFinalGroup(row);
	}
	if (await finalGroupRow(tx, key)) throw new FieldsLifecycleError("validation", "field-group key already exists", key);
	const now = (/* @__PURE__ */ new Date()).toISOString();
	await tx.execute(sql`INSERT INTO field_group_definitions (key,origin,version,active,current_revision,canonical_hash,definition,created_at,updated_at) VALUES (${key},'db',1,${normalized.active},1,${canonicalHash},${JSON.stringify(normalized)},${now},${now})`);
	await tx.execute(sql`INSERT INTO field_definition_versions (group_key,revision,canonical_hash,definition,origin,created_at) VALUES (${key},1,${canonicalHash},${JSON.stringify(normalized)},'db',${now})`);
	const result = Object.freeze({
		...normalized,
		origin: "db",
		version: 1,
		revision: 1
	});
	await writeFieldsReceipt(tx, {
		operationId: input.operationId,
		kind: "fields:create-field-group",
		context: authorized,
		requestHash,
		result: Object.freeze({
			key,
			version: 1,
			revision: 1
		})
	});
	return result;
}
async function previewFieldGroupChange(db, key, expectedVersion, patch, strategyInput, context) {
	const groupKey = normalizedGroupKey$1(key);
	await assertFieldsAuthorized(context, "manageDefinitions", groupDefinitionRef(groupKey));
	const row = await finalGroupRow(db, groupKey);
	if (!row) throw new FieldsLifecycleError("not-found", "field-group definition is unavailable");
	const current = resolvedFinalGroup(row);
	if (current.origin === "code") throw new FieldsLifecycleError("validation", "code-owned field groups change only through registry reconciliation");
	if (current.version !== expectedVersion) throw new FieldsLifecycleError("stale-version", "field-group version changed");
	const strategy = normalizeGroupStrategy(strategyInput);
	const next = parseFieldGroupDefinition({
		...codeGroupDefinition(current),
		...patch,
		key: groupKey,
		active: strategy.kind === "deactivate" ? false : patch.active ?? current.active
	});
	const corpus = await groupCorpus(db, groupKey);
	const migration = await assertDefinitionMigration(context, corpus.entityTypes.length ? corpus.entityTypes : ["fields-definition"]);
	const incompatibilities = await groupIncompatibilities(current, next, corpus);
	const payload = Object.freeze({
		kind: "field-group-change",
		groupKey,
		expectedVersion,
		authorizationPolicyVersion: migration.policyVersion,
		valueCorpusVersion: corpus.version,
		valueCorpusHash: corpus.hash,
		affectedCounts: corpus.counts,
		nextDefinition: freezeStorage(next, "nextDefinition"),
		strategy: freezeStorage(strategy, "strategy"),
		incompatibilities: Object.freeze(incompatibilities),
		entityTypes: Object.freeze(corpus.entityTypes)
	});
	return Object.freeze({
		token: await groupTokenEncode(payload),
		groupKey,
		expectedVersion,
		authorizationPolicyVersion: migration.policyVersion,
		valueCorpusVersion: corpus.version,
		valueCorpusHash: corpus.hash,
		affectedCounts: corpus.counts,
		incompatibilities
	});
}
function corpusNode(row) {
	return Object.freeze({
		nodeId: row.nodeId,
		entityType: row.entityType,
		entityId: row.entityId,
		groupKey: row.groupKey,
		definitionRevision: Number(row.definitionRevision),
		fieldKey: row.fieldKey,
		path: row.path,
		parentNodeId: row.parentNodeId,
		rowId: row.rowId,
		layoutKey: row.layoutKey,
		nodeKind: row.nodeKind,
		ordinal: Number(row.ordinal),
		isNull: row.isNull === true || row.isNull === 1,
		valueText: row.valueText,
		valueNumber: row.valueNumber === null ? null : Number(row.valueNumber),
		valueBoolean: row.valueBoolean === null ? null : row.valueBoolean === true || row.valueBoolean === 1,
		valueDateTime: row.valueDateTime,
		valueRef: row.valueRef,
		valueJson: row.valueJson
	});
}
function pathKey(path) {
	return JSON.stringify(path);
}
function deepClone(value) {
	if (value === null || typeof value !== "object") return value;
	if (Array.isArray(value)) return value.map(deepClone);
	const out = {};
	for (const [key, child] of Object.entries(value)) out[key] = deepClone(child);
	return out;
}
function pathGet(root, path) {
	let current = root;
	for (const segment of path) if (typeof segment === "number") {
		if (!Array.isArray(current) || segment < 0 || segment >= current.length) return {
			present: false,
			value: void 0
		};
		current = current[segment];
	} else {
		if (typeof current !== "object" || current === null || Array.isArray(current) || !Object.prototype.hasOwnProperty.call(current, segment)) return {
			present: false,
			value: void 0
		};
		current = current[segment];
	}
	return {
		present: true,
		value: current
	};
}
function pathDelete(root, path) {
	if (path.length === 0) return;
	let current = root;
	for (let i = 0; i < path.length - 1; i++) {
		const segment = path[i];
		if (typeof segment === "number") {
			if (!Array.isArray(current) || segment < 0 || segment >= current.length) return;
			current = current[segment];
		} else {
			if (typeof current !== "object" || current === null || Array.isArray(current)) return;
			current = current[segment];
		}
	}
	const last = path[path.length - 1];
	if (typeof last === "number") {
		if (Array.isArray(current) && last >= 0 && last < current.length) current.splice(last, 1);
	} else if (typeof current === "object" && current !== null && !Array.isArray(current)) delete current[last];
}
function pathSet(root, path, value) {
	if (path.length === 0) throw new FieldsLifecycleError("validation", "mapping destination path must not be empty");
	let current = root;
	for (let i = 0; i < path.length - 1; i++) {
		const segment = path[i], next = path[i + 1];
		if (typeof segment === "number") {
			if (!Array.isArray(current) || segment < 0) throw new FieldsLifecycleError("validation", "mapping destination crosses a non-array value");
			while (current.length <= segment) current.push(typeof next === "number" ? [] : {});
			if (current[segment] === null || typeof current[segment] !== "object") current[segment] = typeof next === "number" ? [] : {};
			current = current[segment];
		} else {
			if (typeof current !== "object" || current === null || Array.isArray(current)) throw new FieldsLifecycleError("validation", "mapping destination crosses a non-object value");
			const record = current;
			if (record[segment] === void 0) record[segment] = typeof next === "number" ? [] : {};
			if (record[segment] === null || typeof record[segment] !== "object") record[segment] = typeof next === "number" ? [] : {};
			current = record[segment];
		}
	}
	const last = path[path.length - 1];
	if (typeof last === "number") {
		if (!Array.isArray(current) || last < 0) throw new FieldsLifecycleError("validation", "mapping destination is not an array");
		while (current.length < last) current.push(null);
		current[last] = deepClone(value);
	} else {
		if (typeof current !== "object" || current === null || Array.isArray(current)) throw new FieldsLifecycleError("validation", "mapping destination is not an object");
		current[last] = deepClone(value);
	}
}
function applyMappings(values, mappings) {
	const output = deepClone(values);
	for (const mapping of mappings) {
		const found = pathGet(values, mapping.from);
		if (!found.present) continue;
		pathDelete(output, mapping.from);
		if (mapping.to !== null) pathSet(output, mapping.to, found.value);
	}
	return Object.freeze(output);
}
function ensureMappings(current, next, strategy, incompatibilities) {
	const before = groupPaths(current.fields), after = groupPaths(next.fields), mappingBySource = new Map(strategy.mappings.map((mapping) => [pathKey(mapping.from), mapping]));
	for (const issue of incompatibilities) {
		const raw = issue.slice(issue.indexOf(":") + 1), mapping = mappingBySource.get(raw);
		if (!mapping) throw new FieldsLifecycleError("validation", `migration does not cover ${issue}`);
		if (mapping.to !== null && !after.has(pathKey(mapping.to))) throw new FieldsLifecycleError("validation", `migration target for ${issue} does not exist`);
	}
	for (const mapping of strategy.mappings) {
		if (!before.has(pathKey(mapping.from))) throw new FieldsLifecycleError("validation", "migration source path does not exist", pathKey(mapping.from));
		if (mapping.to !== null && !after.has(pathKey(mapping.to))) throw new FieldsLifecycleError("validation", "migration target path does not exist", pathKey(mapping.to));
	}
}
async function writeMigratedNodes(tx, groupKey, next, nextRevision, corpus, mappings, context) {
	const buckets = /* @__PURE__ */ new Map();
	for (const row of corpus.nodes) {
		const id = `${row.entityType}\u0000${row.entityId}`;
		const list = buckets.get(id) ?? [];
		list.push(row);
		buckets.set(id, list);
	}
	for (const [identity, rows] of buckets) {
		const revisions = [...new Set(rows.map((row) => Number(row.definitionRevision)))];
		if (revisions.length !== 1) throw new FieldsLifecycleError("integrity", "current group value tree mixes immutable definition revisions");
		const oldRevision = revisions[0], oldDefinition = (await resolveFieldDefinitionVersion(tx, groupKey, oldRevision)).definition;
		const migrated = applyMappings(decodeFieldValueNodes(oldDefinition, rows.map(corpusNode), {
			definitionRevision: oldRevision,
			...context.cloneResolver ? { cloneResolver: { resolve: (definition) => context.cloneResolver.resolve(definition) } } : {}
		}), mappings);
		const [entityType, entityId] = identity.split("\0");
		const ids = /* @__PURE__ */ new Map(), nodeIdForPath = (path) => {
			let id = ids.get(path);
			if (!id) {
				id = crypto.randomUUID();
				ids.set(path, id);
			}
			return id;
		};
		const encoded = encodeFieldValueNodes(next, migrated, {
			entityType,
			entityId,
			definitionRevision: nextRevision,
			nodeIdForPath,
			...context.cloneResolver ? { cloneResolver: { resolve: (definition) => context.cloneResolver.resolve(definition) } } : {}
		});
		await tx.execute(sql`DELETE FROM field_value_nodes WHERE entity_type=${entityType} AND entity_id=${entityId} AND group_key=${groupKey}`);
		for (const row of encoded) await tx.execute(sql`INSERT INTO field_value_nodes (node_id,entity_type,entity_id,group_key,definition_revision,field_key,path,parent_node_id,row_id,layout_key,node_kind,ordinal,is_null,value_text,value_number,value_boolean,value_date_time,value_ref,value_json,created_at,updated_at) VALUES (${row.nodeId},${row.entityType},${row.entityId},${row.groupKey},${row.definitionRevision},${row.fieldKey},${row.path},${row.parentNodeId},${row.rowId},${row.layoutKey},${row.nodeKind},${row.ordinal},${row.isNull},${row.valueText},${row.valueNumber},${row.valueBoolean},${row.valueDateTime},${row.valueRef},${row.valueJson},${(/* @__PURE__ */ new Date()).toISOString()},${(/* @__PURE__ */ new Date()).toISOString()})`);
	}
}
function migrateGroupInDocument(value, groupKey, nextRevision, mappings) {
	const walk = (item) => {
		if (Array.isArray(item)) return item.map(walk);
		if (typeof item !== "object" || item === null) return item;
		const record = item, out = {};
		for (const [key, value] of Object.entries(record)) out[key] = walk(value);
		if (record.groupKey === groupKey && typeof record.values === "object" && record.values !== null && !Array.isArray(record.values)) {
			out.definitionRevision = nextRevision;
			out.values = applyMappings(record.values, mappings);
		}
		return out;
	};
	return walk(lifecycleJson(value, "block document"));
}
function definitionVersionsWithGroup(value, groupKey, revision) {
	const out = { ...lifecycleRecord(value, "definitionVersions") };
	if (Object.prototype.hasOwnProperty.call(out, `group:${groupKey}`)) out[`group:${groupKey}`] = revision;
	if (Object.prototype.hasOwnProperty.call(out, groupKey)) out[groupKey] = revision;
	return Object.freeze(out);
}
async function migrateCurrentDocuments(tx, groupKey, nextRevision, corpus, mappings) {
	for (const entry of corpus.documents) {
		const document = migrateGroupInDocument(entry.document, groupKey, nextRevision, mappings), versions = definitionVersionsWithGroup(entry.definitionVersions, groupKey, nextRevision);
		if (entry.section === "current") await tx.execute(sql`UPDATE field_block_documents SET document=${JSON.stringify(document)},definition_versions=${JSON.stringify(versions)},version=version+1,updated_at=${(/* @__PURE__ */ new Date()).toISOString()} WHERE entity_type=${entry.entityType} AND entity_id=${entry.entityId}`);
		else await tx.execute(sql`UPDATE field_reusable_blocks SET document=${JSON.stringify(document)},definition_versions=${JSON.stringify(versions)},version=version+1,updated_at=${(/* @__PURE__ */ new Date()).toISOString()} WHERE id=${entry.identity}`);
	}
}
async function purgeGroupCorpus(tx, groupKey, corpus) {
	await tx.execute(sql`DELETE FROM field_value_nodes WHERE group_key=${groupKey}`);
	for (const revision of corpus.revisions) await tx.execute(sql`DELETE FROM field_revisions WHERE id=${revision.id}`);
	for (const document of corpus.documents) if (document.section === "current") await tx.execute(sql`DELETE FROM field_block_documents WHERE entity_type=${document.entityType} AND entity_id=${document.entityId}`);
	else await tx.execute(sql`DELETE FROM field_reusable_blocks WHERE id=${document.identity}`);
}
function groupCountsEqual(left, right) {
	if (typeof right !== "object" || right === null || Array.isArray(right)) return false;
	const normalized = {};
	for (const [key, value] of Object.entries(right)) {
		const number = Number(value);
		if (!Number.isSafeInteger(number) || number < 0) return false;
		normalized[key] = number;
	}
	return JSON.stringify(Object.entries(left).sort()) === JSON.stringify(Object.entries(normalized).sort());
}
function parseTokenGroupDefinition(value, groupKey) {
	const definition = parseFieldGroupDefinition(value);
	if (definition.key !== groupKey) throw new FieldsLifecycleError("validation", "impact token field-group key mismatch");
	return definition;
}
function groupStrategyEqual(left, right) {
	try {
		return JSON.stringify(freezeStorage(left, "strategy")) === JSON.stringify(freezeStorage(right, "strategy"));
	} catch {
		return false;
	}
}
async function applyFieldGroupChange(tx, impactToken, strategyInput, operationId, context, destructive) {
	assertActiveFieldsTransaction(tx);
	const token = await groupTokenDecode(impactToken);
	if (token.kind !== "field-group-change" || typeof token.groupKey !== "string") throw new FieldsLifecycleError("validation", "field-group impact token has wrong operation kind");
	const groupKey = normalizedGroupKey$1(token.groupKey), strategy = normalizeGroupStrategy(strategyInput);
	if (!groupStrategyEqual(strategy, token.strategy)) throw new FieldsLifecycleError("operation-conflict", "field-group strategy differs from preview");
	const authorized = await assertFieldsAuthorized(context, "manageDefinitions", groupDefinitionRef(groupKey));
	const entityTypes = Array.isArray(token.entityTypes) ? token.entityTypes.map((value, index) => {
		if (typeof value !== "string" || !value || value.length > 256) throw new FieldsLifecycleError("validation", "impact token entity type is invalid", `entityTypes.${index}`);
		return value;
	}) : [];
	const migration = await assertDefinitionMigration(context, entityTypes.length ? entityTypes : ["fields-definition"]);
	if (token.authorizationPolicyVersion !== migration.policyVersion) throw new FieldsLifecycleError("corpus-drift", "authorization policy changed since preview");
	const requestHash = await fieldsRequestHash({
		impactToken,
		strategy
	});
	const replay = await readFieldsReceipt(tx, operationId);
	if (replay) {
		assertReceiptReplay(replay, {
			kind: "fields:apply-field-group-change",
			context: authorized,
			requestHash
		});
		const row = await finalGroupRow(tx, groupKey);
		return row ? resolvedFinalGroup(row) : null;
	}
	const row = await finalGroupRow(tx, groupKey);
	if (!row) throw new FieldsLifecycleError("not-found", "field-group definition is unavailable");
	const current = resolvedFinalGroup(row);
	if (current.origin === "code") throw new FieldsLifecycleError("validation", "code-owned field groups change only through registry reconciliation");
	if (Number(token.expectedVersion) !== current.version) throw new FieldsLifecycleError("stale-version", "field-group version changed");
	const corpus = await groupCorpus(tx, groupKey);
	if (token.valueCorpusVersion !== corpus.version || token.valueCorpusHash !== corpus.hash || !groupCountsEqual(corpus.counts, token.affectedCounts)) throw new FieldsLifecycleError("corpus-drift", "field-group value corpus changed since preview");
	if (JSON.stringify([...corpus.entityTypes].sort()) !== JSON.stringify([...entityTypes].sort())) throw new FieldsLifecycleError("corpus-drift", "field-group authorization scope changed since preview");
	const next = parseTokenGroupDefinition(token.nextDefinition, groupKey);
	const incompatibilities = await groupIncompatibilities(current, next, corpus);
	const tokenIncompatibilities = Array.isArray(token.incompatibilities) ? token.incompatibilities.map(String).sort() : [];
	if (JSON.stringify([...incompatibilities].sort()) !== JSON.stringify(tokenIncompatibilities)) throw new FieldsLifecycleError("corpus-drift", "field-group compatibility facts changed since preview");
	if (strategy.kind === "reject" && incompatibilities.length > 0) throw new FieldsLifecycleError("validation", "reject strategy cannot apply an incompatible field-group change");
	if (strategy.kind === "migrateValues") ensureMappings(current, next, strategy, incompatibilities);
	const nextHash = await canonicalFieldGroupHash(next), definitionChanged = nextHash !== row.canonicalHash;
	const nextRevision = definitionChanged ? current.revision + 1 : current.revision;
	const nextVersion = current.version + 1;
	if (definitionChanged) await tx.execute(sql`INSERT INTO field_definition_versions (group_key,revision,canonical_hash,definition,origin,created_at) VALUES (${groupKey},${nextRevision},${nextHash},${JSON.stringify(next)},'db',${(/* @__PURE__ */ new Date()).toISOString()})`);
	if (strategy.kind === "migrateValues") {
		await writeMigratedNodes(tx, groupKey, next, nextRevision, corpus, strategy.mappings, context);
		await migrateCurrentDocuments(tx, groupKey, nextRevision, corpus, strategy.mappings);
	} else if (strategy.kind === "purgeValues") {
		if (!destructive) throw new FieldsLifecycleError("backup-invalid", "destructive dependencies are required");
		const scopeHash = await fieldsRequestHash({
			definitionKind: "group",
			definitionKey: groupKey,
			strategy,
			authorizationPolicyVersion: migration.policyVersion,
			corpusVersion: corpus.version,
			corpusHash: corpus.hash,
			previewToken: impactToken,
			affectedCounts: corpus.counts
		});
		const backup = await verifyFieldsBackup(tx, {
			backupId: strategy.backupId,
			expectedScopeHash: scopeHash,
			corpusVersion: corpus.version,
			corpusHash: corpus.hash,
			counts: corpus.counts
		}, destructive.backups);
		const event = Object.freeze({
			operationId,
			principalId: authorized.principal.id,
			definitionKind: "group",
			definitionKey: groupKey,
			strategy: freezeStorage(strategy, "strategy"),
			authorizationPolicyVersion: migration.policyVersion,
			corpusVersion: corpus.version,
			corpusHash: corpus.hash,
			previewToken: impactToken,
			affectedCounts: corpus.counts,
			backup
		});
		await destructive.effects.audit.record(tx, event);
		await destructive.effects.outbox.enqueue(tx, event);
		await purgeGroupCorpus(tx, groupKey, corpus);
	}
	await tx.execute(sql`UPDATE field_group_definitions SET version=${nextVersion},active=${next.active},current_revision=${nextRevision},canonical_hash=${nextHash},definition=${JSON.stringify(next)},updated_at=${(/* @__PURE__ */ new Date()).toISOString()} WHERE key=${groupKey} AND version=${current.version}`);
	const result = Object.freeze({
		...next,
		origin: "db",
		version: nextVersion,
		revision: nextRevision,
		...current.shadowedDbVersion === void 0 ? {} : { shadowedDbVersion: current.shadowedDbVersion }
	});
	await writeFieldsReceipt(tx, {
		operationId,
		kind: "fields:apply-field-group-change",
		context: authorized,
		requestHash,
		result: Object.freeze({
			key: groupKey,
			version: nextVersion,
			revision: nextRevision
		})
	});
	return result;
}
function backupString(value, field, max = 512) {
	if (typeof value !== "string" || value.length === 0 || value.length > max) throw new FieldsLifecycleError("backup-invalid", `${field} must be a bounded non-empty string`);
	return value;
}
function backupRef(value, field) {
	const record = lifecycleRecord(value, field);
	return Object.freeze({
		entityType: backupString(record.entityType, `${field}.entityType`, 256),
		entityId: backupString(record.entityId, `${field}.entityId`, 512)
	});
}
function backupVersions(value, field) {
	const record = lifecycleRecord(value, field), output = {};
	for (const [key, raw] of Object.entries(record)) {
		const revision = Number(raw);
		if (!Number.isSafeInteger(revision) || revision < 1) throw new FieldsLifecycleError("backup-invalid", `${field}.${key} must be a positive revision`);
		output[key] = revision;
	}
	return Object.freeze(output);
}
function backupArray(value, field, max = 5e3) {
	if (value === void 0) return Object.freeze([]);
	if (!Array.isArray(value) || value.length > max) throw new FieldsLifecycleError("backup-invalid", `${field} must be a bounded array`);
	return value;
}
async function parseFieldsBackupPayload(value) {
	const root = lifecycleRecord(value, "backup payload");
	if (root.version !== 1) throw new FieldsLifecycleError("backup-invalid", "backup payload version must be 1");
	const groups = [], groupKeys = /* @__PURE__ */ new Set();
	for (const [index, raw] of backupArray(root.groupDefinitions, "groupDefinitions").entries()) {
		const item = lifecycleRecord(raw, `groupDefinitions.${index}`), definition = parseFieldGroupDefinition(item.definition), key = backupString(item.key, `groupDefinitions.${index}.key`, 128);
		if (definition.key !== key || groupKeys.has(key)) throw new FieldsLifecycleError("backup-invalid", "backup group definition identity is invalid");
		groupKeys.add(key);
		groups.push(Object.freeze({
			key,
			definition
		}));
	}
	const optionsModule = await Promise.resolve().then(() => dist_exports).then((n) => n.n), options = [], optionKeys = /* @__PURE__ */ new Set();
	for (const [index, raw] of backupArray(root.optionsDefinitions, "optionsDefinitions").entries()) {
		const item = lifecycleRecord(raw, `optionsDefinitions.${index}`), key = backupString(item.key, `optionsDefinitions.${index}.key`, 128);
		const definition = optionsModule.__optionsLifecycleInternals.normalizeOptionsPage(item.definition);
		if (definition.key !== key || optionKeys.has(key) || typeof item.active !== "boolean") throw new FieldsLifecycleError("backup-invalid", "backup options definition identity is invalid");
		optionKeys.add(key);
		options.push(Object.freeze({
			key,
			definition,
			active: item.active
		}));
	}
	const blocksModule = await Promise.resolve().then(() => dist_exports).then((n) => n.t), blocks = [], blockKeys = /* @__PURE__ */ new Set();
	for (const [index, raw] of backupArray(root.blockDefinitions, "blockDefinitions").entries()) {
		const item = lifecycleRecord(raw, `blockDefinitions.${index}`), key = backupString(item.key, `blockDefinitions.${index}.key`, 128);
		const definition = blocksModule.__fieldBlockLifecycleInternals.normalizeDefinition(item.definition);
		if (definition.key !== key || blockKeys.has(key) || typeof item.active !== "boolean") throw new FieldsLifecycleError("backup-invalid", "backup block definition identity is invalid");
		blockKeys.add(key);
		blocks.push(Object.freeze({
			key,
			definition,
			active: item.active
		}));
	}
	const values = [], valueKeys = /* @__PURE__ */ new Set();
	for (const [index, raw] of backupArray(root.values, "values", 2e4).entries()) {
		const item = lifecycleRecord(raw, `values.${index}`), ref = backupRef(item.ref, `values.${index}.ref`), groupKey = normalizedGroupKey$1(item.groupKey), definitionRevision = Number(item.definitionRevision);
		if (!Number.isSafeInteger(definitionRevision) || definitionRevision < 1) throw new FieldsLifecycleError("backup-invalid", "backup value definition revision is invalid");
		const identity = `${ref.entityType}\u0000${ref.entityId}\u0000${groupKey}`;
		if (valueKeys.has(identity)) throw new FieldsLifecycleError("backup-invalid", "backup contains duplicate value entity/group snapshot");
		valueKeys.add(identity);
		values.push(Object.freeze({
			ref,
			groupKey,
			definitionRevision,
			values: freezeStorage(item.values, `values.${index}.values`)
		}));
	}
	const blockDocuments = [], documentKeys = /* @__PURE__ */ new Set();
	for (const [index, raw] of backupArray(root.blockDocuments, "blockDocuments", 1e4).entries()) {
		const item = lifecycleRecord(raw, `blockDocuments.${index}`), ref = backupRef(item.ref, `blockDocuments.${index}.ref`), identity = `${ref.entityType}\u0000${ref.entityId}`;
		if (documentKeys.has(identity)) throw new FieldsLifecycleError("backup-invalid", "backup contains duplicate block document snapshot");
		documentKeys.add(identity);
		blockDocuments.push(Object.freeze({
			ref,
			document: freezeStorage(item.document, `blockDocuments.${index}.document`),
			definitionVersions: backupVersions(item.definitionVersions, `blockDocuments.${index}.definitionVersions`),
			parentRevisionId: backupString(item.parentRevisionId, `blockDocuments.${index}.parentRevisionId`)
		}));
	}
	const reusableBlocks = [], reusableIds = /* @__PURE__ */ new Set();
	for (const [index, raw] of backupArray(root.reusableBlocks, "reusableBlocks", 1e4).entries()) {
		const item = lifecycleRecord(raw, `reusableBlocks.${index}`), id = backupString(item.id, `reusableBlocks.${index}.id`);
		if (reusableIds.has(id)) throw new FieldsLifecycleError("backup-invalid", "backup contains duplicate reusable block");
		reusableIds.add(id);
		reusableBlocks.push(Object.freeze({
			id,
			document: freezeStorage(item.document, `reusableBlocks.${index}.document`),
			definitionVersions: backupVersions(item.definitionVersions, `reusableBlocks.${index}.definitionVersions`)
		}));
	}
	const revisions = [], revisionIds = /* @__PURE__ */ new Set();
	for (const [index, raw] of backupArray(root.revisions, "revisions", 2e4).entries()) {
		const item = lifecycleRecord(raw, `revisions.${index}`), id = backupString(item.id, `revisions.${index}.id`), ref = backupRef(item.ref, `revisions.${index}.ref`);
		if (revisionIds.has(id) || item.kind !== "revision" && item.kind !== "autosave") throw new FieldsLifecycleError("backup-invalid", "backup revision identity is invalid");
		revisionIds.add(id);
		const createdAt = backupString(item.createdAt, `revisions.${index}.createdAt`), date = new Date(createdAt);
		if (Number.isNaN(date.getTime())) throw new FieldsLifecycleError("backup-invalid", "backup revision timestamp is invalid");
		revisions.push(Object.freeze({
			id,
			ref,
			parentRevisionId: backupString(item.parentRevisionId, `revisions.${index}.parentRevisionId`),
			...item.parentAutosaveId === void 0 ? {} : { parentAutosaveId: backupString(item.parentAutosaveId, `revisions.${index}.parentAutosaveId`) },
			kind: item.kind,
			...item.retentionClass === void 0 ? {} : { retentionClass: backupString(item.retentionClass, `revisions.${index}.retentionClass`, 128) },
			definitionVersions: backupVersions(item.definitionVersions, `revisions.${index}.definitionVersions`),
			values: freezeStorage(item.values, `revisions.${index}.values`),
			...item.blockDocument === void 0 || item.blockDocument === null ? {} : { blockDocument: freezeStorage(item.blockDocument, `revisions.${index}.blockDocument`) },
			createdAt: date.toISOString(),
			createdBy: backupString(item.createdBy, `revisions.${index}.createdBy`),
			sourceVersion: backupString(item.sourceVersion, `revisions.${index}.sourceVersion`)
		}));
	}
	return Object.freeze({
		version: 1,
		...groups.length ? { groupDefinitions: Object.freeze(groups) } : {},
		...options.length ? { optionsDefinitions: Object.freeze(options) } : {},
		...blocks.length ? { blockDefinitions: Object.freeze(blocks) } : {},
		...values.length ? { values: Object.freeze(values) } : {},
		...blockDocuments.length ? { blockDocuments: Object.freeze(blockDocuments) } : {},
		...reusableBlocks.length ? { reusableBlocks: Object.freeze(reusableBlocks) } : {},
		...revisions.length ? { revisions: Object.freeze(revisions) } : {}
	});
}
function restoreTargetKey(ref, groupKey) {
	return `${ref.entityType}\u0000${ref.entityId}${groupKey === void 0 ? "" : `\u0000${groupKey}`}`;
}
async function fieldsBackupDestinationState(db, payload) {
	const groups = [];
	for (const item of [...payload.groupDefinitions ?? []].sort((a, b) => a.key.localeCompare(b.key))) {
		const row = await finalGroupRow(db, item.key);
		groups.push(freezeStorage(row ? {
			key: row.key,
			origin: row.origin,
			version: Number(row.version),
			active: lifecycleBool(row.active),
			revision: Number(row.currentRevision),
			hash: row.canonicalHash
		} : {
			key: item.key,
			missing: true
		}, "destination.group"));
	}
	const options = [];
	for (const item of [...payload.optionsDefinitions ?? []].sort((a, b) => a.key.localeCompare(b.key))) {
		const row = (await lifecycleExecute(db, sql`SELECT key,origin,version,active,current_revision AS revision,canonical_hash AS hash FROM field_options_definitions WHERE key=${item.key} LIMIT 1`))[0];
		options.push(freezeStorage(row ? {
			key: row.key,
			origin: row.origin,
			version: Number(row.version),
			active: lifecycleBool(row.active),
			revision: Number(row.revision),
			hash: row.hash
		} : {
			key: item.key,
			missing: true
		}, "destination.options"));
	}
	const blocks = [];
	for (const item of [...payload.blockDefinitions ?? []].sort((a, b) => a.key.localeCompare(b.key))) {
		const row = (await lifecycleExecute(db, sql`SELECT key,origin,version,active,current_revision AS revision,canonical_hash AS hash FROM field_block_definitions WHERE key=${item.key} LIMIT 1`))[0];
		blocks.push(freezeStorage(row ? {
			key: row.key,
			origin: row.origin,
			version: Number(row.version),
			active: lifecycleBool(row.active),
			revision: Number(row.revision),
			hash: row.hash
		} : {
			key: item.key,
			missing: true
		}, "destination.blocks"));
	}
	const values = [];
	for (const item of [...payload.values ?? []].sort((a, b) => restoreTargetKey(a.ref, a.groupKey).localeCompare(restoreTargetKey(b.ref, b.groupKey)))) {
		const rows = await lifecycleExecute(db, sql`SELECT node_id AS "nodeId",definition_revision AS "definitionRevision",field_key AS "fieldKey",path,parent_node_id AS "parentNodeId",row_id AS "rowId",layout_key AS "layoutKey",node_kind AS "nodeKind",ordinal,is_null AS "isNull",value_text AS "valueText",value_number AS "valueNumber",value_boolean AS "valueBoolean",value_date_time AS "valueDateTime",value_ref AS "valueRef",value_json AS "valueJson" FROM field_value_nodes WHERE entity_type=${item.ref.entityType} AND entity_id=${item.ref.entityId} AND group_key=${item.groupKey} ORDER BY path`);
		values.push(freezeStorage({
			ref: item.ref,
			groupKey: item.groupKey,
			rows
		}, "destination.values"));
	}
	const documents = [];
	for (const item of [...payload.blockDocuments ?? []].sort((a, b) => restoreTargetKey(a.ref).localeCompare(restoreTargetKey(b.ref)))) {
		const rows = await lifecycleExecute(db, sql`SELECT version,document,definition_versions AS "definitionVersions",parent_revision_id AS "parentRevisionId" FROM field_block_documents WHERE entity_type=${item.ref.entityType} AND entity_id=${item.ref.entityId} LIMIT 1`);
		documents.push(freezeStorage({
			ref: item.ref,
			current: rows[0] ?? null
		}, "destination.documents"));
	}
	const reusable = [];
	for (const item of [...payload.reusableBlocks ?? []].sort((a, b) => a.id.localeCompare(b.id))) {
		const rows = await lifecycleExecute(db, sql`SELECT id,version,document,definition_versions AS "definitionVersions",deleted_at AS "deletedAt" FROM field_reusable_blocks WHERE id=${item.id} LIMIT 1`);
		reusable.push(freezeStorage({
			id: item.id,
			current: rows[0] ?? null
		}, "destination.reusable"));
	}
	const revisions = [];
	for (const item of [...payload.revisions ?? []].sort((a, b) => a.id.localeCompare(b.id))) {
		const rows = await lifecycleExecute(db, sql`SELECT id,entity_type AS "entityType",entity_id AS "entityId",kind,parent_revision_id AS "parentRevisionId",parent_autosave_id AS "parentAutosaveId",definition_versions AS "definitionVersions","values" AS "values",block_document AS "blockDocument",source_version AS "sourceVersion" FROM field_revisions WHERE id=${item.id} LIMIT 1`);
		revisions.push(freezeStorage({
			id: item.id,
			current: rows[0] ?? null
		}, "destination.revisions"));
	}
	return Object.freeze({
		version: 1,
		groups: Object.freeze(groups),
		options: Object.freeze(options),
		blocks: Object.freeze(blocks),
		values: Object.freeze(values),
		documents: Object.freeze(documents),
		reusable: Object.freeze(reusable),
		revisions: Object.freeze(revisions)
	});
}
async function fieldsBackupDestinationHash(db, payload) {
	return fieldsRequestHash(await fieldsBackupDestinationState(db, payload));
}
function manifestsEqual(left, right) {
	return left.id === right.id && left.scopeHash === right.scopeHash && left.corpusVersion === right.corpusVersion && left.corpusHash === right.corpusHash && left.byteCount === right.byteCount && left.immutable === true && right.immutable === true && JSON.stringify(Object.entries(left.itemCounts).sort()) === JSON.stringify(Object.entries(right.itemCounts).sort());
}
function remapDefinitionVersions(value, groupRevisions, blockRevisions) {
	const out = { ...value };
	for (const [key, revision] of groupRevisions) {
		if (Object.prototype.hasOwnProperty.call(out, key)) out[key] = revision;
		if (Object.prototype.hasOwnProperty.call(out, `group:${key}`)) out[`group:${key}`] = revision;
	}
	for (const [key, revision] of blockRevisions) if (Object.prototype.hasOwnProperty.call(out, `block:${key}`)) out[`block:${key}`] = revision;
	return Object.freeze(out);
}
function remapBlockDocument(value, groupRevisions, blockRevisions) {
	const walk = (item) => {
		if (Array.isArray(item)) return item.map(walk);
		if (typeof item !== "object" || item === null) return item;
		const record = item, out = {};
		for (const [key, child] of Object.entries(record)) out[key] = walk(child);
		if (record.kind === "inline" && typeof record.type === "string" && blockRevisions.has(record.type)) out.blockDefinitionRevision = blockRevisions.get(record.type);
		if (typeof record.groupKey === "string" && groupRevisions.has(record.groupKey)) out.definitionRevision = groupRevisions.get(record.groupKey);
		return out;
	};
	return walk(value);
}
function fieldsContainPrivateCredential(fields, context) {
	for (const field of fields) {
		if (field.type === "password") return true;
		if (field.type === "group" || field.type === "repeater") {
			if (fieldsContainPrivateCredential(field.settings.fields, context)) return true;
		}
		if (field.type === "flexible") {
			for (const layout of field.settings.layouts) if (fieldsContainPrivateCredential(layout.fields, context)) return true;
		}
		if (field.type === "clone") {
			if (!context.cloneResolver) return true;
			if (fieldsContainPrivateCredential(context.cloneResolver.resolve(field), context)) return true;
		}
	}
	return false;
}
function backupPayloadEntityTypes(payload) {
	const types = /* @__PURE__ */ new Set();
	for (const item of payload.values ?? []) types.add(item.ref.entityType);
	for (const item of payload.blockDocuments ?? []) types.add(item.ref.entityType);
	for (const item of payload.revisions ?? []) types.add(item.ref.entityType);
	if ((payload.optionsDefinitions?.length ?? 0) > 0) types.add("options");
	if ((payload.reusableBlocks?.length ?? 0) > 0) types.add("reusableBlock");
	if (types.size === 0) types.add("fields-definition");
	return Object.freeze([...types].sort());
}
function restoredPayloadCounts(payload) {
	return Object.freeze({
		groupDefinitions: payload.groupDefinitions?.length ?? 0,
		optionsDefinitions: payload.optionsDefinitions?.length ?? 0,
		blockDefinitions: payload.blockDefinitions?.length ?? 0,
		values: payload.values?.length ?? 0,
		blockDocuments: payload.blockDocuments?.length ?? 0,
		reusableBlocks: payload.reusableBlocks?.length ?? 0,
		revisions: payload.revisions?.length ?? 0
	});
}
async function writeRestoredValueSnapshot(tx, item, definition, definitionRevision, context) {
	if (fieldsContainPrivateCredential(definition.fields, context)) throw new FieldsLifecycleError("capability-unavailable", "restoring current password-bearing values requires a private credential restore adapter");
	const values = await (await Promise.resolve().then(() => dist_exports).then((n) => n.t)).__fieldBlockLifecycleInternals.validateBlockFieldMap(definition.fields, item.values, context, `backup.values.${definition.key}`);
	const ids = /* @__PURE__ */ new Map();
	const rows = encodeFieldValueNodes(definition, values, {
		entityType: item.ref.entityType,
		entityId: item.ref.entityId,
		definitionRevision,
		nodeIdForPath: (path) => {
			let id = ids.get(path);
			if (!id) {
				id = crypto.randomUUID();
				ids.set(path, id);
			}
			return id;
		},
		...context.cloneResolver ? { cloneResolver: { resolve: (field) => context.cloneResolver.resolve(field) } } : {}
	});
	await tx.execute(sql`DELETE FROM field_value_nodes WHERE entity_type=${item.ref.entityType} AND entity_id=${item.ref.entityId} AND group_key=${item.groupKey}`);
	for (const row of rows) await tx.execute(sql`
    INSERT INTO field_value_nodes
      (node_id,entity_type,entity_id,group_key,definition_revision,field_key,path,parent_node_id,row_id,layout_key,node_kind,ordinal,is_null,value_text,value_number,value_boolean,value_date_time,value_ref,value_json,created_at,updated_at)
    VALUES
      (${row.nodeId},${row.entityType},${row.entityId},${row.groupKey},${row.definitionRevision},${row.fieldKey},${row.path},${row.parentNodeId},${row.rowId},${row.layoutKey},${row.nodeKind},${row.ordinal},${row.isNull},${row.valueText},${row.valueNumber},${row.valueBoolean},${row.valueDateTime},${row.valueRef},${row.valueJson},${(/* @__PURE__ */ new Date()).toISOString()},${(/* @__PURE__ */ new Date()).toISOString()})
  `);
}
async function requireRestoredDefinitionVersions(db, versions) {
	const blocksModule = await Promise.resolve().then(() => dist_exports).then((n) => n.t);
	for (const [identity, revision] of Object.entries(versions)) if (identity.startsWith("block:")) {
		if (!await blocksModule.__fieldBlockLifecycleInternals.readBlockVersion(db, identity.slice(6), revision)) throw new FieldsLifecycleError("backup-invalid", `restored snapshot references missing block definition ${identity}@${revision}`);
	} else {
		const groupKey = identity.startsWith("group:") ? identity.slice(6) : identity;
		try {
			await resolveFieldDefinitionVersion(db, groupKey, revision);
		} catch {
			throw new FieldsLifecycleError("backup-invalid", `restored snapshot references missing field definition ${groupKey}@${revision}`);
		}
	}
}
async function restoreFieldsBackup(tx, manifest, destinationCorpusHash, operationId, context, effects, backups) {
	assertActiveFieldsTransaction(tx);
	const authorized = await assertFieldsAuthorized(context, "manageDefinitions", {
		entityType: "fields-definition",
		entityId: manifest.id
	});
	let verified;
	try {
		verified = await backups.verify(tx, manifest.id, manifest.scopeHash, manifest.corpusVersion, manifest.corpusHash, manifest.itemCounts);
	} catch {
		throw new FieldsLifecycleError("backup-invalid", "backup manifest verification failed");
	}
	if (!manifestsEqual(manifest, verified)) throw new FieldsLifecycleError("backup-invalid", "backup manifest identity changed");
	let snapshot;
	try {
		snapshot = await backups.read(tx, verified);
	} catch {
		throw new FieldsLifecycleError("backup-invalid", "backup payload could not be read");
	}
	if (!snapshot || !manifestsEqual(snapshot.manifest, verified)) throw new FieldsLifecycleError("backup-invalid", "backup payload manifest does not match verified manifest");
	const payload = await parseFieldsBackupPayload(snapshot.payload);
	const migration = await assertDefinitionMigration(context, backupPayloadEntityTypes(payload));
	const requestHash = await fieldsRequestHash({
		manifestId: manifest.id,
		destinationCorpusHash
	});
	const replay = await readFieldsReceipt(tx, operationId);
	if (replay) {
		assertReceiptReplay(replay, {
			kind: "fields:restore-backup",
			context: authorized,
			requestHash
		});
		const result = lifecycleRecord(replay.result, "backup restore receipt");
		if (result.operationId !== operationId || result.manifestId !== manifest.id || result.destinationCorpusHash !== destinationCorpusHash) throw new FieldsLifecycleError("integrity", "backup restore receipt is malformed");
		const restoredCounts = lifecycleRecord(result.restoredCounts, "backup restore counts"), counts = {};
		for (const [key, value] of Object.entries(restoredCounts)) {
			const number = Number(value);
			if (!Number.isSafeInteger(number) || number < 0) throw new FieldsLifecycleError("integrity", "backup restore receipt count is invalid");
			counts[key] = number;
		}
		return Object.freeze({
			operationId,
			manifestId: manifest.id,
			destinationCorpusHash,
			restoredCounts: Object.freeze(counts)
		});
	}
	if (await fieldsBackupDestinationHash(tx, payload) !== destinationCorpusHash) throw new FieldsLifecycleError("corpus-drift", "backup restore destination changed");
	const refs = /* @__PURE__ */ new Map();
	for (const item of payload.values ?? []) refs.set(restoreTargetKey(item.ref), item.ref);
	for (const item of payload.blockDocuments ?? []) refs.set(restoreTargetKey(item.ref), item.ref);
	for (const item of payload.revisions ?? []) refs.set(restoreTargetKey(item.ref), item.ref);
	for (const ref of refs.values()) await assertFieldsAuthorized(context, "write", ref);
	for (const item of payload.reusableBlocks ?? []) await assertFieldsAuthorized(context, "write", {
		entityType: "reusableBlock",
		entityId: item.id
	});
	const currentGroupRows = await finalGroupRows(tx);
	const availableGroups = new Set(currentGroupRows.filter((row) => lifecycleBool(row.active)).map((row) => row.key));
	for (const item of payload.groupDefinitions ?? []) availableGroups.add(item.key);
	const currentBlockRows = await lifecycleExecute(tx, sql`SELECT key,active FROM field_block_definitions`);
	const availableBlocks = new Set(currentBlockRows.filter((row) => lifecycleBool(row.active)).map((row) => String(row.key)));
	for (const item of payload.blockDefinitions ?? []) availableBlocks.add(item.key);
	for (const item of payload.blockDefinitions ?? []) {
		for (const groupKey of item.definition.fieldGroupKeys) if (!availableGroups.has(groupKey)) throw new FieldsLifecycleError("backup-invalid", `backup block ${item.key} references missing field group ${groupKey}`);
		for (const parent of item.definition.parent ?? []) if (!availableBlocks.has(parent)) throw new FieldsLifecycleError("backup-invalid", `backup block ${item.key} references missing parent ${parent}`);
		for (const ancestor of item.definition.ancestor ?? []) if (!availableBlocks.has(ancestor)) throw new FieldsLifecycleError("backup-invalid", `backup block ${item.key} references missing ancestor ${ancestor}`);
	}
	const currentOptionsRows = await lifecycleExecute(tx, sql`SELECT key FROM field_options_definitions WHERE active=true`), availableOptions = new Set(currentOptionsRows.map((row) => String(row.key)));
	for (const item of payload.optionsDefinitions ?? []) availableOptions.add(item.key);
	for (const item of payload.optionsDefinitions ?? []) if (item.definition.parentKey && !availableOptions.has(item.definition.parentKey)) throw new FieldsLifecycleError("backup-invalid", `backup options page ${item.key} references missing parent ${item.definition.parentKey}`);
	const groupRevisions = /* @__PURE__ */ new Map(), blockRevisions = /* @__PURE__ */ new Map();
	for (const item of payload.groupDefinitions ?? []) {
		const existing = await finalGroupRow(tx, item.key), canonicalHash = await canonicalFieldGroupHash(item.definition), revision = existing ? Number(existing.currentRevision) + 1 : 1, version = existing ? Number(existing.version) + 1 : 1, now = (/* @__PURE__ */ new Date()).toISOString();
		await tx.execute(sql`INSERT INTO field_definition_versions (group_key,revision,canonical_hash,definition,origin,created_at) VALUES (${item.key},${revision},${canonicalHash},${JSON.stringify(item.definition)},'db',${now})`);
		if (existing) await tx.execute(sql`UPDATE field_group_definitions SET origin='db',version=${version},active=${item.definition.active},current_revision=${revision},canonical_hash=${canonicalHash},definition=${JSON.stringify(item.definition)},shadowed_db_version=NULL,updated_at=${now} WHERE key=${item.key}`);
		else await tx.execute(sql`INSERT INTO field_group_definitions (key,origin,version,active,current_revision,canonical_hash,definition,created_at,updated_at) VALUES (${item.key},'db',1,${item.definition.active},1,${canonicalHash},${JSON.stringify(item.definition)},${now},${now})`);
		groupRevisions.set(item.key, revision);
	}
	const optionsModule = await Promise.resolve().then(() => dist_exports).then((n) => n.n);
	for (const item of payload.optionsDefinitions ?? []) {
		const definition = optionsModule.__optionsLifecycleInternals.normalizeOptionsPage(item.definition), canonicalHash = await fieldsRequestHash(definition), current = await optionsModule.__optionsLifecycleInternals.readDbPage(tx, item.key), revision = current ? Number(current.row.currentRevision) + 1 : 1, version = current ? Number(current.row.version) + 1 : 1, now = (/* @__PURE__ */ new Date()).toISOString();
		await tx.execute(sql`INSERT INTO field_options_definition_versions (options_key,revision,canonical_hash,definition,origin,created_at) VALUES (${item.key},${revision},${canonicalHash},${JSON.stringify(definition)},'db',${now})`);
		if (current) await tx.execute(sql`UPDATE field_options_definitions SET origin='db',version=${version},active=${item.active},current_revision=${revision},canonical_hash=${canonicalHash},definition=${JSON.stringify(definition)},shadowed_db_version=NULL,updated_at=${now} WHERE key=${item.key}`);
		else await tx.execute(sql`INSERT INTO field_options_definitions (key,origin,version,active,current_revision,canonical_hash,definition,created_at,updated_at) VALUES (${item.key},'db',1,${item.active},1,${canonicalHash},${JSON.stringify(definition)},${now},${now})`);
	}
	const blocksModule = await Promise.resolve().then(() => dist_exports).then((n) => n.t);
	for (const item of payload.blockDefinitions ?? []) {
		const definition = blocksModule.__fieldBlockLifecycleInternals.normalizeDefinition(item.definition), canonicalHash = await fieldsRequestHash(definition), current = await blocksModule.__fieldBlockLifecycleInternals.readCurrentBlock(tx, item.key), revision = current ? Number(current.row.currentRevision) + 1 : 1, version = current ? Number(current.row.version) + 1 : 1, now = (/* @__PURE__ */ new Date()).toISOString();
		await tx.execute(sql`INSERT INTO field_block_definition_versions (block_key,revision,canonical_hash,definition,origin,created_at) VALUES (${item.key},${revision},${canonicalHash},${JSON.stringify(definition)},'db',${now})`);
		if (current) await tx.execute(sql`UPDATE field_block_definitions SET origin='db',version=${version},active=${item.active},current_revision=${revision},canonical_hash=${canonicalHash},definition=${JSON.stringify(definition)},shadowed_db_version=NULL,updated_at=${now} WHERE key=${item.key}`);
		else await tx.execute(sql`INSERT INTO field_block_definitions (key,origin,version,active,current_revision,canonical_hash,definition,created_at,updated_at) VALUES (${item.key},'db',1,${item.active},1,${canonicalHash},${JSON.stringify(definition)},${now},${now})`);
		blockRevisions.set(item.key, revision);
	}
	for (const item of payload.values ?? []) {
		const restoredRevision = groupRevisions.get(item.groupKey) ?? item.definitionRevision;
		const definition = groupRevisions.has(item.groupKey) ? (payload.groupDefinitions ?? []).find((candidate) => candidate.key === item.groupKey)?.definition : (await resolveFieldDefinitionVersion(tx, item.groupKey, item.definitionRevision)).definition;
		if (!definition) throw new FieldsLifecycleError("backup-invalid", `backup value references missing field group ${item.groupKey}`);
		await writeRestoredValueSnapshot(tx, item, definition, restoredRevision, context);
	}
	const remappedReusable = /* @__PURE__ */ new Map();
	for (const item of payload.reusableBlocks ?? []) {
		const document = remapBlockDocument(item.document, groupRevisions, blockRevisions);
		remappedReusable.set(item.id, {
			document,
			version: 1
		});
	}
	const persistedReusableResolver = blocksModule.createReusableBlockResolver(tx);
	const reusableResolver = { resolve: async (id, ctx) => remappedReusable.get(id) ?? persistedReusableResolver.resolve(id, ctx) };
	const registry = await blocksModule.resolveFieldBlocks(tx);
	for (const item of payload.blockDocuments ?? []) {
		const document = remapBlockDocument(item.document, groupRevisions, blockRevisions);
		const validated = await blocksModule.validateBlockDocument(document, registry, reusableResolver, context, blocksModule.DEFAULT_BLOCK_POLICY);
		const versions = remapDefinitionVersions(item.definitionVersions, groupRevisions, blockRevisions);
		const current = await lifecycleExecute(tx, sql`SELECT version FROM field_block_documents WHERE entity_type=${item.ref.entityType} AND entity_id=${item.ref.entityId} LIMIT 1`), version = Number(current[0]?.version ?? 0) + 1, now = (/* @__PURE__ */ new Date()).toISOString();
		await tx.execute(sql`INSERT INTO field_block_documents (entity_type,entity_id,version,document,definition_versions,parent_revision_id,updated_by,updated_at) VALUES (${item.ref.entityType},${item.ref.entityId},${version},${blocksModule.serializeBlockDocument(validated)},${JSON.stringify(versions)},${item.parentRevisionId},${authorized.principal.id},${now}) ON CONFLICT (entity_type,entity_id) DO UPDATE SET version=EXCLUDED.version,document=EXCLUDED.document,definition_versions=EXCLUDED.definition_versions,parent_revision_id=EXCLUDED.parent_revision_id,updated_by=EXCLUDED.updated_by,updated_at=EXCLUDED.updated_at`);
	}
	for (const item of payload.reusableBlocks ?? []) {
		const document = remappedReusable.get(item.id).document;
		const validated = await blocksModule.validateBlockDocument(document, registry, reusableResolver, context, blocksModule.DEFAULT_BLOCK_POLICY);
		const versions = remapDefinitionVersions(item.definitionVersions, groupRevisions, blockRevisions);
		const current = await lifecycleExecute(tx, sql`SELECT version FROM field_reusable_blocks WHERE id=${item.id} LIMIT 1`), version = Number(current[0]?.version ?? 0) + 1, now = (/* @__PURE__ */ new Date()).toISOString();
		await tx.execute(sql`INSERT INTO field_reusable_blocks (id,version,document,definition_versions,deleted_at,updated_by,updated_at) VALUES (${item.id},${version},${blocksModule.serializeBlockDocument(validated)},${JSON.stringify(versions)},NULL,${authorized.principal.id},${now}) ON CONFLICT (id) DO UPDATE SET version=EXCLUDED.version,document=EXCLUDED.document,definition_versions=EXCLUDED.definition_versions,deleted_at=NULL,updated_by=EXCLUDED.updated_by,updated_at=EXCLUDED.updated_at`);
	}
	for (const item of payload.revisions ?? []) {
		if ((await lifecycleExecute(tx, sql`SELECT id FROM field_revisions WHERE id=${item.id} LIMIT 1`)).length > 0) throw new FieldsLifecycleError("corpus-drift", `backup revision ${item.id} already exists at destination`);
		const versions = remapDefinitionVersions(item.definitionVersions, groupRevisions, blockRevisions);
		await requireRestoredDefinitionVersions(tx, versions);
		const blockDocument = item.blockDocument === void 0 ? null : remapBlockDocument(item.blockDocument, groupRevisions, blockRevisions);
		if (blockDocument !== null) await blocksModule.validateBlockDocument(blockDocument, registry, reusableResolver, context, blocksModule.DEFAULT_BLOCK_POLICY);
		await tx.execute(sql`INSERT INTO field_revisions (id,entity_type,entity_id,parent_revision_id,parent_autosave_id,kind,retention_class,definition_versions,"values",block_document,created_at,created_by,source_version) VALUES (${item.id},${item.ref.entityType},${item.ref.entityId},${item.parentRevisionId},${item.parentAutosaveId ?? null},${item.kind},${item.retentionClass ?? null},${JSON.stringify(versions)},${JSON.stringify(item.values)},${blockDocument === null ? null : JSON.stringify(blockDocument)},${item.createdAt},${item.createdBy},${item.sourceVersion})`);
	}
	const restoredCounts = restoredPayloadCounts(payload);
	const result = Object.freeze({
		operationId,
		manifestId: manifest.id,
		destinationCorpusHash,
		restoredCounts
	});
	const event = Object.freeze({
		kind: "backupRestored",
		operationId,
		principalId: authorized.principal.id,
		authorizationPolicyVersion: migration.policyVersion,
		manifest: verified,
		destinationCorpusHash,
		restoredCounts
	});
	await effects.audit.record(tx, event);
	await effects.outbox.enqueue(tx, event);
	await writeFieldsReceipt(tx, {
		operationId,
		kind: "fields:restore-backup",
		context: authorized,
		requestHash,
		result: freezeStorage(result, "restore result")
	});
	return result;
}
//#endregion
//#region ../../packages/fields/dist/index.js
var dist_exports = /* @__PURE__ */ __exportAll$1({
	BUILTIN_LOCATION_RESOLVERS: () => BUILTIN_LOCATION_RESOLVERS,
	DEFAULT_BLOCK_POLICY: () => DEFAULT_BLOCK_POLICY,
	EMPTY_BLOCK_DOCUMENT_VERSION: () => "0",
	FIELDS_RECURSIVE_EAV_MIGRATION_ID: () => FIELDS_RECURSIVE_EAV_MIGRATION_ID,
	FIELD_DEFINITION_LIMITS: () => FIELD_DEFINITION_LIMITS,
	FIELD_KEY_RE: () => FIELD_KEY_RE,
	FIELD_TYPES: () => FIELD_TYPES,
	FieldAuthorizationError: () => FieldAuthorizationError,
	FieldGroupConflictError: () => FieldGroupConflictError,
	FieldStoreError: () => FieldStoreError,
	FieldValidationError: () => FieldValidationError,
	FieldsHeadlessError: () => FieldsHeadlessError,
	FieldsImportError: () => FieldsImportError,
	FieldsLifecycleError: () => FieldsLifecycleError,
	FieldsStoreContractError: () => FieldsStoreContractError,
	applyFieldBlockChange: () => applyFieldBlockChange,
	applyOptionsPageDeactivation: () => applyOptionsPageDeactivation,
	assertCanEditFields: () => assertCanEditFields,
	assertCanManageGroups: () => assertCanManageGroups,
	assertFieldsTransactionIdentity: () => assertFieldsTransactionIdentity,
	assertNoCodeKeyShadow: () => assertNoCodeKeyShadow,
	assertNoCrossGroupFieldKeyConflict: () => assertNoCrossGroupFieldKeyConflict,
	canonicalFieldGroupHash: () => canonicalFieldGroupHash,
	captureFieldsRevision: () => captureFieldsRevision,
	createFieldBlock: () => createFieldBlock,
	createFieldTypeRegistry: () => createFieldTypeRegistry,
	createGroup: () => createGroup,
	createLocationResolverRegistry: () => createLocationResolverRegistry,
	createOptionsPage: () => createOptionsPage,
	createReusableBlockResolver: () => createReusableBlockResolver,
	decodeFieldValueNodes: () => decodeFieldValueNodes,
	defineFieldBlock: () => defineFieldBlock,
	defineFieldGroup: () => defineFieldGroup,
	defineOptionsPage: () => defineOptionsPage,
	deleteBlockDocument: () => deleteBlockDocument,
	deleteEntityValues: () => deleteEntityValues,
	deleteGroup: () => deleteGroup,
	encodeFieldValueNodes: () => encodeFieldValueNodes,
	exportFields: () => exportFields,
	fieldGroups: () => fieldGroups,
	fieldValues: () => fieldValues,
	fieldsRuntimeMigrationSql: () => fieldsRuntimeMigrationSql,
	generateFieldsHeadlessSchema: () => generateFieldsHeadlessSchema,
	getBlockDocument: () => getBlockDocument,
	getEntityValues: () => getEntityValues,
	getFieldsRevision: () => getFieldsRevision,
	getOptionsValues: () => getOptionsValues,
	isMultipleCapable: () => isMultipleCapable,
	listGroups: () => listGroups,
	n: () => options_exports,
	parseBlockDocument: () => parseBlockDocument,
	parseFieldGroupDefinition: () => parseFieldGroupDefinition,
	parseFieldsImport: () => parseFieldsImport,
	planFieldsImport: () => planFieldsImport,
	planFieldsImportD1: () => planFieldsImportD1,
	preparePublishFieldsImportD1: () => preparePublishFieldsImportD1,
	prepareResumeFieldsImportD1: () => prepareResumeFieldsImportD1,
	prepareRollbackFieldsImportD1: () => prepareRollbackFieldsImportD1,
	prepareStagedFieldsImportGuardD1: () => prepareStagedFieldsImportGuardD1,
	prepareStartFieldsImportD1: () => prepareStartFieldsImportD1,
	previewFieldBlockChange: () => previewFieldBlockChange,
	previewOptionsPageDeactivation: () => previewOptionsPageDeactivation,
	publishFieldsImport: () => publishFieldsImport,
	readFlatFieldValues: () => readFlatFieldValues,
	redactFieldValueForRevision: () => redactFieldValueForRevision,
	renderBlockDocument: () => renderBlockDocument,
	resolveFieldBlocks: () => resolveFieldBlocks,
	resolveFieldDefinitionVersion: () => resolveFieldDefinitionVersion,
	resolveGroups: () => resolveGroups,
	resolveOptionsPages: () => resolveOptionsPages,
	restoreFieldsRevision: () => restoreFieldsRevision,
	resumeFieldsImport: () => resumeFieldsImport,
	rollbackFieldsImport: () => rollbackFieldsImport,
	serializeBlockDocument: () => serializeBlockDocument,
	setBlockDocument: () => setBlockDocument,
	setEntityValues: () => setEntityValues,
	setOptionsValues: () => setOptionsValues,
	startFieldsImport: () => startFieldsImport,
	t: () => blocks_exports,
	updateGroup: () => updateGroup,
	updateOptionsPage: () => updateOptionsPage,
	validateBlockDocument: () => validateBlockDocument,
	validateBlockPublication: () => validateBlockPublication,
	validateFieldValue: () => validateFieldValue,
	validateValues: () => validateValues
});
var __defProp = Object.defineProperty;
var __exportAll = (all, no_symbols) => {
	let target = {};
	for (var name in all) __defProp(target, name, {
		get: all[name],
		enumerable: true
	});
	if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
	return target;
};
var FIELD_TYPES = [
	"text",
	"textarea",
	"number",
	"boolean",
	"select",
	"date",
	"color",
	"url",
	"email",
	"media",
	"relationship"
];
/** stable machine key + storage/read key */
var FIELD_KEY_RE = /^[a-z][a-z0-9_]*$/;
var MULTIPLE_CAPABLE = /* @__PURE__ */ new Set([
	"select",
	"media",
	"relationship"
]);
function isMultipleCapable(t) {
	return MULTIPLE_CAPABLE.has(t);
}
function assertCanEditFields(actor) {
	if (!actor.canEditFields) throw new FieldAuthorizationError(actor.id, "editFields");
}
function assertCanManageGroups(actor) {
	if (!actor.canManageGroups) throw new FieldAuthorizationError(actor.id, "manageGroups");
}
var COLOR_RE = /^#([0-9a-f]{6}|[0-9a-f]{8})$/i;
var EMAIL_RE = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
function isValidUrl(s) {
	try {
		const u = new URL(s);
		return u.protocol === "http:" || u.protocol === "https:";
	} catch {
		return false;
	}
}
function isMediaRef(v) {
	return typeof v === "object" && v !== null && typeof v.key === "string" && v.key.length > 0;
}
function isRelRef(v) {
	return typeof v === "object" && v !== null && typeof v.entityType === "string" && typeof v.entityId === "string";
}
/** Pure, validator-agnostic. Throws FieldValidationError on first offending field.
*  Does NOT check relationship existence (that is setEntityValues' optional async resolver, §6). */
function validateValues(group, values) {
	const defs = new Map(group.fields.map((f) => [f.key, f]));
	for (const k of Object.keys(values)) if (!defs.has(k)) throw new FieldValidationError(k, "not defined in group");
	for (const f of group.fields) validateField(f, values[f.key]);
}
function validateField(f, v) {
	if (v === void 0 || v === null) {
		if (f.required) throw new FieldValidationError(f.key, "required");
		return;
	}
	if ("multiple" in f && f.multiple === true) {
		if (!Array.isArray(v)) throw new FieldValidationError(f.key, "must be an array (multiple)");
		for (const item of v) validateScalar$1(f, item);
		return;
	}
	if (Array.isArray(v) && !isMultipleCapable(f.type)) throw new FieldValidationError(f.key, "array not allowed for this type");
	validateScalar$1(f, v);
}
function validateScalar$1(f, v) {
	switch (f.type) {
		case "text":
		case "textarea":
			if (typeof v !== "string") throw new FieldValidationError(f.key, "must be a string");
			if (f.maxLength !== void 0 && v.length > f.maxLength) throw new FieldValidationError(f.key, `exceeds maxLength ${f.maxLength}`);
			if (f.type === "text" && f.pattern !== void 0) try {
				if (!new RegExp(f.pattern).test(v)) throw new FieldValidationError(f.key, "pattern mismatch");
			} catch {
				throw new FieldValidationError(f.key, "pattern mismatch");
			}
			break;
		case "number":
			if (typeof v !== "number" || Number.isNaN(v)) throw new FieldValidationError(f.key, "must be a number");
			if (f.integer && !Number.isInteger(v)) throw new FieldValidationError(f.key, "must be an integer");
			if (f.min !== void 0 && v < f.min) throw new FieldValidationError(f.key, `below min ${f.min}`);
			if (f.max !== void 0 && v > f.max) throw new FieldValidationError(f.key, `above max ${f.max}`);
			break;
		case "boolean":
			if (typeof v !== "boolean") throw new FieldValidationError(f.key, "must be a boolean");
			break;
		case "select":
			if (typeof v !== "string") throw new FieldValidationError(f.key, "must be a string");
			if (!new Set(f.options.map((o) => o.value)).has(v)) throw new FieldValidationError(f.key, "value not in options");
			break;
		case "date": {
			const d = v instanceof Date ? v : new Date(v);
			if (Number.isNaN(d.getTime())) throw new FieldValidationError(f.key, "must be a parseable date");
			break;
		}
		case "color":
			if (typeof v !== "string" || !COLOR_RE.test(v)) throw new FieldValidationError(f.key, "invalid color format");
			break;
		case "url":
			if (typeof v !== "string" || !isValidUrl(v)) throw new FieldValidationError(f.key, "invalid url");
			break;
		case "email":
			if (typeof v !== "string" || !EMAIL_RE.test(v)) throw new FieldValidationError(f.key, "invalid email");
			break;
		case "media":
			if (!isMediaRef(v)) throw new FieldValidationError(f.key, "media requires key");
			break;
		case "relationship":
			if (!isRelRef(v)) throw new FieldValidationError(f.key, "invalid relationship ref");
			if (v.entityType !== f.targetEntityType) throw new FieldValidationError(f.key, "targetEntityType mismatch");
	}
}
function matchesLocation(entityType, subType, rule) {
	if (rule.entityType !== entityType) return false;
	if (rule.subType === void 0) return true;
	if (subType === void 0) return false;
	return rule.subType === subType;
}
function validateGroupShape(group) {
	if (!FIELD_KEY_RE.test(group.key)) throw new FieldValidationError(group.key, "invalid group key");
	const seen = /* @__PURE__ */ new Set();
	for (const f of group.fields) {
		if (!FIELD_KEY_RE.test(f.key)) throw new FieldValidationError(f.key, "invalid field key");
		if (seen.has(f.key)) throw new FieldGroupConflictError(group.key, `duplicate field key ${f.key}`);
		seen.add(f.key);
		if (f.type === "select" && (!f.options || f.options.length === 0)) throw new FieldValidationError(f.key, "select requires options");
		if (f.type === "relationship" && !f.targetEntityType) throw new FieldValidationError(f.key, "relationship requires targetEntityType");
	}
}
function defineFieldGroup(group) {
	validateGroupShape(group);
	return {
		...group,
		origin: "code"
	};
}
function assertNoCrossGroupFieldKeyConflict(groups) {
	const fieldOwners = /* @__PURE__ */ new Map();
	for (const g of groups) for (const f of g.fields) {
		const prev = fieldOwners.get(f.key);
		if (prev !== void 0 && prev !== g.key) throw new FieldGroupConflictError(f.key, `field key ${f.key} defined in groups ${prev} and ${g.key}`);
		fieldOwners.set(f.key, g.key);
	}
}
function assertNoCodeKeyShadow(dbKey, entityType, codeGroups) {
	if (codeGroups?.find((g) => g.location.entityType === entityType && g.key === dbKey)) throw new FieldGroupConflictError(dbKey, "shadows code key");
}
async function resolveGroups(db, opts) {
	const { entityType, subType, codeGroups = [] } = opts;
	const dbResolved = (await db.select().from(fieldGroups).where(and(eq(fieldGroups.entityType, entityType), subType === void 0 ? isNull(fieldGroups.subType) : or(isNull(fieldGroups.subType), eq(fieldGroups.subType, subType))))).map((row) => ({
		key: row.key,
		label: row.label,
		location: {
			entityType: row.entityType,
			subType: row.subType ?? void 0
		},
		fields: row.fields,
		position: row.position,
		origin: "db",
		id: row.id
	}));
	const codeResolved = codeGroups.filter((g) => matchesLocation(entityType, subType, g.location)).map((g) => ({
		...g,
		origin: "code"
	}));
	for (const dbG of dbResolved) assertNoCodeKeyShadow(dbG.key, entityType, codeGroups);
	const merged = [...codeResolved, ...dbResolved].sort((a, b) => (a.position ?? 0) - (b.position ?? 0));
	assertNoCrossGroupFieldKeyConflict(merged);
	return merged;
}
/** Typed structural error for flat reads and composite transaction capability checks. */
var FieldsStoreContractError = class extends Error {
	code;
	detail;
	field;
	name = "FieldsStoreContractError";
	constructor(code, detail, field) {
		super(`fields store ${code}: ${detail}`);
		this.code = code;
		this.detail = detail;
		this.field = field;
	}
};
function trustedFlatRow(row) {
	if (typeof row !== "object" || row === null || Array.isArray(row) || Object.getPrototypeOf(row) !== Object.prototype || Object.getOwnPropertySymbols(row).length !== 0) throw new FieldsStoreContractError("invalid-flat-row", "must be a plain data row", "row");
	for (const key of Object.getOwnPropertyNames(row)) {
		const descriptor = Object.getOwnPropertyDescriptor(row, key);
		if (!descriptor.enumerable || !("value" in descriptor)) throw new FieldsStoreContractError("invalid-flat-row", "must not contain non-enumerable properties or accessors", "row");
	}
	return row;
}
function flatString(row, field, nullable = false) {
	const value = row[field];
	if (nullable && value === null) return null;
	if (typeof value !== "string") throw new FieldsStoreContractError("invalid-flat-row", "must be a string", field);
	return value;
}
function flatBoolean(row, field) {
	const value = row[field];
	if (value === null) return null;
	if (typeof value === "boolean") return value;
	if (value === 0 || value === 1) return value === 1;
	throw new FieldsStoreContractError("invalid-flat-row", "must be a boolean, D1 0/1, or null", field);
}
function flatOrdinal(row) {
	const value = row.ordinal;
	if (typeof value !== "number" || !Number.isInteger(value) || value < 0) throw new FieldsStoreContractError("invalid-flat-row", "must be a non-negative integer", "ordinal");
	return value;
}
function flatDate(row, field, nullable = false) {
	const value = row[field];
	if (nullable && value === null) return null;
	const date = value instanceof Date ? new Date(Date.prototype.getTime.call(value)) : typeof value === "string" ? new Date(value) : null;
	if (date === null || Number.isNaN(date.getTime())) throw new FieldsStoreContractError("invalid-flat-row", "must be an ISO timestamp or Date", field);
	return date;
}
function freezeStorageValue(value, field, ancestors = /* @__PURE__ */ new Set()) {
	if (value === null || typeof value === "string" || typeof value === "boolean") return value;
	if (typeof value === "number") {
		if (!Number.isFinite(value)) throw new FieldsStoreContractError("invalid-flat-row", "must be finite", field);
		return value;
	}
	if (typeof value !== "object" || value === null || ancestors.has(value)) throw new FieldsStoreContractError("invalid-flat-row", "must be an acyclic plain serializable value", field);
	if (Object.getOwnPropertySymbols(value).length !== 0) throw new FieldsStoreContractError("invalid-flat-row", "must not contain symbols", field);
	ancestors.add(value);
	try {
		if (Array.isArray(value)) {
			const names = Object.getOwnPropertyNames(value);
			if (names.length !== value.length + 1 || !names.includes("length")) throw new FieldsStoreContractError("invalid-flat-row", "must be a dense data array", field);
			const values = [];
			for (let index = 0; index < value.length; index += 1) {
				const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
				if (!descriptor?.enumerable || !("value" in descriptor)) throw new FieldsStoreContractError("invalid-flat-row", "must not contain accessors", field);
				values.push(freezeStorageValue(descriptor.value, field, ancestors));
			}
			return Object.freeze(values);
		}
		if (Object.getPrototypeOf(value) !== Object.prototype) throw new FieldsStoreContractError("invalid-flat-row", "must be a plain serializable value", field);
		const output = {};
		for (const key of Object.getOwnPropertyNames(value)) {
			const descriptor = Object.getOwnPropertyDescriptor(value, key);
			if (!descriptor.enumerable || !("value" in descriptor)) throw new FieldsStoreContractError("invalid-flat-row", "must not contain non-enumerable properties or accessors", field);
			if (key === "__proto__" || key === "constructor" || key === "prototype") throw new FieldsStoreContractError("invalid-flat-row", "contains a forbidden object key", field);
			output[key] = freezeStorageValue(descriptor.value, field, ancestors);
		}
		return Object.freeze(output);
	} finally {
		ancestors.delete(value);
	}
}
function assertExactlyOneFlatLane(row) {
	const lanes = [
		"valueText",
		"valueNum",
		"valueBool",
		"valueDate",
		"refId"
	];
	const reference = row.refId !== null;
	if (lanes.filter((lane) => row[lane] !== null).length !== 1) throw new FieldsStoreContractError("invalid-flat-row", "must contain exactly one populated value lane");
	if (reference && typeof row.refType !== "string") throw new FieldsStoreContractError("invalid-flat-row", "must be a string when refId is populated", "refType");
	if (!reference && (row.refType !== null || row.refMeta !== null)) throw new FieldsStoreContractError("invalid-flat-row", "must be null without a reference lane", row.refType !== null ? "refType" : "refMeta");
}
/**
* Reads the current flat EAV corpus without interpreting definitions or
* converting it to recursive nodes. The output preserves each typed lane for
* the migration's later count/hash/value comparison.
*/
async function readFlatFieldValues(reader) {
	if (reader.adapter !== "d1" && reader.adapter !== "postgres") throw new FieldsStoreContractError("unsupported-adapter", `unknown adapter ${String(reader.adapter)}`);
	const rows = await reader.execute(sql`
    SELECT id, entity_type AS "entityType", entity_id AS "entityId",
      group_id AS "groupId", field_key AS "fieldKey", ordinal,
      value_text AS "valueText", value_num AS "valueNum",
      value_bool AS "valueBool", value_date AS "valueDate",
      ref_type AS "refType", ref_id AS "refId", ref_meta AS "refMeta",
      created_at AS "createdAt", updated_at AS "updatedAt"
    FROM field_values
    ORDER BY entity_type ASC, entity_id ASC, group_id ASC, field_key ASC, ordinal ASC
  `);
	return Object.freeze(rows.map((candidate) => {
		const row = trustedFlatRow(candidate);
		assertExactlyOneFlatLane(row);
		const valueNum = row.valueNum;
		if (valueNum !== null && (typeof valueNum !== "string" || !/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(valueNum))) throw new FieldsStoreContractError("invalid-flat-row", "must be an exact finite decimal string", "valueNum");
		const refMeta = typeof row.refMeta === "string" ? (() => {
			try {
				return JSON.parse(row.refMeta);
			} catch {
				throw new FieldsStoreContractError("invalid-flat-row", "must be valid JSON when returned as D1 text", "refMeta");
			}
		})() : row.refMeta;
		return Object.freeze({
			id: flatString(row, "id"),
			entityType: flatString(row, "entityType"),
			entityId: flatString(row, "entityId"),
			groupId: flatString(row, "groupId"),
			fieldKey: flatString(row, "fieldKey"),
			ordinal: flatOrdinal(row),
			valueText: flatString(row, "valueText", true),
			valueNum: valueNum === null ? null : valueNum,
			valueBool: flatBoolean(row, "valueBool"),
			valueDate: flatDate(row, "valueDate", true),
			refType: flatString(row, "refType", true),
			refId: flatString(row, "refId", true),
			refMeta: refMeta === null ? null : freezeStorageValue(refMeta, "refMeta"),
			createdAt: flatDate(row, "createdAt"),
			updatedAt: flatDate(row, "updatedAt")
		});
	}));
}
/** Require the same callback-minted identity supplied by a parent composite. */
function assertFieldsTransactionIdentity(tx, expectedIdentity) {
	try {
		assertTransactionIdentity(tx, expectedIdentity);
	} catch (error) {
		if (isTransactionCapabilityError(error)) throw new FieldsStoreContractError("transaction-capability", error.reason);
		throw error;
	}
}
function fieldDefByKey(groups) {
	const m = /* @__PURE__ */ new Map();
	for (const g of groups) for (const f of g.fields) m.set(f.key, f);
	return m;
}
function valueToRows(ref, groupId, field, value) {
	if ("multiple" in field && field.multiple === true && Array.isArray(value)) return value.map((item, ordinal) => scalarToRow(ref, groupId, field, item, ordinal));
	return [scalarToRow(ref, groupId, field, value, 0)];
}
function scalarToRow(ref, groupId, field, value, ordinal) {
	const base = {
		entityType: ref.entityType,
		entityId: ref.entityId,
		groupId,
		fieldKey: field.key,
		ordinal
	};
	switch (field.type) {
		case "text":
		case "textarea":
		case "select":
		case "color":
		case "url":
		case "email": return {
			...base,
			valueText: String(value)
		};
		case "number": return {
			...base,
			valueNum: String(value)
		};
		case "boolean": return {
			...base,
			valueBool: value
		};
		case "date": {
			const d = value instanceof Date ? value : new Date(value);
			return {
				...base,
				valueDate: d
			};
		}
		case "media": {
			const { key, url, mime, meta } = value;
			const refMeta = {};
			if (url !== void 0) refMeta.url = url;
			if (mime !== void 0) refMeta.mime = mime;
			if (meta !== void 0) refMeta.meta = meta;
			return {
				...base,
				refType: "media",
				refId: key,
				refMeta: Object.keys(refMeta).length > 0 ? refMeta : null
			};
		}
		case "relationship": {
			const r = value;
			return {
				...base,
				refType: r.entityType,
				refId: r.entityId
			};
		}
	}
}
function rowToValue(field, rows) {
	if (rows.length === 0) return void 0;
	const multiple = "multiple" in field && field.multiple === true;
	const sorted = [...rows].sort((a, b) => a.ordinal - b.ordinal);
	if (multiple) return sorted.map((r) => rowScalar(field, r));
	return rowScalar(field, sorted[0]);
}
function rowScalar(field, row) {
	switch (field.type) {
		case "text":
		case "textarea":
		case "select":
		case "color":
		case "url":
		case "email": return row.valueText ?? "";
		case "number": return row.valueNum !== null && row.valueNum !== void 0 ? Number(row.valueNum) : 0;
		case "boolean": return row.valueBool ?? false;
		case "date": return row.valueDate ?? /* @__PURE__ */ new Date(0);
		case "media": {
			const meta = row.refMeta ?? {};
			const out = { key: row.refId ?? "" };
			if (typeof meta.url === "string") out.url = meta.url;
			if (typeof meta.mime === "string") out.mime = meta.mime;
			if (meta.meta !== void 0 && typeof meta.meta === "object" && meta.meta !== null) out.meta = meta.meta;
			return out;
		}
		case "relationship": return {
			entityType: row.refType ?? "",
			entityId: row.refId ?? ""
		};
	}
}
async function assertRefsExist(resolved, values, resolveRef) {
	if (!resolveRef) return;
	for (const f of resolved.fields) {
		if (f.type !== "relationship") continue;
		const v = values[f.key];
		if (v === void 0 || v === null) continue;
		const refs = Array.isArray(v) ? v : [v];
		for (const ref of refs) if (!await resolveRef(ref)) throw new FieldValidationError(f.key, "referenced entity not found");
	}
}
function wrapStoreError(e) {
	if (e instanceof FieldValidationError || e instanceof FieldStoreError) throw e;
	throw new FieldStoreError(e instanceof Error ? e.message : String(e));
}
async function getEntityValues(db, ref, opts) {
	const defs = fieldDefByKey(await resolveGroups(db, {
		entityType: opts.entityType,
		subType: opts.subType,
		codeGroups: opts.codeGroups
	}));
	const rows = await db.select().from(fieldValues).where(and(eq(fieldValues.entityType, ref.entityType), eq(fieldValues.entityId, ref.entityId)));
	const byKey = /* @__PURE__ */ new Map();
	for (const row of rows) {
		const list = byKey.get(row.fieldKey) ?? [];
		list.push(row);
		byKey.set(row.fieldKey, list);
	}
	const out = {};
	for (const [key, fieldRows] of byKey) {
		const def = defs.get(key);
		if (!def) continue;
		out[key] = rowToValue(def, fieldRows);
	}
	return out;
}
async function setEntityValues(db, actor, input) {
	assertCanEditFields(actor);
	validateValues(input.resolved, input.values);
	await assertRefsExist(input.resolved, input.values, input.resolveRef);
	const rows = [];
	for (const f of input.resolved.fields) {
		const v = input.values[f.key];
		if (v === void 0 || v === null) continue;
		rows.push(...valueToRows(input.ref, input.groupId, f, v));
	}
	try {
		await db.transaction(async (tx) => {
			await tx.delete(fieldValues).where(and(eq(fieldValues.entityType, input.ref.entityType), eq(fieldValues.entityId, input.ref.entityId), eq(fieldValues.groupId, input.groupId)));
			if (rows.length > 0) await tx.insert(fieldValues).values(rows);
		});
	} catch (e) {
		wrapStoreError(e);
	}
}
/**
* Host-cascade op: removes ALL field values for an entity (call on parent-entity delete, spec §8.1).
* Takes NO `Actor` and runs NO capability check by design — so the HOST MUST gate BOTH capability
* AND object-level ownership BEFORE calling this. The engine never knows who owns `entityId`
* (no owner column; spec §5). Never assume the engine authorizes this delete.
*/
async function deleteEntityValues(db, ref) {
	await db.delete(fieldValues).where(and(eq(fieldValues.entityType, ref.entityType), eq(fieldValues.entityId, ref.entityId)));
}
async function createGroup(db, actor, group, codeGroups) {
	assertCanManageGroups(actor);
	defineFieldGroup(group);
	assertNoCodeKeyShadow(group.key, group.location.entityType, codeGroups);
	const existing = await resolveGroups(db, {
		entityType: group.location.entityType,
		subType: group.location.subType,
		codeGroups
	});
	const candidate = {
		...group,
		origin: "db"
	};
	assertNoCrossGroupFieldKeyConflict([...existing, candidate]);
	try {
		const [row] = await db.insert(fieldGroups).values({
			entityType: group.location.entityType,
			subType: group.location.subType ?? null,
			key: group.key,
			label: group.label,
			fields: group.fields,
			position: group.position ?? 0
		}).returning();
		return {
			key: row.key,
			label: row.label,
			location: {
				entityType: row.entityType,
				subType: row.subType ?? void 0
			},
			fields: row.fields,
			position: row.position,
			origin: "db",
			id: row.id
		};
	} catch (e) {
		wrapStoreError(e);
	}
}
async function updateGroup(db, actor, id, patch, codeGroups) {
	assertCanManageGroups(actor);
	const [current] = await db.select().from(fieldGroups).where(eq(fieldGroups.id, id)).limit(1);
	if (!current) throw new FieldStoreError(`group not found: ${id}`);
	const merged = {
		key: patch.key ?? current.key,
		label: patch.label ?? current.label,
		location: patch.location ?? {
			entityType: current.entityType,
			subType: current.subType ?? void 0
		},
		fields: patch.fields ?? current.fields,
		position: patch.position ?? current.position
	};
	defineFieldGroup(merged);
	if (merged.key !== current.key) assertNoCodeKeyShadow(merged.key, merged.location.entityType, codeGroups);
	assertNoCrossGroupFieldKeyConflict([...(await resolveGroups(db, {
		entityType: merged.location.entityType,
		subType: merged.location.subType,
		codeGroups
	})).filter((g) => g.id !== id), {
		...merged,
		origin: "db",
		id
	}]);
	try {
		const [row] = await db.update(fieldGroups).set({
			entityType: merged.location.entityType,
			subType: merged.location.subType ?? null,
			key: merged.key,
			label: merged.label,
			fields: merged.fields,
			position: merged.position ?? 0,
			updatedAt: /* @__PURE__ */ new Date()
		}).where(eq(fieldGroups.id, id)).returning();
		return {
			key: row.key,
			label: row.label,
			location: {
				entityType: row.entityType,
				subType: row.subType ?? void 0
			},
			fields: row.fields,
			position: row.position,
			origin: "db",
			id: row.id
		};
	} catch (e) {
		wrapStoreError(e);
	}
}
async function deleteGroup(db, actor, id) {
	assertCanManageGroups(actor);
	await db.delete(fieldGroups).where(eq(fieldGroups.id, id));
}
async function listGroups(db, opts) {
	const filters = [];
	if (opts.entityType !== void 0) filters.push(eq(fieldGroups.entityType, opts.entityType));
	if (opts.subType !== void 0) filters.push(eq(fieldGroups.subType, opts.subType));
	return (await db.select().from(fieldGroups).where(filters.length > 0 ? and(...filters) : void 0)).map((row) => ({
		key: row.key,
		label: row.label,
		location: {
			entityType: row.entityType,
			subType: row.subType ?? void 0
		},
		fields: row.fields,
		position: row.position,
		origin: "db",
		id: row.id
	}));
}
sql.raw("="), sql.raw("<"), sql.raw("<="), sql.raw(">"), sql.raw(">=");
sql`SELECT entity_id FROM field_values WHERE false`;
function fail$2(field, detail) {
	throw new FieldValidationError(field, detail);
}
function hash(seed) {
	let h = 2166136261;
	for (let i = 0; i < seed.length; i++) h = Math.imul(h ^ seed.charCodeAt(i), 16777619);
	return (h >>> 0).toString(16).padStart(8, "0");
}
function scalarEqual(left, right) {
	return typeof left === typeof right && left === right;
}
function arrayValue(value) {
	return Array.isArray(value) ? value : [];
}
function match(rule, actual) {
	if (actual === void 0) return rule.operator === "neq" || rule.operator === "notIn";
	if (rule.operator === "eq") return !Array.isArray(actual) && !Array.isArray(rule.value) && scalarEqual(actual, rule.value);
	if (rule.operator === "neq") return !match({
		...rule,
		operator: "eq"
	}, actual);
	if (rule.operator === "in") {
		const allowed = arrayValue(rule.value);
		if (Array.isArray(actual)) return actual.some((item) => allowed.some((allowedItem) => scalarEqual(item, allowedItem)));
		return allowed.some((item) => scalarEqual(actual, item));
	}
	if (rule.operator === "notIn") return !match({
		...rule,
		operator: "in"
	}, actual);
	if (rule.operator === "contains") {
		if (Array.isArray(actual)) return actual.some((item) => scalarEqual(item, rule.value));
		if (typeof actual === "string" && typeof rule.value === "string") return actual.includes(rule.value);
		return false;
	}
	return false;
}
var direct = (parameter) => Object.freeze({
	parameter: String(parameter),
	resolve: (context) => {
		const value = context[parameter];
		if (value === void 0 || typeof value === "object") return void 0;
		return value;
	}
});
var BUILTIN_LOCATION_RESOLVERS = Object.freeze([
	direct("entityType"),
	direct("subType"),
	direct("entityId"),
	direct("status"),
	direct("template"),
	direct("parentId"),
	direct("format"),
	direct("authorId"),
	direct("surface"),
	direct("blockType"),
	direct("route"),
	direct("optionsPage"),
	Object.freeze({
		parameter: "actorRole",
		resolve: (context) => context.actorRoles
	}),
	Object.freeze({
		parameter: "taxonomy",
		resolve: (context) => context.taxonomy ? Object.values(context.taxonomy).flat() : void 0
	})
]);
function createLocationResolverRegistry(input = {}) {
	const ordered = [...input.builtIns ?? BUILTIN_LOCATION_RESOLVERS, ...input.extensions ?? []];
	const map = /* @__PURE__ */ new Map();
	for (const resolver of ordered) {
		if (!resolver.parameter || resolver.parameter.length > 128) fail$2("location.parameter", "must be a bounded non-empty string");
		if (map.has(resolver.parameter)) fail$2("location.parameter", `duplicate resolver ${resolver.parameter}`);
		if (typeof resolver.resolve !== "function") fail$2("location.resolver", "must be a function");
		map.set(resolver.parameter, Object.freeze(resolver));
	}
	const taxonomyPrefix = "taxonomy:";
	const version = `location-v1:${hash([...map.keys()].sort().join("|"))}`;
	return Object.freeze({
		version,
		async evaluate(rules, context) {
			if (!Array.isArray(rules) || rules.length === 0) return false;
			for (let gi = 0; gi < rules.length; gi++) {
				const group = rules[gi];
				if (!Array.isArray(group) || group.length === 0) fail$2(`location.${gi}`, "AND group must not be empty");
				let groupMatch = true;
				for (let ri = 0; ri < group.length; ri++) {
					const rule = group[ri];
					let resolver = map.get(rule.parameter), actual;
					if (!resolver && rule.parameter.startsWith(taxonomyPrefix)) {
						const taxonomy = rule.parameter.slice(9);
						if (!taxonomy) fail$2(`location.${gi}.${ri}.parameter`, "taxonomy parameter must name a taxonomy");
						actual = context.taxonomy?.[taxonomy];
					} else {
						if (!resolver) fail$2(`location.${gi}.${ri}.parameter`, `unknown location parameter ${rule.parameter}`);
						try {
							actual = await resolver.resolve(context);
						} catch {
							fail$2(`location.${gi}.${ri}.parameter`, `resolver ${rule.parameter} failed`);
						}
					}
					if (!match(rule, actual)) {
						groupMatch = false;
						break;
					}
				}
				if (groupMatch) return true;
			}
			return false;
		}
	});
}
var options_exports = /* @__PURE__ */ __exportAll({
	__optionsLifecycleInternals: () => __optionsLifecycleInternals,
	applyOptionsPageDeactivation: () => applyOptionsPageDeactivation,
	createOptionsPage: () => createOptionsPage,
	defineOptionsPage: () => defineOptionsPage,
	getOptionsValues: () => getOptionsValues,
	previewOptionsPageDeactivation: () => previewOptionsPageDeactivation,
	resolveOptionsPages: () => resolveOptionsPages,
	setOptionsValues: () => setOptionsValues,
	updateOptionsPage: () => updateOptionsPage
});
function rowsOf$5(value) {
	if (Array.isArray(value)) return value;
	if (typeof value === "object" && value !== null && Array.isArray(value.rows)) return value.rows;
	throw new FieldsLifecycleError("integrity", "database adapter returned an invalid row result");
}
async function executeRows$2(db, query) {
	return rowsOf$5(await db.execute(query));
}
function parseJson$4(value, field) {
	if (typeof value !== "string") return value;
	try {
		return JSON.parse(value);
	} catch {
		throw new FieldsLifecycleError("integrity", `${field} contains invalid JSON`);
	}
}
function bool$3(value) {
	return value === true || value === 1;
}
function boundedString$1(value, field, max = 4096) {
	if (typeof value !== "string" || value.length === 0 || value.length > max) throw new FieldsLifecycleError("validation", "must be a bounded non-empty string", field);
	return value;
}
function normalizedKey(value, field) {
	const key = boundedString$1(value, field, 128);
	if (!/^[a-z][a-z0-9_-]*$/.test(key)) throw new FieldsLifecycleError("validation", "must be a normalized key", field);
	return key;
}
function normalizeOptionsPage(input) {
	const key = normalizedKey(input.key, "key");
	const title = boundedString$1(input.title, "title");
	const readCapability = boundedString$1(input.readCapability, "readCapability", 256);
	const writeCapability = boundedString$1(input.writeCapability, "writeCapability", 256);
	const manageCapability = boundedString$1(input.manageCapability, "manageCapability", 256);
	const parentKey = input.parentKey === void 0 ? void 0 : normalizedKey(input.parentKey, "parentKey");
	if (parentKey === key) throw new FieldsLifecycleError("validation", "page cannot parent itself", "parentKey");
	if (input.position !== void 0 && (!Number.isSafeInteger(input.position) || Math.abs(input.position) > 1e6)) throw new FieldsLifecycleError("validation", "must be a bounded integer", "position");
	return Object.freeze({
		key,
		title,
		...input.menuTitle === void 0 ? {} : { menuTitle: boundedString$1(input.menuTitle, "menuTitle") },
		...parentKey === void 0 ? {} : { parentKey },
		readCapability,
		writeCapability,
		manageCapability,
		...input.position === void 0 ? {} : { position: input.position },
		...input.icon === void 0 ? {} : { icon: boundedString$1(input.icon, "icon", 512) },
		...input.redirectToFirstChild === void 0 ? {} : { redirectToFirstChild: Boolean(input.redirectToFirstChild) },
		...input.autoload === void 0 ? {} : { autoload: Boolean(input.autoload) }
	});
}
function parseOptionsDefinition(value) {
	const raw = parseJson$4(value, "options definition");
	if (typeof raw !== "object" || raw === null || Array.isArray(raw)) throw new FieldsLifecycleError("integrity", "options definition is malformed");
	return normalizeOptionsPage(raw);
}
function resolvedDb(row) {
	const definition = parseOptionsDefinition(row.definition);
	if (definition.key !== row.key) throw new FieldsLifecycleError("integrity", "options definition key does not match persisted key");
	return Object.freeze({
		...definition,
		origin: row.origin === "code" ? "code" : "db",
		version: Number(row.version),
		active: bool$3(row.active),
		...row.shadowedDbVersion === null ? {} : { shadowedDbVersion: Number(row.shadowedDbVersion) }
	});
}
async function readOptionRows(db) {
	return executeRows$2(db, sql`SELECT key, origin, version, active, current_revision AS "currentRevision", canonical_hash AS "canonicalHash", definition, shadowed_db_version AS "shadowedDbVersion" FROM field_options_definitions ORDER BY key`);
}
function mergePages(rows, codePages) {
	const db = new Map(rows.map((row) => [row.key, resolvedDb(row)]));
	const code = /* @__PURE__ */ new Map();
	for (const raw of codePages) {
		const normalized = Object.freeze({
			...normalizeOptionsPage(raw),
			origin: "code"
		});
		if (code.has(normalized.key)) throw new FieldsLifecycleError("validation", "duplicate code options key", normalized.key);
		code.set(normalized.key, normalized);
	}
	const merged = /* @__PURE__ */ new Map();
	for (const page of db.values()) merged.set(page.key, page);
	for (const page of code.values()) {
		const previous = db.get(page.key);
		merged.set(page.key, Object.freeze({
			...page,
			version: previous?.version ?? 1,
			active: true,
			...previous?.origin === "db" ? { shadowedDbVersion: previous.version } : previous?.shadowedDbVersion === void 0 ? {} : { shadowedDbVersion: previous.shadowedDbVersion }
		}));
	}
	validatePageTree([...merged.values()].filter((page) => page.active));
	return Object.freeze([...merged.values()].sort((a, b) => (a.parentKey ?? "").localeCompare(b.parentKey ?? "") || (a.position ?? 0) - (b.position ?? 0) || a.key.localeCompare(b.key)));
}
function validatePageTree(pages) {
	const byKey = new Map(pages.map((page) => [page.key, page]));
	const siblingPositions = /* @__PURE__ */ new Set();
	for (const page of pages) {
		if (page.parentKey && !byKey.has(page.parentKey)) throw new FieldsLifecycleError("validation", "parent page does not resolve in effective registry", page.key);
		if (page.position !== void 0) {
			const identity = `${page.parentKey ?? ""}:${page.position}`;
			if (siblingPositions.has(identity)) throw new FieldsLifecycleError("validation", "duplicate sibling position", page.key);
			siblingPositions.add(identity);
		}
		const seen = /* @__PURE__ */ new Set([page.key]);
		let cursor = page.parentKey;
		while (cursor) {
			if (seen.has(cursor)) throw new FieldsLifecycleError("validation", "options page parent cycle", page.key);
			seen.add(cursor);
			cursor = byKey.get(cursor)?.parentKey;
		}
	}
}
function defineOptionsPage(definition) {
	return Object.freeze({
		...normalizeOptionsPage(definition),
		origin: "code"
	});
}
async function resolveOptionsPages(db, input = {}) {
	return [...mergePages(await readOptionRows(db), input.codePages ?? [])];
}
async function readDbPage(db, key) {
	const rows = await executeRows$2(db, sql`SELECT key, origin, version, active, current_revision AS "currentRevision", canonical_hash AS "canonicalHash", definition, shadowed_db_version AS "shadowedDbVersion" FROM field_options_definitions WHERE key = ${key} LIMIT 1`);
	return rows[0] ? {
		row: rows[0],
		page: resolvedDb(rows[0])
	} : null;
}
function definitionRef$1(key) {
	return Object.freeze({
		entityType: "fields-options-definition",
		entityId: key
	});
}
function valueRef(key) {
	return Object.freeze({
		entityType: "options",
		entityId: key
	});
}
async function createOptionsPage(tx, definition, context, input) {
	assertActiveFieldsTransaction(tx);
	const normalized = normalizeOptionsPage(definition);
	const authorized = await assertFieldsAuthorized(context, "manageDefinitions", definitionRef$1(normalized.key));
	assertPrincipalCapability(authorized, normalized.manageCapability);
	const codePages = input.codePages ?? [];
	if (codePages.some((page) => page.key === normalized.key)) throw new FieldsLifecycleError("validation", "effective key is owned by code", normalized.key);
	const canonicalHash = await fieldsRequestHash(normalized);
	const requestHash = await fieldsRequestHash({
		kind: "create-options-page",
		canonicalHash,
		codeKeys: codePages.map((page) => page.key).sort()
	});
	const receipt = await readFieldsReceipt(tx, input.operationId);
	if (receipt) {
		assertReceiptReplay(receipt, {
			kind: "fields:create-options-page",
			context: authorized,
			requestHash
		});
		const replay = await readDbPage(tx, normalized.key);
		if (!replay) throw new FieldsLifecycleError("integrity", "committed options receipt has no page");
		return replay.page;
	}
	if (await readDbPage(tx, normalized.key)) throw new FieldsLifecycleError("validation", "options page key already exists", normalized.key);
	validatePageTree([...mergePages(await readOptionRows(tx), codePages), Object.freeze({
		...normalized,
		origin: "db",
		version: 1,
		active: true
	})]);
	const now = (/* @__PURE__ */ new Date()).toISOString();
	await tx.execute(sql`INSERT INTO field_options_definitions (key, origin, version, active, current_revision, canonical_hash, definition, created_at, updated_at) VALUES (${normalized.key}, 'db', 1, true, 1, ${canonicalHash}, ${JSON.stringify(normalized)}, ${now}, ${now})`);
	await tx.execute(sql`INSERT INTO field_options_definition_versions (options_key, revision, canonical_hash, definition, origin, created_at) VALUES (${normalized.key}, 1, ${canonicalHash}, ${JSON.stringify(normalized)}, 'db', ${now})`);
	const result = Object.freeze({
		...normalized,
		origin: "db",
		version: 1,
		active: true
	});
	await writeFieldsReceipt(tx, {
		operationId: input.operationId,
		kind: "fields:create-options-page",
		context: authorized,
		requestHash,
		result: Object.freeze({
			key: normalized.key,
			version: 1
		})
	});
	return result;
}
async function updateOptionsPage(tx, key, patch, expectedVersion, context, input) {
	assertActiveFieldsTransaction(tx);
	const normalizedKeyValue = normalizedKey(key, "key");
	const current = await readDbPage(tx, normalizedKeyValue);
	if (!current) throw new FieldsLifecycleError("not-found", "options page is unavailable");
	const authorized = await assertFieldsAuthorized(context, "manageDefinitions", definitionRef$1(normalizedKeyValue));
	assertPrincipalCapability(authorized, current.page.manageCapability);
	if (current.page.origin === "code" || (input.codePages ?? []).some((page) => page.key === normalizedKeyValue)) throw new FieldsLifecycleError("validation", "effective key is owned by code", normalizedKeyValue);
	const requestHash = await fieldsRequestHash({
		kind: "update-options-page",
		key: normalizedKeyValue,
		expectedVersion,
		patch
	});
	const receipt = await readFieldsReceipt(tx, input.operationId);
	if (receipt) {
		assertReceiptReplay(receipt, {
			kind: "fields:update-options-page",
			context: authorized,
			requestHash
		});
		const replay = await readDbPage(tx, normalizedKeyValue);
		if (!replay) throw new FieldsLifecycleError("integrity", "committed options receipt has no page");
		return replay.page;
	}
	if (current.page.version !== expectedVersion) throw new FieldsLifecycleError("stale-version", "options page version changed");
	const next = normalizeOptionsPage({
		...current.page,
		...patch,
		key: normalizedKeyValue
	});
	const canonicalHash = await fieldsRequestHash(next);
	const allRows = await readOptionRows(tx);
	const replacement = {
		...current.row,
		version: expectedVersion + 1,
		definition: next,
		canonicalHash,
		currentRevision: Number(current.row.currentRevision) + (canonicalHash === current.row.canonicalHash ? 0 : 1)
	};
	validatePageTree(mergePages(allRows.map((row) => row.key === normalizedKeyValue ? replacement : row), input.codePages ?? []).filter((page) => page.active));
	if (canonicalHash === current.row.canonicalHash) {
		await writeFieldsReceipt(tx, {
			operationId: input.operationId,
			kind: "fields:update-options-page",
			context: authorized,
			requestHash,
			result: Object.freeze({
				key: normalizedKeyValue,
				version: current.page.version
			})
		});
		return current.page;
	}
	const revision = Number(current.row.currentRevision) + 1, version = expectedVersion + 1, now = (/* @__PURE__ */ new Date()).toISOString();
	await tx.execute(sql`INSERT INTO field_options_definition_versions (options_key, revision, canonical_hash, definition, origin, created_at) VALUES (${normalizedKeyValue}, ${revision}, ${canonicalHash}, ${JSON.stringify(next)}, 'db', ${now})`);
	await tx.execute(sql`UPDATE field_options_definitions SET version = ${version}, current_revision = ${revision}, canonical_hash = ${canonicalHash}, definition = ${JSON.stringify(next)}, updated_at = ${now} WHERE key = ${normalizedKeyValue} AND version = ${expectedVersion}`);
	const result = Object.freeze({
		...next,
		origin: "db",
		version,
		active: current.page.active,
		...current.page.shadowedDbVersion === void 0 ? {} : { shadowedDbVersion: current.page.shadowedDbVersion }
	});
	await writeFieldsReceipt(tx, {
		operationId: input.operationId,
		kind: "fields:update-options-page",
		context: authorized,
		requestHash,
		result: Object.freeze({
			key: normalizedKeyValue,
			version
		})
	});
	return result;
}
async function optionsCorpus(db, key) {
	const valueRows = await executeRows$2(db, sql`SELECT node_id AS "nodeId", group_key AS "groupKey", definition_revision AS "definitionRevision", field_key AS "fieldKey", path, row_id AS "rowId", layout_key AS "layoutKey", node_kind AS "nodeKind", ordinal, is_null AS "isNull", value_text AS "valueText", value_number AS "valueNumber", value_boolean AS "valueBoolean", value_date_time AS "valueDateTime", value_ref AS "valueRef", value_json AS "valueJson" FROM field_value_nodes WHERE entity_type = 'options' AND entity_id = ${key} ORDER BY group_key, path`);
	const revisions = await executeRows$2(db, sql`SELECT id, parent_revision_id AS "parentRevisionId", parent_autosave_id AS "parentAutosaveId", kind, retention_class AS "retentionClass", definition_versions AS "definitionVersions", "values" AS "values", block_document AS "blockDocument", created_at AS "createdAt", created_by AS "createdBy", source_version AS "sourceVersion" FROM field_revisions WHERE entity_type = 'options' AND entity_id = ${key} ORDER BY created_at, id`);
	const counts = Object.freeze({
		values: valueRows.length,
		revisions: revisions.length
	});
	const version = await fieldsRequestHash({
		valueIds: valueRows.map((row) => row.nodeId),
		revisionIds: revisions.map((row) => row.id)
	});
	const hash = await fieldsRequestHash({
		valueRows,
		revisions
	});
	return Object.freeze({
		version,
		hash,
		counts
	});
}
function tokenEncode(payload) {
	const bytes = new TextEncoder().encode(JSON.stringify(payload));
	const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
	return fieldsRequestHash(payload).then((digest) => `${hex}.${digest}`);
}
async function tokenDecode(token) {
	const match = /^([a-f0-9]+)\.([a-f0-9]{64})$/i.exec(token);
	if (!match || match[1].length % 2 !== 0 || match[1].length > 64e3) throw new FieldsLifecycleError("validation", "impact token is invalid");
	const bytes = new Uint8Array(match[1].match(/../g).map((pair) => Number.parseInt(pair, 16)));
	let value;
	try {
		value = JSON.parse(new TextDecoder().decode(bytes));
	} catch {
		throw new FieldsLifecycleError("validation", "impact token is invalid");
	}
	if (typeof value !== "object" || value === null || Array.isArray(value)) throw new FieldsLifecycleError("validation", "impact token is invalid");
	if (await fieldsRequestHash(value) !== match[2].toLowerCase()) throw new FieldsLifecycleError("validation", "impact token integrity check failed");
	return value;
}
function countsEqual(left, right) {
	if (typeof right !== "object" || right === null || Array.isArray(right)) return false;
	const normalized = {};
	for (const [key, value] of Object.entries(right)) {
		const number = Number(value);
		if (!Number.isSafeInteger(number) || number < 0) return false;
		normalized[key] = number;
	}
	return JSON.stringify(Object.entries(left).sort()) === JSON.stringify(Object.entries(normalized).sort());
}
async function previewOptionsPageDeactivation(db, key, expectedVersion, context) {
	const normalized = normalizedKey(key, "key");
	const current = await readDbPage(db, normalized);
	if (!current) throw new FieldsLifecycleError("not-found", "options page is unavailable");
	assertPrincipalCapability(await assertFieldsAuthorized(context, "manageDefinitions", definitionRef$1(normalized)), current.page.manageCapability);
	if (current.page.origin === "code") throw new FieldsLifecycleError("validation", "code-owned options page changes require registry reconciliation");
	if (current.page.version !== expectedVersion) throw new FieldsLifecycleError("stale-version", "options page version changed");
	const migration = await assertDefinitionMigration(context, ["options"]);
	const corpus = await optionsCorpus(db, normalized);
	const payload = Object.freeze({
		kind: "options-page-deactivation",
		pageKey: normalized,
		expectedVersion,
		authorizationPolicyVersion: migration.policyVersion,
		valueCorpusVersion: corpus.version,
		valueCorpusHash: corpus.hash,
		affectedCounts: corpus.counts
	});
	return Object.freeze({
		token: await tokenEncode(payload),
		pageKey: normalized,
		expectedVersion,
		authorizationPolicyVersion: migration.policyVersion,
		valueCorpusVersion: corpus.version,
		valueCorpusHash: corpus.hash,
		affectedCounts: corpus.counts
	});
}
async function applyOptionsPageDeactivation(tx, impactToken, strategy, operationId, context, destructive) {
	assertActiveFieldsTransaction(tx);
	const payload = await tokenDecode(impactToken);
	if (payload.kind !== "options-page-deactivation" || typeof payload.pageKey !== "string") throw new FieldsLifecycleError("validation", "impact token has wrong operation kind");
	const key = normalizedKey(payload.pageKey, "pageKey");
	const current = await readDbPage(tx, key);
	if (!current) throw new FieldsLifecycleError("not-found", "options page is unavailable");
	const authorized = await assertFieldsAuthorized(context, "manageDefinitions", definitionRef$1(key));
	assertPrincipalCapability(authorized, current.page.manageCapability);
	if (current.page.origin === "code") throw new FieldsLifecycleError("validation", "code-owned options page changes require registry reconciliation");
	if (strategy.kind !== "retain" && strategy.kind !== "purge") throw new FieldsLifecycleError("validation", "unknown options deactivation strategy");
	const migration = await assertDefinitionMigration(context, ["options"]);
	if (payload.authorizationPolicyVersion !== migration.policyVersion) throw new FieldsLifecycleError("corpus-drift", "authorization policy changed since preview");
	const requestHash = await fieldsRequestHash({
		impactToken,
		strategy
	});
	const receipt = await readFieldsReceipt(tx, operationId);
	if (receipt) {
		assertReceiptReplay(receipt, {
			kind: "fields:deactivate-options-page",
			context: authorized,
			requestHash
		});
		const replay = await readDbPage(tx, key);
		if (!replay) throw new FieldsLifecycleError("integrity", "committed options receipt has no page");
		return replay.page;
	}
	if (Number(payload.expectedVersion) !== current.page.version) throw new FieldsLifecycleError("stale-version", "options page version changed");
	const corpus = await optionsCorpus(tx, key);
	if (payload.valueCorpusVersion !== corpus.version || payload.valueCorpusHash !== corpus.hash || !countsEqual(corpus.counts, payload.affectedCounts)) throw new FieldsLifecycleError("corpus-drift", "options value corpus changed since preview");
	if (strategy.kind === "purge") {
		if (!destructive) throw new FieldsLifecycleError("backup-invalid", "destructive dependencies are required");
		const scopeHash = await fieldsRequestHash({
			definitionKind: "optionsPage",
			definitionKey: key,
			strategy,
			authorizationPolicyVersion: migration.policyVersion,
			corpusVersion: corpus.version,
			corpusHash: corpus.hash,
			previewToken: impactToken,
			affectedCounts: corpus.counts
		});
		const backup = await verifyFieldsBackup(tx, {
			backupId: strategy.backupId,
			expectedScopeHash: scopeHash,
			corpusVersion: corpus.version,
			corpusHash: corpus.hash,
			counts: corpus.counts
		}, destructive.backups);
		const event = Object.freeze({
			operationId,
			principalId: authorized.principal.id,
			definitionKind: "optionsPage",
			definitionKey: key,
			strategy: Object.freeze({ ...strategy }),
			authorizationPolicyVersion: migration.policyVersion,
			corpusVersion: corpus.version,
			corpusHash: corpus.hash,
			previewToken: impactToken,
			affectedCounts: corpus.counts,
			backup
		});
		await destructive.effects.audit.record(tx, event);
		await destructive.effects.outbox.enqueue(tx, event);
		await tx.execute(sql`DELETE FROM field_value_nodes WHERE entity_type = 'options' AND entity_id = ${key}`);
		await tx.execute(sql`DELETE FROM field_revisions WHERE entity_type = 'options' AND entity_id = ${key}`);
	}
	const nextVersion = current.page.version + 1, now = (/* @__PURE__ */ new Date()).toISOString();
	await tx.execute(sql`UPDATE field_options_definitions SET version = ${nextVersion}, active = false, updated_at = ${now} WHERE key = ${key} AND version = ${current.page.version}`);
	const result = Object.freeze({
		...current.page,
		version: nextVersion,
		active: false
	});
	await writeFieldsReceipt(tx, {
		operationId,
		kind: "fields:deactivate-options-page",
		context: authorized,
		requestHash,
		result: Object.freeze({
			key,
			version: nextVersion
		})
	});
	return result;
}
function nodeFromRow$1(row) {
	return Object.freeze({
		nodeId: row.nodeId,
		entityType: row.entityType,
		entityId: row.entityId,
		groupKey: row.groupKey,
		definitionRevision: Number(row.definitionRevision),
		fieldKey: row.fieldKey,
		path: row.path,
		parentNodeId: row.parentNodeId,
		rowId: row.rowId,
		layoutKey: row.layoutKey,
		nodeKind: row.nodeKind,
		ordinal: Number(row.ordinal),
		isNull: row.isNull === true || row.isNull === 1,
		valueText: row.valueText,
		valueNumber: row.valueNumber === null ? null : Number(row.valueNumber),
		valueBoolean: row.valueBoolean === null ? null : row.valueBoolean === true || row.valueBoolean === 1,
		valueDateTime: row.valueDateTime,
		valueRef: row.valueRef,
		valueJson: row.valueJson
	});
}
async function matchingOptionGroups(db, key) {
	const rows = await executeRows$2(db, sql`SELECT key, current_revision AS "currentRevision", definition FROM field_group_definitions WHERE active = true ORDER BY key`);
	const registry = createLocationResolverRegistry(), output = [];
	for (const row of rows) {
		const revision = Number(row.currentRevision);
		const version = await resolveFieldDefinitionVersion(db, row.key, revision);
		if (await registry.evaluate(version.definition.location, {
			entityType: "options",
			surface: "options",
			optionsPage: key,
			entityId: key
		})) output.push({
			group: version.definition,
			revision
		});
	}
	return Object.freeze(output);
}
async function readOptionValuesSnapshot(db, key, context) {
	const groups = await matchingOptionGroups(db, key);
	const rows = await executeRows$2(db, sql`SELECT node_id AS "nodeId", entity_type AS "entityType", entity_id AS "entityId", group_key AS "groupKey", definition_revision AS "definitionRevision", field_key AS "fieldKey", path, parent_node_id AS "parentNodeId", row_id AS "rowId", layout_key AS "layoutKey", node_kind AS "nodeKind", ordinal, is_null AS "isNull", value_text AS "valueText", value_number AS "valueNumber", value_boolean AS "valueBoolean", value_date_time AS "valueDateTime", value_ref AS "valueRef", value_json AS "valueJson" FROM field_value_nodes WHERE entity_type = 'options' AND entity_id = ${key} ORDER BY group_key, path`);
	const byGroup = /* @__PURE__ */ new Map();
	for (const row of rows) {
		const list = byGroup.get(row.groupKey) ?? [];
		list.push(row);
		byGroup.set(row.groupKey, list);
	}
	const values = {}, definitionVersions = {};
	for (const current of groups) {
		const nodes = byGroup.get(current.group.key) ?? [];
		const revisions = [...new Set(nodes.map((row) => Number(row.definitionRevision)))];
		const revision = revisions.length === 0 ? current.revision : revisions.length === 1 ? revisions[0] : (() => {
			throw new FieldsLifecycleError("integrity", "options values mix immutable group revisions");
		})();
		const version = revision === current.revision ? current.group : (await resolveFieldDefinitionVersion(db, current.group.key, revision)).definition;
		values[current.group.key] = decodeFieldValueNodes(version, nodes.map(nodeFromRow$1), {
			definitionRevision: revision,
			...context.cloneResolver ? { cloneResolver: { resolve: (definition) => context.cloneResolver.resolve(definition) } } : {}
		});
		definitionVersions[current.group.key] = revision;
	}
	const version = await fieldsRequestHash({
		definitionVersions,
		values
	});
	return Object.freeze({
		values: Object.freeze(values),
		version,
		definitionVersions: Object.freeze(definitionVersions)
	});
}
async function getOptionsValues(db, key, context) {
	const normalized = normalizedKey(key, "key");
	const page = await readDbPage(db, normalized);
	if (!page || !page.page.active) throw new FieldsLifecycleError("not-found", "options page is unavailable");
	assertPrincipalCapability(await assertFieldsAuthorized(context, "read", valueRef(normalized)), page.page.readCapability);
	return readOptionValuesSnapshot(db, normalized, context);
}
function containsPassword(fields) {
	for (const field of fields) {
		if (field.type === "password") return true;
		if (field.type === "group" || field.type === "repeater") {
			if (containsPassword(field.settings.fields)) return true;
		}
		if (field.type === "flexible") {
			for (const layout of field.settings.layouts) if (containsPassword(layout.fields)) return true;
		}
		if (field.type === "clone") return true;
	}
	return false;
}
async function validateGroupWrite(group, input, context) {
	if (containsPassword(group.fields)) throw new FieldsLifecycleError("capability-unavailable", "options groups containing password or unresolved clone fields require a private credential adapter");
	const registry = context.fieldTypeRegistry ?? createFieldTypeRegistry(), output = {};
	const allowed = new Set(group.fields.map((field) => field.key));
	for (const key of Object.keys(input)) if (!allowed.has(key)) throw new FieldsLifecycleError("validation", "value names a field outside the resolved group", `${group.key}.${key}`);
	for (const field of group.fields) if (Object.prototype.hasOwnProperty.call(input, field.key)) output[field.key] = await validateFieldValue(field, input[field.key], registry, {
		sanitizer: context.sanitizer,
		...context.cloneResolver ? { cloneResolver: { resolve: (definition) => context.cloneResolver.resolve(definition) } } : {}
	});
	return Object.freeze(output);
}
async function writeNodes(tx, key, group, revision, values, context) {
	await tx.execute(sql`DELETE FROM field_value_nodes WHERE entity_type = 'options' AND entity_id = ${key} AND group_key = ${group.key}`);
	const ids = /* @__PURE__ */ new Map(), nodeIdForPath = (path) => {
		let id = ids.get(path);
		if (!id) {
			id = crypto.randomUUID();
			ids.set(path, id);
		}
		return id;
	};
	const rows = encodeFieldValueNodes(group, values, {
		entityType: "options",
		entityId: key,
		definitionRevision: revision,
		nodeIdForPath,
		...context.cloneResolver ? { cloneResolver: { resolve: (definition) => context.cloneResolver.resolve(definition) } } : {}
	});
	for (const row of rows) await tx.execute(sql`INSERT INTO field_value_nodes (node_id, entity_type, entity_id, group_key, definition_revision, field_key, path, parent_node_id, row_id, layout_key, node_kind, ordinal, is_null, value_text, value_number, value_boolean, value_date_time, value_ref, value_json, created_at, updated_at) VALUES (${row.nodeId}, ${row.entityType}, ${row.entityId}, ${row.groupKey}, ${row.definitionRevision}, ${row.fieldKey}, ${row.path}, ${row.parentNodeId}, ${row.rowId}, ${row.layoutKey}, ${row.nodeKind}, ${row.ordinal}, ${row.isNull}, ${row.valueText}, ${row.valueNumber}, ${row.valueBoolean}, ${row.valueDateTime}, ${row.valueRef}, ${row.valueJson}, ${(/* @__PURE__ */ new Date()).toISOString()}, ${(/* @__PURE__ */ new Date()).toISOString()})`);
}
async function setOptionsValues(tx, key, values, mutation, context) {
	if (mutation.expectedTransactionIdentity !== void 0) assertActiveFieldsTransaction(tx, mutation.expectedTransactionIdentity);
	else assertActiveFieldsTransaction(tx);
	const normalized = normalizedKey(key, "key");
	const page = await readDbPage(tx, normalized);
	if (!page || !page.page.active) throw new FieldsLifecycleError("not-found", "options page is unavailable");
	const authorized = await assertFieldsAuthorized(context, "write", valueRef(normalized));
	assertPrincipalCapability(authorized, page.page.writeCapability);
	const requestHash = await fieldsRequestHash({
		key: normalized,
		expectedVersion: mutation.expectedVersion,
		values
	});
	const receipt = await readFieldsReceipt(tx, mutation.operationId);
	if (receipt) {
		assertReceiptReplay(receipt, {
			kind: "fields:set-options-values",
			context: authorized,
			requestHash
		});
		const replay = receipt.result;
		return Object.freeze({
			version: String(replay.version),
			changedPaths: Object.freeze([])
		});
	}
	if ((await readOptionValuesSnapshot(tx, normalized, context)).version !== mutation.expectedVersion) throw new FieldsLifecycleError("stale-version", "options values changed");
	const groups = await matchingOptionGroups(tx, normalized), byKey = new Map(groups.map((item) => [item.group.key, item]));
	for (const groupKey of Object.keys(values)) if (!byKey.has(groupKey)) throw new FieldsLifecycleError("validation", "value names a group outside the resolved options page", groupKey);
	const changedPaths = [];
	for (const [groupKey, input] of Object.entries(values)) {
		const resolved = byKey.get(groupKey);
		const validated = await validateGroupWrite(resolved.group, input, context);
		await writeNodes(tx, normalized, resolved.group, resolved.revision, validated, context);
		for (const fieldKey of Object.keys(input).sort()) changedPaths.push(Object.freeze([groupKey, fieldKey]));
	}
	const next = await readOptionValuesSnapshot(tx, normalized, context);
	await writeFieldsReceipt(tx, {
		operationId: mutation.operationId,
		kind: "fields:set-options-values",
		context: authorized,
		requestHash,
		result: Object.freeze({ version: next.version })
	});
	return Object.freeze({
		version: next.version,
		changedPaths: Object.freeze(changedPaths)
	});
}
/** Internal composition seam for definition reconciliation; intentionally not re-exported from package index. */
var __optionsLifecycleInternals = Object.freeze({
	normalizeOptionsPage,
	readOptionRows,
	readDbPage,
	mergePages,
	optionsCorpus
});
var blocks_exports = /* @__PURE__ */ __exportAll({
	DEFAULT_BLOCK_POLICY: () => DEFAULT_BLOCK_POLICY,
	EMPTY_BLOCK_DOCUMENT_VERSION: () => "0",
	__fieldBlockLifecycleInternals: () => __fieldBlockLifecycleInternals,
	applyFieldBlockChange: () => applyFieldBlockChange,
	createFieldBlock: () => createFieldBlock,
	createReusableBlockResolver: () => createReusableBlockResolver,
	defineFieldBlock: () => defineFieldBlock,
	deleteBlockDocument: () => deleteBlockDocument,
	getBlockDocument: () => getBlockDocument,
	parseBlockDocument: () => parseBlockDocument,
	previewFieldBlockChange: () => previewFieldBlockChange,
	renderBlockDocument: () => renderBlockDocument,
	resolveFieldBlocks: () => resolveFieldBlocks,
	serializeBlockDocument: () => serializeBlockDocument,
	setBlockDocument: () => setBlockDocument,
	validateBlockDocument: () => validateBlockDocument,
	validateBlockPublication: () => validateBlockPublication
});
var validatedBlockNodeBrand = Symbol("validatedBlockNode");
var validatedBlockDocumentBrand = Symbol("validatedBlockDocument");
var validatedRegistryVersion = Symbol("validatedRegistryVersion");
function rowsOf$4(value) {
	if (Array.isArray(value)) return value;
	if (typeof value === "object" && value !== null && Array.isArray(value.rows)) return value.rows;
	throw new FieldsLifecycleError("integrity", "database adapter returned an invalid row result");
}
async function executeRows$1(db, query) {
	return rowsOf$4(await db.execute(query));
}
function parseJson$3(value, field) {
	if (typeof value !== "string") return value;
	try {
		return JSON.parse(value);
	} catch {
		throw new FieldsLifecycleError("integrity", `${field} contains invalid JSON`);
	}
}
function object(value, field) {
	if (typeof value !== "object" || value === null || Array.isArray(value) || Object.getPrototypeOf(value) !== Object.prototype) throw new FieldsLifecycleError("validation", "must be a plain object", field);
	return value;
}
function string(value, field, max = 4096) {
	if (typeof value !== "string" || value.length === 0 || value.length > max) throw new FieldsLifecycleError("validation", "must be a bounded non-empty string", field);
	return value;
}
function key(value, field) {
	const result = string(value, field, 128);
	if (!/^[a-z][a-z0-9_-]*$/.test(result)) throw new FieldsLifecycleError("validation", "must be a normalized key", field);
	return result;
}
function positiveInt(value, field) {
	const result = Number(value);
	if (!Number.isSafeInteger(result) || result < 1) throw new FieldsLifecycleError("validation", "must be a positive safe integer", field);
	return result;
}
function bool$2(value) {
	return value === true || value === 1;
}
function uniqueStrings(value, field, maxItems = 128) {
	if (!Array.isArray(value) || value.length > maxItems) throw new FieldsLifecycleError("validation", "must be a bounded array", field);
	const result = value.map((item, index) => string(item, `${field}.${index}`, 256));
	if (new Set(result).size !== result.length) throw new FieldsLifecycleError("validation", "must not contain duplicates", field);
	return Object.freeze(result);
}
function jsonValue(value, field, depth = 0, budget = {
	nodes: 0,
	bytes: 0
}) {
	if (depth > 20 || ++budget.nodes > 5e3) throw new FieldsLifecycleError("validation", "exceeds structural bounds", field);
	if (value === null || typeof value === "boolean") return value;
	if (typeof value === "number") {
		if (!Number.isFinite(value)) throw new FieldsLifecycleError("validation", "contains non-finite number", field);
		budget.bytes += 8;
		return value;
	}
	if (typeof value === "string") {
		budget.bytes += new TextEncoder().encode(value).byteLength;
		if (budget.bytes > 1048576) throw new FieldsLifecycleError("validation", "exceeds byte bound", field);
		return value;
	}
	if (Array.isArray(value)) return Object.freeze(value.map((item, index) => jsonValue(item, `${field}.${index}`, depth + 1, budget)));
	const source = object(value, field), output = {};
	for (const name of Object.keys(source).sort()) {
		if (name === "__proto__" || name === "prototype" || name === "constructor") throw new FieldsLifecycleError("validation", "contains forbidden key", `${field}.${name}`);
		output[name] = jsonValue(source[name], `${field}.${name}`, depth + 1, budget);
	}
	return Object.freeze(output);
}
function parseAttributes(value, policy, field) {
	if (value === void 0) return void 0;
	const source = object(value, field), output = {};
	let bytes = 0;
	const parse = (input, path, depth = 0) => {
		if (depth > 8) throw new FieldsLifecycleError("validation", "attribute exceeds maximum depth", path);
		if (input === null || typeof input === "boolean") return input;
		if (typeof input === "number") {
			if (!Number.isFinite(input)) throw new FieldsLifecycleError("validation", "attribute contains non-finite number", path);
			bytes += 8;
			return input;
		}
		if (typeof input === "string") {
			bytes += new TextEncoder().encode(input).byteLength;
			if (bytes > policy.maxAttributeBytes) throw new FieldsLifecycleError("validation", "attributes exceed byte limit", field);
			return input;
		}
		if (Array.isArray(input)) return Object.freeze(input.map((item, index) => parse(item, `${path}.${index}`, depth + 1)));
		throw new FieldsLifecycleError("validation", "block attributes permit only primitive trees", path);
	};
	for (const name of Object.keys(source).sort()) output[name] = parse(source[name], `${field}.${name}`);
	return Object.freeze(output);
}
function parseFieldGroups(value, field) {
	if (!Array.isArray(value) || value.length > 128) throw new FieldsLifecycleError("validation", "must be a bounded array", field);
	const seen = /* @__PURE__ */ new Set(), output = [];
	for (let index = 0; index < value.length; index++) {
		const row = object(value[index], `${field}.${index}`), allowed = /* @__PURE__ */ new Set([
			"groupKey",
			"definitionRevision",
			"values"
		]);
		for (const name of Object.keys(row)) if (!allowed.has(name)) throw new FieldsLifecycleError("validation", "unknown block field-group property", `${field}.${index}.${name}`);
		const groupKey = key(row.groupKey, `${field}.${index}.groupKey`);
		if (seen.has(groupKey)) throw new FieldsLifecycleError("validation", "duplicate field group", `${field}.${index}.groupKey`);
		seen.add(groupKey);
		const values = jsonValue(row.values, `${field}.${index}.values`);
		output.push(Object.freeze({
			groupKey,
			definitionRevision: positiveInt(row.definitionRevision, `${field}.${index}.definitionRevision`),
			values
		}));
	}
	return Object.freeze(output);
}
function parseNode(value, policy, field, depth = 0) {
	if (depth > policy.maxDepth) throw new FieldsLifecycleError("validation", "block document exceeds maximum depth", field);
	const row = object(value, field), kind = row.kind;
	if (kind === "reusable") {
		const allowed = /* @__PURE__ */ new Set([
			"kind",
			"id",
			"reusableId"
		]);
		for (const name of Object.keys(row)) if (!allowed.has(name)) throw new FieldsLifecycleError("validation", "unknown reusable node property", `${field}.${name}`);
		return Object.freeze({
			kind: "reusable",
			id: string(row.id, `${field}.id`, 256),
			reusableId: string(row.reusableId, `${field}.reusableId`, 256)
		});
	}
	if (kind !== "inline") throw new FieldsLifecycleError("validation", "node kind must be inline or reusable", `${field}.kind`);
	const allowed = /* @__PURE__ */ new Set([
		"kind",
		"id",
		"type",
		"blockDefinitionRevision",
		"fieldGroups",
		"attributes",
		"children"
	]);
	for (const name of Object.keys(row)) if (!allowed.has(name)) throw new FieldsLifecycleError("validation", "unknown inline node property", `${field}.${name}`);
	const children = row.children === void 0 ? void 0 : (() => {
		if (!Array.isArray(row.children) || row.children.length > policy.maxChildren) throw new FieldsLifecycleError("validation", "children exceed maximum size", `${field}.children`);
		return Object.freeze(row.children.map((child, index) => parseNode(child, policy, `${field}.children.${index}`, depth + 1)));
	})();
	return Object.freeze({
		kind: "inline",
		id: string(row.id, `${field}.id`, 256),
		type: key(row.type, `${field}.type`),
		blockDefinitionRevision: positiveInt(row.blockDefinitionRevision, `${field}.blockDefinitionRevision`),
		fieldGroups: parseFieldGroups(row.fieldGroups, `${field}.fieldGroups`),
		...row.attributes === void 0 ? {} : { attributes: parseAttributes(row.attributes, policy, `${field}.attributes`) },
		...children === void 0 ? {} : { children }
	});
}
function normalizeDocument(input, policy) {
	const source = object(input, "document"), allowed = /* @__PURE__ */ new Set(["version", "roots"]);
	for (const name of Object.keys(source)) if (!allowed.has(name)) throw new FieldsLifecycleError("validation", "unknown block document property", `document.${name}`);
	if (source.version !== 1) throw new FieldsLifecycleError("validation", "block document version must be 1", "document.version");
	if (!Array.isArray(source.roots) || source.roots.length > policy.maxChildren) throw new FieldsLifecycleError("validation", "roots exceed maximum size", "document.roots");
	return Object.freeze({
		version: 1,
		roots: Object.freeze(source.roots.map((node, index) => parseNode(node, policy, `document.roots.${index}`)))
	});
}
function normalizeDefinition(input) {
	const blockKey = key(input.key, "key");
	const title = string(input.title, "title");
	const fieldGroupKeys = uniqueStrings(input.fieldGroupKeys, "fieldGroupKeys").map((item, index) => key(item, `fieldGroupKeys.${index}`));
	if (fieldGroupKeys.length === 0) throw new FieldsLifecycleError("validation", "block must reference at least one field group", "fieldGroupKeys");
	const keywords = input.keywords === void 0 ? void 0 : uniqueStrings(input.keywords, "keywords", 64);
	const align = input.align === void 0 ? void 0 : (() => {
		if (!Array.isArray(input.align) || input.align.length > 5) throw new FieldsLifecycleError("validation", "align must be bounded", "align");
		const allowed = /* @__PURE__ */ new Set([
			"left",
			"center",
			"right",
			"wide",
			"full"
		]);
		const output = input.align.map((item, index) => {
			if (!allowed.has(item)) throw new FieldsLifecycleError("validation", "invalid alignment", `align.${index}`);
			return item;
		});
		if (new Set(output).size !== output.length) throw new FieldsLifecycleError("validation", "align must not contain duplicates", "align");
		return Object.freeze(output);
	})();
	if (input.mode !== void 0 && ![
		"preview",
		"edit",
		"auto"
	].includes(input.mode)) throw new FieldsLifecycleError("validation", "invalid block mode", "mode");
	if (input.templateLock !== void 0 && input.templateLock !== false && ![
		"insert",
		"all",
		"contentOnly"
	].includes(input.templateLock)) throw new FieldsLifecycleError("validation", "invalid template lock", "templateLock");
	const supports = input.supports === void 0 ? void 0 : (() => {
		const source = object(input.supports, "supports");
		const allowed = /* @__PURE__ */ new Set([
			"anchor",
			"className",
			"multiple",
			"reusable",
			"innerBlocks",
			"jsx"
		]);
		const out = {};
		for (const name of Object.keys(source)) {
			if (!allowed.has(name)) throw new FieldsLifecycleError("validation", "unknown supports flag", `supports.${name}`);
			if (typeof source[name] !== "boolean") throw new FieldsLifecycleError("validation", "supports flag must be boolean", `supports.${name}`);
			out[name] = source[name];
		}
		return Object.freeze(out);
	})();
	const parent = input.parent === void 0 ? void 0 : uniqueStrings(input.parent, "parent", 64).map((item, index) => key(item, `parent.${index}`));
	const ancestor = input.ancestor === void 0 ? void 0 : uniqueStrings(input.ancestor, "ancestor", 64).map((item, index) => key(item, `ancestor.${index}`));
	const templatePolicy = Object.freeze({
		maxBytes: 262144,
		maxNodes: 1e3,
		maxDepth: 12,
		maxChildren: 128,
		maxAttributeBytes: 65536,
		allowUnknownPreserved: false
	});
	const template = input.template === void 0 ? void 0 : normalizeDocument({
		version: 1,
		roots: input.template
	}, templatePolicy).roots;
	return Object.freeze({
		key: blockKey,
		title,
		...input.description === void 0 ? {} : { description: string(input.description, "description") },
		...input.category === void 0 ? {} : { category: string(input.category, "category", 256) },
		...input.icon === void 0 ? {} : { icon: string(input.icon, "icon", 512) },
		...keywords === void 0 ? {} : { keywords },
		fieldGroupKeys: Object.freeze(fieldGroupKeys),
		...input.mode === void 0 ? {} : { mode: input.mode },
		...align === void 0 ? {} : { align },
		...supports === void 0 ? {} : { supports },
		...parent === void 0 ? {} : { parent: Object.freeze(parent) },
		...ancestor === void 0 ? {} : { ancestor: Object.freeze(ancestor) },
		...template === void 0 ? {} : { template },
		...input.templateLock === void 0 ? {} : { templateLock: input.templateLock }
	});
}
function parseDefinition(value) {
	const raw = parseJson$3(value, "block definition");
	if (typeof raw !== "object" || raw === null || Array.isArray(raw)) throw new FieldsLifecycleError("integrity", "block definition is malformed");
	return normalizeDefinition(raw);
}
function resolvedCurrent(row) {
	const definition = parseDefinition(row.definition);
	if (definition.key !== row.key) throw new FieldsLifecycleError("integrity", "block definition key does not match persisted key");
	return Object.freeze({
		...definition,
		origin: row.origin === "code" ? "code" : "db",
		version: Number(row.version),
		active: bool$2(row.active),
		...row.shadowedDbVersion === null ? {} : { shadowedDbVersion: Number(row.shadowedDbVersion) }
	});
}
async function readCurrentRows(db) {
	return executeRows$1(db, sql`SELECT key, origin, version, active, current_revision AS "currentRevision", canonical_hash AS "canonicalHash", definition, shadowed_db_version AS "shadowedDbVersion" FROM field_block_definitions ORDER BY key`);
}
async function readBlockVersion(db, blockKey, revision) {
	const row = (await executeRows$1(db, sql`SELECT block_key AS "blockKey", revision, canonical_hash AS "canonicalHash", definition, created_at AS "createdAt", origin FROM field_block_definition_versions WHERE block_key = ${blockKey} AND revision = ${revision} LIMIT 1`))[0];
	if (!row) return null;
	const definition = parseDefinition(row.definition);
	const canonicalHash = await fieldsRequestHash(definition);
	if (definition.key !== row.blockKey || canonicalHash !== row.canonicalHash) throw new FieldsLifecycleError("integrity", "pinned block definition is corrupt");
	const createdAt = row.createdAt instanceof Date ? new Date(row.createdAt) : new Date(row.createdAt);
	if (Number.isNaN(createdAt.getTime())) throw new FieldsLifecycleError("integrity", "pinned block definition timestamp is invalid");
	return Object.freeze({
		blockKey: row.blockKey,
		revision: Number(row.revision),
		canonicalHash,
		definition,
		createdAt,
		origin: row.origin
	});
}
function mergeCurrent(rows, codeBlocks) {
	const blocks = /* @__PURE__ */ new Map();
	const rowByKey = new Map(rows.map((row) => [row.key, row]));
	const codeRevisions = /* @__PURE__ */ new Map();
	for (const row of rows) blocks.set(row.key, resolvedCurrent(row));
	const seen = /* @__PURE__ */ new Set();
	for (const raw of codeBlocks) {
		const definition = normalizeDefinition(raw);
		if (seen.has(definition.key)) throw new FieldsLifecycleError("validation", "duplicate code block key", definition.key);
		seen.add(definition.key);
		const previousRow = rowByKey.get(definition.key);
		const previous = previousRow ? resolvedCurrent(previousRow) : void 0;
		const revision = previousRow?.origin === "code" ? Number(previousRow.currentRevision) : 1;
		blocks.set(definition.key, Object.freeze({
			...definition,
			origin: "code",
			version: previous?.version ?? 1,
			active: true,
			...previous?.origin === "db" ? { shadowedDbVersion: previous.version } : previous?.shadowedDbVersion === void 0 ? {} : { shadowedDbVersion: previous.shadowedDbVersion }
		}));
		codeRevisions.set(`${definition.key}@${revision}`, Object.freeze({
			blockKey: definition.key,
			revision,
			canonicalHash: "",
			definition,
			createdAt: /* @__PURE__ */ new Date(0),
			origin: "code"
		}));
	}
	return {
		blocks,
		codeRevisions
	};
}
function templateTypes(nodes, out = /* @__PURE__ */ new Set()) {
	for (const node of nodes ?? []) if (node.kind === "inline") {
		out.add(node.type);
		templateTypes(node.children, out);
	}
	return out;
}
function validateDefinitionGraph(blocks) {
	for (const block of blocks.values()) {
		for (const parent of block.parent ?? []) if (!blocks.has(parent)) throw new FieldsLifecycleError("validation", "block parent references missing definition", `${block.key}.parent`);
		for (const ancestor of block.ancestor ?? []) if (!blocks.has(ancestor)) throw new FieldsLifecycleError("validation", "block ancestor references missing definition", `${block.key}.ancestor`);
		for (const type of templateTypes(block.template)) if (!blocks.has(type)) throw new FieldsLifecycleError("validation", "block template references missing definition", `${block.key}.template`);
	}
	const visiting = /* @__PURE__ */ new Set(), visited = /* @__PURE__ */ new Set();
	const visit = (blockKey) => {
		if (visiting.has(blockKey)) throw new FieldsLifecycleError("validation", "block templates form a recursive cycle", blockKey);
		if (visited.has(blockKey)) return;
		visiting.add(blockKey);
		for (const child of templateTypes(blocks.get(blockKey)?.template)) visit(child);
		visiting.delete(blockKey);
		visited.add(blockKey);
	};
	for (const blockKey of blocks.keys()) visit(blockKey);
}
function defineFieldBlock(definition) {
	return Object.freeze({
		...normalizeDefinition(definition),
		origin: "code"
	});
}
async function resolveFieldBlocks(db, input = {}) {
	const merged = mergeCurrent(await readCurrentRows(db), input.codeBlocks ?? []);
	validateDefinitionGraph(merged.blocks);
	const version = await fieldsRequestHash([...merged.blocks.values()].map((block) => ({ ...block })).sort((a, b) => a.key.localeCompare(b.key)));
	return attachRegistryReader(Object.freeze({
		version,
		blocks: new Map([...merged.blocks.entries()].sort(([left], [right]) => left.localeCompare(right))),
		definitions: Object.freeze({ resolve: async (blockKey, revision) => {
			const persisted = await readBlockVersion(db, blockKey, revision);
			if (persisted) return persisted;
			const code = merged.codeRevisions.get(`${blockKey}@${revision}`);
			return code ? Object.freeze({
				...code,
				canonicalHash: await fieldsRequestHash(code.definition)
			}) : null;
		} })
	}), db);
}
async function readCurrentBlock(db, blockKey) {
	const rows = await executeRows$1(db, sql`SELECT key, origin, version, active, current_revision AS "currentRevision", canonical_hash AS "canonicalHash", definition, shadowed_db_version AS "shadowedDbVersion" FROM field_block_definitions WHERE key = ${blockKey} LIMIT 1`);
	return rows[0] ? {
		row: rows[0],
		block: resolvedCurrent(rows[0])
	} : null;
}
async function assertGroupDependencies(db, definition) {
	const rows = await executeRows$1(db, sql`SELECT key, current_revision AS "currentRevision", active FROM field_group_definitions WHERE key IN (${sql.join(definition.fieldGroupKeys.map((groupKey) => sql`${groupKey}`), sql`, `)}) ORDER BY key`);
	const active = new Set(rows.filter((row) => bool$2(row.active)).map((row) => row.key));
	for (const groupKey of definition.fieldGroupKeys) if (!active.has(groupKey)) throw new FieldsLifecycleError("validation", "block references missing or inactive field group", groupKey);
}
function definitionRef(blockKey) {
	return Object.freeze({
		entityType: "fields-block-definition",
		entityId: blockKey
	});
}
async function createFieldBlock(tx, definition, context, input) {
	assertActiveFieldsTransaction(tx);
	const normalized = normalizeDefinition(definition);
	const authorized = await assertFieldsAuthorized(context, "manageDefinitions", definitionRef(normalized.key));
	if ((input.codeBlocks ?? []).some((block) => block.key === normalized.key)) throw new FieldsLifecycleError("validation", "effective block key is owned by code", normalized.key);
	await assertGroupDependencies(tx, normalized);
	const canonicalHash = await fieldsRequestHash(normalized);
	const requestHash = await fieldsRequestHash({
		kind: "create-field-block",
		canonicalHash,
		codeKeys: (input.codeBlocks ?? []).map((block) => block.key).sort()
	});
	const replay = await readFieldsReceipt(tx, input.operationId);
	if (replay) {
		assertReceiptReplay(replay, {
			kind: "fields:create-field-block",
			context: authorized,
			requestHash
		});
		const current = await readCurrentBlock(tx, normalized.key);
		if (!current) throw new FieldsLifecycleError("integrity", "committed block receipt has no definition");
		return current.block;
	}
	const currentRows = await readCurrentRows(tx);
	if (currentRows.some((row) => row.key === normalized.key)) throw new FieldsLifecycleError("validation", "block key already exists", normalized.key);
	const candidateRow = {
		key: normalized.key,
		origin: "db",
		version: 1,
		active: true,
		currentRevision: 1,
		canonicalHash,
		definition: normalized,
		shadowedDbVersion: null
	};
	validateDefinitionGraph(mergeCurrent([...currentRows, candidateRow], input.codeBlocks ?? []).blocks);
	const now = (/* @__PURE__ */ new Date()).toISOString();
	await tx.execute(sql`INSERT INTO field_block_definitions (key, origin, version, active, current_revision, canonical_hash, definition, created_at, updated_at) VALUES (${normalized.key}, 'db', 1, true, 1, ${canonicalHash}, ${JSON.stringify(normalized)}, ${now}, ${now})`);
	await tx.execute(sql`INSERT INTO field_block_definition_versions (block_key, revision, canonical_hash, definition, origin, created_at) VALUES (${normalized.key}, 1, ${canonicalHash}, ${JSON.stringify(normalized)}, 'db', ${now})`);
	if (normalized.template) {
		const registry = await resolveFieldBlocks(tx, { codeBlocks: input.codeBlocks });
		await validateBlockDocument({
			version: 1,
			roots: normalized.template
		}, registry, { resolve: async () => null }, context, DEFAULT_BLOCK_POLICY);
	}
	const result = Object.freeze({
		...normalized,
		origin: "db",
		version: 1,
		active: true
	});
	await writeFieldsReceipt(tx, {
		operationId: input.operationId,
		kind: "fields:create-field-block",
		context: authorized,
		requestHash,
		result: Object.freeze({
			key: normalized.key,
			version: 1
		})
	});
	return result;
}
var DEFAULT_BLOCK_POLICY = Object.freeze({
	maxBytes: 1048576,
	maxNodes: 2e3,
	maxDepth: 16,
	maxChildren: 256,
	maxAttributeBytes: 65536,
	allowUnknownPreserved: false
});
function validatePolicy(policy) {
	for (const [name, value, max] of [
		[
			"maxBytes",
			policy.maxBytes,
			16777216
		],
		[
			"maxNodes",
			policy.maxNodes,
			1e5
		],
		[
			"maxDepth",
			policy.maxDepth,
			128
		],
		[
			"maxChildren",
			policy.maxChildren,
			1e4
		],
		[
			"maxAttributeBytes",
			policy.maxAttributeBytes,
			1048576
		]
	]) if (!Number.isSafeInteger(value) || value < 1 || value > max) throw new FieldsLifecycleError("validation", "block policy value is out of bounds", `policy.${name}`);
}
function plainRecord(value, field) {
	const serialized = jsonValue(value, field);
	if (typeof serialized !== "object" || serialized === null || Array.isArray(serialized)) throw new FieldsLifecycleError("validation", "must be an object", field);
	return serialized;
}
function hasPassword(fields) {
	for (const field of fields) {
		if (field.type === "password") return true;
		if (field.type === "group" || field.type === "repeater") {
			if (hasPassword(field.settings.fields)) return true;
		}
		if (field.type === "flexible") {
			for (const layout of field.settings.layouts) if (hasPassword(layout.fields)) return true;
		}
	}
	return false;
}
async function validateBlockFieldMap(fields, input, context, field) {
	const source = plainRecord(input, field), definitions = new Map(fields.map((definition) => [definition.key, definition])), output = {};
	for (const name of Object.keys(source)) if (!definitions.has(name)) throw new FieldsLifecycleError("validation", "block value names an unknown field", `${field}.${name}`);
	const registry = context.fieldTypeRegistry ?? createFieldTypeRegistry();
	const auth = authorizedFieldsContext(context);
	const valueContext = {
		sanitizer: context.sanitizer,
		...context.cloneResolver ? { cloneResolver: { resolve: (definition) => context.cloneResolver.resolve(definition) } } : {},
		authorization: { assertTarget: async (target, action) => {
			try {
				await auth.authorization.assert(auth.principal, action, {
					entityType: target.entityType,
					entityId: target.id
				});
			} catch {
				throw new FieldsLifecycleError("access-denied", "block field target is unavailable");
			}
		} }
	};
	for (const definition of fields) {
		if (definition.type === "message" || definition.type === "accordion" || definition.type === "tab") continue;
		if (!Object.prototype.hasOwnProperty.call(source, definition.key)) {
			if (definition.required) throw new FieldsLifecycleError("validation", "required block field is missing", `${field}.${definition.key}`);
			continue;
		}
		const value = source[definition.key];
		if (definition.type === "password") {
			const password = plainRecord(value, `${field}.${definition.key}`);
			if (Object.keys(password).length !== 1 || typeof password.configured !== "boolean") throw new FieldsLifecycleError("validation", "block documents may contain only the redacted password configured marker", `${field}.${definition.key}`);
			output[definition.key] = Object.freeze({ configured: password.configured });
			continue;
		}
		if (definition.type === "group") {
			output[definition.key] = await validateBlockFieldMap(definition.settings.fields, value, context, `${field}.${definition.key}`);
			continue;
		}
		if (definition.type === "repeater") {
			if (!Array.isArray(value)) throw new FieldsLifecycleError("validation", "repeater block value must be an array", `${field}.${definition.key}`);
			const settings = definition.settings;
			if (settings.min !== void 0 && value.length < settings.min || settings.max !== void 0 && value.length > settings.max) throw new FieldsLifecycleError("validation", "repeater row count violates definition", `${field}.${definition.key}`);
			const rowIds = /* @__PURE__ */ new Set(), rows = [];
			for (let index = 0; index < value.length; index++) {
				const row = plainRecord(value[index], `${field}.${definition.key}.${index}`), rowId = string(row.rowId, `${field}.${definition.key}.${index}.rowId`, 256);
				if (rowIds.has(rowId)) throw new FieldsLifecycleError("validation", "repeater row id is duplicated", `${field}.${definition.key}.${index}.rowId`);
				rowIds.add(rowId);
				rows.push(Object.freeze({
					rowId,
					values: await validateBlockFieldMap(settings.fields, row.values, context, `${field}.${definition.key}.${index}.values`)
				}));
			}
			output[definition.key] = Object.freeze(rows);
			continue;
		}
		if (definition.type === "flexible") {
			if (!Array.isArray(value)) throw new FieldsLifecycleError("validation", "flexible block value must be an array", `${field}.${definition.key}`);
			const settings = definition.settings;
			if (settings.min !== void 0 && value.length < settings.min || settings.max !== void 0 && value.length > settings.max) throw new FieldsLifecycleError("validation", "flexible row count violates definition", `${field}.${definition.key}`);
			const rowIds = /* @__PURE__ */ new Set(), rows = [];
			for (let index = 0; index < value.length; index++) {
				const row = plainRecord(value[index], `${field}.${definition.key}.${index}`), rowId = string(row.rowId, `${field}.${definition.key}.${index}.rowId`, 256), layoutKey = key(row.layoutKey, `${field}.${definition.key}.${index}.layoutKey`);
				if (rowIds.has(rowId)) throw new FieldsLifecycleError("validation", "flexible row id is duplicated", `${field}.${definition.key}.${index}.rowId`);
				rowIds.add(rowId);
				const layout = settings.layouts.find((candidate) => candidate.key === layoutKey);
				if (!layout) throw new FieldsLifecycleError("validation", "flexible row references unknown layout", `${field}.${definition.key}.${index}.layoutKey`);
				rows.push(Object.freeze({
					rowId,
					layoutKey,
					values: await validateBlockFieldMap(layout.fields, row.values, context, `${field}.${definition.key}.${index}.values`)
				}));
			}
			output[definition.key] = Object.freeze(rows);
			continue;
		}
		if (definition.type === "clone") {
			if (!context.cloneResolver) throw new FieldsLifecycleError("capability-unavailable", "clone resolver is required for block field validation");
			output[definition.key] = await validateBlockFieldMap(context.cloneResolver.resolve(definition), value, context, `${field}.${definition.key}`);
			continue;
		}
		output[definition.key] = await validateFieldValue(definition, value, registry, valueContext);
	}
	return Object.freeze(output);
}
function structureSignature(nodes) {
	return Object.freeze((nodes ?? []).map((node) => node.kind === "reusable" ? Object.freeze({
		kind: "reusable",
		reusableId: node.reusableId
	}) : Object.freeze({
		kind: "inline",
		type: node.type,
		children: structureSignature(node.children)
	})));
}
function checkTemplateLock(definition, children) {
	if (!definition.template || definition.templateLock === void 0 || definition.templateLock === false) return;
	const expected = structureSignature(definition.template), actual = structureSignature(children);
	if (definition.templateLock === "insert") {
		if (actual.length < expected.length || JSON.stringify(actual.slice(0, expected.length)) !== JSON.stringify(expected)) throw new FieldsLifecycleError("validation", "children violate insert template lock", definition.key);
		return;
	}
	if (JSON.stringify(actual) !== JSON.stringify(expected)) throw new FieldsLifecycleError("validation", `children violate ${definition.templateLock} template lock`, definition.key);
}
function allowedAttributeKeys(definition) {
	const allowed = /* @__PURE__ */ new Set();
	if (definition.supports?.anchor) allowed.add("anchor");
	if (definition.supports?.className) allowed.add("className");
	if ((definition.align?.length ?? 0) > 0) allowed.add("align");
	return allowed;
}
async function validateBlockDocument(document, registry, resolver, context, policy) {
	validatePolicy(policy);
	const normalized = normalizeDocument(document, policy);
	if (new TextEncoder().encode(JSON.stringify(normalized)).byteLength > policy.maxBytes) throw new FieldsLifecycleError("validation", "block document exceeds byte limit");
	authorizedFieldsContext(context);
	const expanded = { nodes: 0 };
	const typeCounts = /* @__PURE__ */ new Map();
	const reusableStack = /* @__PURE__ */ new Set();
	const validateDocument = async (input, ancestors, localIds, depth) => {
		const result = [];
		for (let index = 0; index < input.roots.length; index++) result.push(await validateNode(input.roots[index], ancestors, localIds, depth, `roots.${index}`));
		return Object.freeze(result);
	};
	const validateNode = async (node, ancestors, localIds, depth, field) => {
		if (depth > policy.maxDepth) throw new FieldsLifecycleError("validation", "expanded block document exceeds maximum depth", field);
		if (++expanded.nodes > policy.maxNodes) throw new FieldsLifecycleError("validation", "expanded block document exceeds maximum node count", field);
		if (localIds.has(node.id)) throw new FieldsLifecycleError("validation", "block node id is duplicated", `${field}.id`);
		localIds.add(node.id);
		if (node.kind === "reusable") {
			await assertFieldsAuthorized(context, "read", {
				entityType: "reusableBlock",
				entityId: node.reusableId
			});
			let resolved;
			try {
				resolved = await resolver.resolve(node.reusableId, context);
			} catch {
				throw new FieldsLifecycleError("access-denied", "reusable block is unavailable");
			}
			if (!resolved) throw new FieldsLifecycleError("access-denied", "reusable block is unavailable");
			const cycleKey = `${node.reusableId}@${resolved.version}`;
			if (reusableStack.has(cycleKey)) throw new FieldsLifecycleError("validation", "reusable block cycle detected", field);
			reusableStack.add(cycleKey);
			const nested = normalizeDocument(resolved.document, policy);
			await validateDocument(nested, ancestors, /* @__PURE__ */ new Set(), depth + 1);
			reusableStack.delete(cycleKey);
			return Object.freeze({
				...node,
				[validatedBlockNodeBrand]: true
			});
		}
		const version = await registry.definitions.resolve(node.type, node.blockDefinitionRevision);
		if (!version) throw new FieldsLifecycleError("integrity", "pinned block definition is unavailable", node.type);
		if (version.blockKey !== node.type || version.definition.key !== node.type) throw new FieldsLifecycleError("integrity", "pinned block definition identity mismatch", node.type);
		const current = registry.blocks.get(node.type);
		if ((!current || !current.active) && policy.allowUnknownPreserved !== true) throw new FieldsLifecycleError("validation", "block type is not active in the current registry", node.type);
		const parentType = ancestors.at(-1);
		if ((version.definition.parent?.length ?? 0) > 0 && (!parentType || !version.definition.parent.includes(parentType))) throw new FieldsLifecycleError("validation", "block violates parent restriction", node.type);
		if ((version.definition.ancestor?.length ?? 0) > 0 && !ancestors.some((ancestor) => version.definition.ancestor.includes(ancestor))) throw new FieldsLifecycleError("validation", "block violates ancestor restriction", node.type);
		const count = (typeCounts.get(node.type) ?? 0) + 1;
		typeCounts.set(node.type, count);
		if (version.definition.supports?.multiple === false && count > 1) throw new FieldsLifecycleError("validation", "block definition does not allow multiple instances", node.type);
		if ((node.children?.length ?? 0) > 0 && version.definition.supports?.innerBlocks !== true) throw new FieldsLifecycleError("validation", "block definition does not allow children", node.type);
		checkTemplateLock(version.definition, node.children);
		const expectedGroups = [...version.definition.fieldGroupKeys].sort();
		const actualGroups = node.fieldGroups.map((group) => group.groupKey).sort();
		if (JSON.stringify(expectedGroups) !== JSON.stringify(actualGroups)) throw new FieldsLifecycleError("validation", "block must contain exactly one value namespace per configured field group", node.type);
		const fieldGroups = [];
		for (const groupValue of node.fieldGroups) {
			const groupVersion = await resolveFieldDefinitionVersion(registryReader(registry), groupValue.groupKey, groupValue.definitionRevision);
			if (hasPassword(groupVersion.definition.fields)) {}
			const values = await validateBlockFieldMap(groupVersion.definition.fields, groupValue.values, context, `${field}.fieldGroups.${groupValue.groupKey}`);
			fieldGroups.push(Object.freeze({
				groupKey: groupValue.groupKey,
				definitionRevision: groupValue.definitionRevision,
				values
			}));
		}
		const allowedAttributes = allowedAttributeKeys(version.definition);
		for (const name of Object.keys(node.attributes ?? {})) {
			if (!allowedAttributes.has(name)) throw new FieldsLifecycleError("validation", "block attribute is not registered by the definition", `${field}.attributes.${name}`);
			if (name === "align" && typeof node.attributes?.align === "string" && !(version.definition.align ?? []).includes(node.attributes.align)) throw new FieldsLifecycleError("validation", "block alignment is not allowed", `${field}.attributes.align`);
		}
		const children = [];
		for (let index = 0; index < (node.children?.length ?? 0); index++) children.push(await validateNode(node.children[index], [...ancestors, node.type], localIds, depth + 1, `${field}.children.${index}`));
		return Object.freeze({
			...node,
			fieldGroups: Object.freeze(fieldGroups),
			...children.length ? { children: Object.freeze(children) } : node.children ? { children: Object.freeze([]) } : {},
			[validatedBlockNodeBrand]: true
		});
	};
	const roots = await validateDocument(normalized, Object.freeze([]), /* @__PURE__ */ new Set(), 1);
	return Object.freeze({
		version: 1,
		roots,
		[validatedBlockDocumentBrand]: true,
		[validatedRegistryVersion]: registry.version
	});
}
var registryReaders = /* @__PURE__ */ new WeakMap();
function registryReader(registry) {
	const reader = registryReaders.get(registry);
	if (!reader) throw new FieldsLifecycleError("capability-unavailable", "block registry has no immutable field-definition reader");
	return reader;
}
function attachRegistryReader(registry, reader) {
	registryReaders.set(registry, reader);
	return registry;
}
function parseBlockDocument(input, policy) {
	validatePolicy(policy);
	if (new TextEncoder().encode(input).byteLength > policy.maxBytes) throw new FieldsLifecycleError("validation", "block document exceeds byte limit");
	let parsed;
	try {
		parsed = JSON.parse(input);
	} catch {
		throw new FieldsLifecycleError("validation", "block document is not valid JSON");
	}
	return normalizeDocument(parsed, policy);
}
function isValidatedDocument(document) {
	return document[validatedBlockDocumentBrand] === true;
}
function serializeBlockDocument(document) {
	if (!isValidatedDocument(document)) throw new FieldsLifecycleError("validation", "block document has not passed validation");
	return JSON.stringify({
		version: 1,
		roots: document.roots
	});
}
async function validateBlockPublication(document, registry, resolver, context, policy) {
	if (!isValidatedDocument(document)) throw new FieldsLifecycleError("validation", "block document has not passed validation");
	await validateBlockDocument(parseBlockDocument(serializeBlockDocument(document), policy), registry, resolver, context, {
		...policy,
		allowUnknownPreserved: false
	});
}
async function renderBlockDocument(document, registry, resolver, renderer, context) {
	if (!isValidatedDocument(document)) throw new FieldsLifecycleError("validation", "block document has not passed validation");
	const output = [];
	const walk = async (nodes) => {
		for (const node of nodes) {
			if (node.kind === "reusable") {
				await assertFieldsAuthorized(context, "read", {
					entityType: "reusableBlock",
					entityId: node.reusableId
				});
				const resolved = await resolver.resolve(node.reusableId, context);
				if (!resolved) throw new FieldsLifecycleError("access-denied", "reusable block is unavailable");
				const validated = await validateBlockDocument(resolved.document, registry, resolver, context, DEFAULT_BLOCK_POLICY);
				await walk(validated.roots);
				continue;
			}
			const definition = await registry.definitions.resolve(node.type, node.blockDefinitionRevision);
			if (!definition) throw new FieldsLifecycleError("integrity", "pinned block definition is unavailable", node.type);
			output.push(await renderer.render(node, definition, context));
			if (node.children) await walk(node.children);
		}
	};
	await walk(document.roots);
	return output;
}
function parseDefinitionVersions(value) {
	const source = parseJson$3(value, "definitionVersions");
	if (typeof source !== "object" || source === null || Array.isArray(source)) throw new FieldsLifecycleError("integrity", "definition version map is malformed");
	const output = {};
	for (const [name, raw] of Object.entries(source)) output[name] = positiveInt(raw, `definitionVersions.${name}`);
	return Object.freeze(output);
}
function collectDefinitionVersions(document) {
	const output = {};
	const set = (name, revision) => {
		const previous = output[name];
		if (previous !== void 0 && previous !== revision) throw new FieldsLifecycleError("integrity", "one current document cannot mix revisions for the same definition identity", name);
		output[name] = revision;
	};
	const walk = (nodes) => {
		for (const node of nodes) {
			if (node.kind === "reusable") continue;
			set(`block:${node.type}`, node.blockDefinitionRevision);
			for (const group of node.fieldGroups) set(`group:${group.groupKey}`, group.definitionRevision);
			if (node.children) walk(node.children);
		}
	};
	walk(document.roots);
	return Object.freeze(output);
}
async function readDocumentRow(db, ref) {
	return (await executeRows$1(db, sql`SELECT entity_type AS "entityType", entity_id AS "entityId", version, document, definition_versions AS "definitionVersions", parent_revision_id AS "parentRevisionId", updated_by AS "updatedBy", updated_at AS "updatedAt" FROM field_block_documents WHERE entity_type = ${ref.entityType} AND entity_id = ${ref.entityId} LIMIT 1`))[0] ?? null;
}
async function currentDocumentFromRow(row) {
	const document = normalizeDocument(parseJson$3(row.document, "block document"), DEFAULT_BLOCK_POLICY);
	const definitionVersions = parseDefinitionVersions(row.definitionVersions);
	const version = await fieldsRequestHash({
		rowVersion: Number(row.version),
		document,
		definitionVersions
	});
	return Object.freeze({
		ref: Object.freeze({
			entityType: row.entityType,
			entityId: row.entityId
		}),
		document,
		version,
		definitionVersions
	});
}
async function getBlockDocument(db, ref, context) {
	await assertFieldsAuthorized(context, "read", ref);
	const row = await readDocumentRow(db, ref);
	return row ? currentDocumentFromRow(row) : null;
}
async function setBlockDocument(tx, ref, document, mutation, registry, context) {
	assertActiveFieldsTransaction(tx, mutation.expectedTransactionIdentity);
	const authorized = await assertFieldsAuthorized(context, "write", ref);
	if (!isValidatedDocument(document)) throw new FieldsLifecycleError("validation", "block document has not passed validation");
	if (document[validatedRegistryVersion] !== registry.version) throw new FieldsLifecycleError("stale-version", "block registry changed after document validation");
	if (!mutation.parentRevisionId || mutation.parentRevisionId.length > 256) throw new FieldsLifecycleError("validation", "parentRevisionId is required", "parentRevisionId");
	const definitionVersions = collectDefinitionVersions(document);
	const serialized = serializeBlockDocument(document);
	const requestHash = await fieldsRequestHash({
		ref,
		expectedVersion: mutation.expectedVersion,
		document: JSON.parse(serialized),
		definitionVersions,
		parentRevisionId: mutation.parentRevisionId,
		registryVersion: registry.version
	});
	const receipt = await readFieldsReceipt(tx, mutation.operationId);
	if (receipt) {
		assertReceiptReplay(receipt, {
			kind: "fields:set-block-document",
			context: authorized,
			requestHash
		});
		const replayRow = await readDocumentRow(tx, ref);
		if (!replayRow) throw new FieldsLifecycleError("integrity", "committed block document receipt has no document");
		return currentDocumentFromRow(replayRow);
	}
	const existingRow = await readDocumentRow(tx, ref);
	if (((existingRow ? await currentDocumentFromRow(existingRow) : null)?.version ?? "0") !== mutation.expectedVersion) throw new FieldsLifecycleError("stale-version", "block document changed");
	const numericVersion = Number(existingRow?.version ?? 0) + 1;
	const now = (/* @__PURE__ */ new Date()).toISOString();
	await tx.execute(sql`INSERT INTO field_block_documents (entity_type, entity_id, version, document, definition_versions, parent_revision_id, updated_by, updated_at) VALUES (${ref.entityType}, ${ref.entityId}, ${numericVersion}, ${serialized}, ${JSON.stringify(definitionVersions)}, ${mutation.parentRevisionId}, ${authorized.principal.id}, ${now}) ON CONFLICT (entity_type, entity_id) DO UPDATE SET version = EXCLUDED.version, document = EXCLUDED.document, definition_versions = EXCLUDED.definition_versions, parent_revision_id = EXCLUDED.parent_revision_id, updated_by = EXCLUDED.updated_by, updated_at = EXCLUDED.updated_at`);
	const result = await currentDocumentFromRow({
		entityType: ref.entityType,
		entityId: ref.entityId,
		version: numericVersion,
		document: serialized,
		definitionVersions,
		parentRevisionId: mutation.parentRevisionId,
		updatedBy: authorized.principal.id,
		updatedAt: now
	});
	await writeFieldsReceipt(tx, {
		operationId: mutation.operationId,
		kind: "fields:set-block-document",
		context: authorized,
		requestHash,
		result: Object.freeze({ version: result.version })
	});
	return result;
}
async function deleteBlockDocument(tx, ref, mutation, context) {
	assertActiveFieldsTransaction(tx, mutation.expectedTransactionIdentity);
	const authorized = await assertFieldsAuthorized(context, "write", ref);
	if (!mutation.parentRevisionId || mutation.parentRevisionId.length > 256) throw new FieldsLifecycleError("validation", "parentRevisionId is required", "parentRevisionId");
	const requestHash = await fieldsRequestHash({
		ref,
		expectedVersion: mutation.expectedVersion,
		parentRevisionId: mutation.parentRevisionId
	});
	const receipt = await readFieldsReceipt(tx, mutation.operationId);
	if (receipt) {
		assertReceiptReplay(receipt, {
			kind: "fields:delete-block-document",
			context: authorized,
			requestHash
		});
		return;
	}
	const existingRow = await readDocumentRow(tx, ref);
	const existing = existingRow ? await currentDocumentFromRow(existingRow) : null;
	if ((existing?.version ?? "0") !== mutation.expectedVersion) throw new FieldsLifecycleError("stale-version", "block document changed");
	await tx.execute(sql`DELETE FROM field_block_documents WHERE entity_type = ${ref.entityType} AND entity_id = ${ref.entityId}`);
	await writeFieldsReceipt(tx, {
		operationId: mutation.operationId,
		kind: "fields:delete-block-document",
		context: authorized,
		requestHash,
		result: Object.freeze({ deleted: existing !== null })
	});
}
function createReusableBlockResolver(db) {
	return Object.freeze({ resolve: async (id) => {
		const row = (await executeRows$1(db, sql`SELECT version, document FROM field_reusable_blocks WHERE id = ${id} AND deleted_at IS NULL LIMIT 1`))[0];
		if (!row) return null;
		return Object.freeze({
			document: normalizeDocument(parseJson$3(row.document, "reusable block document"), DEFAULT_BLOCK_POLICY),
			version: positiveInt(row.version, "reusableBlock.version")
		});
	} });
}
function documentReferencesType(document, blockKey) {
	const walk = (nodes) => nodes.some((node) => node.kind === "inline" && (node.type === blockKey || walk(node.children ?? [])));
	return walk(document.roots);
}
function transformDocumentType(document, from, to, revision) {
	const walk = (nodes) => Object.freeze(nodes.map((node) => {
		if (node.kind === "reusable") return node;
		const children = node.children ? walk(node.children) : void 0;
		return Object.freeze({
			...node,
			...node.type === from ? {
				type: to,
				blockDefinitionRevision: revision
			} : {},
			...children ? { children } : {}
		});
	}));
	return Object.freeze({
		version: 1,
		roots: walk(document.roots)
	});
}
async function blockCorpus(db, blockKey) {
	const currentRows = await executeRows$1(db, sql`SELECT entity_type AS "entityType", entity_id AS "entityId", version, document, definition_versions AS "definitionVersions", parent_revision_id AS "parentRevisionId" FROM field_block_documents ORDER BY entity_type, entity_id`);
	const reusableRows = await executeRows$1(db, sql`SELECT id, version, document, definition_versions AS "definitionVersions", deleted_at AS "deletedAt" FROM field_reusable_blocks ORDER BY id`);
	const revisionRows = await executeRows$1(db, sql`SELECT id, entity_type AS "entityType", entity_id AS "entityId", kind, block_document AS "blockDocument", definition_versions AS "definitionVersions", source_version AS "sourceVersion" FROM field_revisions WHERE block_document IS NOT NULL ORDER BY entity_type, entity_id, id`);
	const definitionRows = await readCurrentRows(db);
	const versionRows = await executeRows$1(db, sql`SELECT revision, canonical_hash AS "canonicalHash" FROM field_block_definition_versions WHERE block_key = ${blockKey} ORDER BY revision`);
	const entries = [], entityTypes = /* @__PURE__ */ new Set(), templateOwners = [];
	for (const row of currentRows) {
		const document = normalizeDocument(parseJson$3(row.document, "block document"), DEFAULT_BLOCK_POLICY);
		if (!documentReferencesType(document, blockKey)) continue;
		const entityType = String(row.entityType);
		entityTypes.add(entityType);
		entries.push({
			section: "current",
			identity: `${entityType}:${String(row.entityId)}`,
			entityType,
			payload: {
				entityId: row.entityId,
				version: row.version,
				document,
				definitionVersions: parseJson$3(row.definitionVersions, "definitionVersions"),
				parentRevisionId: row.parentRevisionId
			}
		});
	}
	for (const row of reusableRows) {
		const document = normalizeDocument(parseJson$3(row.document, "reusable block document"), DEFAULT_BLOCK_POLICY);
		if (!documentReferencesType(document, blockKey)) continue;
		entityTypes.add("reusableBlock");
		entries.push({
			section: "reusable",
			identity: String(row.id),
			entityType: "reusableBlock",
			payload: {
				version: row.version,
				document,
				definitionVersions: parseJson$3(row.definitionVersions, "definitionVersions"),
				deletedAt: row.deletedAt ?? null
			}
		});
	}
	for (const row of revisionRows) {
		const document = normalizeDocument(parseJson$3(row.blockDocument, "revision block document"), DEFAULT_BLOCK_POLICY);
		if (!documentReferencesType(document, blockKey)) continue;
		const entityType = String(row.entityType);
		entityTypes.add(entityType);
		entries.push({
			section: "revision",
			identity: String(row.id),
			entityType,
			payload: {
				entityId: row.entityId,
				kind: row.kind,
				document,
				definitionVersions: parseJson$3(row.definitionVersions, "definitionVersions"),
				sourceVersion: row.sourceVersion
			}
		});
	}
	for (const row of definitionRows) if (row.key !== blockKey && templateTypes(resolvedCurrent(row).template).has(blockKey)) templateOwners.push(row.key);
	entries.sort((left, right) => left.section.localeCompare(right.section) || left.identity.localeCompare(right.identity));
	templateOwners.sort();
	const version = await fieldsRequestHash({
		identity: entries.map((entry) => ({
			section: entry.section,
			identity: entry.identity,
			entityType: entry.entityType
		})),
		templateOwners,
		definitionVersions: versionRows.map((row) => row.revision)
	});
	const hash = await fieldsRequestHash({
		entries,
		templateOwners,
		definitionVersions: versionRows
	});
	return Object.freeze({
		version,
		hash,
		entries: Object.freeze(entries),
		templateOwners: Object.freeze(templateOwners),
		affectedDefinitionVersions: versionRows.length,
		entityTypes: Object.freeze([...entityTypes].sort())
	});
}
function blockTokenEncode(payload) {
	const bytes = new TextEncoder().encode(JSON.stringify(payload)), hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
	return fieldsRequestHash(payload).then((digest) => `${hex}.${digest}`);
}
async function blockTokenDecode(token) {
	const match = /^([a-f0-9]+)\.([a-f0-9]{64})$/i.exec(token);
	if (!match || match[1].length % 2 || match[1].length > 128e3) throw new FieldsLifecycleError("validation", "block impact token is invalid");
	let parsed;
	try {
		parsed = JSON.parse(new TextDecoder().decode(new Uint8Array(match[1].match(/../g).map((pair) => Number.parseInt(pair, 16)))));
	} catch {
		throw new FieldsLifecycleError("validation", "block impact token is invalid");
	}
	if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || await fieldsRequestHash(parsed) !== match[2].toLowerCase()) throw new FieldsLifecycleError("validation", "block impact token integrity check failed");
	return parsed;
}
function strategyStorage(strategy) {
	return jsonValue(strategy, "strategy");
}
function strategyEqual(left, right) {
	try {
		return JSON.stringify(strategyStorage(left)) === JSON.stringify(jsonValue(right, "strategy"));
	} catch {
		return false;
	}
}
function blockChangeIncompatibilities(current, proposed, corpus, strategy, deactivate, deleting, replacement) {
	const output = [];
	if (strategy.kind === "reject" && (deactivate || deleting) && corpus.entries.length > 0) output.push("affected documents require an explicit retaining, mapping, or purge strategy");
	if (proposed) {
		const removedGroups = current.fieldGroupKeys.filter((groupKey) => !proposed.fieldGroupKeys.includes(groupKey));
		if (removedGroups.length && corpus.entries.length) output.push(`field groups removed while referenced: ${removedGroups.join(",")}`);
		if (current.supports?.innerBlocks === true && proposed.supports?.innerBlocks !== true && corpus.entries.length) output.push("innerBlocks support removed while documents remain");
		if (current.supports?.multiple !== false && proposed.supports?.multiple === false && corpus.entries.length) output.push("multiple support narrowed while documents remain");
	}
	if (strategy.kind === "mapDefinition") {
		if (!replacement || !replacement.active) output.push("replacement block is missing or inactive");
		else if (JSON.stringify([...replacement.fieldGroupKeys].sort()) !== JSON.stringify([...current.fieldGroupKeys].sort())) output.push("replacement block field groups do not match the affected document namespaces");
		if (corpus.templateOwners.length) output.push("template references require an explicit template definition migration");
	}
	if (strategy.kind === "purgeWithBackup" && corpus.templateOwners.length) output.push("template references must be removed or mapped before purge");
	return Object.freeze(output.sort());
}
function normalizeBlockStrategy(strategy) {
	if (strategy.kind === "reject" || strategy.kind === "retainUnknown") return Object.freeze({ kind: strategy.kind });
	if (strategy.kind === "mapDefinition") return Object.freeze({
		kind: "mapDefinition",
		replacementKey: key(strategy.replacementKey, "strategy.replacementKey")
	});
	if (strategy.kind === "purgeWithBackup") return Object.freeze({
		kind: "purgeWithBackup",
		backupId: string(strategy.backupId, "strategy.backupId", 512)
	});
	throw new FieldsLifecycleError("validation", "unknown block change strategy");
}
async function previewFieldBlockChange(db, context, input) {
	const blockKey = key(input.key, "key");
	await assertFieldsAuthorized(context, "manageDefinitions", definitionRef(blockKey));
	const current = await readCurrentBlock(db, blockKey);
	if (!current) throw new FieldsLifecycleError("not-found", "block definition is unavailable");
	if (current.block.origin === "code") throw new FieldsLifecycleError("validation", "code-owned block changes require registry reconciliation");
	if (current.block.version !== input.expectedVersion) throw new FieldsLifecycleError("stale-version", "block definition version changed");
	const deactivate = input.deactivate === true, deleting = input.delete === true;
	if (!input.patch && !deactivate && !deleting) throw new FieldsLifecycleError("validation", "block change must patch, deactivate, or delete");
	if (deactivate && deleting) throw new FieldsLifecycleError("validation", "block change cannot deactivate and delete simultaneously");
	const proposed = input.patch ? normalizeDefinition({
		...current.block,
		...input.patch,
		key: blockKey
	}) : null;
	if (proposed) await assertGroupDependencies(db, proposed);
	const strategy = normalizeBlockStrategy(input.strategy);
	const corpus = await blockCorpus(db, blockKey);
	const migration = await assertDefinitionMigration(context, corpus.entityTypes.length ? corpus.entityTypes : ["fields-definition"]);
	const replacementCurrent = strategy.kind === "mapDefinition" ? await readCurrentBlock(db, strategy.replacementKey) : null;
	const incompatibilities = [...blockChangeIncompatibilities(current.block, proposed, corpus, strategy, deactivate, deleting, replacementCurrent?.block)];
	if (strategy.kind === "mapDefinition" && replacementCurrent) {
		if (JSON.stringify(replacementCurrent.block.parent ?? []) !== JSON.stringify(current.block.parent ?? [])) incompatibilities.push("replacement parent constraints differ from source");
		if (JSON.stringify(replacementCurrent.block.ancestor ?? []) !== JSON.stringify(current.block.ancestor ?? [])) incompatibilities.push("replacement ancestor constraints differ from source");
		if (replacementCurrent.block.supports?.innerBlocks !== current.block.supports?.innerBlocks) incompatibilities.push("replacement inner-block support differs from source");
	}
	const normalizedIncompatibilities = Object.freeze([...new Set(incompatibilities)].sort());
	const payload = Object.freeze({
		kind: "field-block-change",
		blockKey,
		expectedVersion: current.block.version,
		authorizationPolicyVersion: migration.policyVersion,
		documentCorpusVersion: corpus.version,
		documentCorpusHash: corpus.hash,
		affectedDocuments: corpus.entries.length,
		affectedDefinitionVersions: corpus.affectedDefinitionVersions,
		entityTypes: Object.freeze(corpus.entityTypes),
		templateOwners: Object.freeze(corpus.templateOwners),
		proposedDefinition: proposed ? jsonValue(proposed, "proposedDefinition") : null,
		deactivate,
		delete: deleting,
		strategy: strategyStorage(strategy),
		incompatibilities: Object.freeze(normalizedIncompatibilities)
	});
	return Object.freeze({
		token: await blockTokenEncode(payload),
		blockKey,
		expectedVersion: current.block.version,
		authorizationPolicyVersion: migration.policyVersion,
		documentCorpusVersion: corpus.version,
		documentCorpusHash: corpus.hash,
		affectedDocuments: corpus.entries.length,
		affectedDefinitionVersions: corpus.affectedDefinitionVersions,
		incompatibilities: normalizedIncompatibilities
	});
}
function definitionVersionMapAfterMap(value, from, to, revision) {
	const output = { ...parseDefinitionVersions(value) };
	if (output[`block:${from}`] !== void 0) delete output[`block:${from}`];
	const prior = output[`block:${to}`];
	if (prior !== void 0 && prior !== revision) throw new FieldsLifecycleError("integrity", "mapping would mix replacement block revisions");
	output[`block:${to}`] = revision;
	return Object.freeze(output);
}
async function applyBlockMap(tx, corpus, from, replacement) {
	const revision = Number(replacement.row.currentRevision);
	for (const entry of corpus.entries) {
		const payload = entry.payload;
		const mapped = transformDocumentType(normalizeDocument(payload.document, DEFAULT_BLOCK_POLICY), from, replacement.block.key, revision);
		const versions = definitionVersionMapAfterMap(payload.definitionVersions, from, replacement.block.key, revision);
		if (entry.section === "current") {
			const entityId = String(payload.entityId);
			await tx.execute(sql`UPDATE field_block_documents SET document = ${JSON.stringify(mapped)}, definition_versions = ${JSON.stringify(versions)}, version = version + 1, updated_at = ${(/* @__PURE__ */ new Date()).toISOString()} WHERE entity_type = ${entry.entityType} AND entity_id = ${entityId}`);
		} else if (entry.section === "reusable") await tx.execute(sql`UPDATE field_reusable_blocks SET document = ${JSON.stringify(mapped)}, definition_versions = ${JSON.stringify(versions)}, version = version + 1, updated_at = ${(/* @__PURE__ */ new Date()).toISOString()} WHERE id = ${entry.identity}`);
		else continue;
	}
}
async function purgeBlockCorpus(tx, corpus) {
	for (const entry of corpus.entries) {
		const payload = entry.payload;
		if (entry.section === "current") await tx.execute(sql`DELETE FROM field_block_documents WHERE entity_type = ${entry.entityType} AND entity_id = ${String(payload.entityId)}`);
		else if (entry.section === "reusable") await tx.execute(sql`DELETE FROM field_reusable_blocks WHERE id = ${entry.identity}`);
		else await tx.execute(sql`DELETE FROM field_revisions WHERE id = ${entry.identity}`);
	}
}
function parsedTokenDefinition(value, blockKey) {
	if (value === null) return null;
	if (typeof value !== "object" || value === null || Array.isArray(value)) throw new FieldsLifecycleError("validation", "block impact token contains invalid proposed definition");
	const definition = normalizeDefinition(value);
	if (definition.key !== blockKey) throw new FieldsLifecycleError("validation", "block impact token definition key mismatch");
	return definition;
}
async function applyFieldBlockChange(tx, context, input, options) {
	assertActiveFieldsTransaction(tx);
	const token = await blockTokenDecode(input.impactToken);
	if (token.kind !== "field-block-change" || typeof token.blockKey !== "string") throw new FieldsLifecycleError("validation", "block impact token has wrong operation kind");
	const blockKey = key(token.blockKey, "blockKey");
	const strategy = normalizeBlockStrategy(input.strategy);
	if (!strategyEqual(strategy, token.strategy)) throw new FieldsLifecycleError("operation-conflict", "block strategy differs from preview");
	const authorized = await assertFieldsAuthorized(context, "manageDefinitions", definitionRef(blockKey));
	const entityTypes = Array.isArray(token.entityTypes) ? token.entityTypes.map((value, index) => string(value, `entityTypes.${index}`, 256)) : [];
	const migration = await assertDefinitionMigration(context, entityTypes.length ? entityTypes : ["fields-definition"]);
	if (token.authorizationPolicyVersion !== migration.policyVersion) throw new FieldsLifecycleError("corpus-drift", "authorization policy changed since preview");
	const requestHash = await fieldsRequestHash({
		impactToken: input.impactToken,
		strategy,
		codeKeys: (options.codeBlocks ?? []).map((block) => block.key).sort()
	});
	const replay = await readFieldsReceipt(tx, input.operationId);
	if (replay) {
		assertReceiptReplay(replay, {
			kind: "fields:apply-block-change",
			context: authorized,
			requestHash
		});
		return (await readCurrentBlock(tx, blockKey))?.block ?? null;
	}
	const current = await readCurrentBlock(tx, blockKey);
	if (!current) throw new FieldsLifecycleError("not-found", "block definition is unavailable");
	if (current.block.origin === "code" || (options.codeBlocks ?? []).some((block) => block.key === blockKey)) throw new FieldsLifecycleError("validation", "code-owned block changes require registry reconciliation");
	if (Number(token.expectedVersion) !== current.block.version) throw new FieldsLifecycleError("stale-version", "block definition version changed");
	const corpus = await blockCorpus(tx, blockKey);
	if (token.documentCorpusVersion !== corpus.version || token.documentCorpusHash !== corpus.hash || Number(token.affectedDocuments) !== corpus.entries.length || Number(token.affectedDefinitionVersions) !== corpus.affectedDefinitionVersions) throw new FieldsLifecycleError("corpus-drift", "block document corpus changed since preview");
	if (JSON.stringify([...corpus.entityTypes].sort()) !== JSON.stringify([...entityTypes].sort())) throw new FieldsLifecycleError("corpus-drift", "block corpus authorization scope changed since preview");
	const proposed = parsedTokenDefinition(token.proposedDefinition, blockKey);
	const deactivate = token.deactivate === true;
	const deleting = token.delete === true;
	const replacement = strategy.kind === "mapDefinition" ? await readCurrentBlock(tx, strategy.replacementKey) : null;
	const incompatibilities = [...blockChangeIncompatibilities(current.block, proposed, corpus, strategy, deactivate, deleting, replacement?.block)];
	if (strategy.kind === "mapDefinition" && replacement) {
		if (JSON.stringify(replacement.block.parent ?? []) !== JSON.stringify(current.block.parent ?? [])) incompatibilities.push("replacement parent constraints differ from source");
		if (JSON.stringify(replacement.block.ancestor ?? []) !== JSON.stringify(current.block.ancestor ?? [])) incompatibilities.push("replacement ancestor constraints differ from source");
		if (replacement.block.supports?.innerBlocks !== current.block.supports?.innerBlocks) incompatibilities.push("replacement inner-block support differs from source");
	}
	const normalizedIncompatibilities = [...new Set(incompatibilities)].sort();
	const tokenIncompatibilities = Array.isArray(token.incompatibilities) ? token.incompatibilities.map(String).sort() : [];
	if (JSON.stringify(normalizedIncompatibilities) !== JSON.stringify(tokenIncompatibilities)) throw new FieldsLifecycleError("corpus-drift", "block compatibility facts changed since preview");
	if (normalizedIncompatibilities.length > 0) throw new FieldsLifecycleError("validation", normalizedIncompatibilities.join("; "));
	if (strategy.kind === "purgeWithBackup") {
		if (!options.destructive) throw new FieldsLifecycleError("backup-invalid", "destructive dependencies are required");
		const counts = Object.freeze({
			documents: corpus.entries.length,
			definitionVersions: corpus.affectedDefinitionVersions
		});
		const scopeHash = await fieldsRequestHash({
			definitionKind: "block",
			definitionKey: blockKey,
			strategy,
			authorizationPolicyVersion: migration.policyVersion,
			corpusVersion: corpus.version,
			corpusHash: corpus.hash,
			previewToken: input.impactToken,
			affectedCounts: counts
		});
		const backup = await verifyFieldsBackup(tx, {
			backupId: strategy.backupId,
			expectedScopeHash: scopeHash,
			corpusVersion: corpus.version,
			corpusHash: corpus.hash,
			counts
		}, options.destructive.backups);
		const event = Object.freeze({
			operationId: input.operationId,
			principalId: authorized.principal.id,
			definitionKind: "block",
			definitionKey: blockKey,
			strategy: strategyStorage(strategy),
			authorizationPolicyVersion: migration.policyVersion,
			corpusVersion: corpus.version,
			corpusHash: corpus.hash,
			previewToken: input.impactToken,
			affectedCounts: counts,
			backup
		});
		await options.destructive.effects.audit.record(tx, event);
		await options.destructive.effects.outbox.enqueue(tx, event);
		await purgeBlockCorpus(tx, corpus);
	} else if (strategy.kind === "mapDefinition") {
		if (!replacement) throw new FieldsLifecycleError("validation", "replacement block is unavailable");
		await applyBlockMap(tx, corpus, blockKey, replacement);
	}
	let result;
	if (deleting) {
		await tx.execute(sql`DELETE FROM field_block_definitions WHERE key = ${blockKey} AND version = ${current.block.version}`);
		if (strategy.kind === "purgeWithBackup") await tx.execute(sql`DELETE FROM field_block_definition_versions WHERE block_key = ${blockKey}`);
		result = null;
	} else {
		const nextVersion = current.block.version + 1;
		let currentRevision = Number(current.row.currentRevision);
		let canonicalHash = current.row.canonicalHash;
		let definition = current.block;
		if (proposed) {
			await assertGroupDependencies(tx, proposed);
			canonicalHash = await fieldsRequestHash(proposed);
			if (canonicalHash !== current.row.canonicalHash) {
				currentRevision += 1;
				await tx.execute(sql`INSERT INTO field_block_definition_versions (block_key, revision, canonical_hash, definition, origin, created_at) VALUES (${blockKey}, ${currentRevision}, ${canonicalHash}, ${JSON.stringify(proposed)}, 'db', ${(/* @__PURE__ */ new Date()).toISOString()})`);
				definition = proposed;
			}
		}
		const active = deactivate ? false : current.block.active;
		await tx.execute(sql`UPDATE field_block_definitions SET version = ${nextVersion}, active = ${active}, current_revision = ${currentRevision}, canonical_hash = ${canonicalHash}, definition = ${JSON.stringify(definition)}, updated_at = ${(/* @__PURE__ */ new Date()).toISOString()} WHERE key = ${blockKey} AND version = ${current.block.version}`);
		result = Object.freeze({
			...definition,
			origin: "db",
			version: nextVersion,
			active,
			...current.block.shadowedDbVersion === void 0 ? {} : { shadowedDbVersion: current.block.shadowedDbVersion }
		});
	}
	await writeFieldsReceipt(tx, {
		operationId: input.operationId,
		kind: "fields:apply-block-change",
		context: authorized,
		requestHash,
		result: result ? Object.freeze({
			key: result.key,
			version: result.version
		}) : Object.freeze({ deleted: true })
	});
	return result;
}
/** Internal composition seam for definition reconciliation; intentionally not re-exported from package index. */
var __fieldBlockLifecycleInternals = Object.freeze({
	normalizeDefinition,
	readCurrentRows,
	readCurrentBlock,
	mergeCurrent,
	validateDefinitionGraph,
	assertGroupDependencies,
	blockCorpus,
	blockChangeIncompatibilities,
	applyBlockMap,
	purgeBlockCorpus,
	validateBlockFieldMap,
	readBlockVersion
});
function rowsOf$3(result) {
	if (Array.isArray(result)) return result;
	if (typeof result === "object" && result !== null) {
		const rows = result.rows;
		if (Array.isArray(rows)) return rows;
	}
	throw new FieldsLifecycleError("integrity", "database adapter returned an invalid row result");
}
async function executeRows(db, query) {
	return rowsOf$3(await db.execute(query));
}
function fieldsRuntimeMigrationSql(adapter) {
	if (adapter === "postgres") return Object.freeze([
		`CREATE TABLE IF NOT EXISTS field_block_documents (entity_type text NOT NULL, entity_id text NOT NULL, version integer NOT NULL DEFAULT 1 CHECK (version > 0), document jsonb NOT NULL, definition_versions jsonb NOT NULL, parent_revision_id text NOT NULL, host_session_id text, updated_by text NOT NULL, updated_at timestamptz(3) NOT NULL DEFAULT NOW(), PRIMARY KEY (entity_type, entity_id))`,
		`CREATE TABLE IF NOT EXISTS field_reusable_blocks (id text PRIMARY KEY, version integer NOT NULL DEFAULT 1 CHECK (version > 0), document jsonb NOT NULL, definition_versions jsonb NOT NULL, deleted_at timestamptz(3), host_session_id text, updated_by text NOT NULL, updated_at timestamptz(3) NOT NULL DEFAULT NOW())`,
		`CREATE TABLE IF NOT EXISTS field_revisions (id uuid PRIMARY KEY, entity_type text NOT NULL, entity_id text NOT NULL, parent_revision_id text NOT NULL, parent_autosave_id text, kind text NOT NULL CHECK (kind IN ('revision','autosave')), retention_class text, definition_versions jsonb NOT NULL, "values" jsonb NOT NULL, block_document jsonb, created_at timestamptz(3) NOT NULL DEFAULT NOW(), created_by text NOT NULL, source_version text NOT NULL, host_session_id text)`,
		`CREATE INDEX IF NOT EXISTS field_revisions_entity_created_idx ON field_revisions (entity_type, entity_id, created_at, id)`,
		`CREATE INDEX IF NOT EXISTS field_revisions_parent_idx ON field_revisions (parent_revision_id, kind)`,
		`CREATE TABLE IF NOT EXISTS fields_operation_receipts (operation_id text PRIMARY KEY, kind text NOT NULL, principal_scope text NOT NULL, request_hash text NOT NULL, result jsonb NOT NULL, created_at timestamptz(3) NOT NULL DEFAULT NOW())`,
		`CREATE INDEX IF NOT EXISTS fields_operation_receipts_kind_idx ON fields_operation_receipts (kind, created_at)`
	]);
	return Object.freeze([
		`CREATE TABLE IF NOT EXISTS field_block_documents (entity_type TEXT NOT NULL, entity_id TEXT NOT NULL, version INTEGER NOT NULL DEFAULT 1 CHECK (version > 0), document TEXT NOT NULL, definition_versions TEXT NOT NULL, parent_revision_id TEXT NOT NULL, host_session_id TEXT, updated_by TEXT NOT NULL, updated_at TEXT NOT NULL, PRIMARY KEY (entity_type, entity_id))`,
		`CREATE TABLE IF NOT EXISTS field_reusable_blocks (id TEXT PRIMARY KEY, version INTEGER NOT NULL DEFAULT 1 CHECK (version > 0), document TEXT NOT NULL, definition_versions TEXT NOT NULL, deleted_at TEXT, host_session_id TEXT, updated_by TEXT NOT NULL, updated_at TEXT NOT NULL)`,
		`CREATE TABLE IF NOT EXISTS field_revisions (id TEXT PRIMARY KEY, entity_type TEXT NOT NULL, entity_id TEXT NOT NULL, parent_revision_id TEXT NOT NULL, parent_autosave_id TEXT, kind TEXT NOT NULL CHECK (kind IN ('revision','autosave')), retention_class TEXT, definition_versions TEXT NOT NULL, "values" TEXT NOT NULL, block_document TEXT, created_at TEXT NOT NULL, created_by TEXT NOT NULL, source_version TEXT NOT NULL, host_session_id TEXT)`,
		`CREATE INDEX IF NOT EXISTS field_revisions_entity_created_idx ON field_revisions (entity_type, entity_id, created_at, id)`,
		`CREATE INDEX IF NOT EXISTS field_revisions_parent_idx ON field_revisions (parent_revision_id, kind)`,
		`CREATE TABLE IF NOT EXISTS fields_operation_receipts (operation_id TEXT PRIMARY KEY, kind TEXT NOT NULL, principal_scope TEXT NOT NULL, request_hash TEXT NOT NULL, result TEXT NOT NULL, created_at TEXT NOT NULL)`,
		`CREATE INDEX IF NOT EXISTS fields_operation_receipts_kind_idx ON fields_operation_receipts (kind, created_at)`
	]);
}
function parseJson$2(value, field) {
	if (typeof value !== "string") return value;
	try {
		return JSON.parse(value);
	} catch {
		throw new FieldsLifecycleError("integrity", `${field} contains invalid JSON`);
	}
}
function storage(value, depth = 0) {
	if (depth > 24) throw new FieldsLifecycleError("integrity", "snapshot exceeds maximum depth");
	if (value === null || typeof value === "string" || typeof value === "boolean") return value;
	if (typeof value === "number") {
		if (!Number.isFinite(value)) throw new FieldsLifecycleError("integrity", "snapshot contains a non-finite number");
		return value;
	}
	if (Array.isArray(value)) return Object.freeze(value.map((item) => storage(item, depth + 1)));
	if (typeof value === "object") {
		const out = {};
		for (const key of Object.keys(value).sort()) {
			if (key === "__proto__" || key === "prototype" || key === "constructor") throw new FieldsLifecycleError("integrity", "snapshot contains a forbidden key");
			const child = value[key];
			if (child !== void 0) out[key] = storage(child, depth + 1);
		}
		return Object.freeze(out);
	}
	throw new FieldsLifecycleError("integrity", `snapshot contains unsupported ${typeof value}`);
}
function record$1(value, field) {
	const parsed = parseJson$2(value, field);
	if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new FieldsLifecycleError("integrity", `${field} is malformed`);
	return parsed;
}
function numericRecord(value, field) {
	const input = record$1(value, field), out = {};
	for (const [key, raw] of Object.entries(input)) {
		const number = Number(raw);
		if (!Number.isSafeInteger(number) || number < 1) throw new FieldsLifecycleError("integrity", `${field}.${key} must be a positive revision`);
		out[key] = number;
	}
	return Object.freeze(out);
}
function storedBlock(value) {
	const input = record$1(value, "blockDocument");
	if (input.version !== 1 || !Array.isArray(input.roots)) throw new FieldsLifecycleError("integrity", "block document is malformed");
	return Object.freeze({
		version: 1,
		roots: Object.freeze(input.roots.map(storage))
	});
}
function nodeFromRow(row) {
	return Object.freeze({
		nodeId: row.nodeId,
		entityType: row.entityType,
		entityId: row.entityId,
		groupKey: row.groupKey,
		definitionRevision: Number(row.definitionRevision),
		fieldKey: row.fieldKey,
		path: row.path,
		parentNodeId: row.parentNodeId,
		rowId: row.rowId,
		layoutKey: row.layoutKey,
		nodeKind: row.nodeKind,
		ordinal: Number(row.ordinal),
		isNull: row.isNull === true || row.isNull === 1,
		valueText: row.valueText,
		valueNumber: row.valueNumber === null ? null : Number(row.valueNumber),
		valueBoolean: row.valueBoolean === null ? null : row.valueBoolean === true || row.valueBoolean === 1,
		valueDateTime: row.valueDateTime,
		valueRef: row.valueRef,
		valueJson: row.valueJson
	});
}
function recursiveRedact(definitions, values, context) {
	const registry = context.fieldTypeRegistry ?? createFieldTypeRegistry();
	const out = {};
	for (const definition of definitions) {
		const value = values[definition.key];
		if (value === void 0) continue;
		if (definition.type === "password") {
			out[definition.key] = storage({ configured: Boolean(value?.configured) });
			continue;
		}
		if (definition.type === "message" || definition.type === "accordion" || definition.type === "tab") continue;
		if (definition.type === "group") {
			out[definition.key] = storage(recursiveRedact(definition.settings.fields, value ?? {}, context));
			continue;
		}
		if (definition.type === "repeater") {
			const fields = definition.settings.fields;
			out[definition.key] = storage(value.map((row) => ({
				rowId: row.rowId,
				values: recursiveRedact(fields, row.values, context)
			})));
			continue;
		}
		if (definition.type === "flexible") {
			const layouts = definition.settings.layouts;
			out[definition.key] = storage(value.map((row) => {
				const layout = layouts.find((item) => item.key === row.layoutKey);
				if (!layout) throw new FieldsLifecycleError("integrity", "snapshot references unknown flexible layout");
				return {
					rowId: row.rowId,
					layoutKey: row.layoutKey,
					values: recursiveRedact(layout.fields, row.values, context)
				};
			}));
			continue;
		}
		if (definition.type === "clone") {
			if (!context.cloneResolver) throw new FieldsLifecycleError("capability-unavailable", "clone resolver is required to snapshot clone values");
			out[definition.key] = storage(recursiveRedact(context.cloneResolver.resolve(definition), value ?? {}, context));
			continue;
		}
		const redacted = redactFieldValueForRevision(definition, value, registry);
		if (redacted !== "omit") out[definition.key] = storage(redacted);
	}
	return Object.freeze(out);
}
async function snapshotEntity(db, ref, context) {
	const rows = await executeRows(db, sql`
    SELECT node_id AS "nodeId", entity_type AS "entityType", entity_id AS "entityId",
      group_key AS "groupKey", definition_revision AS "definitionRevision", field_key AS "fieldKey",
      path, parent_node_id AS "parentNodeId", row_id AS "rowId", layout_key AS "layoutKey",
      node_kind AS "nodeKind", ordinal, is_null AS "isNull", value_text AS "valueText",
      value_number AS "valueNumber", value_boolean AS "valueBoolean", value_date_time AS "valueDateTime",
      value_ref AS "valueRef", value_json AS "valueJson"
    FROM field_value_nodes
    WHERE entity_type = ${ref.entityType} AND entity_id = ${ref.entityId}
    ORDER BY group_key, path
  `);
	const byGroup = /* @__PURE__ */ new Map();
	for (const row of rows) {
		const bucket = byGroup.get(row.groupKey) ?? [];
		bucket.push(row);
		byGroup.set(row.groupKey, bucket);
	}
	const definitionVersions = {};
	const values = {};
	for (const [groupKey, bucket] of [...byGroup].sort(([left], [right]) => left.localeCompare(right))) {
		const revisions = [...new Set(bucket.map((row) => Number(row.definitionRevision)))];
		if (revisions.length !== 1) throw new FieldsLifecycleError("integrity", `current group ${groupKey} mixes immutable definition revisions`);
		const revision = revisions[0];
		const version = await resolveFieldDefinitionVersion(db, groupKey, revision);
		const decoded = decodeFieldValueNodes(version.definition, bucket.map(nodeFromRow), {
			definitionRevision: revision,
			...context.cloneResolver ? { cloneResolver: { resolve: (definition) => context.cloneResolver.resolve(definition) } } : {}
		});
		definitionVersions[groupKey] = revision;
		values[groupKey] = storage(recursiveRedact(version.definition.fields, decoded, context));
	}
	const blockRows = await executeRows(db, sql`
    SELECT version, document, definition_versions AS "definitionVersions"
    FROM field_block_documents
    WHERE entity_type = ${ref.entityType} AND entity_id = ${ref.entityId}
    LIMIT 1
  `);
	const blockDocument = blockRows[0] ? storedBlock(parseJson$2(blockRows[0].document, "blockDocument")) : void 0;
	const version = await fieldsRequestHash({
		definitionVersions,
		values,
		blockDocument: blockDocument ?? null
	});
	return Object.freeze({
		version,
		definitionVersions: Object.freeze(definitionVersions),
		values: Object.freeze(values),
		...blockDocument ? { blockDocument } : {},
		guardNodes: Object.freeze([...rows]),
		guardBlockDocument: blockRows[0] ? typeof blockRows[0].document === "string" ? blockRows[0].document : JSON.stringify(blockRows[0].document) : null
	});
}
function revisionFromRow(row) {
	const definitionVersions = numericRecord(row.definitionVersions, "definitionVersions");
	const valuesObject = record$1(row.values, "values");
	const values = {};
	for (const [key, value] of Object.entries(valuesObject)) values[key] = storage(value);
	const blockDocument = row.blockDocument === null ? void 0 : storedBlock(parseJson$2(row.blockDocument, "blockDocument"));
	return Object.freeze({
		id: row.id,
		ref: Object.freeze({
			entityType: row.entityType,
			entityId: row.entityId
		}),
		parentRevisionId: row.parentRevisionId,
		...row.parentAutosaveId ? { parentAutosaveId: row.parentAutosaveId } : {},
		kind: row.kind,
		...row.retentionClass ? { retentionClass: row.retentionClass } : {},
		definitionVersions,
		values: Object.freeze(values),
		...blockDocument ? { blockDocument } : {},
		createdAt: row.createdAt instanceof Date ? new Date(row.createdAt) : new Date(row.createdAt),
		createdBy: row.createdBy,
		sourceVersion: row.sourceVersion
	});
}
async function requireRevision(db, ref, id) {
	const row = (await executeRows(db, sql`
    SELECT id, entity_type AS "entityType", entity_id AS "entityId",
      parent_revision_id AS "parentRevisionId", parent_autosave_id AS "parentAutosaveId",
      kind, retention_class AS "retentionClass", definition_versions AS "definitionVersions",
      "values" AS "values", block_document AS "blockDocument", created_at AS "createdAt",
      created_by AS "createdBy", source_version AS "sourceVersion"
    FROM field_revisions
    WHERE id = ${id} AND entity_type = ${ref.entityType} AND entity_id = ${ref.entityId}
    LIMIT 1
  `))[0];
	if (!row) throw new FieldsLifecycleError("not-found", "revision is unavailable");
	return revisionFromRow(row);
}
async function insertRevision(tx, input) {
	const createdAt = /* @__PURE__ */ new Date();
	await tx.execute(sql`
    INSERT INTO field_revisions (
      id, entity_type, entity_id, parent_revision_id, parent_autosave_id, kind,
      retention_class, definition_versions, "values", block_document,
      created_at, created_by, source_version
    ) VALUES (
      ${input.id}, ${input.ref.entityType}, ${input.ref.entityId}, ${input.parentRevisionId},
      ${input.parentAutosaveId ?? null}, ${input.kind}, ${input.retentionClass ?? null},
      ${JSON.stringify(input.snapshot.definitionVersions)}, ${JSON.stringify(input.snapshot.values)},
      ${input.snapshot.blockDocument ? JSON.stringify(input.snapshot.blockDocument) : null},
      ${createdAt.toISOString()}, ${input.createdBy}, ${input.snapshot.version}
    )
  `);
	return Object.freeze({
		id: input.id,
		ref: Object.freeze({ ...input.ref }),
		parentRevisionId: input.parentRevisionId,
		...input.parentAutosaveId ? { parentAutosaveId: input.parentAutosaveId } : {},
		kind: input.kind,
		...input.retentionClass ? { retentionClass: input.retentionClass } : {},
		definitionVersions: input.snapshot.definitionVersions,
		values: input.snapshot.values,
		...input.snapshot.blockDocument ? { blockDocument: input.snapshot.blockDocument } : {},
		createdAt,
		createdBy: input.createdBy,
		sourceVersion: input.snapshot.version
	});
}
async function capture(tx, ref, mutation, context, kind) {
	assertActiveFieldsTransaction(tx, mutation.expectedTransactionIdentity);
	const authorized = await assertFieldsAuthorized(context, "write", ref);
	if (!mutation.parentRevisionId || mutation.parentRevisionId.length > 256) throw new FieldsLifecycleError("validation", "parentRevisionId is required", "parentRevisionId");
	const autosave = kind === "autosave" ? mutation : void 0;
	if (autosave && (!autosave.parentAutosaveId || autosave.parentAutosaveId.length > 256)) throw new FieldsLifecycleError("validation", "parentAutosaveId is required", "parentAutosaveId");
	if (autosave && (!autosave.retentionClass || autosave.retentionClass.length > 128)) throw new FieldsLifecycleError("validation", "retentionClass is required", "retentionClass");
	const current = await snapshotEntity(tx, ref, context);
	if (current.version !== mutation.expectedVersion) throw new FieldsLifecycleError("stale-version", "current fields version changed");
	const requestHash = await fieldsRequestHash({
		ref,
		kind,
		expectedVersion: mutation.expectedVersion,
		parentRevisionId: mutation.parentRevisionId,
		parentAutosaveId: autosave?.parentAutosaveId ?? null,
		retentionClass: autosave?.retentionClass ?? null
	});
	const existing = await readFieldsReceipt(tx, mutation.operationId);
	if (existing) {
		assertReceiptReplay(existing, {
			kind: `fields:${kind}`,
			context: authorized,
			requestHash
		});
		const result = record$1(existing.result, "receipt");
		if (typeof result.id !== "string") throw new FieldsLifecycleError("integrity", "revision receipt is malformed");
		return requireRevision(tx, ref, result.id);
	}
	const revision = await insertRevision(tx, {
		id: crypto.randomUUID(),
		ref,
		parentRevisionId: mutation.parentRevisionId,
		...autosave ? {
			parentAutosaveId: autosave.parentAutosaveId,
			retentionClass: autosave.retentionClass
		} : {},
		kind,
		snapshot: current,
		createdBy: authorized.principal.id
	});
	await writeFieldsReceipt(tx, {
		operationId: mutation.operationId,
		kind: `fields:${kind}`,
		context: authorized,
		requestHash,
		result: storage({ id: revision.id })
	});
	return revision;
}
async function captureFieldsRevision(tx, ref, mutation, context) {
	return capture(tx, ref, mutation, context, "revision");
}
async function getFieldsRevision(db, ref, revisionId, context) {
	await assertFieldsAuthorized(context, "read", ref);
	try {
		return await requireRevision(db, ref, revisionId);
	} catch (error) {
		if (error instanceof FieldsLifecycleError && error.code === "not-found") return null;
		throw error;
	}
}
function preservePasswordValues(definitions, revision, current, context) {
	const out = { ...revision };
	for (const definition of definitions) {
		if (definition.type === "password") {
			if (Object.prototype.hasOwnProperty.call(current, definition.key)) out[definition.key] = current[definition.key];
			else delete out[definition.key];
			continue;
		}
		const revisionValue = revision[definition.key], currentValue = current[definition.key];
		if (definition.type === "group" && revisionValue && typeof revisionValue === "object" && !Array.isArray(revisionValue)) {
			out[definition.key] = preservePasswordValues(definition.settings.fields, revisionValue, currentValue ?? {}, context);
			continue;
		}
		if (definition.type === "repeater" && Array.isArray(revisionValue)) {
			const fields = definition.settings.fields;
			const currentRows = Array.isArray(currentValue) ? currentValue : [];
			out[definition.key] = revisionValue.map((raw) => {
				const row = raw;
				const currentRow = currentRows.find((candidate) => candidate.rowId === row.rowId);
				return {
					...row,
					values: preservePasswordValues(fields, row.values, currentRow?.values ?? {}, context)
				};
			});
			continue;
		}
		if (definition.type === "flexible" && Array.isArray(revisionValue)) {
			const layouts = definition.settings.layouts;
			const currentRows = Array.isArray(currentValue) ? currentValue : [];
			out[definition.key] = revisionValue.map((raw) => {
				const row = raw;
				const layout = layouts.find((candidate) => candidate.key === row.layoutKey);
				if (!layout) throw new FieldsLifecycleError("integrity", "revision references unknown flexible layout");
				const currentRow = currentRows.find((candidate) => candidate.rowId === row.rowId);
				return {
					...row,
					values: preservePasswordValues(layout.fields, row.values, currentRow?.values ?? {}, context)
				};
			});
			continue;
		}
		if (definition.type === "clone" && revisionValue && typeof revisionValue === "object" && !Array.isArray(revisionValue)) {
			if (!context.cloneResolver) throw new FieldsLifecycleError("capability-unavailable", "clone resolver is required to restore clone values");
			out[definition.key] = preservePasswordValues(context.cloneResolver.resolve(definition), revisionValue, currentValue ?? {}, context);
		}
	}
	return out;
}
async function writeValueNodes(tx, ref, rows) {
	await tx.execute(sql`DELETE FROM field_value_nodes WHERE entity_type = ${ref.entityType} AND entity_id = ${ref.entityId}`);
	for (const row of rows) await tx.execute(sql`
      INSERT INTO field_value_nodes (
        node_id, entity_type, entity_id, group_key, definition_revision, field_key, path,
        parent_node_id, row_id, layout_key, node_kind, ordinal, is_null,
        value_text, value_number, value_boolean, value_date_time, value_ref, value_json,
        created_at, updated_at
      ) VALUES (
        ${row.nodeId}, ${row.entityType}, ${row.entityId}, ${row.groupKey}, ${row.definitionRevision},
        ${row.fieldKey}, ${row.path}, ${row.parentNodeId}, ${row.rowId}, ${row.layoutKey}, ${row.nodeKind},
        ${row.ordinal}, ${row.isNull}, ${row.valueText}, ${row.valueNumber}, ${row.valueBoolean},
        ${row.valueDateTime}, ${row.valueRef}, ${row.valueJson}, ${(/* @__PURE__ */ new Date()).toISOString()}, ${(/* @__PURE__ */ new Date()).toISOString()}
      )
    `);
}
async function writeBlockSnapshot(tx, ref, document, definitionVersions, parentRevisionId, principalId) {
	const current = await tx.execute(sql`
    SELECT version FROM field_block_documents
    WHERE entity_type = ${ref.entityType} AND entity_id = ${ref.entityId}
    LIMIT 1
  `);
	const version = Number(current[0]?.version ?? 0) + 1;
	await tx.execute(sql`
    INSERT INTO field_block_documents (
      entity_type, entity_id, version, document, definition_versions,
      parent_revision_id, updated_by, updated_at
    ) VALUES (
      ${ref.entityType}, ${ref.entityId}, ${version}, ${JSON.stringify(document)},
      ${JSON.stringify(definitionVersions)}, ${parentRevisionId}, ${principalId}, ${(/* @__PURE__ */ new Date()).toISOString()}
    )
    ON CONFLICT (entity_type, entity_id) DO UPDATE SET
      version = EXCLUDED.version,
      document = EXCLUDED.document,
      definition_versions = EXCLUDED.definition_versions,
      parent_revision_id = EXCLUDED.parent_revision_id,
      updated_by = EXCLUDED.updated_by,
      updated_at = EXCLUDED.updated_at
  `);
}
async function restoreFieldsRevision(tx, ref, revisionId, mutation, context) {
	assertActiveFieldsTransaction(tx, mutation.expectedTransactionIdentity);
	const authorized = await assertFieldsAuthorized(context, "write", ref);
	const source = await requireRevision(tx, ref, revisionId);
	const current = await snapshotEntity(tx, ref, context);
	if (current.version !== mutation.expectedVersion) throw new FieldsLifecycleError("stale-version", "current fields version changed");
	const requestHash = await fieldsRequestHash({
		ref,
		revisionId,
		expectedVersion: mutation.expectedVersion,
		parentRevisionId: mutation.parentRevisionId
	});
	const existing = await readFieldsReceipt(tx, mutation.operationId);
	if (existing) {
		assertReceiptReplay(existing, {
			kind: "fields:restore-revision",
			context: authorized,
			requestHash
		});
		const result = record$1(existing.result, "restore receipt");
		if (typeof result.version !== "string" || typeof result.revisionId !== "string") throw new FieldsLifecycleError("integrity", "restore receipt is malformed");
		return Object.freeze({
			version: result.version,
			revision: await requireRevision(tx, ref, result.revisionId)
		});
	}
	const nodes = [];
	for (const [groupKey, definitionRevision] of Object.entries(source.definitionVersions).sort(([left], [right]) => left.localeCompare(right))) {
		const definition = await resolveFieldDefinitionVersion(tx, groupKey, definitionRevision);
		const revisionValues = record$1(source.values[groupKey] ?? {}, `revision.values.${groupKey}`);
		const currentValues = record$1(current.values[groupKey] ?? {}, `current.values.${groupKey}`);
		const restoredValues = preservePasswordValues(definition.definition.fields, revisionValues, currentValues, context);
		const ids = /* @__PURE__ */ new Map();
		const nodeIdForPath = (path) => {
			let id = ids.get(path);
			if (!id) {
				id = crypto.randomUUID();
				ids.set(path, id);
			}
			return id;
		};
		nodes.push(...encodeFieldValueNodes(definition.definition, restoredValues, {
			entityType: ref.entityType,
			entityId: ref.entityId,
			definitionRevision,
			nodeIdForPath,
			...context.cloneResolver ? { cloneResolver: { resolve: (field) => context.cloneResolver.resolve(field) } } : {}
		}));
	}
	await writeValueNodes(tx, ref, nodes);
	if (source.blockDocument) await writeBlockSnapshot(tx, ref, source.blockDocument, source.definitionVersions, mutation.parentRevisionId, authorized.principal.id);
	const restored = await snapshotEntity(tx, ref, context);
	const restoreRevision = await insertRevision(tx, {
		id: crypto.randomUUID(),
		ref,
		parentRevisionId: mutation.parentRevisionId,
		kind: "revision",
		snapshot: restored,
		createdBy: authorized.principal.id
	});
	await writeFieldsReceipt(tx, {
		operationId: mutation.operationId,
		kind: "fields:restore-revision",
		context: authorized,
		requestHash,
		result: storage({
			version: restored.version,
			revisionId: restoreRevision.id
		})
	});
	return Object.freeze({
		version: restored.version,
		revision: restoreRevision
	});
}
var IMPORT_SESSION_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
function importSessionId(value) {
	const id = boundedString(value, "staging.hostSessionId", 128);
	if (!IMPORT_SESSION_UUID_RE.test(id)) fail("validation", "staging.hostSessionId must be a UUID");
	return id;
}
var FieldsImportError = class extends Error {
	code;
	field;
	name = "FieldsImportError";
	constructor(code, message, field) {
		super(message);
		this.code = code;
		this.field = field;
	}
};
var SECTIONS = Object.freeze([
	"definitions",
	"optionsPages",
	"blocks",
	"entities",
	"revisions",
	"options",
	"blockDocuments"
]);
/** D1 permits 100 bound parameters per statement. Corpus guards repeat the scope in three subqueries. */
var MAX_IMPORT_SCOPE_ENTITY_TYPES = 24;
/** Leave 100 of D1's 1,000 batch statements for host-owned effects and sibling contributions. */
var MAX_D1_IMPORT_CONTRIBUTION_ITEMS = 900;
var DEFAULT_IMPORT_LIMITS = Object.freeze({
	maxBytes: 8388608,
	maxDefinitions: 2e3,
	maxEntities: 1e4,
	maxRevisions: 2e4,
	maxBlockNodes: 2e4,
	maxDepth: 24
});
function boundedD1Contribution(items, result) {
	if (items.length > MAX_D1_IMPORT_CONTRIBUTION_ITEMS) fail("limit", `D1 import contribution exceeds ${MAX_D1_IMPORT_CONTRIBUTION_ITEMS} statements`, "contribution.items");
	return Object.freeze({
		items,
		result
	});
}
function fail(code, detail, field) {
	throw new FieldsImportError(code === "stale-version" ? "stale-plan" : code, detail, field);
}
function isImportUniqueViolation(error) {
	let current = error;
	while (current) {
		const code = current.code, message = current instanceof Error ? current.message : String(current);
		if (code === "23505" || /unique constraint|duplicate key|fields_import_journal_session_uq/i.test(message)) return true;
		current = current instanceof Error ? current.cause : void 0;
	}
	return false;
}
function plain$2(value, field) {
	if (typeof value !== "object" || value === null || Array.isArray(value) || Object.getPrototypeOf(value) !== Object.prototype) fail("validation", `${field} must be a plain object`);
	return value;
}
function boundedString(value, field, max = 4096) {
	if (typeof value !== "string" || value.length === 0 || value.length > max) fail("validation", `${field} must be a bounded non-empty string`);
	return value;
}
function positive$2(value, field) {
	const n = Number(value);
	if (!Number.isSafeInteger(n) || n < 1) fail("validation", `${field} must be a positive safe integer`);
	return n;
}
function array(value, field, max) {
	if (!Array.isArray(value) || value.length > max) fail("validation", `${field} must be a bounded array`);
	return value;
}
function jsonStorage(value, field = "value", depth = 0, budget = {
	nodes: 0,
	bytes: 0
}) {
	if (depth > 64 || ++budget.nodes > 1e5) fail("validation", `${field} exceeds structural bounds`);
	if (value === null || typeof value === "boolean") return value;
	if (typeof value === "number") {
		if (!Number.isFinite(value)) fail("validation", `${field} contains non-finite number`);
		budget.bytes += 8;
		return value;
	}
	if (typeof value === "string") {
		budget.bytes += new TextEncoder().encode(value).byteLength;
		if (budget.bytes > 16777216) fail("validation", `${field} exceeds byte bounds`);
		return value;
	}
	if (Array.isArray(value)) return Object.freeze(value.map((item, index) => jsonStorage(item, `${field}.${index}`, depth + 1, budget)));
	const source = plain$2(value, field), out = {};
	for (const key of Object.keys(source).sort()) {
		if (key === "__proto__" || key === "constructor" || key === "prototype") fail("validation", `${field} contains forbidden key`);
		out[key] = jsonStorage(source[key], `${field}.${key}`, depth + 1, budget);
	}
	return Object.freeze(out);
}
function preflight(value, limits, depth = 0, budget = { nodes: 0 }) {
	if (depth > limits.maxDepth) fail("validation", "manifest exceeds maximum depth");
	if (value === null || [
		"string",
		"number",
		"boolean"
	].includes(typeof value)) return;
	if (typeof value !== "object" || value === null) fail("validation", "manifest contains unsupported value");
	if (++budget.nodes > Math.max(1e3, limits.maxDefinitions * 20 + limits.maxEntities * 20 + limits.maxRevisions * 10 + limits.maxBlockNodes * 10)) fail("validation", "manifest exceeds node budget");
	if (Array.isArray(value)) {
		for (const child of value) preflight(child, limits, depth + 1, budget);
		return;
	}
	if (Object.getPrototypeOf(value) !== Object.prototype) fail("validation", "manifest must contain plain JSON objects");
	for (const [key, child] of Object.entries(value)) {
		if (key === "__proto__" || key === "constructor" || key === "prototype") fail("validation", "manifest contains forbidden key");
		preflight(child, limits, depth + 1, budget);
	}
}
function ref(value, field) {
	const row = plain$2(value, field);
	return Object.freeze({
		entityType: boundedString(row.entityType, `${field}.entityType`, 256),
		entityId: boundedString(row.entityId, `${field}.entityId`, 512)
	});
}
function revisionsMap(value, field) {
	const row = plain$2(value, field), out = {};
	for (const [key, v] of Object.entries(row)) out[boundedString(key, field, 256)] = positive$2(v, `${field}.${key}`);
	return Object.freeze(out);
}
function fieldPath$1(value, field) {
	const parts = array(value, field, 64);
	if (parts.length === 0) fail("validation", `${field} must not be empty`);
	return Object.freeze(parts.map((item, index) => typeof item === "number" && Number.isSafeInteger(item) && item >= 0 ? item : boundedString(item, `${field}.${index}`, 256)));
}
function dateString(value, field) {
	const raw = boundedString(value, field, 128), date = new Date(raw);
	if (Number.isNaN(date.getTime())) fail("validation", `${field} must be an ISO timestamp`);
	return date.toISOString();
}
function sanitizeCustomChildren(value, registry) {
	const row = plain$2(value, "field"), type = boundedString(row.type, "field.type", 256), copy = { ...row };
	if (!registry.has(type)) fail("validation", `unregistered field type ${type}`, "field.type");
	const settings = typeof row.settings === "object" && row.settings !== null && !Array.isArray(row.settings) ? { ...row.settings } : row.settings;
	if (type === "group" || type === "repeater") {
		const s = plain$2(settings, "field.settings");
		copy.settings = {
			...s,
			fields: array(s.fields, "field.settings.fields", 1e3).map((child) => sanitizeCustomChildren(child, registry))
		};
	} else if (type === "flexible") {
		const s = plain$2(settings, "field.settings");
		copy.settings = {
			...s,
			layouts: array(s.layouts, "field.settings.layouts", 1e3).map((layout) => {
				const l = plain$2(layout, "layout");
				return {
					...l,
					fields: array(l.fields, "layout.fields", 1e3).map((child) => sanitizeCustomChildren(child, registry))
				};
			})
		};
	}
	if (!registry.builtInTypes.has(type)) return {
		...copy,
		type: "text",
		settings: {}
	};
	return copy;
}
function validateFieldTree$2(value, registry, depth = 0) {
	if (depth > 12) fail("validation", "field definition nesting exceeds maximum depth");
	const raw = plain$2(value, "field"), type = boundedString(raw.type, "field.type", 256), descriptor = registry.resolve(type);
	if (!descriptor) fail("validation", `unregistered field type ${type}`, "field.type");
	if (descriptor.parseDefinition(registry.builtInTypes.has(type) ? sanitizeCustomChildren(raw, registry) : raw, FIELD_DEFINITION_LIMITS).type !== type) fail("validation", "field descriptor changed type identity");
	const settings = raw.settings;
	if (type === "group" || type === "repeater") for (const child of array(plain$2(settings, "field.settings").fields, "field.settings.fields", 1e3)) validateFieldTree$2(child, registry, depth + 1);
	if (type === "flexible") for (const layout of array(plain$2(settings, "field.settings").layouts, "field.settings.layouts", 1e3)) for (const child of array(plain$2(layout, "layout").fields, "layout.fields", 1e3)) validateFieldTree$2(child, registry, depth + 1);
	if (!registry.builtInTypes.has(type)) registry.parseDefinition(raw, FIELD_DEFINITION_LIMITS);
	return Object.freeze({ ...raw });
}
function parseImportGroup(value, registry) {
	const raw = plain$2(value, "group"), fields = array(raw.fields, "group.fields", 1e3);
	for (const field of fields) validateFieldTree$2(field, registry);
	const validated = parseFieldGroupDefinition({
		...raw,
		fields: fields.map((field) => sanitizeCustomChildren(field, registry))
	});
	return Object.freeze({
		...validated,
		fields: Object.freeze(fields.map((field) => Object.freeze({ ...plain$2(field, "field") })))
	});
}
function assertNoPasswordValue(group, value, field) {
	const map = plain$2(value, field);
	const walk = (definitions, source, path) => {
		for (const definition of definitions) {
			if (definition.type === "password" && Object.prototype.hasOwnProperty.call(source, definition.key)) fail("validation", `imported password value is forbidden at ${path}.${definition.key}`);
			const child = source[definition.key];
			if (child === void 0) continue;
			if (definition.type === "group" && typeof child === "object" && child !== null && !Array.isArray(child)) walk(definition.settings.fields, child, `${path}.${definition.key}`);
			if (definition.type === "repeater" && Array.isArray(child)) for (const [index, row] of child.entries()) {
				const r = plain$2(row, `${path}.${definition.key}.${index}`);
				if (r.values && typeof r.values === "object") walk(definition.settings.fields, r.values, `${path}.${definition.key}.${index}`);
			}
			if (definition.type === "flexible" && Array.isArray(child)) for (const [index, row] of child.entries()) {
				const r = plain$2(row, `${path}.${definition.key}.${index}`), layout = definition.settings.layouts.find((item) => item.key === r.layoutKey);
				if (layout && r.values && typeof r.values === "object") walk(layout.fields, r.values, `${path}.${definition.key}.${index}`);
			}
		}
	};
	walk(group.fields, map, field);
}
function entityValues(value, field, groups) {
	const source = plain$2(value, field), out = {};
	for (const [groupKey, raw] of Object.entries(source)) {
		const group = groups.get(groupKey);
		if (!group) fail("validation", `${field} references unknown group ${groupKey}`);
		assertNoPasswordValue(group, raw, `${field}.${groupKey}`);
		out[groupKey] = Object.freeze({ ...plain$2(raw, `${field}.${groupKey}`) });
	}
	return Object.freeze(out);
}
function countBlockNodes(document) {
	let count = 0;
	const walk = (nodes, depth = 0) => {
		if (depth > 64) fail("validation", "block document exceeds parser depth");
		for (const node of nodes) {
			count++;
			if (node.kind === "inline" && node.children) walk(node.children, depth + 1);
		}
	};
	walk(document.roots);
	return count;
}
function blockDocument(value, limits, field) {
	const document = parseBlockDocument(JSON.stringify(jsonStorage(value, field)), {
		...DEFAULT_BLOCK_POLICY,
		maxBytes: Math.min(DEFAULT_BLOCK_POLICY.maxBytes, limits.maxBytes),
		maxNodes: limits.maxBlockNodes,
		maxDepth: Math.min(DEFAULT_BLOCK_POLICY.maxDepth, limits.maxDepth)
	});
	if (countBlockNodes(document) > limits.maxBlockNodes) fail("validation", `${field} exceeds block node limit`);
	return document;
}
function sourceKey(refValue) {
	return `${refValue.entityType}:${refValue.entityId}`;
}
async function parseFieldsImport(input, limitsInput, registry) {
	const limits = {
		...DEFAULT_IMPORT_LIMITS,
		...limitsInput
	};
	for (const [name, value] of Object.entries(limits)) if (!Number.isSafeInteger(value) || value < 1) fail("validation", `limits.${name} must be a positive safe integer`);
	if (input.byteLength > limits.maxBytes) fail("validation", "import exceeds maximum byte size");
	let text;
	try {
		text = new TextDecoder("utf-8", { fatal: true }).decode(input);
	} catch {
		fail("validation", "import is not valid UTF-8");
	}
	let raw;
	try {
		raw = JSON.parse(text);
	} catch {
		fail("validation", "import is not valid JSON");
	}
	preflight(raw, limits);
	const root = plain$2(raw, "manifest");
	if (root.version !== 1) fail("validation", "manifest.version must be 1");
	const definitions = plain$2(root.definitions, "manifest.definitions");
	const groupRows = array(definitions.groups, "manifest.definitions.groups", limits.maxDefinitions);
	const groups = [], groupByKey = /* @__PURE__ */ new Map();
	for (const item of groupRows) {
		const group = parseImportGroup(item, registry);
		if (groupByKey.has(group.key)) fail("validation", `duplicate group key ${group.key}`);
		groupByKey.set(group.key, group);
		groups.push(group);
	}
	const versionRows = array(definitions.versions, "manifest.definitions.versions", limits.maxDefinitions);
	const versions = [], versionIds = /* @__PURE__ */ new Set();
	for (const [index, item] of versionRows.entries()) {
		const row = plain$2(item, `definitions.versions.${index}`), definition = parseImportGroup(row.definition, registry), groupKey = boundedString(row.groupKey, `definitions.versions.${index}.groupKey`, 128), revision = positive$2(row.revision, `definitions.versions.${index}.revision`), canonicalHash = boundedString(row.canonicalHash, `definitions.versions.${index}.canonicalHash`, 128), origin = row.origin;
		if (definition.key !== groupKey || ![
			"code",
			"db",
			"import"
		].includes(String(origin))) fail("validation", "definition version identity is invalid");
		if (await canonicalFieldGroupHash(definition) !== canonicalHash) fail("validation", `definition version hash mismatch for ${groupKey}@${revision}`);
		const id = `${groupKey}@${revision}`;
		if (versionIds.has(id)) fail("validation", `duplicate definition version ${id}`);
		versionIds.add(id);
		versions.push(Object.freeze({
			groupKey,
			revision,
			canonicalHash,
			definition,
			createdAt: dateString(row.createdAt, `definitions.versions.${index}.createdAt`),
			origin
		}));
	}
	for (const group of groups) {
		const candidates = versions.filter((version) => version.groupKey === group.key);
		if (candidates.length === 0) fail("validation", `group ${group.key} has no immutable definition version`);
		const currentHash = await canonicalFieldGroupHash(group);
		if (!candidates.some((version) => version.canonicalHash === currentHash)) fail("validation", `group ${group.key} current bytes are absent from immutable versions`);
	}
	const optionRows = array(definitions.optionsPages, "manifest.definitions.optionsPages", limits.maxDefinitions);
	const optionsPages = [], optionKeys = /* @__PURE__ */ new Set();
	for (const item of optionRows) {
		const page = __optionsLifecycleInternals.normalizeOptionsPage(item);
		if (optionKeys.has(page.key)) fail("validation", `duplicate options page ${page.key}`);
		optionKeys.add(page.key);
		optionsPages.push(page);
	}
	for (const page of optionsPages) if (page.parentKey && !optionKeys.has(page.parentKey)) fail("validation", `options page ${page.key} references missing parent ${page.parentKey}`);
	const blockRows = array(definitions.blocks, "manifest.definitions.blocks", limits.maxDefinitions);
	const blocks = [], blockKeys = /* @__PURE__ */ new Set();
	for (const item of blockRows) {
		const block = __fieldBlockLifecycleInternals.normalizeDefinition(item);
		if (blockKeys.has(block.key)) fail("validation", `duplicate block ${block.key}`);
		for (const groupKey of block.fieldGroupKeys) if (!groupByKey.has(groupKey)) fail("validation", `block ${block.key} references missing group ${groupKey}`);
		blockKeys.add(block.key);
		blocks.push(block);
	}
	const blockVersionRows = array(definitions.blockVersions, "manifest.definitions.blockVersions", limits.maxDefinitions);
	const blockVersions = [], blockVersionIds = /* @__PURE__ */ new Set();
	for (const [index, item] of blockVersionRows.entries()) {
		const row = plain$2(item, `definitions.blockVersions.${index}`), definition = __fieldBlockLifecycleInternals.normalizeDefinition(row.definition), blockKey = boundedString(row.blockKey, `definitions.blockVersions.${index}.blockKey`, 128), revision = positive$2(row.revision, `definitions.blockVersions.${index}.revision`), canonicalHash = boundedString(row.canonicalHash, `definitions.blockVersions.${index}.canonicalHash`, 128), origin = row.origin;
		if (definition.key !== blockKey || ![
			"code",
			"db",
			"import"
		].includes(String(origin))) fail("validation", "block definition version identity is invalid");
		if (await fieldsRequestHash(definition) !== canonicalHash) fail("validation", `block definition version hash mismatch for ${blockKey}@${revision}`);
		const id = `${blockKey}@${revision}`;
		if (blockVersionIds.has(id)) fail("validation", `duplicate block definition version ${id}`);
		blockVersionIds.add(id);
		blockVersions.push(Object.freeze({
			blockKey,
			revision,
			canonicalHash,
			definition,
			createdAt: dateString(row.createdAt, `definitions.blockVersions.${index}.createdAt`),
			origin
		}));
	}
	for (const block of blocks) {
		const candidates = blockVersions.filter((version) => version.blockKey === block.key);
		if (candidates.length === 0) fail("validation", `block ${block.key} has no immutable definition version`);
		const currentHash = await fieldsRequestHash(block);
		if (!candidates.some((version) => version.canonicalHash === currentHash)) fail("validation", `block ${block.key} current bytes are absent from immutable versions`);
	}
	const entityRows = array(root.entities ?? [], "manifest.entities", limits.maxEntities), entities = [], entityKeys = /* @__PURE__ */ new Set();
	for (const [index, item] of entityRows.entries()) {
		const row = plain$2(item, `entities.${index}`), sourceRef = ref(row.sourceRef, `entities.${index}.sourceRef`), definitionVersions = revisionsMap(row.definitionVersions, `entities.${index}.definitionVersions`), pinned = /* @__PURE__ */ new Map();
		for (const [groupKey, revision] of Object.entries(definitionVersions)) {
			const version = versions.find((candidate) => candidate.groupKey === groupKey && candidate.revision === revision);
			if (!version) fail("validation", `entity references missing definition ${groupKey}@${revision}`);
			pinned.set(groupKey, version.definition);
		}
		const key = sourceKey(sourceRef);
		if (entityKeys.has(key)) fail("validation", `duplicate entity ${key}`);
		entityKeys.add(key);
		entities.push(Object.freeze({
			sourceRef,
			values: entityValues(row.values, `entities.${index}.values`, pinned),
			definitionVersions
		}));
	}
	const revisionRows = array(root.revisions ?? [], "manifest.revisions", limits.maxRevisions), revisions = [], revisionKeys = /* @__PURE__ */ new Set();
	for (const [index, item] of revisionRows.entries()) {
		const row = plain$2(item, `revisions.${index}`), sourceRevisionKey = boundedString(row.sourceRevisionKey, `revisions.${index}.sourceRevisionKey`, 512), sourceRef = ref(row.sourceRef, `revisions.${index}.sourceRef`), definitionVersions = revisionsMap(row.definitionVersions, `revisions.${index}.definitionVersions`), pinned = /* @__PURE__ */ new Map();
		if (revisionKeys.has(sourceRevisionKey)) fail("validation", `duplicate revision ${sourceRevisionKey}`);
		revisionKeys.add(sourceRevisionKey);
		for (const [groupKey, revision] of Object.entries(definitionVersions)) {
			const version = versions.find((candidate) => candidate.groupKey === groupKey && candidate.revision === revision);
			if (!version) fail("validation", `revision references missing definition ${groupKey}@${revision}`);
			pinned.set(groupKey, version.definition);
		}
		const block = row.blockDocument === void 0 ? void 0 : blockDocument(row.blockDocument, limits, `revisions.${index}.blockDocument`);
		revisions.push(Object.freeze({
			sourceRevisionKey,
			sourceRef,
			parentRevisionKey: boundedString(row.parentRevisionKey, `revisions.${index}.parentRevisionKey`, 512),
			definitionVersions,
			values: entityValues(row.values, `revisions.${index}.values`, pinned),
			...block ? { blockDocument: block } : {},
			createdAt: dateString(row.createdAt, `revisions.${index}.createdAt`),
			createdBySourceId: boundedString(row.createdBySourceId, `revisions.${index}.createdBySourceId`, 512),
			sourceVersion: positive$2(row.sourceVersion, `revisions.${index}.sourceVersion`)
		}));
	}
	const optionsRows = array(root.options ?? [], "manifest.options", limits.maxEntities), options = [], optionValueKeys = /* @__PURE__ */ new Set();
	for (const [index, item] of optionsRows.entries()) {
		const row = plain$2(item, `options.${index}`), pageKey = boundedString(row.pageKey, `options.${index}.pageKey`, 128), definitionVersions = revisionsMap(row.definitionVersions, `options.${index}.definitionVersions`), pinned = /* @__PURE__ */ new Map();
		if (optionValueKeys.has(pageKey) || !optionKeys.has(pageKey)) fail("validation", `invalid or duplicate options values page ${pageKey}`);
		optionValueKeys.add(pageKey);
		for (const [groupKey, revision] of Object.entries(definitionVersions)) {
			const version = versions.find((candidate) => candidate.groupKey === groupKey && candidate.revision === revision);
			if (!version) fail("validation", `options values reference missing definition ${groupKey}@${revision}`);
			pinned.set(groupKey, version.definition);
		}
		options.push(Object.freeze({
			pageKey,
			values: entityValues(row.values, `options.${index}.values`, pinned),
			definitionVersions,
			revision: positive$2(row.revision, `options.${index}.revision`)
		}));
	}
	const blockDocumentRows = array(root.blockDocuments ?? [], "manifest.blockDocuments", limits.maxEntities), blockDocuments = [], blockDocumentKeys = /* @__PURE__ */ new Set(), blockBudget = { nodes: 0 };
	for (const [index, item] of blockDocumentRows.entries()) {
		const row = plain$2(item, `blockDocuments.${index}`), sourceRef = ref(row.sourceRef, `blockDocuments.${index}.sourceRef`), document = blockDocument(row.document, limits, `blockDocuments.${index}.document`), definitionVersions = revisionsMap(row.definitionVersions, `blockDocuments.${index}.definitionVersions`), key = sourceKey(sourceRef);
		if (blockDocumentKeys.has(key)) fail("validation", `duplicate block document ${key}`);
		blockDocumentKeys.add(key);
		blockBudget.nodes += countBlockNodes(document);
		if (blockBudget.nodes > limits.maxBlockNodes) fail("validation", "manifest exceeds total block node limit");
		blockDocuments.push(Object.freeze({
			sourceRef,
			document,
			version: boundedString(row.version, `blockDocuments.${index}.version`, 128),
			definitionVersions
		}));
	}
	const omissionRows = array(root.omissions ?? [], "manifest.omissions", limits.maxEntities + limits.maxRevisions), omissions = [];
	for (const [index, item] of omissionRows.entries()) {
		const row = plain$2(item, `omissions.${index}`), reason = row.reason;
		if (reason !== "sensitive" && reason !== "unauthorized") fail("validation", "omission reason is invalid");
		omissions.push(Object.freeze({
			sourceRef: ref(row.sourceRef, `omissions.${index}.sourceRef`),
			fieldPath: fieldPath$1(row.fieldPath, `omissions.${index}.fieldPath`),
			reason
		}));
	}
	const normalized = Object.freeze({
		version: 1,
		definitions: Object.freeze({
			groups: Object.freeze(groups),
			versions: Object.freeze(versions),
			optionsPages: Object.freeze(optionsPages),
			blocks: Object.freeze(blocks),
			blockVersions: Object.freeze(blockVersions)
		}),
		...entities.length ? { entities: Object.freeze(entities) } : {},
		...revisions.length ? { revisions: Object.freeze(revisions) } : {},
		...options.length ? { options: Object.freeze(options) } : {},
		...blockDocuments.length ? { blockDocuments: Object.freeze(blockDocuments) } : {},
		omissions: Object.freeze(omissions)
	});
	return Object.freeze({
		manifestHash: await fieldsRequestHash(normalized),
		registryVersion: registry.version,
		manifest: normalized
	});
}
function rowsOf$2(value) {
	if (Array.isArray(value)) return value;
	if (typeof value === "object" && value !== null && Array.isArray(value.rows)) return value.rows;
	throw new FieldsLifecycleError("integrity", "database adapter returned invalid rows");
}
async function execRows(db, query) {
	return rowsOf$2(await db.execute(query));
}
function d1Items(first, ...rest) {
	return Object.freeze([first, ...rest]);
}
function normalizeScope(scope) {
	const tenantKey = boundedString(scope.tenantKey, "scope.tenantKey", 256), types = [...scope.entityTypes];
	if (types.length === 0 || types.length > 256) fail("validation", "scope.entityTypes must be bounded and non-empty", "scope.entityTypes");
	const normalized = types.map((type, index) => boundedString(type, `scope.entityTypes.${index}`, 256)).sort();
	if (new Set(normalized).size !== normalized.length) fail("validation", "scope.entityTypes contains duplicates");
	return Object.freeze({
		tenantKey,
		entityTypes: Object.freeze(normalized)
	});
}
function assertD1Scope(scope) {
	const normalized = normalizeScope(scope);
	if (normalized.entityTypes.length > MAX_IMPORT_SCOPE_ENTITY_TYPES) fail("limit", `native D1 import scope requires ${normalized.entityTypes.length} entity types; maximum is ${MAX_IMPORT_SCOPE_ENTITY_TYPES}`, "scope.entityTypes");
	return normalized;
}
async function assertScopeAuthorized(context, scope) {
	await assertFieldsAuthorized(context, "manageDefinitions", {
		entityType: "fields-import-scope",
		entityId: scope.tenantKey
	});
	const migration = await assertDefinitionMigration(context, scope.entityTypes);
	for (const entityType of scope.entityTypes) await assertFieldsAuthorized(context, "write", {
		entityType,
		entityId: "*"
	});
	return migration.policyVersion;
}
async function assertCodeRegistry$1(codeRegistry) {
	if (await fieldsRequestHash({
		version: codeRegistry.version,
		groups: codeRegistry.groups,
		optionsPages: codeRegistry.optionsPages,
		blocks: codeRegistry.blocks
	}) !== codeRegistry.canonicalHash) fail("validation", "code registry canonical hash mismatch");
}
function mappingKey(kind, value) {
	return `${kind}:${value}`;
}
function hashUuid(hex) {
	const clean = hex.slice(0, 32).padEnd(32, "0").split("");
	clean[12] = "4";
	clean[16] = [
		"8",
		"9",
		"a",
		"b"
	][Number.parseInt(clean[16] ?? "0", 16) % 4];
	const value = clean.join("");
	return `${value.slice(0, 8)}-${value.slice(8, 12)}-${value.slice(12, 16)}-${value.slice(16, 20)}-${value.slice(20, 32)}`;
}
async function deterministicRevisionId(manifestHash, sourceRevisionKey) {
	return hashUuid(await fieldsRequestHash({
		kind: "fields-import-revision",
		manifestHash,
		sourceRevisionKey
	}));
}
async function remapFieldMap(group, input, remappers, mappings, conflicts, sourceKeyValue) {
	const out = { ...input };
	const remapFields = async (definitions, source, target, path) => {
		for (const definition of definitions) {
			const value = source[definition.key];
			if (value === void 0) continue;
			const fieldPathValue = `${path}.${definition.key}`;
			if (definition.type === "password") fail("validation", `password import is forbidden at ${fieldPathValue}`);
			if (definition.type === "group" && value && typeof value === "object" && !Array.isArray(value)) {
				const child = { ...value };
				await remapFields(definition.settings.fields, value, child, fieldPathValue);
				target[definition.key] = Object.freeze(child);
				continue;
			}
			if (definition.type === "repeater" && Array.isArray(value)) {
				const rows = [];
				for (const [index, rowRaw] of value.entries()) {
					const row = plain$2(rowRaw, `${fieldPathValue}.${index}`), values = plain$2(row.values, `${fieldPathValue}.${index}.values`), mapped = { ...values };
					await remapFields(definition.settings.fields, values, mapped, `${fieldPathValue}.${index}.values`);
					rows.push(Object.freeze({
						...row,
						values: Object.freeze(mapped)
					}));
				}
				target[definition.key] = Object.freeze(rows);
				continue;
			}
			if (definition.type === "flexible" && Array.isArray(value)) {
				const rows = [];
				for (const [index, rowRaw] of value.entries()) {
					const row = plain$2(rowRaw, `${fieldPathValue}.${index}`), layout = definition.settings.layouts.find((item) => item.key === row.layoutKey);
					if (!layout) fail("validation", `unknown flexible layout at ${fieldPathValue}.${index}`);
					const values = plain$2(row.values, `${fieldPathValue}.${index}.values`), mapped = { ...values };
					await remapFields(layout.fields, values, mapped, `${fieldPathValue}.${index}.values`);
					rows.push(Object.freeze({
						...row,
						values: Object.freeze(mapped)
					}));
				}
				target[definition.key] = Object.freeze(rows);
				continue;
			}
			if (definition.type === "clone") continue;
			if (definition.type === "entity" || definition.type === "entityLink") {
				if (value === null) {
					target[definition.key] = null;
					continue;
				}
				const sourceRef = ref(value, fieldPathValue), mapped = await remappers.entity(sourceRef);
				if (!mapped) {
					conflicts.push(Object.freeze({
						section: "entities",
						sourceKey: sourceKeyValue,
						kind: "missingDependency"
					}));
					continue;
				}
				mappings[mappingKey("entity", sourceKey(sourceRef))] = sourceKey(mapped);
				target[definition.key] = mapped;
				continue;
			}
			if (definition.type === "relationship") {
				if (!Array.isArray(value)) fail("validation", `${fieldPathValue} must be an array`);
				const mappedValues = [];
				for (const item of value) {
					const sourceRef = ref(item, fieldPathValue), mapped = await remappers.entity(sourceRef);
					if (!mapped) {
						conflicts.push(Object.freeze({
							section: "entities",
							sourceKey: sourceKeyValue,
							kind: "missingDependency"
						}));
						continue;
					}
					mappings[mappingKey("entity", sourceKey(sourceRef))] = sourceKey(mapped);
					mappedValues.push(mapped);
				}
				target[definition.key] = Object.freeze(mappedValues);
				continue;
			}
			if (definition.type === "image" || definition.type === "file") {
				if (value === null) {
					target[definition.key] = null;
					continue;
				}
				const media = plain$2(value, fieldPathValue), mapped = await remappers.media(media);
				if (!mapped) {
					conflicts.push(Object.freeze({
						section: "entities",
						sourceKey: sourceKeyValue,
						kind: "missingDependency"
					}));
					continue;
				}
				mappings[mappingKey("media", media.id)] = mapped.id;
				target[definition.key] = mapped;
				continue;
			}
			if (definition.type === "gallery") {
				if (!Array.isArray(value)) fail("validation", `${fieldPathValue} must be an array`);
				const mappedValues = [];
				for (const item of value) {
					const media = plain$2(item, fieldPathValue), mapped = await remappers.media(media);
					if (!mapped) {
						conflicts.push(Object.freeze({
							section: "entities",
							sourceKey: sourceKeyValue,
							kind: "missingDependency"
						}));
						continue;
					}
					mappings[mappingKey("media", media.id)] = mapped.id;
					mappedValues.push(mapped);
				}
				target[definition.key] = Object.freeze(mappedValues);
				continue;
			}
			if (definition.type === "taxonomy") {
				if (value === null) {
					target[definition.key] = null;
					continue;
				}
				const items = Array.isArray(value) ? value : [value], mappedValues = [];
				for (const item of items) {
					const term = plain$2(item, fieldPathValue), mapped = await remappers.term(term);
					if (!mapped) {
						conflicts.push(Object.freeze({
							section: "entities",
							sourceKey: sourceKeyValue,
							kind: "missingDependency"
						}));
						continue;
					}
					mappings[mappingKey("term", `${term.taxonomy}:${term.id}`)] = `${mapped.taxonomy}:${mapped.id}`;
					mappedValues.push(mapped);
				}
				target[definition.key] = Array.isArray(value) ? Object.freeze(mappedValues) : mappedValues[0] ?? null;
				continue;
			}
			if (definition.type === "user") {
				if (value === null) {
					target[definition.key] = null;
					continue;
				}
				const items = Array.isArray(value) ? value : [value], mappedValues = [];
				for (const item of items) {
					const id = boundedString(plain$2(item, fieldPathValue).id, `${fieldPathValue}.id`, 512), mapped = await remappers.user(id);
					if (!mapped) {
						conflicts.push(Object.freeze({
							section: "entities",
							sourceKey: sourceKeyValue,
							kind: "missingDependency"
						}));
						continue;
					}
					mappings[mappingKey("user", id)] = mapped;
					mappedValues.push(Object.freeze({ id: mapped }));
				}
				target[definition.key] = Array.isArray(value) ? Object.freeze(mappedValues) : mappedValues[0] ?? null;
				continue;
			}
		}
	};
	await remapFields(group.fields, input, out, group.key);
	return Object.freeze(out);
}
async function remapEntityValues(values, versions, manifest, remappers, mappings, conflicts, sourceKeyValue) {
	const out = {};
	for (const [groupKey, map] of Object.entries(values)) {
		const revision = versions[groupKey];
		if (!revision) fail("validation", `missing pinned version for ${groupKey}`);
		const definition = manifest.definitions.versions.find((item) => item.groupKey === groupKey && item.revision === revision)?.definition;
		if (!definition) fail("integrity", `missing manifest definition ${groupKey}@${revision}`);
		out[groupKey] = await remapFieldMap(definition, map, remappers, mappings, conflicts, sourceKeyValue);
	}
	return Object.freeze(out);
}
async function remapBlockReusableIds(document, remappers, mappings, conflicts, sourceKeyValue) {
	const walk = async (nodes) => Object.freeze(await Promise.all(nodes.map(async (node) => {
		if (node.kind === "reusable") {
			const mapped = await remappers.reusableBlock(node.reusableId);
			if (!mapped) {
				conflicts.push(Object.freeze({
					section: "blockDocuments",
					sourceKey: sourceKeyValue,
					kind: "missingDependency"
				}));
				return node;
			}
			mappings[mappingKey("reusable", node.reusableId)] = mapped;
			return Object.freeze({
				...node,
				reusableId: mapped
			});
		}
		return Object.freeze({
			...node,
			...node.children ? { children: await walk(node.children) } : {}
		});
	})));
	return Object.freeze({
		version: 1,
		roots: await walk(document.roots)
	});
}
function corpusJson(value, field) {
	if (typeof value !== "string") return snapshotStorage(value, field);
	try {
		return snapshotStorage(JSON.parse(value), field);
	} catch {
		return fail("integrity", `${field} contains invalid JSON`);
	}
}
function storedJsonText(value, field) {
	if (typeof value === "string") {
		corpusJson(value, field);
		return value;
	}
	return JSON.stringify(snapshotStorage(value, field));
}
function corpusDate(value, field) {
	const date = value instanceof Date ? value : new Date(String(value));
	if (Number.isNaN(date.getTime())) return fail("integrity", `${field} contains an invalid timestamp`);
	return date.toISOString();
}
function corpusInteger(value, field) {
	const number = Number(value);
	if (!Number.isSafeInteger(number)) return fail("integrity", `${field} contains an invalid integer`);
	return number;
}
function corpusNullableString(value) {
	return value === null || value === void 0 ? null : String(value);
}
function corpusNullableBoolean(value, field) {
	if (value === null || value === void 0) return null;
	if (value === true || value === 1 || value === "1") return true;
	if (value === false || value === 0 || value === "0") return false;
	return fail("integrity", `${field} contains an invalid boolean`);
}
function canonicalNodeRow(row) {
	return snapshotStorage({
		entityType: String(row.entityType),
		entityId: String(row.entityId),
		groupKey: String(row.groupKey),
		definitionRevision: corpusInteger(row.definitionRevision, "node.definitionRevision"),
		fieldKey: String(row.fieldKey),
		path: String(row.path),
		nodeKind: String(row.nodeKind),
		ordinal: corpusInteger(row.ordinal, "node.ordinal"),
		isNull: corpusNullableBoolean(row.isNull, "node.isNull") ?? false,
		valueText: corpusNullableString(row.valueText),
		valueNumber: corpusNullableString(row.valueNumber),
		valueBoolean: corpusNullableBoolean(row.valueBoolean, "node.valueBoolean"),
		valueDateTime: corpusNullableString(row.valueDateTime),
		valueRef: corpusNullableString(row.valueRef),
		valueJson: row.valueJson === null || row.valueJson === void 0 ? null : corpusJson(row.valueJson, "node.valueJson"),
		hostSessionId: corpusNullableString(row.hostSessionId)
	}, "node");
}
function canonicalDocumentRow(row) {
	return snapshotStorage({
		entityType: String(row.entityType),
		entityId: String(row.entityId),
		version: corpusInteger(row.version, "document.version"),
		document: corpusJson(row.document, "document.document"),
		definitionVersions: corpusJson(row.definitionVersions, "document.definitionVersions"),
		hostSessionId: corpusNullableString(row.hostSessionId)
	}, "document");
}
function canonicalRevisionRow(row) {
	return snapshotStorage({
		id: String(row.id),
		entityType: String(row.entityType),
		entityId: String(row.entityId),
		parentRevisionId: String(row.parentRevisionId),
		parentAutosaveId: corpusNullableString(row.parentAutosaveId),
		kind: String(row.kind),
		retentionClass: corpusNullableString(row.retentionClass),
		definitionVersions: corpusJson(row.definitionVersions, "revision.definitionVersions"),
		values: corpusJson(row.values, "revision.values"),
		blockDocument: row.blockDocument === null || row.blockDocument === void 0 ? null : corpusJson(row.blockDocument, "revision.blockDocument"),
		createdAt: corpusDate(row.createdAt, "revision.createdAt"),
		createdBy: String(row.createdBy),
		sourceVersion: String(row.sourceVersion),
		hostSessionId: corpusNullableString(row.hostSessionId)
	}, "revision");
}
function canonicalCurrentDefinitionRow(row, field) {
	return snapshotStorage({
		key: String(row.key),
		origin: String(row.origin),
		version: corpusInteger(row.version, `${field}.version`),
		active: corpusNullableBoolean(row.active, `${field}.active`) ?? false,
		currentRevision: corpusInteger(row.currentRevision, `${field}.currentRevision`),
		canonicalHash: String(row.canonicalHash),
		definition: corpusJson(row.definition, `${field}.definition`),
		shadowedDbVersion: row.shadowedDbVersion === null || row.shadowedDbVersion === void 0 ? null : corpusInteger(row.shadowedDbVersion, `${field}.shadowedDbVersion`),
		hostSessionId: corpusNullableString(row.hostSessionId)
	}, field);
}
function canonicalDefinitionVersionRow(row, keyField, field) {
	return snapshotStorage({
		[keyField]: String(row[keyField]),
		revision: corpusInteger(row.revision, `${field}.revision`),
		canonicalHash: String(row.canonicalHash),
		definition: corpusJson(row.definition, `${field}.definition`),
		origin: String(row.origin),
		hostSessionId: corpusNullableString(row.hostSessionId)
	}, field);
}
async function readValueCorpus(db, scope) {
	const types = scope.entityTypes;
	const typeSql = sql.join(types.map((type) => sql`${type}`), sql`, `);
	const nodeRows = await execRows(db, sql`SELECT entity_type AS "entityType",entity_id AS "entityId",group_key AS "groupKey",definition_revision AS "definitionRevision",field_key AS "fieldKey",path,node_kind AS "nodeKind",ordinal,is_null AS "isNull",value_text AS "valueText",value_number AS "valueNumber",value_boolean AS "valueBoolean",value_date_time AS "valueDateTime",value_ref AS "valueRef",value_json AS "valueJson",host_session_id AS "hostSessionId" FROM field_value_nodes WHERE entity_type IN (${typeSql}) OR entity_type='options' ORDER BY entity_type,entity_id,group_key,path`);
	const documentRows = await execRows(db, sql`SELECT entity_type AS "entityType",entity_id AS "entityId",version,document,definition_versions AS "definitionVersions",host_session_id AS "hostSessionId" FROM field_block_documents WHERE entity_type IN (${typeSql}) ORDER BY entity_type,entity_id`);
	const revisionRows = await execRows(db, sql`SELECT id,entity_type AS "entityType",entity_id AS "entityId",parent_revision_id AS "parentRevisionId",parent_autosave_id AS "parentAutosaveId",kind,retention_class AS "retentionClass",definition_versions AS "definitionVersions","values" AS "values",block_document AS "blockDocument",created_at AS "createdAt",created_by AS "createdBy",source_version AS "sourceVersion",host_session_id AS "hostSessionId" FROM field_revisions WHERE entity_type IN (${typeSql}) ORDER BY entity_type,entity_id,created_at,id`);
	const groupRows = await execRows(db, sql`SELECT key,origin,version,active,current_revision AS "currentRevision",canonical_hash AS "canonicalHash",definition,shadowed_db_version AS "shadowedDbVersion",host_session_id AS "hostSessionId" FROM field_group_definitions ORDER BY key`);
	const groupVersionRows = await execRows(db, sql`SELECT group_key AS "groupKey",revision,canonical_hash AS "canonicalHash",definition,origin,host_session_id AS "hostSessionId" FROM field_definition_versions ORDER BY group_key,revision`);
	const optionRows = await execRows(db, sql`SELECT key,origin,version,active,current_revision AS "currentRevision",canonical_hash AS "canonicalHash",definition,shadowed_db_version AS "shadowedDbVersion",host_session_id AS "hostSessionId" FROM field_options_definitions ORDER BY key`);
	const optionVersionRows = await execRows(db, sql`SELECT options_key AS "optionsKey",revision,canonical_hash AS "canonicalHash",definition,origin,host_session_id AS "hostSessionId" FROM field_options_definition_versions ORDER BY options_key,revision`);
	const blockRows = await execRows(db, sql`SELECT key,origin,version,active,current_revision AS "currentRevision",canonical_hash AS "canonicalHash",definition,shadowed_db_version AS "shadowedDbVersion",host_session_id AS "hostSessionId" FROM field_block_definitions ORDER BY key`);
	const blockVersionRows = await execRows(db, sql`SELECT block_key AS "blockKey",revision,canonical_hash AS "canonicalHash",definition,origin,host_session_id AS "hostSessionId" FROM field_block_definition_versions ORDER BY block_key,revision`);
	return Object.freeze({
		scope,
		nodes: Object.freeze(nodeRows.map(canonicalNodeRow)),
		documents: Object.freeze(documentRows.map(canonicalDocumentRow)),
		revisions: Object.freeze(revisionRows.map(canonicalRevisionRow)),
		groups: Object.freeze(groupRows.map((row) => canonicalCurrentDefinitionRow(row, "group"))),
		groupVersions: Object.freeze(groupVersionRows.map((row) => canonicalDefinitionVersionRow(row, "groupKey", "groupVersion"))),
		options: Object.freeze(optionRows.map((row) => canonicalCurrentDefinitionRow(row, "options"))),
		optionVersions: Object.freeze(optionVersionRows.map((row) => canonicalDefinitionVersionRow(row, "optionsKey", "optionVersion"))),
		blocks: Object.freeze(blockRows.map((row) => canonicalCurrentDefinitionRow(row, "block"))),
		blockVersions: Object.freeze(blockVersionRows.map((row) => canonicalDefinitionVersionRow(row, "blockKey", "blockVersion")))
	});
}
async function hashValueCorpus(snapshot) {
	return fieldsRequestHash(snapshot);
}
async function valueCorpusVersion(db, scope) {
	return hashValueCorpus(await readValueCorpus(db, scope));
}
async function planFieldsImport(db, scopeInput, parsed, policy, remappers, registry, codeRegistry, context) {
	const scope = normalizeScope(scopeInput);
	if (![
		"reject",
		"preserveDestination",
		"replaceMapped"
	].includes(policy)) fail("validation", "invalid import conflict policy");
	const authorizationPolicyVersion = await assertScopeAuthorized(context, scope);
	if (parsed.registryVersion !== registry.version) fail("stale-version", "field type registry changed since parse");
	await assertCodeRegistry$1(codeRegistry);
	const mappings = {}, conflicts = [];
	const entityOut = [];
	for (const item of parsed.manifest.entities ?? []) {
		if (!scope.entityTypes.includes(item.sourceRef.entityType)) fail("access-denied", "import scope is unavailable");
		const mapped = await remappers.entity(item.sourceRef);
		if (!mapped) {
			conflicts.push(Object.freeze({
				section: "entities",
				sourceKey: sourceKey(item.sourceRef),
				kind: "missingDependency"
			}));
			continue;
		}
		if (!scope.entityTypes.includes(mapped.entityType)) fail("access-denied", "mapped entity falls outside import scope");
		await assertFieldsAuthorized(context, "write", mapped);
		mappings[mappingKey("entity", sourceKey(item.sourceRef))] = sourceKey(mapped);
		entityOut.push(Object.freeze({
			sourceRef: mapped,
			values: await remapEntityValues(item.values, item.definitionVersions, parsed.manifest, remappers, mappings, conflicts, sourceKey(item.sourceRef)),
			definitionVersions: item.definitionVersions
		}));
	}
	const revisionOut = [];
	for (const item of parsed.manifest.revisions ?? []) {
		const mapped = await remappers.entity(item.sourceRef);
		if (!mapped) {
			conflicts.push(Object.freeze({
				section: "revisions",
				sourceKey: item.sourceRevisionKey,
				kind: "missingDependency"
			}));
			continue;
		}
		if (!scope.entityTypes.includes(mapped.entityType)) fail("access-denied", "mapped revision falls outside import scope");
		await assertFieldsAuthorized(context, "write", mapped);
		const user = await remappers.user(item.createdBySourceId);
		if (!user) {
			conflicts.push(Object.freeze({
				section: "revisions",
				sourceKey: item.sourceRevisionKey,
				kind: "missingDependency"
			}));
			continue;
		}
		mappings[mappingKey("user", item.createdBySourceId)] = user;
		revisionOut.push(Object.freeze({
			...item,
			sourceRef: mapped,
			createdBySourceId: user,
			values: await remapEntityValues(item.values, item.definitionVersions, parsed.manifest, remappers, mappings, conflicts, item.sourceRevisionKey),
			...item.blockDocument ? { blockDocument: await remapBlockReusableIds(item.blockDocument, remappers, mappings, conflicts, item.sourceRevisionKey) } : {}
		}));
	}
	const optionOut = [];
	for (const item of parsed.manifest.options ?? []) {
		await assertFieldsAuthorized(context, "write", {
			entityType: "options",
			entityId: item.pageKey
		});
		optionOut.push(Object.freeze({
			...item,
			values: await remapEntityValues(item.values, item.definitionVersions, parsed.manifest, remappers, mappings, conflicts, `options:${item.pageKey}`)
		}));
	}
	const blockOut = [];
	for (const item of parsed.manifest.blockDocuments ?? []) {
		const mapped = await remappers.entity(item.sourceRef);
		if (!mapped) {
			conflicts.push(Object.freeze({
				section: "blockDocuments",
				sourceKey: sourceKey(item.sourceRef),
				kind: "missingDependency"
			}));
			continue;
		}
		if (!scope.entityTypes.includes(mapped.entityType)) fail("access-denied", "mapped block document falls outside import scope");
		await assertFieldsAuthorized(context, "write", mapped);
		blockOut.push(Object.freeze({
			...item,
			sourceRef: mapped,
			document: await remapBlockReusableIds(item.document, remappers, mappings, conflicts, sourceKey(item.sourceRef))
		}));
	}
	const codeGroupKeys = new Set(codeRegistry.groups.map((item) => item.key)), codeOptionKeys = new Set(codeRegistry.optionsPages.map((item) => item.key)), codeBlockKeys = new Set(codeRegistry.blocks.map((item) => item.key));
	for (const key of codeGroupKeys) mappings[mappingKey("code-group", key)] = "1";
	for (const key of codeOptionKeys) mappings[mappingKey("code-options", key)] = "1";
	for (const key of codeBlockKeys) mappings[mappingKey("code-block", key)] = "1";
	const groupRows = await execRows(db, sql`SELECT key,origin,current_revision AS "currentRevision" FROM field_group_definitions`), destGroups = new Set(groupRows.map((row) => String(row.key)));
	const optionRows = await execRows(db, sql`SELECT key,origin,current_revision AS "currentRevision" FROM field_options_definitions`), destOptions = new Set(optionRows.map((row) => String(row.key)));
	const blockRows = await execRows(db, sql`SELECT key,origin,current_revision AS "currentRevision" FROM field_block_definitions`), destBlocks = new Set(blockRows.map((row) => String(row.key)));
	const destinationGroupVersions = await execRows(db, sql`SELECT group_key AS "groupKey",revision,canonical_hash AS "canonicalHash" FROM field_definition_versions ORDER BY group_key,revision`);
	for (const group of parsed.manifest.definitions.groups) {
		const existing = groupRows.find((row) => String(row.key) === group.key), sourceVersions = parsed.manifest.definitions.versions.filter((version) => version.groupKey === group.key).sort((a, b) => a.revision - b.revision), destVersions = destinationGroupVersions.filter((row) => String(row.groupKey) === group.key), maxRevision = Math.max(0, ...destVersions.map((row) => Number(row.revision)));
		let allocated = 0;
		for (const sourceVersion of sourceVersions) {
			const match = destVersions.find((row) => String(row.canonicalHash) === sourceVersion.canonicalHash);
			const isCodeCollision = codeGroupKeys.has(group.key);
			if (existing && policy === "preserveDestination" && !isCodeCollision) {
				if (match) mappings[mappingKey("grouprev", `${group.key}@${sourceVersion.revision}`)] = String(Number(match.revision));
				else conflicts.push(Object.freeze({
					section: "definitions",
					sourceKey: `${group.key}@${sourceVersion.revision}`,
					kind: "incompatibleVersion"
				}));
				continue;
			}
			mappings[mappingKey("grouprev", `${group.key}@${sourceVersion.revision}`)] = String(maxRevision + ++allocated);
		}
	}
	const destinationBlockVersions = await execRows(db, sql`SELECT block_key AS "blockKey",revision,canonical_hash AS "canonicalHash" FROM field_block_definition_versions ORDER BY block_key,revision`);
	for (const block of parsed.manifest.definitions.blocks) {
		const existing = blockRows.find((row) => String(row.key) === block.key), sourceVersions = parsed.manifest.definitions.blockVersions.filter((version) => version.blockKey === block.key).sort((a, b) => a.revision - b.revision), destVersions = destinationBlockVersions.filter((row) => String(row.blockKey) === block.key), maxRevision = Math.max(0, ...destVersions.map((row) => Number(row.revision)));
		let allocated = 0;
		for (const sourceVersion of sourceVersions) {
			const match = destVersions.find((row) => String(row.canonicalHash) === sourceVersion.canonicalHash), isCodeCollision = codeBlockKeys.has(block.key);
			if (existing && policy === "preserveDestination" && !isCodeCollision) {
				if (match) mappings[mappingKey("blockrev", `${block.key}@${sourceVersion.revision}`)] = String(Number(match.revision));
				else conflicts.push(Object.freeze({
					section: "definitions",
					sourceKey: `block:${block.key}@${sourceVersion.revision}`,
					kind: "incompatibleVersion"
				}));
				continue;
			}
			mappings[mappingKey("blockrev", `${block.key}@${sourceVersion.revision}`)] = String(maxRevision + ++allocated);
		}
	}
	for (const page of parsed.manifest.definitions.optionsPages) {
		const existing = optionRows.find((row) => String(row.key) === page.key), isCodeCollision = codeOptionKeys.has(page.key);
		if (existing && policy === "preserveDestination" && !isCodeCollision) mappings[mappingKey("optionsrev", page.key)] = String(Number(existing.currentRevision));
		else mappings[mappingKey("optionsrev", page.key)] = String(Number(existing?.currentRevision ?? 0) + 1);
	}
	for (const group of parsed.manifest.definitions.groups) if (destGroups.has(group.key) || codeGroupKeys.has(group.key)) conflicts.push(Object.freeze({
		section: "definitions",
		sourceKey: group.key,
		kind: "exists"
	}));
	for (const page of parsed.manifest.definitions.optionsPages) if (destOptions.has(page.key) || codeOptionKeys.has(page.key)) conflicts.push(Object.freeze({
		section: "definitions",
		sourceKey: `options:${page.key}`,
		kind: "exists"
	}));
	for (const block of parsed.manifest.definitions.blocks) if (destBlocks.has(block.key) || codeBlockKeys.has(block.key)) conflicts.push(Object.freeze({
		section: "definitions",
		sourceKey: `block:${block.key}`,
		kind: "exists"
	}));
	for (const item of entityOut) if ((await execRows(db, sql`SELECT 1 AS present FROM field_value_nodes WHERE entity_type=${item.sourceRef.entityType} AND entity_id=${item.sourceRef.entityId} LIMIT 1`)).length) conflicts.push(Object.freeze({
		section: "entities",
		sourceKey: sourceKey(item.sourceRef),
		kind: "exists"
	}));
	for (const item of blockOut) if ((await execRows(db, sql`SELECT 1 AS present FROM field_block_documents WHERE entity_type=${item.sourceRef.entityType} AND entity_id=${item.sourceRef.entityId} LIMIT 1`)).length) conflicts.push(Object.freeze({
		section: "blockDocuments",
		sourceKey: sourceKey(item.sourceRef),
		kind: "exists"
	}));
	if (policy === "reject" && conflicts.length) fail("validation", "import conflicts require an explicit non-reject policy");
	const transformed = Object.freeze({
		...parsed.manifest,
		...entityOut.length ? { entities: Object.freeze(entityOut) } : { entities: void 0 },
		...revisionOut.length ? { revisions: Object.freeze(revisionOut) } : { revisions: void 0 },
		...optionOut.length ? { options: Object.freeze(optionOut) } : { options: void 0 },
		...blockOut.length ? { blockDocuments: Object.freeze(blockOut) } : { blockDocuments: void 0 }
	});
	const valueCorpus = await valueCorpusVersion(db, scope);
	for (const item of revisionOut) mappings[mappingKey("revision", item.sourceRevisionKey)] = await deterministicRevisionId(await fieldsRequestHash({
		manifestHash: parsed.manifestHash,
		valueCorpus,
		scope
	}), item.sourceRevisionKey);
	const requiredAuthority = Object.freeze(scope.entityTypes.map((entityType) => Object.freeze({
		entityType,
		branches: Object.freeze([
			"manageDefinitions",
			"migrateDefinitions",
			"write"
		])
	})));
	const counts = Object.freeze({
		definitions: parsed.manifest.definitions.groups.length + parsed.manifest.definitions.versions.length + parsed.manifest.definitions.optionsPages.length + parsed.manifest.definitions.blocks.length + parsed.manifest.definitions.blockVersions.length,
		entities: entityOut.length,
		revisions: revisionOut.length,
		options: optionOut.length,
		blockDocuments: blockOut.length
	});
	const planMaterial = {
		manifestHash: parsed.manifestHash,
		registryVersion: registry.version,
		codeRegistryVersion: codeRegistry.version,
		codeRegistryHash: codeRegistry.canonicalHash,
		valueCorpusVersion: valueCorpus,
		authorizationPolicyVersion,
		scope,
		requiredAuthority,
		mappings: Object.freeze({ ...mappings }),
		counts,
		conflicts: Object.freeze(conflicts),
		omissions: parsed.manifest.omissions,
		policy,
		manifest: transformed
	};
	const planId = await fieldsRequestHash(planMaterial);
	return Object.freeze({
		planId,
		...planMaterial
	});
}
function sameScope(a, b) {
	return a.tenantKey === b.tenantKey && JSON.stringify([...a.entityTypes].sort()) === JSON.stringify([...b.entityTypes].sort());
}
function planMaterial(plan) {
	const { planId: _planId, ...rest } = plan;
	return rest;
}
async function assertPlanIdentity(plan) {
	if (await fieldsRequestHash(planMaterial(plan)) !== plan.planId) fail("integrity", "import plan identity is invalid");
	if (await fieldsRequestHash(plan.manifest) === plan.manifestHash) {}
}
function parsePersistedPayload(value) {
	const row = plain$2(typeof value === "string" ? (() => {
		try {
			return JSON.parse(value);
		} catch {
			fail("integrity", "import journal payload is invalid JSON");
		}
	})() : value, "journal.payload");
	if (!row.plan || typeof row.plan !== "object") fail("integrity", "import journal plan is missing");
	return Object.freeze({
		plan: row.plan,
		...typeof row.publishedValueCorpusVersion === "string" ? { publishedValueCorpusVersion: row.publishedValueCorpusVersion } : {}
	});
}
function journalFromRow(row, payload) {
	return Object.freeze({
		importId: String(row.importId),
		version: String(row.version),
		planId: payload.plan.planId,
		manifestHash: String(row.manifestHash),
		codeRegistryVersion: payload.plan.codeRegistryVersion,
		codeRegistryHash: payload.plan.codeRegistryHash,
		staging: Object.freeze({
			hostSessionId: String(row.hostSessionId),
			visibility: "hiddenUntilPublish"
		}),
		scope: payload.plan.scope,
		authorizationPolicyVersion: payload.plan.authorizationPolicyVersion,
		state: row.state,
		nextSection: row.nextSection,
		nextOffset: Number(row.nextOffset ?? 0)
	});
}
async function readJournal(db, importId) {
	const row = (await execRows(db, sql`SELECT import_id AS "importId",host_session_id AS "hostSessionId",manifest_hash AS "manifestHash",plan_hash AS "planHash",state,version,next_section AS "nextSection",next_offset AS "nextOffset",high_water_mark AS "highWaterMark",payload FROM fields_import_journal WHERE import_id=${importId} LIMIT 1`))[0];
	if (!row) return null;
	const payload = parsePersistedPayload(row.payload);
	return {
		row,
		payload,
		journal: journalFromRow(row, payload)
	};
}
function commandVersion(value, field) {
	if (value === null) return null;
	const n = Number(value);
	if (!Number.isSafeInteger(n) || n < 0) fail("validation", `${field} must be a nonnegative integer string`);
	return n;
}
async function planFieldsImportD1(db, scopeInput, parsed, policy, remappers, registry, codeRegistry, context) {
	assertD1Scope(scopeInput);
	return planFieldsImport(db, scopeInput, parsed, policy, remappers, registry, codeRegistry, context);
}
function validateCommand(command, start = false) {
	boundedString(command.operationId, "command.operationId", 512);
	boundedString(command.expectedPlanId, "command.expectedPlanId", 128);
	boundedString(command.expectedManifestHash, "command.expectedManifestHash", 128);
	const scope = normalizeScope(command.scope);
	if (command.expectedSection !== null && !SECTIONS.includes(command.expectedSection)) fail("validation", "command.expectedSection is invalid");
	if (command.expectedOffset !== null && (!Number.isSafeInteger(command.expectedOffset) || command.expectedOffset < 0)) fail("validation", "command.expectedOffset is invalid");
	if (start && (command.expectedJournalVersion !== null || command.expectedSection !== null || command.expectedOffset !== null)) fail("validation", "start command journal coordinates must all be null");
	if (!start) commandVersion(command.expectedJournalVersion, "command.expectedJournalVersion");
	return scope;
}
async function authorizePlan(context, plan) {
	const policy = await assertScopeAuthorized(context, plan.scope);
	for (const item of plan.manifest.entities ?? []) await assertFieldsAuthorized(context, "write", item.sourceRef);
	for (const item of plan.manifest.revisions ?? []) await assertFieldsAuthorized(context, "write", item.sourceRef);
	for (const item of plan.manifest.blockDocuments ?? []) await assertFieldsAuthorized(context, "write", item.sourceRef);
	for (const item of plan.manifest.options ?? []) await assertFieldsAuthorized(context, "write", {
		entityType: "options",
		entityId: item.pageKey
	});
	return policy;
}
async function assertRuntimeBindings(db, plan, registry, codeRegistry, checkCorpus) {
	if (registry.version !== plan.registryVersion) fail("stale-plan", "field type registry changed");
	await assertCodeRegistry$1(codeRegistry);
	if (codeRegistry.version !== plan.codeRegistryVersion || codeRegistry.canonicalHash !== plan.codeRegistryHash) fail("stale-plan", "code fields registry changed");
	if (checkCorpus && await valueCorpusVersion(db, plan.scope) !== plan.valueCorpusVersion) fail("stale-plan", "destination value corpus changed since plan");
}
function countsForSection(plan, section) {
	return sectionItems(plan, section).length;
}
function firstSection(plan, startIndex = 0) {
	for (let i = startIndex; i < SECTIONS.length; i++) if (countsForSection(plan, SECTIONS[i]) > 0) return SECTIONS[i];
	return null;
}
function sectionItems(plan, section) {
	const m = plan.manifest;
	if (section === "definitions") return Object.freeze([...m.definitions.versions.map((data) => ({
		kind: "groupVersion",
		data,
		key: `${data.groupKey}@${data.revision}`
	})), ...m.definitions.groups.map((data) => ({
		kind: "groupCurrent",
		data,
		key: data.key
	}))]);
	if (section === "optionsPages") return Object.freeze(m.definitions.optionsPages.map((data) => ({
		kind: "optionsPage",
		data,
		key: data.key
	})));
	if (section === "blocks") return Object.freeze([...m.definitions.blockVersions.map((data) => ({
		kind: "blockVersion",
		data,
		key: `${data.blockKey}@${data.revision}`
	})), ...m.definitions.blocks.map((data) => ({
		kind: "blockCurrent",
		data,
		key: data.key
	}))]);
	if (section === "entities") return Object.freeze((m.entities ?? []).map((data) => ({
		kind: "entity",
		data,
		key: sourceKey(data.sourceRef)
	})));
	if (section === "revisions") return Object.freeze((m.revisions ?? []).map((data) => ({
		kind: "revision",
		data,
		key: data.sourceRevisionKey
	})));
	if (section === "options") return Object.freeze((m.options ?? []).map((data) => ({
		kind: "optionsValues",
		data,
		key: data.pageKey
	})));
	return Object.freeze((m.blockDocuments ?? []).map((data) => ({
		kind: "blockDocument",
		data,
		key: sourceKey(data.sourceRef)
	})));
}
function codeCollision(plan, kind, key) {
	return plan.mappings[mappingKey(kind === "group" ? "code-group" : kind === "options" ? "code-options" : "code-block", key)] === "1";
}
async function emitImportEvent(tx, effects, event) {
	if (!effects) return;
	await effects.audit(tx, event);
	await effects.enqueue(tx, event);
}
function importEvent(kind, operationId, journal, plan, principalId) {
	return Object.freeze({
		kind,
		operationId,
		importId: journal.importId,
		principalId,
		planId: plan.planId,
		manifestHash: plan.manifestHash,
		state: journal.state,
		version: journal.version,
		nextSection: journal.nextSection,
		nextOffset: journal.nextOffset,
		counts: plan.counts
	});
}
function journalStorage(journal) {
	return jsonStorage(journal, "journal");
}
function receiptJournal(receiptResult) {
	const row = plain$2(receiptResult, "receipt.result");
	return Object.freeze({
		importId: boundedString(row.importId, "receipt.importId", 128),
		version: boundedString(row.version, "receipt.version", 64),
		planId: boundedString(row.planId, "receipt.planId", 128),
		manifestHash: boundedString(row.manifestHash, "receipt.manifestHash", 128),
		codeRegistryVersion: boundedString(row.codeRegistryVersion, "receipt.codeRegistryVersion", 256),
		codeRegistryHash: boundedString(row.codeRegistryHash, "receipt.codeRegistryHash", 128),
		staging: Object.freeze({
			hostSessionId: boundedString(plain$2(row.staging, "receipt.staging").hostSessionId, "receipt.staging.hostSessionId", 512),
			visibility: "hiddenUntilPublish"
		}),
		scope: normalizeScope(row.scope),
		authorizationPolicyVersion: boundedString(row.authorizationPolicyVersion, "receipt.authorizationPolicyVersion", 256),
		state: boundedString(row.state, "receipt.state", 32),
		nextSection: row.nextSection === null ? null : boundedString(row.nextSection, "receipt.nextSection", 32),
		nextOffset: Number(row.nextOffset)
	});
}
function retainedPayloadBytes(value, field = "import journal payload") {
	if (typeof value === "string") return value;
	try {
		return JSON.stringify(value);
	} catch {
		fail("integrity", `${field} is not serializable`);
	}
}
async function startFieldsImport(tx, plan, staging, command, registry, codeRegistry, context, effects) {
	assertActiveFieldsTransaction(tx);
	await assertPlanIdentity(plan);
	if (!sameScope(validateCommand(command, true), plan.scope) || command.expectedPlanId !== plan.planId || command.expectedManifestHash !== plan.manifestHash) fail("operation-conflict", "start command identity differs from plan");
	if (staging.visibility !== "hiddenUntilPublish") fail("validation", "staging visibility must be hiddenUntilPublish");
	const hostSessionId = importSessionId(staging.hostSessionId);
	const authorized = requireAuthorizedFieldsContext(context);
	if (await authorizePlan(context, plan) !== plan.authorizationPolicyVersion) fail("access-denied", "import scope is unavailable");
	await assertRuntimeBindings(tx, plan, registry, codeRegistry, false);
	const requestHash = await fieldsRequestHash({
		kind: "start",
		planId: plan.planId,
		manifestHash: plan.manifestHash,
		scope: plan.scope,
		staging: {
			hostSessionId,
			visibility: "hiddenUntilPublish"
		},
		registryVersion: registry.version,
		codeRegistryVersion: codeRegistry.version,
		codeRegistryHash: codeRegistry.canonicalHash,
		command
	});
	const receipt = await readFieldsReceipt(tx, command.operationId);
	if (receipt) {
		assertReceiptReplay(receipt, {
			kind: "fields:import-start",
			context: authorized,
			requestHash
		});
		return receiptJournal(receipt.result);
	}
	await assertRuntimeBindings(tx, plan, registry, codeRegistry, true);
	if ((await execRows(tx, sql`SELECT import_id FROM fields_import_journal WHERE host_session_id=${hostSessionId} LIMIT 1`)).length) fail("operation-conflict", "staging session already exists");
	const importId = hostSessionId, nextSection = firstSection(plan), now = (/* @__PURE__ */ new Date()).toISOString(), payload = Object.freeze({ plan });
	try {
		await tx.execute(sql`INSERT INTO fields_import_journal (import_id,host_session_id,manifest_hash,plan_hash,state,version,next_section,next_offset,payload,created_at,updated_at) VALUES (${importId},${hostSessionId},${plan.manifestHash},${plan.planId},'planned',0,${nextSection},0,${JSON.stringify(payload)},${now},${now})`);
	} catch (error) {
		if (isImportUniqueViolation(error)) fail("operation-conflict", "staging session already exists");
		throw error;
	}
	const journal = Object.freeze({
		importId,
		version: "0",
		planId: plan.planId,
		manifestHash: plan.manifestHash,
		codeRegistryVersion: plan.codeRegistryVersion,
		codeRegistryHash: plan.codeRegistryHash,
		staging: Object.freeze({
			hostSessionId,
			visibility: "hiddenUntilPublish"
		}),
		scope: plan.scope,
		authorizationPolicyVersion: plan.authorizationPolicyVersion,
		state: nextSection ? "planned" : "staged",
		nextSection,
		nextOffset: 0
	});
	if (!nextSection) await tx.execute(sql`UPDATE fields_import_journal SET state='staged' WHERE import_id=${importId}`);
	await emitImportEvent(tx, effects, importEvent("started", command.operationId, journal, plan, authorized.principal.id));
	await writeFieldsReceipt(tx, {
		operationId: command.operationId,
		kind: "fields:import-start",
		context: authorized,
		requestHash,
		result: journalStorage(journal)
	});
	return journal;
}
function d1JsonValueEqual(left, right) {
	return sql`(NOT EXISTS (SELECT fullkey,type,atom FROM json_tree(${left}) EXCEPT SELECT fullkey,type,atom FROM json_tree(${right})) AND NOT EXISTS (SELECT fullkey,type,atom FROM json_tree(${right}) EXCEPT SELECT fullkey,type,atom FROM json_tree(${left})))`;
}
function d1ExactJsonSet(expected, current) {
	const bytes = JSON.stringify(expected);
	return sql`(WITH expected_rows(value) AS (SELECT value FROM json_each(${bytes})), actual_rows(value) AS (${current}) SELECT NOT EXISTS (SELECT 1 FROM expected_rows expected WHERE NOT EXISTS (SELECT 1 FROM actual_rows actual WHERE ${d1JsonValueEqual(sql`expected.value`, sql`actual.value`)})) AND NOT EXISTS (SELECT 1 FROM actual_rows actual WHERE NOT EXISTS (SELECT 1 FROM expected_rows expected WHERE ${d1JsonValueEqual(sql`actual.value`, sql`expected.value`)})))`;
}
function d1ValueCorpusPredicate(snapshot) {
	const types = sql.join(snapshot.scope.entityTypes.map((type) => sql`${type}`), sql`, `);
	const predicates = [
		d1ExactJsonSet(snapshot.nodes, sql`SELECT json_object('definitionRevision',definition_revision,'entityId',entity_id,'entityType',entity_type,'fieldKey',field_key,'groupKey',group_key,'hostSessionId',host_session_id,'isNull',json(CASE WHEN is_null THEN 'true' ELSE 'false' END),'nodeKind',node_kind,'ordinal',ordinal,'path',path,'valueBoolean',CASE WHEN value_boolean IS NULL THEN NULL ELSE json(CASE WHEN value_boolean THEN 'true' ELSE 'false' END) END,'valueDateTime',value_date_time,'valueJson',CASE WHEN value_json IS NULL THEN NULL ELSE json(value_json) END,'valueNumber',CAST(value_number AS TEXT),'valueRef',value_ref,'valueText',value_text) FROM field_value_nodes WHERE entity_type IN (${types}) OR entity_type='options'`),
		d1ExactJsonSet(snapshot.documents, sql`SELECT json_object('definitionVersions',json(definition_versions),'document',json(document),'entityId',entity_id,'entityType',entity_type,'hostSessionId',host_session_id,'version',version) FROM field_block_documents WHERE entity_type IN (${types})`),
		d1ExactJsonSet(snapshot.revisions, sql`SELECT json_object('blockDocument',CASE WHEN block_document IS NULL THEN NULL ELSE json(block_document) END,'createdAt',created_at,'createdBy',created_by,'definitionVersions',json(definition_versions),'entityId',entity_id,'entityType',entity_type,'hostSessionId',host_session_id,'id',id,'kind',kind,'parentAutosaveId',parent_autosave_id,'parentRevisionId',parent_revision_id,'retentionClass',retention_class,'sourceVersion',CAST(source_version AS TEXT),'values',json("values")) FROM field_revisions WHERE entity_type IN (${types})`),
		d1ExactJsonSet(snapshot.groups, sql`SELECT json_object('active',json(CASE WHEN active THEN 'true' ELSE 'false' END),'canonicalHash',canonical_hash,'currentRevision',current_revision,'definition',json(definition),'hostSessionId',host_session_id,'key',key,'origin',origin,'shadowedDbVersion',shadowed_db_version,'version',version) FROM field_group_definitions`),
		d1ExactJsonSet(snapshot.groupVersions, sql`SELECT json_object('canonicalHash',canonical_hash,'definition',json(definition),'groupKey',group_key,'hostSessionId',host_session_id,'origin',origin,'revision',revision) FROM field_definition_versions`),
		d1ExactJsonSet(snapshot.options, sql`SELECT json_object('active',json(CASE WHEN active THEN 'true' ELSE 'false' END),'canonicalHash',canonical_hash,'currentRevision',current_revision,'definition',json(definition),'hostSessionId',host_session_id,'key',key,'origin',origin,'shadowedDbVersion',shadowed_db_version,'version',version) FROM field_options_definitions`),
		d1ExactJsonSet(snapshot.optionVersions, sql`SELECT json_object('canonicalHash',canonical_hash,'definition',json(definition),'hostSessionId',host_session_id,'optionsKey',options_key,'origin',origin,'revision',revision) FROM field_options_definition_versions`),
		d1ExactJsonSet(snapshot.blocks, sql`SELECT json_object('active',json(CASE WHEN active THEN 'true' ELSE 'false' END),'canonicalHash',canonical_hash,'currentRevision',current_revision,'definition',json(definition),'hostSessionId',host_session_id,'key',key,'origin',origin,'shadowedDbVersion',shadowed_db_version,'version',version) FROM field_block_definitions`),
		d1ExactJsonSet(snapshot.blockVersions, sql`SELECT json_object('blockKey',block_key,'canonicalHash',canonical_hash,'definition',json(definition),'hostSessionId',host_session_id,'origin',origin,'revision',revision) FROM field_block_definition_versions`)
	];
	return sql.join(predicates, sql` AND `);
}
async function d1ImportReplayGuard(db, operationId, kind, scope, requestHash, expectedImportId, result) {
	const receiptRow = (await execRows(db, sql`SELECT result FROM fields_operation_receipts WHERE operation_id=${operationId} AND kind=${kind} AND principal_scope=${scope} AND request_hash=${requestHash} LIMIT 1`))[0];
	if (!receiptRow) fail("integrity", "committed import receipt evidence is unavailable");
	const receiptResultBytes = retainedPayloadBytes(receiptRow.result, "import receipt result");
	const retained = await readJournal(db, expectedImportId);
	if (!retained) fail("integrity", "committed import receipt has no retained journal");
	await assertPlanIdentity(retained.payload.plan);
	if (String(retained.row.planHash) !== retained.journal.planId || String(retained.row.manifestHash) !== retained.journal.manifestHash || String(retained.row.hostSessionId) !== retained.journal.staging.hostSessionId || result.importId !== expectedImportId || retained.journal.importId !== result.importId || retained.journal.planId !== result.planId || retained.journal.manifestHash !== result.manifestHash || retained.journal.staging.hostSessionId !== result.staging.hostSessionId || retained.journal.codeRegistryVersion !== result.codeRegistryVersion || retained.journal.codeRegistryHash !== result.codeRegistryHash || retained.journal.authorizationPolicyVersion !== result.authorizationPolicyVersion || !sameScope(retained.journal.scope, result.scope) || retained.journal.state !== result.state || retained.journal.version !== result.version || retained.journal.nextSection !== result.nextSection || retained.journal.nextOffset !== result.nextOffset) fail("integrity", "committed import receipt differs from retained journal identity or coordinate");
	const payloadBytes = retainedPayloadBytes(retained.row.payload), version = Number(retained.row.version), nextOffset = Number(retained.row.nextOffset ?? 0);
	if (!Number.isSafeInteger(version) || version < 0 || !Number.isSafeInteger(nextOffset) || nextOffset < 0) fail("integrity", "retained import journal coordinate is invalid");
	const sectionPredicate = retained.row.nextSection === null ? sql`next_section IS NULL` : sql`next_section=${String(retained.row.nextSection)}`;
	const highWaterPredicate = retained.row.highWaterMark === null ? sql`high_water_mark IS NULL` : sql`high_water_mark=${String(retained.row.highWaterMark)}`;
	return db.prepare(sql`SELECT CASE WHEN
    EXISTS (SELECT 1 FROM fields_operation_receipts WHERE operation_id=${operationId} AND kind=${kind} AND principal_scope=${scope} AND request_hash=${requestHash} AND result=${receiptResultBytes})
    AND EXISTS (SELECT 1 FROM fields_import_journal WHERE import_id=${expectedImportId} AND host_session_id=${retained.journal.staging.hostSessionId} AND manifest_hash=${retained.journal.manifestHash} AND plan_hash=${retained.journal.planId} AND state=${retained.row.state} AND version=${version} AND ${sectionPredicate} AND next_offset=${nextOffset} AND ${highWaterPredicate} AND payload=${payloadBytes})
    THEN 1 ELSE json_extract('not-json','$') END AS ok`);
}
/** D1 start-import plan. The host appends its effects and commits the combined batch. */
async function prepareStartFieldsImportD1(db, plan, staging, command, registry, codeRegistry, context) {
	assertD1Scope(plan.scope);
	await assertPlanIdentity(plan);
	if (!sameScope(assertD1Scope(validateCommand(command, true)), plan.scope) || command.expectedPlanId !== plan.planId || command.expectedManifestHash !== plan.manifestHash) fail("operation-conflict", "start command identity differs from plan");
	if (staging.visibility !== "hiddenUntilPublish") fail("validation", "staging visibility must be hiddenUntilPublish");
	const hostSessionId = importSessionId(staging.hostSessionId);
	const authorized = requireAuthorizedFieldsContext(context);
	if (await authorizePlan(context, plan) !== plan.authorizationPolicyVersion) fail("access-denied", "import scope is unavailable");
	await assertRuntimeBindings(db, plan, registry, codeRegistry, false);
	const requestHash = await fieldsRequestHash({
		kind: "start",
		planId: plan.planId,
		manifestHash: plan.manifestHash,
		scope: plan.scope,
		staging: {
			hostSessionId,
			visibility: "hiddenUntilPublish"
		},
		registryVersion: registry.version,
		codeRegistryVersion: codeRegistry.version,
		codeRegistryHash: codeRegistry.canonicalHash,
		command
	});
	const scope = principalScope(authorized), receipt = await readFieldsReceipt(db, command.operationId);
	if (receipt) {
		if (receipt.kind !== "fields:import-start" || receipt.principalScope !== scope || receipt.requestHash !== requestHash) fail("operation-conflict", "operation id was already used with different input or scope");
		const result = receiptJournal(receipt.result);
		if (result.importId !== hostSessionId || result.planId !== plan.planId || result.manifestHash !== plan.manifestHash || !sameScope(result.scope, plan.scope)) fail("operation-conflict", "persisted start result differs from requested import");
		return Object.freeze({
			items: d1Items(await d1ImportReplayGuard(db, command.operationId, "fields:import-start", scope, requestHash, hostSessionId, result)),
			result
		});
	}
	const snapshot = await readValueCorpus(db, plan.scope);
	if (await hashValueCorpus(snapshot) !== plan.valueCorpusVersion) fail("stale-plan", "destination value corpus changed since plan");
	const importId = hostSessionId, nextSection = firstSection(plan), state = nextSection ? "planned" : "staged", now = (/* @__PURE__ */ new Date()).toISOString();
	const result = Object.freeze({
		importId,
		version: "0",
		planId: plan.planId,
		manifestHash: plan.manifestHash,
		codeRegistryVersion: plan.codeRegistryVersion,
		codeRegistryHash: plan.codeRegistryHash,
		staging: Object.freeze({
			hostSessionId,
			visibility: "hiddenUntilPublish"
		}),
		scope: plan.scope,
		authorizationPolicyVersion: plan.authorizationPolicyVersion,
		state,
		nextSection,
		nextOffset: 0
	});
	const payload = Object.freeze({ plan });
	const corpusPredicate = d1ValueCorpusPredicate(snapshot);
	const pending = db.prepare(sql`INSERT INTO fields_operation_receipts (operation_id,kind,principal_scope,request_hash,result,created_at) SELECT ${command.operationId},'fields:import-start',${scope},${requestHash},${JSON.stringify({ pending: true })},${now} WHERE ${corpusPredicate}`);
	const pendingGuard = db.prepare(d1AssertPreviousChanges(1));
	const journal = db.prepare(sql`INSERT INTO fields_import_journal (import_id,host_session_id,manifest_hash,plan_hash,state,version,next_section,next_offset,payload,created_at,updated_at) VALUES (${importId},${hostSessionId},${plan.manifestHash},${plan.planId},${state},0,${nextSection},0,${JSON.stringify(payload)},${now},${now})`);
	const journalGuard = db.prepare(d1AssertPreviousChanges(1));
	const complete = db.prepare(sql`UPDATE fields_operation_receipts SET result=${JSON.stringify(result)} WHERE operation_id=${command.operationId} AND kind='fields:import-start' AND principal_scope=${scope} AND request_hash=${requestHash} AND json(result)=json(${JSON.stringify({ pending: true })})`);
	const completeGuard = db.prepare(d1AssertPreviousChanges(1));
	return Object.freeze({
		items: d1Items(pending, pendingGuard, journal, journalGuard, complete, completeGuard),
		result
	});
}
function snapshotStorage(value, field = "snapshot") {
	let normalized;
	try {
		normalized = JSON.parse(JSON.stringify(value));
	} catch {
		fail("integrity", `${field} is not serializable`);
	}
	return jsonStorage(normalized, field);
}
function mappedRevision(plan, kind, key, sourceRevision) {
	const revision = Number(plan.mappings[mappingKey(kind, `${key}@${sourceRevision}`)]);
	if (!Number.isSafeInteger(revision) || revision < 1) fail("stale-plan", `missing ${kind} mapping for ${key}@${sourceRevision}`);
	return revision;
}
function mappedOptionsRevision(plan, key) {
	const revision = Number(plan.mappings[mappingKey("optionsrev", key)]);
	if (!Number.isSafeInteger(revision) || revision < 1) fail("stale-plan", `missing options revision mapping for ${key}`);
	return revision;
}
function mappedRevisionId(plan, key) {
	const id = plan.mappings[mappingKey("revision", key)];
	if (!id) fail("stale-plan", `missing revision id mapping for ${key}`);
	return id;
}
async function currentGroupSourceRevision(plan, group) {
	const hash = await canonicalFieldGroupHash(group), version = plan.manifest.definitions.versions.find((item) => item.groupKey === group.key && item.canonicalHash === hash);
	if (!version) fail("integrity", `group ${group.key} current version mapping is missing`);
	return version.revision;
}
async function currentBlockSourceRevision(plan, block) {
	const hash = await fieldsRequestHash(block), version = plan.manifest.definitions.blockVersions.find((item) => item.blockKey === block.key && item.canonicalHash === hash);
	if (!version) fail("integrity", `block ${block.key} current version mapping is missing`);
	return version.revision;
}
function destinationDefinitionVersions(plan, versions) {
	const out = {};
	for (const [identity, sourceRevision] of Object.entries(versions)) if (identity.startsWith("block:")) out[identity] = mappedRevision(plan, "blockrev", identity.slice(6), sourceRevision);
	else out[identity] = mappedRevision(plan, "grouprev", identity.startsWith("group:") ? identity.slice(6) : identity, sourceRevision);
	return Object.freeze(out);
}
function remapBlockPins(plan, document) {
	const walk = (nodes) => Object.freeze(nodes.map((node) => {
		if (node.kind === "reusable") return node;
		return Object.freeze({
			...node,
			blockDefinitionRevision: mappedRevision(plan, "blockrev", node.type, node.blockDefinitionRevision),
			fieldGroups: Object.freeze(node.fieldGroups.map((group) => Object.freeze({
				...group,
				definitionRevision: mappedRevision(plan, "grouprev", group.groupKey, group.definitionRevision)
			}))),
			...node.children ? { children: walk(node.children) } : {}
		});
	}));
	return Object.freeze({
		version: 1,
		roots: walk(document.roots)
	});
}
function remapBlockDefinition(plan, definition) {
	return definition.template ? Object.freeze({
		...definition,
		template: remapBlockPins(plan, {
			version: 1,
			roots: definition.template
		}).roots
	}) : definition;
}
function stripSensitiveFields(fields) {
	const output = [];
	for (const field of fields) {
		if (field.type === "password" || field.type === "clone") continue;
		if (field.type === "group" || field.type === "repeater") output.push(Object.freeze({
			...field,
			settings: Object.freeze({
				...field.settings,
				fields: stripSensitiveFields(field.settings.fields)
			})
		}));
		else if (field.type === "flexible") output.push(Object.freeze({
			...field,
			settings: Object.freeze({
				...field.settings,
				layouts: Object.freeze(field.settings.layouts.map((layout) => Object.freeze({
					...layout,
					fields: stripSensitiveFields(layout.fields)
				})))
			})
		}));
		else output.push(field);
	}
	return Object.freeze(output);
}
function importWritableGroup(group) {
	return Object.freeze({
		...group,
		fields: stripSensitiveFields(group.fields)
	});
}
async function nodeBeforeImage(tx, refValue, groups) {
	if (groups.length === 0) return Object.freeze([]);
	return snapshotStorage(await execRows(tx, sql`SELECT node_id AS "nodeId",entity_type AS "entityType",entity_id AS "entityId",group_key AS "groupKey",definition_revision AS "definitionRevision",field_key AS "fieldKey",path,parent_node_id AS "parentNodeId",row_id AS "rowId",layout_key AS "layoutKey",node_kind AS "nodeKind",ordinal,is_null AS "isNull",value_text AS "valueText",value_number AS "valueNumber",value_boolean AS "valueBoolean",value_date_time AS "valueDateTime",value_ref AS "valueRef",value_json AS "valueJson",legacy_source_ids AS "legacySourceIds",legacy_source_hash AS "legacySourceHash",host_session_id AS "hostSessionId",created_at AS "createdAt",updated_at AS "updatedAt" FROM field_value_nodes WHERE entity_type=${refValue.entityType} AND entity_id=${refValue.entityId} AND group_key IN (${sql.join(groups.map((group) => sql`${group}`), sql`, `)}) ORDER BY group_key,path`), "before.nodes");
}
async function prepareDefinitionStagedItem(tx, plan, item) {
	if (item.kind === "groupVersion") {
		const data = item.data, destRevision = mappedRevision(plan, "grouprev", data.groupKey, data.revision);
		const before = (await execRows(tx, sql`SELECT group_key AS "groupKey",revision,canonical_hash AS "canonicalHash",definition,origin,host_session_id AS "hostSessionId",created_at AS "createdAt" FROM field_definition_versions WHERE group_key=${data.groupKey} AND revision=${destRevision} LIMIT 1`))[0] ?? null;
		if (before && String(before.canonicalHash) !== data.canonicalHash) fail("stale-plan", `destination definition revision ${data.groupKey}@${destRevision} changed`);
		return Object.freeze({
			kind: item.kind,
			action: before ? "skip" : "apply",
			after: snapshotStorage({
				...data,
				revision: destRevision
			}, "staged.groupVersion"),
			before: before ? snapshotStorage(before) : null
		});
	}
	if (item.kind === "groupCurrent") {
		const data = item.data, sourceRevision = await currentGroupSourceRevision(plan, data), destRevision = mappedRevision(plan, "grouprev", data.key, sourceRevision);
		const before = (await execRows(tx, sql`SELECT key,origin,version,active,current_revision AS "currentRevision",canonical_hash AS "canonicalHash",definition,shadowed_db_version AS "shadowedDbVersion",host_session_id AS "hostSessionId",created_at AS "createdAt",updated_at AS "updatedAt" FROM field_group_definitions WHERE key=${data.key} LIMIT 1`))[0] ?? null;
		const action = codeCollision(plan, "group", data.key) ? "shadow" : plan.policy === "preserveDestination" && before ? "skip" : "apply";
		return Object.freeze({
			kind: item.kind,
			action,
			after: snapshotStorage({
				definition: data,
				currentRevision: destRevision
			}, "staged.groupCurrent"),
			before: before ? snapshotStorage(before) : null
		});
	}
	if (item.kind === "optionsPage") {
		const data = item.data, destRevision = mappedOptionsRevision(plan, data.key);
		const current = await execRows(tx, sql`SELECT key,origin,version,active,current_revision AS "currentRevision",canonical_hash AS "canonicalHash",definition,shadowed_db_version AS "shadowedDbVersion",host_session_id AS "hostSessionId",created_at AS "createdAt",updated_at AS "updatedAt" FROM field_options_definitions WHERE key=${data.key} LIMIT 1`);
		const version = await execRows(tx, sql`SELECT options_key AS "optionsKey",revision,canonical_hash AS "canonicalHash",definition,origin,host_session_id AS "hostSessionId",created_at AS "createdAt" FROM field_options_definition_versions WHERE options_key=${data.key} AND revision=${destRevision} LIMIT 1`);
		const action = codeCollision(plan, "options", data.key) ? "shadow" : plan.policy === "preserveDestination" && current.length ? "skip" : "apply";
		return Object.freeze({
			kind: item.kind,
			action,
			after: snapshotStorage({
				definition: data,
				currentRevision: destRevision
			}, "staged.optionsPage"),
			before: snapshotStorage({
				current: current[0] ?? null,
				version: version[0] ?? null
			})
		});
	}
	if (item.kind === "blockVersion") {
		const data = item.data, destRevision = mappedRevision(plan, "blockrev", data.blockKey, data.revision), definition = remapBlockDefinition(plan, data.definition), canonicalHash = await fieldsRequestHash(definition);
		const before = (await execRows(tx, sql`SELECT block_key AS "blockKey",revision,canonical_hash AS "canonicalHash",definition,origin,host_session_id AS "hostSessionId",created_at AS "createdAt" FROM field_block_definition_versions WHERE block_key=${data.blockKey} AND revision=${destRevision} LIMIT 1`))[0] ?? null;
		if (before && String(before.canonicalHash) !== canonicalHash) fail("stale-plan", `destination block revision ${data.blockKey}@${destRevision} changed`);
		return Object.freeze({
			kind: item.kind,
			action: before ? "skip" : "apply",
			after: snapshotStorage({
				...data,
				revision: destRevision,
				canonicalHash,
				definition
			}, "staged.blockVersion"),
			before: before ? snapshotStorage(before) : null
		});
	}
	if (item.kind === "blockCurrent") {
		const data = item.data, sourceRevision = await currentBlockSourceRevision(plan, data), destRevision = mappedRevision(plan, "blockrev", data.key, sourceRevision), definition = remapBlockDefinition(plan, data);
		const before = (await execRows(tx, sql`SELECT key,origin,version,active,current_revision AS "currentRevision",canonical_hash AS "canonicalHash",definition,shadowed_db_version AS "shadowedDbVersion",host_session_id AS "hostSessionId",created_at AS "createdAt",updated_at AS "updatedAt" FROM field_block_definitions WHERE key=${data.key} LIMIT 1`))[0] ?? null;
		const action = codeCollision(plan, "block", data.key) ? "shadow" : plan.policy === "preserveDestination" && before ? "skip" : "apply";
		return Object.freeze({
			kind: item.kind,
			action,
			after: snapshotStorage({
				definition,
				currentRevision: destRevision
			}, "staged.blockCurrent"),
			before: before ? snapshotStorage(before) : null
		});
	}
	return null;
}
async function prepareDataStagedItem(tx, plan, item) {
	if (item.kind === "entity") {
		const data = item.data, before = await nodeBeforeImage(tx, data.sourceRef, Object.keys(data.values));
		const action = plan.policy === "preserveDestination" && Array.isArray(before) && before.length ? "skip" : "apply";
		return Object.freeze({
			kind: item.kind,
			action,
			after: snapshotStorage(data, "staged.entity"),
			before
		});
	}
	if (item.kind === "revision") {
		const data = item.data, destId = mappedRevisionId(plan, data.sourceRevisionKey);
		const before = await execRows(tx, sql`SELECT id,entity_type AS "entityType",entity_id AS "entityId",parent_revision_id AS "parentRevisionId",parent_autosave_id AS "parentAutosaveId",kind,retention_class AS "retentionClass",definition_versions AS "definitionVersions","values" AS "values",block_document AS "blockDocument",created_at AS "createdAt",created_by AS "createdBy",source_version AS "sourceVersion",host_session_id AS "hostSessionId" FROM field_revisions WHERE id=${destId} LIMIT 1`);
		if (before.length && plan.policy !== "preserveDestination") fail("stale-plan", `destination revision ${destId} already exists`);
		return Object.freeze({
			kind: item.kind,
			action: before.length ? "skip" : "apply",
			after: snapshotStorage({
				...data,
				destinationRevisionId: destId
			}, "staged.revision"),
			before: before.length ? snapshotStorage(before[0]) : null
		});
	}
	if (item.kind === "optionsValues") {
		const data = item.data, before = await nodeBeforeImage(tx, {
			entityType: "options",
			entityId: data.pageKey
		}, Object.keys(data.values));
		const action = plan.policy === "preserveDestination" && Array.isArray(before) && before.length ? "skip" : "apply";
		return Object.freeze({
			kind: item.kind,
			action,
			after: snapshotStorage(data, "staged.optionsValues"),
			before
		});
	}
	const data = item.data;
	const beforeRows = await execRows(tx, sql`SELECT entity_type AS "entityType",entity_id AS "entityId",version,document,definition_versions AS "definitionVersions",parent_revision_id AS "parentRevisionId",host_session_id AS "hostSessionId",updated_by AS "updatedBy",updated_at AS "updatedAt" FROM field_block_documents WHERE entity_type=${data.sourceRef.entityType} AND entity_id=${data.sourceRef.entityId} LIMIT 1`);
	const action = plan.policy === "preserveDestination" && beforeRows.length ? "skip" : "apply";
	return Object.freeze({
		kind: "blockDocument",
		action,
		after: snapshotStorage(data, "staged.blockDocument"),
		before: beforeRows.length ? snapshotStorage(beforeRows[0]) : null
	});
}
async function prepareStagedItem(tx, plan, section, item) {
	const definition = await prepareDefinitionStagedItem(tx, plan, item);
	if (definition) return definition;
	if (![
		"entities",
		"revisions",
		"options",
		"blockDocuments"
	].includes(section)) fail("integrity", `unsupported staged section ${section}`);
	return prepareDataStagedItem(tx, plan, item);
}
async function casJournal(tx, current, command, next) {
	const expectedVersion = commandVersion(command.expectedJournalVersion, "command.expectedJournalVersion");
	if (expectedVersion === null || command.expectedOffset === null) fail("validation", "continuation requires complete journal coordinates");
	if (current.journal.version !== command.expectedJournalVersion || current.journal.nextSection !== command.expectedSection || current.journal.nextOffset !== command.expectedOffset) fail("stale-journal", "import journal coordinate changed");
	const sectionPredicate = command.expectedSection === null ? sql`next_section IS NULL` : sql`next_section=${command.expectedSection}`;
	const payloadBytes = retainedPayloadBytes(current.row.payload);
	const rows = await execRows(tx, sql`UPDATE fields_import_journal SET version=version+1,state=${next.state},next_section=${next.section},next_offset=${next.offset},updated_at=${(/* @__PURE__ */ new Date()).toISOString()} WHERE import_id=${current.journal.importId} AND version=${expectedVersion} AND ${sectionPredicate} AND next_offset=${command.expectedOffset} AND payload=${payloadBytes} RETURNING version`);
	if (rows.length !== 1) fail("stale-journal", "import journal coordinate changed");
	return Number(rows[0].version);
}
async function resumeFieldsImport(tx, importId, batchSize, command, registry, codeRegistry, context, effects) {
	assertActiveFieldsTransaction(tx);
	boundedString(importId, "importId", 128);
	if (!Number.isSafeInteger(batchSize) || batchSize < 1 || batchSize > 500) fail("validation", "batchSize must be between 1 and 500");
	const scope = validateCommand(command, false), authorized = requireAuthorizedFieldsContext(context), scopePolicy = await assertScopeAuthorized(context, scope);
	const requestHash = await fieldsRequestHash({
		kind: "resume",
		importId,
		batchSize,
		command,
		registryVersion: registry.version,
		codeRegistryVersion: codeRegistry.version,
		codeRegistryHash: codeRegistry.canonicalHash
	});
	const receipt = await readFieldsReceipt(tx, command.operationId);
	if (receipt) {
		assertReceiptReplay(receipt, {
			kind: "fields:import-resume",
			context: authorized,
			requestHash
		});
		return receiptJournal(receipt.result);
	}
	const current = await readJournal(tx, importId);
	if (!current) fail("access-denied", "import session is unavailable");
	const plan = current.payload.plan;
	await assertPlanIdentity(plan);
	if (!sameScope(scope, plan.scope) || command.expectedPlanId !== plan.planId || command.expectedManifestHash !== plan.manifestHash) fail("operation-conflict", "resume command identity differs from import plan");
	if (scopePolicy !== plan.authorizationPolicyVersion) fail("access-denied", "import session is unavailable");
	if (current.journal.state !== "planned" && current.journal.state !== "applying") fail("stale-journal", "import is not resumable");
	if (await authorizePlan(context, plan) !== plan.authorizationPolicyVersion) fail("access-denied", "import session is unavailable");
	await assertRuntimeBindings(tx, plan, registry, codeRegistry, true);
	const section = current.journal.nextSection;
	if (!section) fail("stale-journal", "import has no remaining section");
	const items = sectionItems(plan, section), offset = current.journal.nextOffset;
	if (offset < 0 || offset >= items.length) fail("integrity", "journal offset is outside section");
	const end = Math.min(items.length, offset + batchSize), batch = items.slice(offset, end), sectionIndex = SECTIONS.indexOf(section);
	let nextSection = section, nextOffset = end;
	if (end >= items.length) {
		nextSection = firstSection(plan, sectionIndex + 1);
		nextOffset = 0;
	}
	const nextState = nextSection ? "applying" : "staged";
	const nextVersion = await casJournal(tx, current, command, {
		state: nextState,
		section: nextSection,
		offset: nextOffset
	});
	for (let index = 0; index < batch.length; index++) {
		const ordinal = offset + index, payload = snapshotStorage(await normalizeStagedForPublish(tx, plan, await prepareStagedItem(tx, plan, section, batch[index]), registry, codeRegistry, context), "staged.item"), canonicalHash = await fieldsRequestHash(payload);
		await tx.execute(sql`INSERT INTO fields_import_staging (host_session_id,section,ordinal,canonical_hash,payload,created_at) VALUES (${current.journal.staging.hostSessionId},${section},${ordinal},${canonicalHash},${JSON.stringify(payload)},${(/* @__PURE__ */ new Date()).toISOString()})`);
	}
	const journal = Object.freeze({
		...current.journal,
		version: String(nextVersion),
		state: nextState,
		nextSection,
		nextOffset
	});
	await emitImportEvent(tx, effects, importEvent("batchStaged", command.operationId, journal, plan, authorized.principal.id));
	await writeFieldsReceipt(tx, {
		operationId: command.operationId,
		kind: "fields:import-resume",
		context: authorized,
		requestHash,
		result: journalStorage(journal)
	});
	return journal;
}
async function readVerifiedStagingPrefix(db, journal, plan, observedRows) {
	const rows = observedRows ?? await execRows(db, sql`SELECT section,ordinal,canonical_hash AS "canonicalHash",payload FROM fields_import_staging WHERE host_session_id=${journal.staging.hostSessionId} ORDER BY section,ordinal`);
	const expected = /* @__PURE__ */ new Map();
	const currentIndex = journal.nextSection === null ? SECTIONS.length : SECTIONS.indexOf(journal.nextSection);
	if (currentIndex < 0) fail("integrity", "journal section is invalid");
	for (const [index, section] of SECTIONS.entries()) expected.set(section, index < currentIndex ? sectionItems(plan, section).length : index === currentIndex ? journal.nextOffset : 0);
	const seen = /* @__PURE__ */ new Set(), counts = /* @__PURE__ */ new Map(), identities = [];
	for (const row of rows) {
		if (!SECTIONS.includes(row.section)) fail("integrity", "staging contains unknown section");
		const section = row.section, ordinal = Number(row.ordinal), limit = expected.get(section);
		if (!Number.isSafeInteger(ordinal) || ordinal < 0 || ordinal >= limit) fail("integrity", "staging ordinal is outside the journal coordinate");
		const identity = `${section}:${ordinal}`;
		if (seen.has(identity)) fail("integrity", "staging contains duplicate ordinal");
		seen.add(identity);
		const item = parseStagedItem(row.payload), canonicalHash = await fieldsRequestHash(snapshotStorage(item, "staged.item"));
		if (canonicalHash !== String(row.canonicalHash)) fail("integrity", "staging payload hash mismatch");
		counts.set(section, (counts.get(section) ?? 0) + 1);
		identities.push(snapshotStorage({
			section,
			ordinal,
			canonicalHash,
			payload: item
		}, "staging.identity"));
	}
	for (const section of SECTIONS) if ((counts.get(section) ?? 0) !== expected.get(section)) fail("integrity", `staging section ${section} is not contiguous with the journal`);
	return Object.freeze(identities);
}
function d1StagingPrefixPredicate(journal, identities) {
	return d1ExactJsonSet(identities, sql`SELECT json_object('canonicalHash',canonical_hash,'ordinal',ordinal,'payload',json(payload),'section',section) FROM fields_import_staging WHERE host_session_id=${journal.staging.hostSessionId}`);
}
function retainedStagingBytesPredicate(journal, rows) {
	return d1ExactJsonSet(Object.freeze(rows.map((row) => Object.freeze({
		section: String(row.section),
		ordinal: Number(row.ordinal),
		canonicalHash: String(row.canonicalHash),
		payload: retainedPayloadBytes(row.payload)
	}))), sql`SELECT json_object('canonicalHash',canonical_hash,'ordinal',ordinal,'payload',payload,'section',section) FROM fields_import_staging WHERE host_session_id=${journal.staging.hostSessionId}`);
}
/**
* D1 staged-import guard. The host composes this read-only participant into its
* one atomic batch when fields has no remaining resume transition.
*/
async function prepareStagedFieldsImportGuardD1(db, importId, command, registry, codeRegistry, context) {
	boundedString(importId, "importId", 128);
	const scopeInput = assertD1Scope(validateCommand(command, false));
	requireAuthorizedFieldsContext(context);
	const scopePolicy = await assertScopeAuthorized(context, scopeInput);
	const current = await readJournal(db, importId);
	if (!current) fail("access-denied", "import session is unavailable");
	const plan = current.payload.plan;
	await assertPlanIdentity(plan);
	if (!sameScope(scopeInput, plan.scope) || command.expectedPlanId !== plan.planId || command.expectedManifestHash !== plan.manifestHash) fail("operation-conflict", "staged guard command identity differs from import plan");
	if (scopePolicy !== plan.authorizationPolicyVersion) fail("access-denied", "import session is unavailable");
	if (await authorizePlan(context, plan) !== plan.authorizationPolicyVersion) fail("access-denied", "import session is unavailable");
	await assertRuntimeBindings(db, plan, registry, codeRegistry, false);
	const expectedVersion = commandVersion(command.expectedJournalVersion, "command.expectedJournalVersion");
	if (expectedVersion === null || command.expectedSection !== null || command.expectedOffset !== 0) fail("stale-journal", "staged guard requires the terminal journal coordinate");
	if (current.journal.version !== command.expectedJournalVersion || current.journal.state !== "staged" || current.journal.nextSection !== null || current.journal.nextOffset !== 0) fail("stale-journal", "import is not at the expected staged coordinate");
	if (String(current.row.planHash) !== plan.planId || String(current.row.manifestHash) !== plan.manifestHash || String(current.row.hostSessionId) !== current.journal.staging.hostSessionId) fail("integrity", "import journal identity differs from retained plan");
	const stagingRows = await execRows(db, sql`SELECT section,ordinal,canonical_hash AS "canonicalHash",payload FROM fields_import_staging WHERE host_session_id=${current.journal.staging.hostSessionId} ORDER BY section,ordinal`);
	await readVerifiedStagingPrefix(db, current.journal, plan, stagingRows);
	const payloadBytes = retainedPayloadBytes(current.row.payload), stagingPredicate = retainedStagingBytesPredicate(current.journal, stagingRows);
	const guard = db.prepare(sql`SELECT CASE WHEN EXISTS (
    SELECT 1 FROM fields_import_journal
    WHERE import_id=${importId}
      AND host_session_id=${current.journal.staging.hostSessionId}
      AND state='staged'
      AND version=${expectedVersion}
      AND plan_hash=${plan.planId}
      AND manifest_hash=${plan.manifestHash}
      AND next_section IS NULL
      AND next_offset=0
      AND payload=${payloadBytes}
      AND ${stagingPredicate}
  ) THEN 1 ELSE json_extract('not-json','$') END AS ok`);
	return Object.freeze({
		items: d1Items(guard),
		result: current.journal
	});
}
/** D1 resume-import plan. The host appends its effects and commits the combined batch. */
async function prepareResumeFieldsImportD1(db, importId, batchSize, command, registry, codeRegistry, context) {
	boundedString(importId, "importId", 128);
	if (!Number.isSafeInteger(batchSize) || batchSize < 1 || batchSize > 500) fail("validation", "batchSize must be between 1 and 500");
	const scopeInput = assertD1Scope(validateCommand(command, false)), authorized = requireAuthorizedFieldsContext(context), scopePolicy = await assertScopeAuthorized(context, scopeInput);
	const requestHash = await fieldsRequestHash({
		kind: "resume",
		importId,
		batchSize,
		command,
		registryVersion: registry.version,
		codeRegistryVersion: codeRegistry.version,
		codeRegistryHash: codeRegistry.canonicalHash
	});
	const principal = principalScope(authorized), receipt = await readFieldsReceipt(db, command.operationId);
	if (receipt) {
		if (receipt.kind !== "fields:import-resume" || receipt.principalScope !== principal || receipt.requestHash !== requestHash) fail("operation-conflict", "operation id was already used with different input or scope");
		const result = receiptJournal(receipt.result);
		if (result.importId !== importId || result.planId !== command.expectedPlanId || result.manifestHash !== command.expectedManifestHash || !sameScope(result.scope, scopeInput)) fail("operation-conflict", "persisted resume result differs from requested import");
		return Object.freeze({
			items: d1Items(await d1ImportReplayGuard(db, command.operationId, "fields:import-resume", principal, requestHash, importId, result)),
			result
		});
	}
	const current = await readJournal(db, importId);
	if (!current) fail("access-denied", "import session is unavailable");
	const plan = current.payload.plan;
	await assertPlanIdentity(plan);
	if (!sameScope(scopeInput, plan.scope) || command.expectedPlanId !== plan.planId || command.expectedManifestHash !== plan.manifestHash) fail("operation-conflict", "resume command identity differs from import plan");
	if (scopePolicy !== plan.authorizationPolicyVersion) fail("access-denied", "import session is unavailable");
	if (current.journal.state !== "planned" && current.journal.state !== "applying") fail("stale-journal", "import is not resumable");
	if (await authorizePlan(context, plan) !== plan.authorizationPolicyVersion) fail("access-denied", "import session is unavailable");
	await assertRuntimeBindings(db, plan, registry, codeRegistry, false);
	const expectedVersion = commandVersion(command.expectedJournalVersion, "command.expectedJournalVersion");
	if (expectedVersion === null || command.expectedOffset === null) fail("validation", "continuation requires complete journal coordinates");
	if (current.journal.version !== command.expectedJournalVersion || current.journal.nextSection !== command.expectedSection || current.journal.nextOffset !== command.expectedOffset) fail("stale-journal", "import journal coordinate changed");
	const section = current.journal.nextSection;
	if (!section) fail("stale-journal", "import has no remaining section");
	const items = sectionItems(plan, section), offset = current.journal.nextOffset;
	if (offset < 0 || offset >= items.length) fail("integrity", "journal offset is outside section");
	const end = Math.min(items.length, offset + batchSize), batch = items.slice(offset, end), sectionIndex = SECTIONS.indexOf(section);
	let nextSection = section, nextOffset = end;
	if (end >= items.length) {
		nextSection = firstSection(plan, sectionIndex + 1);
		nextOffset = 0;
	}
	const nextState = nextSection ? "applying" : "staged", nextVersion = expectedVersion + 1;
	const result = Object.freeze({
		...current.journal,
		version: String(nextVersion),
		state: nextState,
		nextSection,
		nextOffset
	});
	const corpus = await readValueCorpus(db, plan.scope);
	if (await hashValueCorpus(corpus) !== plan.valueCorpusVersion) fail("stale-plan", "destination value corpus changed since plan");
	const prefix = await readVerifiedStagingPrefix(db, current.journal, plan), prepared = [];
	for (let index = 0; index < batch.length; index++) {
		const ordinal = offset + index, payload = snapshotStorage(await normalizeStagedForPublish(db, plan, await prepareStagedItem(db, plan, section, batch[index]), registry, codeRegistry, context), "staged.item");
		prepared.push({
			ordinal,
			payload,
			canonicalHash: await fieldsRequestHash(payload)
		});
	}
	const now = (/* @__PURE__ */ new Date()).toISOString(), sectionPredicate = command.expectedSection === null ? sql`next_section IS NULL` : sql`next_section=${command.expectedSection}`, payloadBytes = retainedPayloadBytes(current.row.payload);
	const pending = db.prepare(sql`INSERT INTO fields_operation_receipts (operation_id,kind,principal_scope,request_hash,result,created_at) SELECT ${command.operationId},'fields:import-resume',${principal},${requestHash},${JSON.stringify({ pending: true })},${now} WHERE ${d1ValueCorpusPredicate(corpus)} AND ${d1StagingPrefixPredicate(current.journal, prefix)}`);
	const pendingGuard = db.prepare(d1AssertPreviousChanges(1));
	const journal = db.prepare(sql`UPDATE fields_import_journal SET version=version+1,state=${nextState},next_section=${nextSection},next_offset=${nextOffset},updated_at=${now} WHERE import_id=${importId} AND host_session_id=${current.journal.staging.hostSessionId} AND version=${expectedVersion} AND state=${current.journal.state} AND ${sectionPredicate} AND next_offset=${command.expectedOffset} AND plan_hash=${plan.planId} AND manifest_hash=${plan.manifestHash} AND payload=${payloadBytes}`);
	const journalGuard = db.prepare(d1AssertPreviousChanges(1)), stagingItems = [];
	for (const item of prepared) stagingItems.push(db.prepare(sql`INSERT INTO fields_import_staging (host_session_id,section,ordinal,canonical_hash,payload,created_at) VALUES (${current.journal.staging.hostSessionId},${section},${item.ordinal},${item.canonicalHash},${JSON.stringify(item.payload)},${now})`), db.prepare(d1AssertPreviousChanges(1)));
	const complete = db.prepare(sql`UPDATE fields_operation_receipts SET result=${JSON.stringify(result)} WHERE operation_id=${command.operationId} AND kind='fields:import-resume' AND principal_scope=${principal} AND request_hash=${requestHash} AND json(result)=json(${JSON.stringify({ pending: true })})`);
	const completeGuard = db.prepare(d1AssertPreviousChanges(1));
	return boundedD1Contribution(d1Items(pending, pendingGuard, journal, journalGuard, ...stagingItems, complete, completeGuard), result);
}
function parseStagedItem(value) {
	const row = plain$2(typeof value === "string" ? (() => {
		try {
			return JSON.parse(value);
		} catch {
			fail("integrity", "staged payload is invalid JSON");
		}
	})() : value, "staged.payload");
	if (typeof row.kind !== "string" || ![
		"apply",
		"skip",
		"shadow"
	].includes(String(row.action))) fail("integrity", "staged payload has invalid action");
	return Object.freeze({
		kind: row.kind,
		action: row.action,
		after: jsonStorage(row.after, "staged.after"),
		before: row.before === null ? null : jsonStorage(row.before, "staged.before")
	});
}
async function readVerifiedStaging(tx, journal, plan) {
	const rows = await execRows(tx, sql`SELECT section,ordinal,canonical_hash AS "canonicalHash",payload FROM fields_import_staging WHERE host_session_id=${journal.staging.hostSessionId} ORDER BY section,ordinal`), output = [];
	const expected = new Map(SECTIONS.map((section) => [section, sectionItems(plan, section).length]));
	const seen = /* @__PURE__ */ new Map(), identities = /* @__PURE__ */ new Set();
	for (const row of rows) {
		if (!SECTIONS.includes(row.section)) fail("integrity", "staging contains unknown section");
		const section = row.section, ordinal = Number(row.ordinal);
		if (!Number.isSafeInteger(ordinal) || ordinal < 0 || ordinal >= expected.get(section)) fail("integrity", "staging ordinal is invalid");
		const identity = `${section}:${ordinal}`;
		if (identities.has(identity)) fail("integrity", "staging contains duplicate ordinal");
		identities.add(identity);
		const item = parseStagedItem(row.payload);
		if (await fieldsRequestHash(snapshotStorage(item, "staged.item")) !== row.canonicalHash) fail("integrity", "staging payload hash mismatch");
		seen.set(section, (seen.get(section) ?? 0) + 1);
		output.push({
			section,
			ordinal,
			item
		});
	}
	for (const section of SECTIONS) if ((seen.get(section) ?? 0) !== expected.get(section)) fail("integrity", `staging section ${section} is incomplete`);
	output.sort((left, right) => SECTIONS.indexOf(left.section) - SECTIONS.indexOf(right.section) || left.ordinal - right.ordinal);
	return Object.freeze(output);
}
function sensitiveFieldKeys(fields, out = /* @__PURE__ */ new Set()) {
	for (const field of fields) {
		if (field.type === "password" || field.type === "clone") out.add(field.key);
		if (field.type === "group" || field.type === "repeater") sensitiveFieldKeys(field.settings.fields, out);
		if (field.type === "flexible") for (const layout of field.settings.layouts) sensitiveFieldKeys(layout.fields, out);
	}
	return out;
}
function filterWritableValues(fields, input) {
	const out = {};
	for (const field of fields) {
		if (field.type === "password" || field.type === "clone" || !Object.prototype.hasOwnProperty.call(input, field.key)) continue;
		const value = input[field.key];
		if (field.type === "group" && value && typeof value === "object" && !Array.isArray(value)) out[field.key] = filterWritableValues(field.settings.fields, value);
		else if (field.type === "repeater" && Array.isArray(value)) out[field.key] = Object.freeze(value.map((raw) => {
			const row = plain$2(raw, field.key), values = plain$2(row.values, `${field.key}.values`);
			return Object.freeze({
				...row,
				values: filterWritableValues(field.settings.fields, values)
			});
		}));
		else if (field.type === "flexible" && Array.isArray(value)) out[field.key] = Object.freeze(value.map((raw) => {
			const row = plain$2(raw, field.key), layout = field.settings.layouts.find((candidate) => candidate.key === row.layoutKey);
			if (!layout) return row;
			return Object.freeze({
				...row,
				values: filterWritableValues(layout.fields, plain$2(row.values, `${field.key}.values`))
			});
		}));
		else out[field.key] = value;
	}
	return Object.freeze(out);
}
async function writeImportedGroupValues(tx, plan, refValue, groupKey, sourceRevision, values, sessionId, registry, context) {
	const source = plan.manifest.definitions.versions.find((item) => item.groupKey === groupKey && item.revision === sourceRevision);
	if (!source) fail("integrity", `missing source group definition ${groupKey}@${sourceRevision}`);
	const destinationRevision = mappedRevision(plan, "grouprev", groupKey, sourceRevision), group = source.definition, writable = importWritableGroup(group), filtered = filterWritableValues(group.fields, values), runtimeContext = Object.freeze({
		...context,
		fieldTypeRegistry: registry
	});
	const validated = await __fieldBlockLifecycleInternals.validateBlockFieldMap(writable.fields, filtered, runtimeContext, `import.${refValue.entityType}.${refValue.entityId}.${groupKey}`);
	const existing = await execRows(tx, sql`SELECT node_id AS "nodeId",path,parent_node_id AS "parentNodeId",field_key AS "fieldKey" FROM field_value_nodes WHERE entity_type=${refValue.entityType} AND entity_id=${refValue.entityId} AND group_key=${groupKey} ORDER BY path`), byPath = new Map(existing.map((row) => [String(row.path), String(row.nodeId)])), byId = new Map(existing.map((row) => [String(row.nodeId), row])), protectedIds = /* @__PURE__ */ new Set(), sensitiveKeys = sensitiveFieldKeys(group.fields);
	for (const row of existing) if (sensitiveKeys.has(String(row.fieldKey))) {
		let cursor = row;
		while (cursor) {
			const id = String(cursor.nodeId);
			if (protectedIds.has(id)) break;
			protectedIds.add(id);
			const parentId = cursor.parentNodeId;
			cursor = parentId === null || parentId === void 0 ? void 0 : byId.get(String(parentId));
		}
	}
	if (protectedIds.size) {
		const ids = [...protectedIds];
		await tx.execute(sql`UPDATE field_value_nodes SET definition_revision=${destinationRevision},host_session_id=${sessionId},updated_at=${(/* @__PURE__ */ new Date()).toISOString()} WHERE node_id IN (${sql.join(ids.map((id) => sql`${id}`), sql`, `)})`);
		await tx.execute(sql`DELETE FROM field_value_nodes WHERE entity_type=${refValue.entityType} AND entity_id=${refValue.entityId} AND group_key=${groupKey} AND node_id NOT IN (${sql.join(ids.map((id) => sql`${id}`), sql`, `)})`);
	} else await tx.execute(sql`DELETE FROM field_value_nodes WHERE entity_type=${refValue.entityType} AND entity_id=${refValue.entityId} AND group_key=${groupKey}`);
	const generated = /* @__PURE__ */ new Map(), nodeIdForPath = (path) => byPath.get(path) ?? generated.get(path) ?? (() => {
		const id = crypto.randomUUID();
		generated.set(path, id);
		return id;
	})(), rows = encodeFieldValueNodes(writable, validated, {
		entityType: refValue.entityType,
		entityId: refValue.entityId,
		definitionRevision: destinationRevision,
		nodeIdForPath,
		...context.cloneResolver ? { cloneResolver: { resolve: (definition) => context.cloneResolver.resolve(definition) } } : {}
	});
	for (const row of rows) {
		if (protectedIds.has(row.nodeId)) continue;
		await tx.execute(sql`INSERT INTO field_value_nodes (node_id,entity_type,entity_id,group_key,definition_revision,field_key,path,parent_node_id,row_id,layout_key,node_kind,ordinal,is_null,value_text,value_number,value_boolean,value_date_time,value_ref,value_json,host_session_id,created_at,updated_at) VALUES (${row.nodeId},${row.entityType},${row.entityId},${row.groupKey},${row.definitionRevision},${row.fieldKey},${row.path},${row.parentNodeId},${row.rowId},${row.layoutKey},${row.nodeKind},${row.ordinal},${row.isNull},${row.valueText},${row.valueNumber},${row.valueBoolean},${row.valueDateTime},${row.valueRef},${row.valueJson},${sessionId},${(/* @__PURE__ */ new Date()).toISOString()},${(/* @__PURE__ */ new Date()).toISOString()})`);
	}
}
async function applyDefinitionStagedItem(tx, plan, sessionId, staged) {
	if (staged.action === "skip") return true;
	const after = plain$2(staged.after, "staged.after");
	if (staged.kind === "groupVersion") {
		const groupKey = boundedString(after.groupKey, "staged.groupVersion.groupKey", 128), revision = positive$2(after.revision, "staged.groupVersion.revision"), definition = after.definition, canonicalHash = boundedString(after.canonicalHash, "staged.groupVersion.canonicalHash", 128);
		if (await canonicalFieldGroupHash(definition) !== canonicalHash) fail("integrity", "staged group definition hash mismatch");
		await tx.execute(sql`INSERT INTO field_definition_versions (group_key,revision,canonical_hash,definition,origin,host_session_id,created_at) VALUES (${groupKey},${revision},${canonicalHash},${JSON.stringify(definition)},'import',${sessionId},${dateString(after.createdAt, "staged.groupVersion.createdAt")})`);
		return true;
	}
	if (staged.kind === "groupCurrent") {
		const definition = after.definition, currentRevision = positive$2(after.currentRevision, "staged.groupCurrent.currentRevision"), canonicalHash = await canonicalFieldGroupHash(definition), before = staged.before === null ? null : plain$2(staged.before, "staged.groupCurrent.before"), now = (/* @__PURE__ */ new Date()).toISOString();
		if (staged.action === "shadow") {
			if (!before || before.origin !== "code") fail("stale-plan", "group code collision no longer exists");
			await tx.execute(sql`UPDATE field_group_definitions SET version=version+1,shadowed_db_version=${currentRevision},updated_at=${now} WHERE key=${definition.key} AND origin='code'`);
			return true;
		}
		if (before) {
			const version = Number(before.version) + 1;
			if (!Number.isSafeInteger(version) || version < 2) fail("integrity", "staged group before-image version is invalid");
			await tx.execute(sql`UPDATE field_group_definitions SET origin='import',version=${version},active=${definition.active},current_revision=${currentRevision},canonical_hash=${canonicalHash},definition=${storedJsonText(definition, "before.definition")},shadowed_db_version=NULL,host_session_id=${sessionId},updated_at=${now} WHERE key=${definition.key}`);
		} else await tx.execute(sql`INSERT INTO field_group_definitions (key,origin,version,active,current_revision,canonical_hash,definition,shadowed_db_version,host_session_id,created_at,updated_at) VALUES (${definition.key},'import',1,${definition.active},${currentRevision},${canonicalHash},${JSON.stringify(definition)},NULL,${sessionId},${now},${now})`);
		return true;
	}
	if (staged.kind === "optionsPage") {
		const definition = __optionsLifecycleInternals.normalizeOptionsPage(after.definition), currentRevision = positive$2(after.currentRevision, "staged.optionsPage.currentRevision"), canonicalHash = await fieldsRequestHash(definition), beforeBundle = staged.before === null ? null : plain$2(staged.before, "staged.optionsPage.before"), before = beforeBundle && beforeBundle.current ? plain$2(beforeBundle.current, "staged.optionsPage.before.current") : null, versionBefore = beforeBundle && beforeBundle.version ? plain$2(beforeBundle.version, "staged.optionsPage.before.version") : null, now = (/* @__PURE__ */ new Date()).toISOString();
		if (!versionBefore) await tx.execute(sql`INSERT INTO field_options_definition_versions (options_key,revision,canonical_hash,definition,origin,host_session_id,created_at) VALUES (${definition.key},${currentRevision},${canonicalHash},${JSON.stringify(definition)},'import',${sessionId},${now})`);
		else if (String(versionBefore.canonicalHash) !== canonicalHash && Number(versionBefore.revision) === currentRevision) fail("stale-plan", "options immutable revision changed");
		if (staged.action === "shadow") {
			if (!before || before.origin !== "code") fail("stale-plan", "options code collision no longer exists");
			await tx.execute(sql`UPDATE field_options_definitions SET version=version+1,shadowed_db_version=${currentRevision},updated_at=${now} WHERE key=${definition.key} AND origin='code'`);
			return true;
		}
		if (before) {
			const version = Number(before.version) + 1;
			await tx.execute(sql`UPDATE field_options_definitions SET origin='import',version=${version},active=true,current_revision=${currentRevision},canonical_hash=${canonicalHash},definition=${storedJsonText(definition, "before.definition")},shadowed_db_version=NULL,host_session_id=${sessionId},updated_at=${now} WHERE key=${definition.key}`);
		} else await tx.execute(sql`INSERT INTO field_options_definitions (key,origin,version,active,current_revision,canonical_hash,definition,shadowed_db_version,host_session_id,created_at,updated_at) VALUES (${definition.key},'import',1,true,${currentRevision},${canonicalHash},${JSON.stringify(definition)},NULL,${sessionId},${now},${now})`);
		return true;
	}
	if (staged.kind === "blockVersion") {
		const blockKey = boundedString(after.blockKey, "staged.blockVersion.blockKey", 128), revision = positive$2(after.revision, "staged.blockVersion.revision"), definition = __fieldBlockLifecycleInternals.normalizeDefinition(after.definition), canonicalHash = boundedString(after.canonicalHash, "staged.blockVersion.canonicalHash", 128);
		if (await fieldsRequestHash(definition) !== canonicalHash) fail("integrity", "staged block definition hash mismatch");
		await tx.execute(sql`INSERT INTO field_block_definition_versions (block_key,revision,canonical_hash,definition,origin,host_session_id,created_at) VALUES (${blockKey},${revision},${canonicalHash},${JSON.stringify(definition)},'import',${sessionId},${dateString(after.createdAt, "staged.blockVersion.createdAt")})`);
		return true;
	}
	if (staged.kind === "blockCurrent") {
		const definition = __fieldBlockLifecycleInternals.normalizeDefinition(after.definition), currentRevision = positive$2(after.currentRevision, "staged.blockCurrent.currentRevision"), canonicalHash = await fieldsRequestHash(definition), before = staged.before === null ? null : plain$2(staged.before, "staged.blockCurrent.before"), now = (/* @__PURE__ */ new Date()).toISOString();
		if (staged.action === "shadow") {
			if (!before || before.origin !== "code") fail("stale-plan", "block code collision no longer exists");
			await tx.execute(sql`UPDATE field_block_definitions SET version=version+1,shadowed_db_version=${currentRevision},updated_at=${now} WHERE key=${definition.key} AND origin='code'`);
			return true;
		}
		if (before) {
			const version = Number(before.version) + 1;
			await tx.execute(sql`UPDATE field_block_definitions SET origin='import',version=${version},active=true,current_revision=${currentRevision},canonical_hash=${canonicalHash},definition=${storedJsonText(definition, "before.definition")},shadowed_db_version=NULL,host_session_id=${sessionId},updated_at=${now} WHERE key=${definition.key}`);
		} else await tx.execute(sql`INSERT INTO field_block_definitions (key,origin,version,active,current_revision,canonical_hash,definition,shadowed_db_version,host_session_id,created_at,updated_at) VALUES (${definition.key},'import',1,true,${currentRevision},${canonicalHash},${JSON.stringify(definition)},NULL,${sessionId},${now},${now})`);
		return true;
	}
	return false;
}
async function validateImportedBlockDocument(tx, document, registry, codeRegistry, context) {
	const runtimeContext = Object.freeze({
		...context,
		fieldTypeRegistry: registry
	});
	return serializeBlockDocument(await validateBlockDocument(document, await resolveFieldBlocks(tx, { codeBlocks: codeRegistry.blocks }), createReusableBlockResolver(tx), runtimeContext, DEFAULT_BLOCK_POLICY));
}
async function normalizeStagedForPublish(tx, plan, item, registry, codeRegistry, context, pinsMapped = false) {
	if (item.action === "skip") return item;
	const after = plain$2(item.after, "staged.after");
	if (item.kind === "entity" || item.kind === "optionsValues") {
		const values = plain$2(after.values, "staged.values"), versions = revisionsMap(after.definitionVersions, "staged.definitionVersions"), normalized = {}, refValue = item.kind === "entity" ? ref(after.sourceRef, "staged.entity.sourceRef") : {
			entityType: "options",
			entityId: boundedString(after.pageKey, "staged.options.pageKey", 128)
		}, runtimeContext = Object.freeze({
			...context,
			fieldTypeRegistry: registry
		});
		for (const [groupKey, value] of Object.entries(values)) {
			const revision = versions[groupKey], source = plan.manifest.definitions.versions.find((entry) => entry.groupKey === groupKey && entry.revision === revision);
			if (!revision || !source) fail("integrity", `missing source group definition ${groupKey}`);
			const writable = importWritableGroup(source.definition), filtered = filterWritableValues(source.definition.fields, plain$2(value, `staged.values.${groupKey}`));
			normalized[groupKey] = await __fieldBlockLifecycleInternals.validateBlockFieldMap(writable.fields, filtered, runtimeContext, `import.${refValue.entityType}.${refValue.entityId}.${groupKey}`);
		}
		return Object.freeze({
			...item,
			after: snapshotStorage({
				...after,
				values: Object.freeze(normalized)
			}, "staged.normalized")
		});
	}
	if (item.kind === "revision" && after.blockDocument !== void 0) {
		const parsed = blockDocument(after.blockDocument, DEFAULT_IMPORT_LIMITS, "staged.revision.blockDocument"), serialized = await validateImportedBlockDocument(tx, pinsMapped ? parsed : remapBlockPins(plan, parsed), registry, codeRegistry, context);
		return Object.freeze({
			...item,
			after: snapshotStorage({
				...after,
				blockDocument: JSON.parse(serialized)
			}, "staged.normalized")
		});
	}
	if (item.kind === "blockDocument") {
		const parsed = blockDocument(after.document, DEFAULT_IMPORT_LIMITS, "staged.blockDocument.document"), serialized = await validateImportedBlockDocument(tx, pinsMapped ? parsed : remapBlockPins(plan, parsed), registry, codeRegistry, context);
		return Object.freeze({
			...item,
			after: snapshotStorage({
				...after,
				document: JSON.parse(serialized)
			}, "staged.normalized")
		});
	}
	return item;
}
async function applyValueStagedItem(tx, plan, sessionId, staged, registry, context) {
	if (staged.action === "skip") return staged.kind === "entity" || staged.kind === "optionsValues";
	const after = plain$2(staged.after, "staged.after");
	if (staged.kind === "entity") {
		const refValue = ref(after.sourceRef, "staged.entity.sourceRef"), values = plain$2(after.values, "staged.entity.values"), versions = revisionsMap(after.definitionVersions, "staged.entity.definitionVersions");
		for (const [groupKey, value] of Object.entries(values)) {
			const sourceRevision = versions[groupKey];
			if (!sourceRevision) fail("integrity", `entity value has no pinned revision for ${groupKey}`);
			await writeImportedGroupValues(tx, plan, refValue, groupKey, sourceRevision, plain$2(value, `staged.entity.values.${groupKey}`), sessionId, registry, context);
		}
		return true;
	}
	if (staged.kind === "optionsValues") {
		const pageKey = boundedString(after.pageKey, "staged.options.pageKey", 128), values = plain$2(after.values, "staged.options.values"), versions = revisionsMap(after.definitionVersions, "staged.options.definitionVersions");
		for (const [groupKey, value] of Object.entries(values)) {
			const sourceRevision = versions[groupKey];
			if (!sourceRevision) fail("integrity", `options value has no pinned revision for ${groupKey}`);
			await writeImportedGroupValues(tx, plan, {
				entityType: "options",
				entityId: pageKey
			}, groupKey, sourceRevision, plain$2(value, `staged.options.values.${groupKey}`), sessionId, registry, context);
		}
		return true;
	}
	return false;
}
async function applySnapshotStagedItem(tx, plan, sessionId, staged, principalId, registry, codeRegistry, context) {
	if (staged.action === "skip") return staged.kind === "revision" || staged.kind === "blockDocument";
	const after = plain$2(staged.after, "staged.after");
	if (staged.kind === "revision") {
		const destinationRevisionId = boundedString(after.destinationRevisionId, "staged.revision.destinationRevisionId", 128), sourceRef = ref(after.sourceRef, "staged.revision.sourceRef"), sourceRevisionKey = boundedString(after.sourceRevisionKey, "staged.revision.sourceRevisionKey", 512), definitionVersions = destinationDefinitionVersions(plan, revisionsMap(after.definitionVersions, "staged.revision.definitionVersions")), values = jsonStorage(after.values, "staged.revision.values");
		if (mappedRevisionId(plan, sourceRevisionKey) !== destinationRevisionId) fail("integrity", "revision destination identity differs from plan");
		let serializedBlock = null;
		if (after.blockDocument !== void 0) serializedBlock = await validateImportedBlockDocument(tx, blockDocument(after.blockDocument, DEFAULT_IMPORT_LIMITS, "staged.revision.blockDocument"), registry, codeRegistry, context);
		await tx.execute(sql`INSERT INTO field_revisions (id,entity_type,entity_id,parent_revision_id,parent_autosave_id,kind,retention_class,definition_versions,"values",block_document,created_at,created_by,source_version,host_session_id) VALUES (${destinationRevisionId},${sourceRef.entityType},${sourceRef.entityId},${boundedString(after.parentRevisionKey, "staged.revision.parentRevisionKey", 512)},NULL,'revision',NULL,${JSON.stringify(definitionVersions)},${JSON.stringify(values)},${serializedBlock},${dateString(after.createdAt, "staged.revision.createdAt")},${boundedString(after.createdBySourceId, "staged.revision.createdBySourceId", 512)},${String(positive$2(after.sourceVersion, "staged.revision.sourceVersion"))},${sessionId})`);
		return true;
	}
	if (staged.kind === "blockDocument") {
		const sourceRef = ref(after.sourceRef, "staged.blockDocument.sourceRef"), serialized = await validateImportedBlockDocument(tx, blockDocument(after.document, DEFAULT_IMPORT_LIMITS, "staged.blockDocument.document"), registry, codeRegistry, context), definitionVersions = destinationDefinitionVersions(plan, revisionsMap(after.definitionVersions, "staged.blockDocument.definitionVersions")), before = staged.before === null ? null : plain$2(staged.before, "staged.blockDocument.before"), numericVersion = Number(before?.version ?? 0) + 1, parentRevisionId = `fields-import:${plan.manifestHash.slice(0, 32)}:${(await fieldsRequestHash(sourceRef)).slice(0, 24)}`, now = (/* @__PURE__ */ new Date()).toISOString();
		if (!Number.isSafeInteger(numericVersion) || numericVersion < 1) fail("integrity", "block document before-image version is invalid");
		await tx.execute(sql`INSERT INTO field_block_documents (entity_type,entity_id,version,document,definition_versions,parent_revision_id,host_session_id,updated_by,updated_at) VALUES (${sourceRef.entityType},${sourceRef.entityId},${numericVersion},${serialized},${JSON.stringify(definitionVersions)},${parentRevisionId},${sessionId},${principalId},${now}) ON CONFLICT (entity_type,entity_id) DO UPDATE SET version=EXCLUDED.version,document=EXCLUDED.document,definition_versions=EXCLUDED.definition_versions,parent_revision_id=EXCLUDED.parent_revision_id,host_session_id=EXCLUDED.host_session_id,updated_by=EXCLUDED.updated_by,updated_at=EXCLUDED.updated_at`);
		return true;
	}
	return false;
}
async function applyStagedItem(tx, plan, sessionId, staged, principalId, registry, codeRegistry, context) {
	if (await applyDefinitionStagedItem(tx, plan, sessionId, staged)) return;
	if (await applyValueStagedItem(tx, plan, sessionId, staged, registry, context)) return;
	if (await applySnapshotStagedItem(tx, plan, sessionId, staged, principalId, registry, codeRegistry, context)) return;
	fail("integrity", `unknown staged item kind ${staged.kind}`);
}
function replaceCorpusRow(rows, key, value) {
	const identity = key(plain$2(value, "corpus.row"));
	return Object.freeze([...rows.filter((row) => key(plain$2(row, "corpus.row")) !== identity), value]);
}
function sortedCorpus(snapshot) {
	const sort = (rows, key) => Object.freeze([...rows].sort((a, b) => key(plain$2(a, "corpus.row")).localeCompare(key(plain$2(b, "corpus.row")))));
	return Object.freeze({
		...snapshot,
		nodes: sort(snapshot.nodes, (r) => `${r.entityType}\0${r.entityId}\0${r.groupKey}\0${r.path}`),
		documents: sort(snapshot.documents, (r) => `${r.entityType}\0${r.entityId}`),
		revisions: sort(snapshot.revisions, (r) => `${r.entityType}\0${r.entityId}\0${r.createdAt}\0${r.id}`),
		groups: sort(snapshot.groups, (r) => String(r.key)),
		groupVersions: sort(snapshot.groupVersions, (r) => `${r.groupKey}\0${String(r.revision).padStart(16, "0")}`),
		options: sort(snapshot.options, (r) => String(r.key)),
		optionVersions: sort(snapshot.optionVersions, (r) => `${r.optionsKey}\0${String(r.revision).padStart(16, "0")}`),
		blocks: sort(snapshot.blocks, (r) => String(r.key)),
		blockVersions: sort(snapshot.blockVersions, (r) => `${r.blockKey}\0${String(r.revision).padStart(16, "0")}`)
	});
}
var PUBLISH_KIND_ORDER = Object.freeze({
	groupVersion: 0,
	groupCurrent: 1,
	optionsPage: 2,
	blockVersion: 3,
	blockCurrent: 4,
	entity: 5,
	optionsValues: 5,
	revision: 6,
	blockDocument: 7
});
function inFieldsPublicationOrder(staged) {
	return Object.freeze([...staged].sort((left, right) => (PUBLISH_KIND_ORDER[left.item.kind] ?? Number.MAX_SAFE_INTEGER) - (PUBLISH_KIND_ORDER[right.item.kind] ?? Number.MAX_SAFE_INTEGER) || SECTIONS.indexOf(left.section) - SECTIONS.indexOf(right.section) || left.ordinal - right.ordinal));
}
async function predictFieldsCorpus(db, journal, plan, staged) {
	let snapshot = await readValueCorpus(db, plan.scope);
	const sessionId = journal.staging.hostSessionId;
	for (const { item } of inFieldsPublicationOrder(staged)) {
		if (item.action === "skip") continue;
		const after = plain$2(item.after, "staged.after");
		if (item.kind === "groupVersion") {
			const row = canonicalDefinitionVersionRow({
				groupKey: after.groupKey,
				revision: after.revision,
				canonicalHash: after.canonicalHash,
				definition: after.definition,
				origin: "import",
				hostSessionId: sessionId
			}, "groupKey", "groupVersion");
			snapshot = {
				...snapshot,
				groupVersions: replaceCorpusRow(snapshot.groupVersions, (r) => `${r.groupKey}@${r.revision}`, row)
			};
			continue;
		}
		if (item.kind === "blockVersion") {
			const row = canonicalDefinitionVersionRow({
				blockKey: after.blockKey,
				revision: after.revision,
				canonicalHash: after.canonicalHash,
				definition: after.definition,
				origin: "import",
				hostSessionId: sessionId
			}, "blockKey", "blockVersion");
			snapshot = {
				...snapshot,
				blockVersions: replaceCorpusRow(snapshot.blockVersions, (r) => `${r.blockKey}@${r.revision}`, row)
			};
			continue;
		}
		if (item.kind === "groupCurrent" || item.kind === "blockCurrent" || item.kind === "optionsPage") {
			const definition = after.definition, before = item.before === null ? null : plain$2(item.before, "staged.before"), currentBefore = item.kind === "optionsPage" && before?.current ? plain$2(before.current, "staged.before.current") : before, shadow = item.action === "shadow", currentRevision = positive$2(after.currentRevision, "staged.currentRevision"), canonicalHash = item.kind === "groupCurrent" ? await canonicalFieldGroupHash(after.definition) : await fieldsRequestHash(item.kind === "optionsPage" ? __optionsLifecycleInternals.normalizeOptionsPage(after.definition) : __fieldBlockLifecycleInternals.normalizeDefinition(after.definition)), row = canonicalCurrentDefinitionRow({
				key: definition.key,
				origin: shadow ? currentBefore?.origin ?? "code" : "import",
				version: Number(currentBefore?.version ?? 0) + 1,
				active: shadow ? currentBefore?.active ?? true : definition.active ?? true,
				currentRevision: shadow ? currentBefore?.currentRevision : currentRevision,
				canonicalHash: shadow ? currentBefore?.canonicalHash : canonicalHash,
				definition: shadow ? currentBefore?.definition : definition,
				shadowedDbVersion: shadow ? currentRevision : null,
				hostSessionId: shadow ? currentBefore?.hostSessionId : sessionId
			}, item.kind);
			if (item.kind === "groupCurrent") snapshot = {
				...snapshot,
				groups: replaceCorpusRow(snapshot.groups, (r) => String(r.key), row)
			};
			else if (item.kind === "blockCurrent") snapshot = {
				...snapshot,
				blocks: replaceCorpusRow(snapshot.blocks, (r) => String(r.key), row)
			};
			else {
				snapshot = {
					...snapshot,
					options: replaceCorpusRow(snapshot.options, (r) => String(r.key), row)
				};
				const bundle = before;
				if (!(bundle?.version ? plain$2(bundle.version, "staged.before.version") : null)) {
					const versionRow = canonicalDefinitionVersionRow({
						optionsKey: definition.key,
						revision: currentRevision,
						canonicalHash,
						definition,
						origin: "import",
						hostSessionId: sessionId
					}, "optionsKey", "optionVersion");
					snapshot = {
						...snapshot,
						optionVersions: replaceCorpusRow(snapshot.optionVersions, (r) => `${r.optionsKey}@${r.revision}`, versionRow)
					};
				}
			}
			continue;
		}
		if (item.kind === "entity" || item.kind === "optionsValues") {
			const refValue = item.kind === "entity" ? ref(after.sourceRef, "staged.entity.sourceRef") : {
				entityType: "options",
				entityId: boundedString(after.pageKey, "staged.options.pageKey", 128)
			}, values = plain$2(after.values, "staged.values"), versions = revisionsMap(after.definitionVersions, "staged.definitionVersions");
			for (const [groupKey, value] of Object.entries(values)) {
				const sourceRevision = versions[groupKey];
				if (!sourceRevision) fail("integrity", `value has no pinned revision for ${groupKey}`);
				const source = plan.manifest.definitions.versions.find((entry) => entry.groupKey === groupKey && entry.revision === sourceRevision);
				if (!source) fail("integrity", `missing source group definition ${groupKey}@${sourceRevision}`);
				const destinationRevision = mappedRevision(plan, "grouprev", groupKey, sourceRevision), beforeRows = Array.isArray(item.before) ? item.before.map((raw) => plain$2(raw, "staged.before.node")).filter((row) => row.groupKey === groupKey) : [], byId = new Map(beforeRows.map((row) => [String(row.nodeId), row])), protectedPaths = /* @__PURE__ */ new Set(), sensitiveKeys = sensitiveFieldKeys(source.definition.fields);
				for (const row of beforeRows) if (sensitiveKeys.has(String(row.fieldKey))) {
					let cursor = row;
					while (cursor) {
						protectedPaths.add(String(cursor.path));
						const parentNodeId = cursor.parentNodeId;
						cursor = parentNodeId === null || parentNodeId === void 0 ? void 0 : byId.get(String(parentNodeId));
					}
				}
				const retained = snapshot.nodes.filter((raw) => {
					const row = plain$2(raw, "node");
					return !(row.entityType === refValue.entityType && row.entityId === refValue.entityId && row.groupKey === groupKey) || protectedPaths.has(String(row.path));
				}).map((raw) => {
					const row = plain$2(raw, "node");
					return row.entityType === refValue.entityType && row.entityId === refValue.entityId && row.groupKey === groupKey && protectedPaths.has(String(row.path)) ? canonicalNodeRow({
						...row,
						definitionRevision: destinationRevision,
						hostSessionId: sessionId
					}) : raw;
				}), rows = encodeFieldValueNodes(importWritableGroup(source.definition), filterWritableValues(source.definition.fields, plain$2(value, `staged.values.${groupKey}`)), {
					entityType: refValue.entityType,
					entityId: refValue.entityId,
					definitionRevision: destinationRevision,
					nodeIdForPath: (path) => path
				});
				snapshot = {
					...snapshot,
					nodes: Object.freeze([...retained, ...rows.filter((row) => !protectedPaths.has(row.path)).map((row) => canonicalNodeRow({
						...row,
						hostSessionId: sessionId
					}))])
				};
			}
			continue;
		}
		if (item.kind === "revision") {
			const sourceRef = ref(after.sourceRef, "staged.revision.sourceRef");
			boundedString(after.sourceRevisionKey, "staged.revision.sourceRevisionKey", 512);
			const row = canonicalRevisionRow({
				id: boundedString(after.destinationRevisionId, "staged.revision.destinationRevisionId", 128),
				entityType: sourceRef.entityType,
				entityId: sourceRef.entityId,
				parentRevisionId: boundedString(after.parentRevisionKey, "staged.revision.parentRevisionKey", 512),
				parentAutosaveId: null,
				kind: "revision",
				retentionClass: null,
				definitionVersions: destinationDefinitionVersions(plan, revisionsMap(after.definitionVersions, "staged.revision.definitionVersions")),
				values: after.values,
				blockDocument: after.blockDocument === void 0 ? null : blockDocument(after.blockDocument, DEFAULT_IMPORT_LIMITS, "staged.revision.blockDocument"),
				createdAt: dateString(after.createdAt, "staged.revision.createdAt"),
				createdBy: boundedString(after.createdBySourceId, "staged.revision.createdBySourceId", 512),
				sourceVersion: String(positive$2(after.sourceVersion, "staged.revision.sourceVersion")),
				hostSessionId: sessionId
			});
			snapshot = {
				...snapshot,
				revisions: replaceCorpusRow(snapshot.revisions, (r) => String(r.id), row)
			};
			continue;
		}
		if (item.kind === "blockDocument") {
			const sourceRef = ref(after.sourceRef, "staged.blockDocument.sourceRef"), before = item.before === null ? null : plain$2(item.before, "staged.blockDocument.before"), row = canonicalDocumentRow({
				entityType: sourceRef.entityType,
				entityId: sourceRef.entityId,
				version: Number(before?.version ?? 0) + 1,
				document: blockDocument(after.document, DEFAULT_IMPORT_LIMITS, "staged.blockDocument.document"),
				definitionVersions: destinationDefinitionVersions(plan, revisionsMap(after.definitionVersions, "staged.blockDocument.definitionVersions")),
				hostSessionId: sessionId
			});
			snapshot = {
				...snapshot,
				documents: replaceCorpusRow(snapshot.documents, (r) => `${r.entityType}\0${r.entityId}`, row)
			};
			continue;
		}
		fail("integrity", `unknown staged item kind ${item.kind}`);
	}
	return hashValueCorpus(sortedCorpus(snapshot));
}
function d1StagedNodeBeforePredicate(staged) {
	const expected = [], scopes = [];
	for (const { item } of staged) if ((item.kind === "entity" || item.kind === "optionsValues") && item.action !== "skip") {
		for (const raw of Array.isArray(item.before) ? item.before : []) {
			const row = plain$2(raw, "before.node");
			expected.push(snapshotStorage({
				...row,
				valueJson: row.valueJson === null || row.valueJson === void 0 ? null : corpusJson(row.valueJson, "before.node.valueJson"),
				legacySourceIds: row.legacySourceIds === null || row.legacySourceIds === void 0 ? null : corpusJson(row.legacySourceIds, "before.node.legacySourceIds")
			}, "before.node"));
		}
		const after = plain$2(item.after, "staged.after"), entityType = item.kind === "entity" ? ref(after.sourceRef, "staged.sourceRef").entityType : "options", entityId = item.kind === "entity" ? ref(after.sourceRef, "staged.sourceRef").entityId : String(after.pageKey);
		for (const groupKey of Object.keys(plain$2(after.values, "staged.values"))) scopes.push({
			entityType,
			entityId,
			groupKey
		});
	}
	if (!scopes.length) return sql`1=1`;
	const scopeBytes = JSON.stringify(scopes);
	const where = sql`EXISTS (SELECT 1 FROM json_each(${scopeBytes}) AS imported_scope WHERE json_extract(imported_scope.value,'$.entityType')=entity_type AND json_extract(imported_scope.value,'$.entityId')=entity_id AND json_extract(imported_scope.value,'$.groupKey')=group_key)`;
	return d1ExactJsonSet(expected, sql`SELECT json_object('createdAt',created_at,'definitionRevision',definition_revision,'entityId',entity_id,'entityType',entity_type,'fieldKey',field_key,'groupKey',group_key,'hostSessionId',host_session_id,'isNull',is_null,'layoutKey',layout_key,'legacySourceHash',legacy_source_hash,'legacySourceIds',CASE WHEN legacy_source_ids IS NULL THEN NULL ELSE json(legacy_source_ids) END,'nodeId',node_id,'nodeKind',node_kind,'ordinal',ordinal,'parentNodeId',parent_node_id,'path',path,'rowId',row_id,'updatedAt',updated_at,'valueBoolean',value_boolean,'valueDateTime',value_date_time,'valueJson',CASE WHEN value_json IS NULL THEN NULL ELSE json(value_json) END,'valueNumber',value_number,'valueRef',value_ref,'valueText',value_text) FROM field_value_nodes WHERE ${where}`);
}
async function preparePublishedStagedItems(db, plan, journal, staged, principalId) {
	const items = [], sessionId = journal.staging.hostSessionId, guard = (expected = 1) => items.push(db.prepare(d1AssertPreviousChanges(expected))), push = (statement, expected = 1) => {
		items.push(db.prepare(statement));
		guard(expected);
	};
	for (const { item } of inFieldsPublicationOrder(staged)) {
		if (item.action === "skip") continue;
		const after = plain$2(item.after, "staged.after"), now = (/* @__PURE__ */ new Date()).toISOString();
		if (item.kind === "groupVersion") {
			push(sql`INSERT INTO field_definition_versions (group_key,revision,canonical_hash,definition,origin,host_session_id,created_at) VALUES (${boundedString(after.groupKey, "staged.groupVersion.groupKey", 128)},${positive$2(after.revision, "staged.groupVersion.revision")},${boundedString(after.canonicalHash, "staged.groupVersion.canonicalHash", 128)},${JSON.stringify(after.definition)},'import',${sessionId},${dateString(after.createdAt, "staged.groupVersion.createdAt")})`);
			continue;
		}
		if (item.kind === "blockVersion") {
			push(sql`INSERT INTO field_block_definition_versions (block_key,revision,canonical_hash,definition,origin,host_session_id,created_at) VALUES (${boundedString(after.blockKey, "staged.blockVersion.blockKey", 128)},${positive$2(after.revision, "staged.blockVersion.revision")},${boundedString(after.canonicalHash, "staged.blockVersion.canonicalHash", 128)},${JSON.stringify(after.definition)},'import',${sessionId},${dateString(after.createdAt, "staged.blockVersion.createdAt")})`);
			continue;
		}
		if (item.kind === "groupCurrent" || item.kind === "blockCurrent") {
			const definition = item.kind === "groupCurrent" ? after.definition : __fieldBlockLifecycleInternals.normalizeDefinition(after.definition), active = item.kind === "groupCurrent" ? definition.active : true, key = definition.key, currentRevision = positive$2(after.currentRevision, "staged.current.currentRevision"), canonicalHash = item.kind === "groupCurrent" ? await canonicalFieldGroupHash(definition) : await fieldsRequestHash(definition), table = item.kind === "groupCurrent" ? "field_group_definitions" : "field_block_definitions", before = item.before === null ? null : plain$2(item.before, "staged.before");
			if (item.action === "shadow") {
				push(sql.raw(`UPDATE ${table} SET version=version+1,shadowed_db_version=${currentRevision},updated_at='${now.replaceAll("'", "''")}' WHERE key='${key.replaceAll("'", "''")}' AND origin='code'`));
				continue;
			}
			if (before) {
				const version = Number(before.version) + 1;
				if (!Number.isSafeInteger(version)) fail("integrity", "staged definition version is invalid");
				push(sql.raw(`UPDATE ${table} SET origin='import',version=${version},active=${active ? 1 : 0},current_revision=${currentRevision},canonical_hash='${canonicalHash}',definition='${JSON.stringify(definition).replaceAll("'", "''")}',shadowed_db_version=NULL,host_session_id='${sessionId}',updated_at='${now}' WHERE key='${key.replaceAll("'", "''")}'`));
			} else if (item.kind === "groupCurrent") push(sql`INSERT INTO field_group_definitions (key,origin,version,active,current_revision,canonical_hash,definition,shadowed_db_version,host_session_id,created_at,updated_at) VALUES (${key},'import',1,${active},${currentRevision},${canonicalHash},${JSON.stringify(definition)},NULL,${sessionId},${now},${now})`);
			else push(sql`INSERT INTO field_block_definitions (key,origin,version,active,current_revision,canonical_hash,definition,shadowed_db_version,host_session_id,created_at,updated_at) VALUES (${key},'import',1,true,${currentRevision},${canonicalHash},${JSON.stringify(definition)},NULL,${sessionId},${now},${now})`);
			continue;
		}
		if (item.kind === "optionsPage") {
			const definition = __optionsLifecycleInternals.normalizeOptionsPage(after.definition), currentRevision = positive$2(after.currentRevision, "staged.optionsPage.currentRevision"), canonicalHash = await fieldsRequestHash(definition), bundle = item.before === null ? null : plain$2(item.before, "staged.before"), prior = bundle?.current ? plain$2(bundle.current, "staged.options.before.current") : null;
			if (!(bundle?.version ? plain$2(bundle.version, "staged.options.before.version") : null)) push(sql`INSERT INTO field_options_definition_versions (options_key,revision,canonical_hash,definition,origin,host_session_id,created_at) VALUES (${definition.key},${currentRevision},${canonicalHash},${JSON.stringify(definition)},'import',${sessionId},${now})`);
			if (item.action === "shadow") push(sql`UPDATE field_options_definitions SET version=version+1,shadowed_db_version=${currentRevision},updated_at=${now} WHERE key=${definition.key} AND origin='code'`);
			else if (prior) push(sql`UPDATE field_options_definitions SET origin='import',version=${Number(prior.version) + 1},active=true,current_revision=${currentRevision},canonical_hash=${canonicalHash},definition=${storedJsonText(definition, "before.definition")},shadowed_db_version=NULL,host_session_id=${sessionId},updated_at=${now} WHERE key=${definition.key}`);
			else push(sql`INSERT INTO field_options_definitions (key,origin,version,active,current_revision,canonical_hash,definition,shadowed_db_version,host_session_id,created_at,updated_at) VALUES (${definition.key},'import',1,true,${currentRevision},${canonicalHash},${JSON.stringify(definition)},NULL,${sessionId},${now},${now})`);
			continue;
		}
		if (item.kind === "entity" || item.kind === "optionsValues") {
			const refValue = item.kind === "entity" ? ref(after.sourceRef, "staged.entity.sourceRef") : {
				entityType: "options",
				entityId: boundedString(after.pageKey, "staged.options.pageKey", 128)
			}, values = plain$2(after.values, "staged.values"), versions = revisionsMap(after.definitionVersions, "staged.definitionVersions");
			for (const [groupKey, value] of Object.entries(values)) {
				const sourceRevision = versions[groupKey], source = plan.manifest.definitions.versions.find((entry) => entry.groupKey === groupKey && entry.revision === sourceRevision);
				if (!source || !sourceRevision) fail("integrity", `missing source group definition ${groupKey}`);
				const destinationRevision = mappedRevision(plan, "grouprev", groupKey, sourceRevision), beforeRows = Array.isArray(item.before) ? item.before.map((raw) => plain$2(raw, "before.node")).filter((row) => row.groupKey === groupKey) : [], byId = new Map(beforeRows.map((row) => [String(row.nodeId), row])), protectedIds = /* @__PURE__ */ new Set(), sensitiveKeys = sensitiveFieldKeys(source.definition.fields);
				for (const row of beforeRows) if (sensitiveKeys.has(String(row.fieldKey))) {
					let cursor = row;
					while (cursor) {
						const id = String(cursor.nodeId);
						if (protectedIds.has(id)) break;
						protectedIds.add(id);
						const parentNodeId = cursor.parentNodeId;
						cursor = parentNodeId === null || parentNodeId === void 0 ? void 0 : byId.get(String(parentNodeId));
					}
				}
				const writable = importWritableGroup(source.definition), filtered = filterWritableValues(source.definition.fields, plain$2(value, `staged.values.${groupKey}`)), generated = /* @__PURE__ */ new Map(), existingByPath = new Map(beforeRows.map((row) => [String(row.path), String(row.nodeId)])), encoded = encodeFieldValueNodes(writable, filtered, {
					entityType: refValue.entityType,
					entityId: refValue.entityId,
					definitionRevision: destinationRevision,
					nodeIdForPath: (path) => {
						const existing = existingByPath.get(path) ?? generated.get(path);
						if (existing) return existing;
						const id = crypto.randomUUID();
						generated.set(path, id);
						return id;
					}
				});
				if (protectedIds.size) {
					const ids = [...protectedIds], idsJson = JSON.stringify(ids);
					push(sql`UPDATE field_value_nodes SET definition_revision=${destinationRevision},host_session_id=${sessionId},updated_at=${now} WHERE node_id IN (SELECT value FROM json_each(${idsJson}))`, ids.length);
					push(sql`DELETE FROM field_value_nodes WHERE entity_type=${refValue.entityType} AND entity_id=${refValue.entityId} AND group_key=${groupKey} AND node_id NOT IN (SELECT value FROM json_each(${idsJson}))`, beforeRows.length - ids.length);
				} else push(sql`DELETE FROM field_value_nodes WHERE entity_type=${refValue.entityType} AND entity_id=${refValue.entityId} AND group_key=${groupKey}`, beforeRows.length);
				for (const row of encoded) {
					if (protectedIds.has(row.nodeId)) continue;
					push(sql`INSERT INTO field_value_nodes (node_id,entity_type,entity_id,group_key,definition_revision,field_key,path,parent_node_id,row_id,layout_key,node_kind,ordinal,is_null,value_text,value_number,value_boolean,value_date_time,value_ref,value_json,host_session_id,created_at,updated_at) VALUES (${row.nodeId},${row.entityType},${row.entityId},${row.groupKey},${row.definitionRevision},${row.fieldKey},${row.path},${row.parentNodeId},${row.rowId},${row.layoutKey},${row.nodeKind},${row.ordinal},${row.isNull},${row.valueText},${row.valueNumber},${row.valueBoolean},${row.valueDateTime},${row.valueRef},${row.valueJson},${sessionId},${now},${now})`);
				}
			}
			continue;
		}
		if (item.kind === "revision") {
			const sourceRef = ref(after.sourceRef, "staged.revision.sourceRef"), definitionVersions = destinationDefinitionVersions(plan, revisionsMap(after.definitionVersions, "staged.revision.definitionVersions"));
			push(sql`INSERT INTO field_revisions (id,entity_type,entity_id,parent_revision_id,parent_autosave_id,kind,retention_class,definition_versions,"values",block_document,created_at,created_by,source_version,host_session_id) VALUES (${boundedString(after.destinationRevisionId, "staged.revision.destinationRevisionId", 128)},${sourceRef.entityType},${sourceRef.entityId},${boundedString(after.parentRevisionKey, "staged.revision.parentRevisionKey", 512)},NULL,'revision',NULL,${JSON.stringify(definitionVersions)},${JSON.stringify(after.values)},${after.blockDocument === void 0 ? null : JSON.stringify(blockDocument(after.blockDocument, DEFAULT_IMPORT_LIMITS, "staged.revision.blockDocument"))},${dateString(after.createdAt, "staged.revision.createdAt")},${boundedString(after.createdBySourceId, "staged.revision.createdBySourceId", 512)},${String(positive$2(after.sourceVersion, "staged.revision.sourceVersion"))},${sessionId})`);
			continue;
		}
		if (item.kind === "blockDocument") {
			const sourceRef = ref(after.sourceRef, "staged.blockDocument.sourceRef"), prior = item.before === null ? null : plain$2(item.before, "staged.before"), numericVersion = Number(prior?.version ?? 0) + 1, document = blockDocument(after.document, DEFAULT_IMPORT_LIMITS, "staged.blockDocument.document"), definitionVersions = destinationDefinitionVersions(plan, revisionsMap(after.definitionVersions, "staged.blockDocument.definitionVersions")), parentRevisionId = `fields-import:${plan.manifestHash.slice(0, 32)}:${(await fieldsRequestHash(sourceRef)).slice(0, 24)}`;
			if (prior) push(sql`UPDATE field_block_documents SET version=${numericVersion},document=${JSON.stringify(document)},definition_versions=${JSON.stringify(definitionVersions)},parent_revision_id=${parentRevisionId},host_session_id=${sessionId},updated_by=${principalId},updated_at=${now} WHERE entity_type=${sourceRef.entityType} AND entity_id=${sourceRef.entityId}`);
			else push(sql`INSERT INTO field_block_documents (entity_type,entity_id,version,document,definition_versions,parent_revision_id,host_session_id,updated_by,updated_at) VALUES (${sourceRef.entityType},${sourceRef.entityId},${numericVersion},${JSON.stringify(document)},${JSON.stringify(definitionVersions)},${parentRevisionId},${sessionId},${principalId},${now})`);
			continue;
		}
		fail("integrity", `unknown staged item kind ${item.kind}`);
	}
	return Object.freeze(items);
}
/** D1 publish-import plan. The host appends effects and commits the combined batch. */
async function preparePublishFieldsImportD1(db, importId, command, registry, codeRegistry, context) {
	boundedString(importId, "importId", 128);
	const scopeInput = assertD1Scope(validateCommand(command, false)), authorized = requireAuthorizedFieldsContext(context), scopePolicy = await assertScopeAuthorized(context, scopeInput), requestHash = await fieldsRequestHash({
		kind: "publish",
		importId,
		command,
		registryVersion: registry.version,
		codeRegistryVersion: codeRegistry.version,
		codeRegistryHash: codeRegistry.canonicalHash
	}), principal = principalScope(authorized), receipt = await readFieldsReceipt(db, command.operationId);
	if (receipt) {
		if (receipt.kind !== "fields:import-publish" || receipt.principalScope !== principal || receipt.requestHash !== requestHash) fail("operation-conflict", "operation id was already used with different input or scope");
		const result = receiptJournal(receipt.result);
		return Object.freeze({
			items: d1Items(await d1ImportReplayGuard(db, command.operationId, "fields:import-publish", principal, requestHash, importId, result)),
			result
		});
	}
	const current = await readJournal(db, importId);
	if (!current) fail("access-denied", "import session is unavailable");
	const plan = current.payload.plan;
	await assertPlanIdentity(plan);
	if (!sameScope(scopeInput, plan.scope) || command.expectedPlanId !== plan.planId || command.expectedManifestHash !== plan.manifestHash) fail("operation-conflict", "publish command identity differs from import plan");
	if (scopePolicy !== plan.authorizationPolicyVersion) fail("access-denied", "import session is unavailable");
	if (current.journal.state !== "staged" || current.journal.nextSection !== null || current.journal.nextOffset !== 0) fail("stale-journal", "import is not staged for publication");
	if (await authorizePlan(context, plan) !== plan.authorizationPolicyVersion) fail("access-denied", "import session is unavailable");
	await assertRuntimeBindings(db, plan, registry, codeRegistry, false);
	const expectedVersion = commandVersion(command.expectedJournalVersion, "command.expectedJournalVersion");
	if (expectedVersion === null || command.expectedOffset !== 0 || command.expectedSection !== null || current.journal.version !== command.expectedJournalVersion) fail("stale-journal", "import journal coordinate changed");
	const corpus = await readValueCorpus(db, plan.scope);
	if (await hashValueCorpus(corpus) !== plan.valueCorpusVersion) fail("stale-plan", "destination value corpus changed since plan");
	const stagedRaw = await readVerifiedStaging(db, current.journal, plan), staged = [];
	for (const row of stagedRaw) staged.push({
		...row,
		item: await normalizeStagedForPublish(db, plan, row.item, registry, codeRegistry, context, true)
	});
	const predicted = await predictFieldsCorpus(db, current.journal, plan, staged), nextVersion = expectedVersion + 1, result = Object.freeze({
		...current.journal,
		version: String(nextVersion),
		state: "published",
		nextSection: null,
		nextOffset: 0
	}), payload = Object.freeze({
		plan,
		publishedValueCorpusVersion: predicted
	}), retainedJournalPayloadBytes = retainedPayloadBytes(current.row.payload), now = (/* @__PURE__ */ new Date()).toISOString(), stagingIdentities = await readVerifiedStagingPrefix(db, current.journal, plan);
	const pending = db.prepare(sql`INSERT INTO fields_operation_receipts (operation_id,kind,principal_scope,request_hash,result,created_at) SELECT ${command.operationId},'fields:import-publish',${principal},${requestHash},${JSON.stringify({ pending: true })},${now} WHERE ${d1ValueCorpusPredicate(corpus)} AND ${d1StagingPrefixPredicate(current.journal, stagingIdentities)} AND ${d1StagedNodeBeforePredicate(staged)}`), pendingGuard = db.prepare(d1AssertPreviousChanges(1)), journal = db.prepare(sql`UPDATE fields_import_journal SET version=version+1,state='published',next_section=NULL,next_offset=0,payload=${JSON.stringify(payload)},high_water_mark=${predicted},updated_at=${now} WHERE import_id=${importId} AND host_session_id=${current.journal.staging.hostSessionId} AND version=${expectedVersion} AND state='staged' AND next_section IS NULL AND next_offset=0 AND plan_hash=${plan.planId} AND manifest_hash=${plan.manifestHash} AND payload=${retainedJournalPayloadBytes}`), journalGuard = db.prepare(d1AssertPreviousChanges(1)), mutations = await preparePublishedStagedItems(db, plan, current.journal, staged, authorized.principal.id), complete = db.prepare(sql`UPDATE fields_operation_receipts SET result=${JSON.stringify(result)} WHERE operation_id=${command.operationId} AND kind='fields:import-publish' AND principal_scope=${principal} AND request_hash=${requestHash} AND json(result)=json(${JSON.stringify({ pending: true })})`), completeGuard = db.prepare(d1AssertPreviousChanges(1));
	return boundedD1Contribution(d1Items(pending, pendingGuard, journal, journalGuard, ...mutations, complete, completeGuard), result);
}
async function publishFieldsImport(tx, importId, command, registry, codeRegistry, context, effects) {
	assertActiveFieldsTransaction(tx);
	boundedString(importId, "importId", 128);
	const scope = validateCommand(command, false), authorized = requireAuthorizedFieldsContext(context), scopePolicy = await assertScopeAuthorized(context, scope);
	const requestHash = await fieldsRequestHash({
		kind: "publish",
		importId,
		command,
		registryVersion: registry.version,
		codeRegistryVersion: codeRegistry.version,
		codeRegistryHash: codeRegistry.canonicalHash
	});
	const receipt = await readFieldsReceipt(tx, command.operationId);
	if (receipt) {
		assertReceiptReplay(receipt, {
			kind: "fields:import-publish",
			context: authorized,
			requestHash
		});
		return receiptJournal(receipt.result);
	}
	const current = await readJournal(tx, importId);
	if (!current) fail("access-denied", "import session is unavailable");
	const plan = current.payload.plan;
	await assertPlanIdentity(plan);
	if (!sameScope(scope, plan.scope) || command.expectedPlanId !== plan.planId || command.expectedManifestHash !== plan.manifestHash) fail("operation-conflict", "publish command identity differs from import plan");
	if (scopePolicy !== plan.authorizationPolicyVersion) fail("access-denied", "import session is unavailable");
	if (current.journal.state !== "staged" || current.journal.nextSection !== null || current.journal.nextOffset !== 0) fail("stale-journal", "import is not staged for publication");
	if (await authorizePlan(context, plan) !== plan.authorizationPolicyVersion) fail("access-denied", "import session is unavailable");
	await assertRuntimeBindings(tx, plan, registry, codeRegistry, true);
	const nextVersion = await casJournal(tx, current, command, {
		state: "published",
		section: null,
		offset: 0
	});
	const staged = await readVerifiedStaging(tx, current.journal, plan);
	for (const entry of staged) await applyStagedItem(tx, plan, current.journal.staging.hostSessionId, entry.item, authorized.principal.id, registry, codeRegistry, context);
	const publishedValueCorpusVersion = await valueCorpusVersion(tx, plan.scope), payload = Object.freeze({
		plan,
		publishedValueCorpusVersion
	});
	await tx.execute(sql`UPDATE fields_import_journal SET payload=${JSON.stringify(payload)},high_water_mark=${publishedValueCorpusVersion},updated_at=${(/* @__PURE__ */ new Date()).toISOString()} WHERE import_id=${importId} AND version=${nextVersion}`);
	const journal = Object.freeze({
		...current.journal,
		version: String(nextVersion),
		state: "published",
		nextSection: null,
		nextOffset: 0
	});
	await emitImportEvent(tx, effects, importEvent("published", command.operationId, journal, plan, authorized.principal.id));
	await writeFieldsReceipt(tx, {
		operationId: command.operationId,
		kind: "fields:import-publish",
		context: authorized,
		requestHash,
		result: journalStorage(journal)
	});
	return journal;
}
/** D1 staged-rollback plan. The host appends effects and commits the combined batch. */
async function prepareRollbackFieldsImportD1(db, importId, command, registry, codeRegistry, context) {
	boundedString(importId, "importId", 128);
	const scopeInput = assertD1Scope(validateCommand(command, false)), authorized = requireAuthorizedFieldsContext(context), scopePolicy = await assertScopeAuthorized(context, scopeInput);
	const requestHash = await fieldsRequestHash({
		kind: "rollback",
		importId,
		command,
		registryVersion: registry.version,
		codeRegistryVersion: codeRegistry.version,
		codeRegistryHash: codeRegistry.canonicalHash
	}), principal = principalScope(authorized);
	const receipt = await readFieldsReceipt(db, command.operationId);
	if (receipt) {
		if (receipt.kind !== "fields:import-rollback" || receipt.principalScope !== principal || receipt.requestHash !== requestHash) fail("operation-conflict", "operation id was already used with different input or scope");
		const result = receiptJournal(receipt.result);
		if (result.importId !== importId || result.planId !== command.expectedPlanId || result.manifestHash !== command.expectedManifestHash || !sameScope(result.scope, scopeInput)) fail("operation-conflict", "persisted rollback result differs from requested import");
		return Object.freeze({
			items: d1Items(await d1ImportReplayGuard(db, command.operationId, "fields:import-rollback", principal, requestHash, importId, result)),
			result
		});
	}
	const current = await readJournal(db, importId);
	if (!current) fail("access-denied", "import session is unavailable");
	const plan = current.payload.plan;
	await assertPlanIdentity(plan);
	if (!sameScope(scopeInput, plan.scope) || command.expectedPlanId !== plan.planId || command.expectedManifestHash !== plan.manifestHash) fail("operation-conflict", "rollback command identity differs from import plan");
	if (scopePolicy !== plan.authorizationPolicyVersion) fail("access-denied", "import session is unavailable");
	if (![
		"planned",
		"applying",
		"staged"
	].includes(current.journal.state)) fail("stale-journal", "published or terminal imports cannot use staged rollback");
	if (await authorizePlan(context, plan) !== plan.authorizationPolicyVersion) fail("access-denied", "import session is unavailable");
	await assertRuntimeBindings(db, plan, registry, codeRegistry, false);
	const expectedVersion = commandVersion(command.expectedJournalVersion, "command.expectedJournalVersion");
	if (expectedVersion === null || command.expectedOffset === null || current.journal.version !== command.expectedJournalVersion || current.journal.nextSection !== command.expectedSection || current.journal.nextOffset !== command.expectedOffset) fail("stale-journal", "import journal coordinate changed");
	const stagingIdentities = await readVerifiedStagingPrefix(db, current.journal, plan), nextVersion = expectedVersion + 1;
	const result = Object.freeze({
		...current.journal,
		version: String(nextVersion),
		state: "rolledBack",
		nextSection: null,
		nextOffset: 0
	});
	const now = (/* @__PURE__ */ new Date()).toISOString(), sectionPredicate = command.expectedSection === null ? sql`next_section IS NULL` : sql`next_section=${command.expectedSection}`, payloadBytes = retainedPayloadBytes(current.row.payload);
	const pending = db.prepare(sql`INSERT INTO fields_operation_receipts (operation_id,kind,principal_scope,request_hash,result,created_at) SELECT ${command.operationId},'fields:import-rollback',${principal},${requestHash},${JSON.stringify({ pending: true })},${now} WHERE ${d1StagingPrefixPredicate(current.journal, stagingIdentities)}`);
	const pendingGuard = db.prepare(d1AssertPreviousChanges(1));
	const journal = db.prepare(sql`UPDATE fields_import_journal SET version=version+1,state='rolledBack',next_section=NULL,next_offset=0,updated_at=${now} WHERE import_id=${importId} AND host_session_id=${current.journal.staging.hostSessionId} AND version=${expectedVersion} AND state=${current.journal.state} AND ${sectionPredicate} AND next_offset=${command.expectedOffset} AND plan_hash=${plan.planId} AND manifest_hash=${plan.manifestHash} AND payload=${payloadBytes}`);
	const journalGuard = db.prepare(d1AssertPreviousChanges(1));
	const cleanup = db.prepare(sql`DELETE FROM fields_import_staging WHERE host_session_id=${current.journal.staging.hostSessionId}`);
	const cleanupGuard = db.prepare(d1AssertPreviousChanges(stagingIdentities.length));
	const complete = db.prepare(sql`UPDATE fields_operation_receipts SET result=${JSON.stringify(result)} WHERE operation_id=${command.operationId} AND kind='fields:import-rollback' AND principal_scope=${principal} AND request_hash=${requestHash} AND json(result)=json(${JSON.stringify({ pending: true })})`);
	const completeGuard = db.prepare(d1AssertPreviousChanges(1));
	return Object.freeze({
		items: d1Items(pending, pendingGuard, journal, journalGuard, cleanup, cleanupGuard, complete, completeGuard),
		result
	});
}
async function rollbackFieldsImport(tx, importId, command, registry, codeRegistry, context, effects) {
	assertActiveFieldsTransaction(tx);
	boundedString(importId, "importId", 128);
	const scope = validateCommand(command, false), authorized = requireAuthorizedFieldsContext(context), scopePolicy = await assertScopeAuthorized(context, scope);
	const requestHash = await fieldsRequestHash({
		kind: "rollback",
		importId,
		command,
		registryVersion: registry.version,
		codeRegistryVersion: codeRegistry.version,
		codeRegistryHash: codeRegistry.canonicalHash
	});
	const receipt = await readFieldsReceipt(tx, command.operationId);
	if (receipt) {
		assertReceiptReplay(receipt, {
			kind: "fields:import-rollback",
			context: authorized,
			requestHash
		});
		return receiptJournal(receipt.result);
	}
	const current = await readJournal(tx, importId);
	if (!current) fail("access-denied", "import session is unavailable");
	const plan = current.payload.plan;
	await assertPlanIdentity(plan);
	if (!sameScope(scope, plan.scope) || command.expectedPlanId !== plan.planId || command.expectedManifestHash !== plan.manifestHash) fail("operation-conflict", "rollback command identity differs from import plan");
	if (scopePolicy !== plan.authorizationPolicyVersion) fail("access-denied", "import session is unavailable");
	if (![
		"planned",
		"applying",
		"staged"
	].includes(current.journal.state)) fail("stale-journal", "published or terminal imports cannot use staged rollback");
	if (await authorizePlan(context, plan) !== plan.authorizationPolicyVersion) fail("access-denied", "import session is unavailable");
	await assertRuntimeBindings(tx, plan, registry, codeRegistry, false);
	const nextVersion = await casJournal(tx, current, command, {
		state: "rolledBack",
		section: null,
		offset: 0
	});
	await tx.execute(sql`DELETE FROM fields_import_staging WHERE host_session_id=${current.journal.staging.hostSessionId}`);
	const journal = Object.freeze({
		...current.journal,
		version: String(nextVersion),
		state: "rolledBack",
		nextSection: null,
		nextOffset: 0
	});
	await emitImportEvent(tx, effects, importEvent("rolledBack", command.operationId, journal, plan, authorized.principal.id));
	await writeFieldsReceipt(tx, {
		operationId: command.operationId,
		kind: "fields:import-rollback",
		context: authorized,
		requestHash,
		result: journalStorage(journal)
	});
	return journal;
}
function rowsOf$1(value) {
	if (Array.isArray(value)) return value;
	if (typeof value === "object" && value !== null && Array.isArray(value.rows)) return value.rows;
	throw new Error("database adapter returned invalid rows");
}
async function execute$1(db, query) {
	return rowsOf$1(await db.execute(query));
}
function parseJson$1(value, field) {
	if (typeof value !== "string") return value;
	try {
		return JSON.parse(value);
	} catch {
		throw new Error(`${field} contains invalid JSON`);
	}
}
function record(value, field) {
	const parsed = parseJson$1(value, field);
	if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new Error(`${field} is malformed`);
	return parsed;
}
function positive$1(value, field) {
	const n = Number(value);
	if (!Number.isSafeInteger(n) || n < 1) throw new Error(`${field} is invalid`);
	return n;
}
function iso(value, field) {
	const date = value instanceof Date ? new Date(value) : new Date(String(value));
	if (Number.isNaN(date.getTime())) throw new Error(`${field} is invalid`);
	return date.toISOString();
}
function normalizedGroupKey(value) {
	if (!/^[a-z][a-z0-9_]*$/.test(value)) throw new Error("selection contains invalid group key");
	return value;
}
function normalizedRef(value) {
	if (!value.entityType || !value.entityId || value.entityType.length > 256 || value.entityId.length > 512) throw new Error("selection contains invalid entity reference");
	return Object.freeze({
		entityType: value.entityType,
		entityId: value.entityId
	});
}
function node(row) {
	return Object.freeze({
		nodeId: String(row.nodeId),
		entityType: String(row.entityType),
		entityId: String(row.entityId),
		groupKey: String(row.groupKey),
		definitionRevision: Number(row.definitionRevision),
		fieldKey: String(row.fieldKey),
		path: String(row.path),
		parentNodeId: row.parentNodeId === null ? null : String(row.parentNodeId),
		rowId: row.rowId === null ? null : String(row.rowId),
		layoutKey: row.layoutKey === null ? null : String(row.layoutKey),
		nodeKind: row.nodeKind,
		ordinal: Number(row.ordinal),
		isNull: row.isNull === true || row.isNull === 1,
		valueText: row.valueText,
		valueNumber: row.valueNumber === null ? null : Number(row.valueNumber),
		valueBoolean: row.valueBoolean === null ? null : row.valueBoolean === true || row.valueBoolean === 1,
		valueDateTime: row.valueDateTime,
		valueRef: row.valueRef,
		valueJson: row.valueJson
	});
}
function plain$1(value, field) {
	if (typeof value !== "object" || value === null || Array.isArray(value) || Object.getPrototypeOf(value) !== Object.prototype) throw new Error(`${field} must be a plain object`);
	return value;
}
function sanitizeCustom$1(value, registry) {
	const row = plain$1(value, "field"), type = String(row.type), copy = { ...row };
	if (!registry.has(type)) throw new Error(`unregistered field type ${type}`);
	if (type === "group" || type === "repeater") {
		const settings = plain$1(row.settings, "field.settings");
		copy.settings = {
			...settings,
			fields: settings.fields.map((child) => sanitizeCustom$1(child, registry))
		};
	}
	if (type === "flexible") {
		const settings = plain$1(row.settings, "field.settings");
		copy.settings = {
			...settings,
			layouts: settings.layouts.map((layoutRaw) => {
				const layout = plain$1(layoutRaw, "layout");
				return {
					...layout,
					fields: layout.fields.map((child) => sanitizeCustom$1(child, registry))
				};
			})
		};
	}
	if (!registry.builtInTypes.has(type)) return {
		...copy,
		type: "text",
		settings: {}
	};
	return copy;
}
function validateFieldTree$1(value, registry) {
	const raw = plain$1(value, "field"), type = String(raw.type), descriptor = registry.resolve(type);
	if (!descriptor) throw new Error(`unregistered field type ${type}`);
	const parsed = descriptor.parseDefinition(registry.builtInTypes.has(type) ? sanitizeCustom$1(raw, registry) : raw, FIELD_DEFINITION_LIMITS);
	if (parsed.type !== type) throw new Error("field descriptor changed type identity");
	if (type === "group" || type === "repeater") {
		const settings = plain$1(raw.settings, "field.settings");
		for (const child of settings.fields) validateFieldTree$1(child, registry);
	}
	if (type === "flexible") {
		const settings = plain$1(raw.settings, "field.settings");
		for (const layoutRaw of settings.layouts) {
			const layout = plain$1(layoutRaw, "layout");
			for (const child of layout.fields) validateFieldTree$1(child, registry);
		}
	}
	return parsed;
}
function parseGroup$1(value, registry) {
	const raw = plain$1(parseJson$1(value, "field group"), "field group"), fields = raw.fields;
	if (!Array.isArray(fields)) throw new Error("field group fields are malformed");
	for (const field of fields) validateFieldTree$1(field, registry);
	const structural = parseFieldGroupDefinition({
		...raw,
		fields: fields.map((field) => sanitizeCustom$1(field, registry))
	});
	return Object.freeze({
		...structural,
		fields: Object.freeze(fields.map((field) => Object.freeze({ ...plain$1(field, "field") })))
	});
}
function definitionVersions(value) {
	const source = record(value, "definitionVersions"), out = {};
	for (const [key, raw] of Object.entries(source)) out[key] = positive$1(raw, `definitionVersions.${key}`);
	return Object.freeze(out);
}
function redactedGroupValues(group, input, registry, sourceRef, base, omissions) {
	const output = {};
	const walk = (fields, source, target, path) => {
		for (const field of fields) {
			if (!Object.prototype.hasOwnProperty.call(source, field.key)) continue;
			const value = source[field.key], fieldPath = Object.freeze([...path, field.key]);
			if (field.type === "password") {
				omissions.push(Object.freeze({
					sourceRef,
					fieldPath,
					reason: "sensitive"
				}));
				continue;
			}
			if (field.type === "group" && value && typeof value === "object" && !Array.isArray(value)) {
				const child = {};
				walk(field.settings.fields, value, child, fieldPath);
				target[field.key] = Object.freeze(child);
				continue;
			}
			if (field.type === "repeater" && Array.isArray(value)) {
				target[field.key] = Object.freeze(value.map((raw, index) => {
					const row = plain$1(raw, `repeater.${index}`), values = plain$1(row.values, `repeater.${index}.values`), child = {};
					walk(field.settings.fields, values, child, Object.freeze([...fieldPath, index]));
					return Object.freeze({
						...row,
						values: Object.freeze(child)
					});
				}));
				continue;
			}
			if (field.type === "flexible" && Array.isArray(value)) {
				target[field.key] = Object.freeze(value.map((raw, index) => {
					const row = plain$1(raw, `flexible.${index}`), layout = field.settings.layouts.find((item) => item.key === row.layoutKey);
					if (!layout) return row;
					const values = plain$1(row.values, `flexible.${index}.values`), child = {};
					walk(layout.fields, values, child, Object.freeze([...fieldPath, index]));
					return Object.freeze({
						...row,
						values: Object.freeze(child)
					});
				}));
				continue;
			}
			if (field.type === "clone") {
				omissions.push(Object.freeze({
					sourceRef,
					fieldPath,
					reason: "sensitive"
				}));
				continue;
			}
			if (!registry.resolve(field.type)) throw new Error(`unregistered field type ${field.type}`);
			const redacted = redactFieldValueForRevision(field, value, registry);
			if (redacted === "omit") {
				omissions.push(Object.freeze({
					sourceRef,
					fieldPath,
					reason: "sensitive"
				}));
				continue;
			}
			target[field.key] = redacted;
		}
	};
	walk(group.fields, input, output, base);
	return Object.freeze(output);
}
async function readGroupVersion(db, groupKey, revision, registry) {
	const row = (await execute$1(db, sql`SELECT group_key AS "groupKey",revision,canonical_hash AS "canonicalHash",definition,created_at AS "createdAt",origin FROM field_definition_versions WHERE group_key=${groupKey} AND revision=${revision} AND (host_session_id IS NULL OR EXISTS (SELECT 1 FROM fields_import_journal j WHERE j.host_session_id=field_definition_versions.host_session_id AND j.state='published')) LIMIT 1`))[0];
	if (!row) throw new Error(`immutable field definition missing: ${groupKey}@${revision}`);
	return {
		definition: parseGroup$1(row.definition, registry),
		row
	};
}
async function readEntityValues(db, refValue, registry, omissions) {
	const rows = await execute$1(db, sql`SELECT node_id AS "nodeId",entity_type AS "entityType",entity_id AS "entityId",group_key AS "groupKey",definition_revision AS "definitionRevision",field_key AS "fieldKey",path,parent_node_id AS "parentNodeId",row_id AS "rowId",layout_key AS "layoutKey",node_kind AS "nodeKind",ordinal,is_null AS "isNull",value_text AS "valueText",value_number AS "valueNumber",value_boolean AS "valueBoolean",value_date_time AS "valueDateTime",value_ref AS "valueRef",value_json AS "valueJson" FROM field_value_nodes WHERE entity_type=${refValue.entityType} AND entity_id=${refValue.entityId} AND (host_session_id IS NULL OR EXISTS (SELECT 1 FROM fields_import_journal j WHERE j.host_session_id=field_value_nodes.host_session_id AND j.state='published')) ORDER BY group_key,path`);
	const buckets = /* @__PURE__ */ new Map();
	for (const row of rows) {
		const bucket = buckets.get(row.groupKey) ?? [];
		bucket.push(row);
		buckets.set(row.groupKey, bucket);
	}
	const values = {}, versions = {};
	for (const [groupKey, bucket] of [...buckets].sort(([a], [b]) => a.localeCompare(b))) {
		const revisions = [...new Set(bucket.map((row) => Number(row.definitionRevision)))];
		if (revisions.length !== 1) throw new Error(`entity group mixes immutable revisions: ${groupKey}`);
		const revision = revisions[0], resolved = await readGroupVersion(db, groupKey, revision, registry), decoded = decodeFieldValueNodes(resolved.definition, bucket.map(node), { definitionRevision: revision });
		values[groupKey] = redactedGroupValues(resolved.definition, decoded, registry, refValue, Object.freeze([groupKey]), omissions);
		versions[groupKey] = revision;
	}
	return {
		values: Object.freeze(values),
		definitionVersions: Object.freeze(versions)
	};
}
async function exportFields(db, selection, context) {
	requireAuthorizedFieldsContext(context);
	const registry = context.fieldTypeRegistry ?? createFieldTypeRegistry(), omissions = [];
	const requestedGroups = selection.groups === void 0 ? null : Object.freeze([...new Set(selection.groups.map(normalizedGroupKey))].sort());
	if (requestedGroups) for (const key of requestedGroups) await assertFieldsAuthorized(context, "manageDefinitions", {
		entityType: "fields-group-definition",
		entityId: key
	});
	else await assertFieldsAuthorized(context, "manageDefinitions", {
		entityType: "fields-group-definition",
		entityId: "*"
	});
	const entities = Object.freeze((selection.entities ?? []).map(normalizedRef));
	if (entities.length > 1e4) throw new Error("too many export entities");
	const readable = [];
	for (const entity of entities) try {
		await assertFieldsAuthorized(context, "read", entity);
		readable.push(entity);
	} catch {
		omissions.push(Object.freeze({
			sourceRef: entity,
			fieldPath: Object.freeze(["*"]),
			reason: "unauthorized"
		}));
	}
	if (selection.includeOptions) await assertFieldsAuthorized(context, "manageDefinitions", {
		entityType: "fields-options-definition",
		entityId: "*"
	});
	if (selection.includeBlocks) await assertFieldsAuthorized(context, "manageDefinitions", {
		entityType: "fields-block-definition",
		entityId: "*"
	});
	const groupClause = requestedGroups && requestedGroups.length ? sql`AND key IN (${sql.join(requestedGroups.map((key) => sql`${key}`), sql`, `)})` : requestedGroups ? sql`AND FALSE` : sql``;
	const groups = (await execute$1(db, sql`SELECT key,definition,current_revision AS "currentRevision" FROM field_group_definitions WHERE (host_session_id IS NULL OR EXISTS (SELECT 1 FROM fields_import_journal j WHERE j.host_session_id=field_group_definitions.host_session_id AND j.state='published')) ${groupClause} ORDER BY key`)).map((row) => parseGroup$1(row.definition, registry)), keys = groups.map((group) => group.key);
	const versions = [];
	if (keys.length) {
		const versionRows = await execute$1(db, sql`SELECT group_key AS "groupKey",revision,canonical_hash AS "canonicalHash",definition,created_at AS "createdAt",origin FROM field_definition_versions WHERE group_key IN (${sql.join(keys.map((key) => sql`${key}`), sql`, `)}) AND (host_session_id IS NULL OR EXISTS (SELECT 1 FROM fields_import_journal j WHERE j.host_session_id=field_definition_versions.host_session_id AND j.state='published')) ORDER BY group_key,revision`);
		for (const row of versionRows) versions.push(Object.freeze({
			groupKey: row.groupKey,
			revision: positive$1(row.revision, "revision"),
			canonicalHash: String(row.canonicalHash),
			definition: parseGroup$1(row.definition, registry),
			createdAt: iso(row.createdAt, "createdAt"),
			origin: row.origin
		}));
	}
	const optionPages = [];
	if (selection.includeOptions) {
		const rows = await execute$1(db, sql`SELECT key,definition FROM field_options_definitions WHERE active=true AND (host_session_id IS NULL OR EXISTS (SELECT 1 FROM fields_import_journal j WHERE j.host_session_id=field_options_definitions.host_session_id AND j.state='published')) ORDER BY key`);
		for (const row of rows) optionPages.push(__optionsLifecycleInternals.normalizeOptionsPage(parseJson$1(row.definition, "options definition")));
	}
	const blocks = [], blockVersions = [];
	if (selection.includeBlocks) {
		const current = await execute$1(db, sql`SELECT key,definition FROM field_block_definitions WHERE active=true AND (host_session_id IS NULL OR EXISTS (SELECT 1 FROM fields_import_journal j WHERE j.host_session_id=field_block_definitions.host_session_id AND j.state='published')) ORDER BY key`);
		for (const row of current) blocks.push(__fieldBlockLifecycleInternals.normalizeDefinition(parseJson$1(row.definition, "block definition")));
		const rows = await execute$1(db, sql`SELECT block_key AS "blockKey",revision,canonical_hash AS "canonicalHash",definition,created_at AS "createdAt",origin FROM field_block_definition_versions WHERE (host_session_id IS NULL OR EXISTS (SELECT 1 FROM fields_import_journal j WHERE j.host_session_id=field_block_definition_versions.host_session_id AND j.state='published')) ORDER BY block_key,revision`);
		for (const row of rows) blockVersions.push(Object.freeze({
			blockKey: row.blockKey,
			revision: positive$1(row.revision, "block revision"),
			canonicalHash: String(row.canonicalHash),
			definition: __fieldBlockLifecycleInternals.normalizeDefinition(parseJson$1(row.definition, "block version")),
			createdAt: iso(row.createdAt, "block createdAt"),
			origin: row.origin
		}));
	}
	const entityExports = [];
	for (const entity of readable) {
		const snapshot = await readEntityValues(db, entity, registry, omissions);
		entityExports.push(Object.freeze({
			sourceRef: entity,
			values: snapshot.values,
			definitionVersions: snapshot.definitionVersions
		}));
	}
	const revisions = [];
	if (selection.includeRevisions && readable.length) for (const entity of readable) {
		const rows = await execute$1(db, sql`SELECT id,entity_type AS "entityType",entity_id AS "entityId",parent_revision_id AS "parentRevisionId",definition_versions AS "definitionVersions","values" AS "values",block_document AS "blockDocument",created_at AS "createdAt",created_by AS "createdBy",source_version AS "sourceVersion" FROM field_revisions WHERE entity_type=${entity.entityType} AND entity_id=${entity.entityId} AND kind='revision' AND (host_session_id IS NULL OR EXISTS (SELECT 1 FROM fields_import_journal j WHERE j.host_session_id=field_revisions.host_session_id AND j.state='published')) ORDER BY created_at,id`);
		for (const row of rows) {
			const pinned = definitionVersions(row.definitionVersions), sourceValues = record(row.values, "revision values"), clean = {};
			for (const [groupKey, value] of Object.entries(sourceValues)) {
				const revision = pinned[groupKey];
				if (!revision) continue;
				clean[groupKey] = redactedGroupValues((await readGroupVersion(db, groupKey, revision, registry)).definition, record(value, `revision.${groupKey}`), registry, entity, Object.freeze([groupKey]), omissions);
			}
			const block = row.blockDocument === null ? void 0 : parseBlockDocument(JSON.stringify(parseJson$1(row.blockDocument, "revision block")), DEFAULT_BLOCK_POLICY);
			revisions.push(Object.freeze({
				sourceRevisionKey: row.id,
				sourceRef: entity,
				parentRevisionKey: row.parentRevisionId,
				definitionVersions: pinned,
				values: Object.freeze(clean),
				...block ? { blockDocument: block } : {},
				createdAt: iso(row.createdAt, "revision createdAt"),
				createdBySourceId: row.createdBy,
				sourceVersion: positive$1(row.sourceVersion, "revision sourceVersion")
			}));
		}
	}
	const options = [];
	if (selection.includeOptions) for (const page of optionPages) {
		try {
			await assertFieldsAuthorized(context, "read", {
				entityType: "options",
				entityId: page.key
			});
		} catch {
			omissions.push(Object.freeze({
				sourceRef: Object.freeze({
					entityType: "options",
					entityId: page.key
				}),
				fieldPath: Object.freeze(["*"]),
				reason: "unauthorized"
			}));
			continue;
		}
		const snapshot = await readEntityValues(db, {
			entityType: "options",
			entityId: page.key
		}, registry, omissions);
		options.push(Object.freeze({
			pageKey: page.key,
			values: snapshot.values,
			definitionVersions: snapshot.definitionVersions,
			revision: 1
		}));
	}
	const blockDocuments = [];
	if (selection.includeBlocks) for (const entity of readable) {
		const row = (await execute$1(db, sql`SELECT entity_type AS "entityType",entity_id AS "entityId",version,document,definition_versions AS "definitionVersions" FROM field_block_documents WHERE entity_type=${entity.entityType} AND entity_id=${entity.entityId} AND (host_session_id IS NULL OR EXISTS (SELECT 1 FROM fields_import_journal j WHERE j.host_session_id=field_block_documents.host_session_id AND j.state='published')) LIMIT 1`))[0];
		if (row) blockDocuments.push(Object.freeze({
			sourceRef: entity,
			document: parseBlockDocument(JSON.stringify(parseJson$1(row.document, "block document")), DEFAULT_BLOCK_POLICY),
			version: String(row.version),
			definitionVersions: definitionVersions(row.definitionVersions)
		}));
	}
	return Object.freeze({
		version: 1,
		definitions: Object.freeze({
			groups: Object.freeze(groups),
			versions: Object.freeze(versions),
			optionsPages: Object.freeze(optionPages),
			blocks: Object.freeze(blocks),
			blockVersions: Object.freeze(blockVersions)
		}),
		...entityExports.length ? { entities: Object.freeze(entityExports) } : {},
		...revisions.length ? { revisions: Object.freeze(revisions) } : {},
		...options.length ? { options: Object.freeze(options) } : {},
		...blockDocuments.length ? { blockDocuments: Object.freeze(blockDocuments) } : {},
		omissions: Object.freeze(omissions)
	});
}
var FieldsHeadlessError = class extends Error {
	code;
	detail;
	field;
	name = "FieldsHeadlessError";
	constructor(code, detail, field) {
		super(`fields headless ${code}: ${detail}${field ? ` (${field})` : ""}`);
		this.code = code;
		this.detail = detail;
		this.field = field;
	}
};
function rowsOf(value) {
	if (Array.isArray(value)) return value;
	if (typeof value === "object" && value !== null && Array.isArray(value.rows)) return value.rows;
	throw new FieldsHeadlessError("integrity", "database adapter returned invalid rows");
}
async function execute(db, query) {
	return rowsOf(await db.execute(query));
}
function parseJson(value, field) {
	if (typeof value !== "string") return value;
	try {
		return JSON.parse(value);
	} catch {
		throw new FieldsHeadlessError("integrity", `${field} contains invalid JSON`);
	}
}
function plain(value, field) {
	const parsed = parseJson(value, field);
	if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || Object.getPrototypeOf(parsed) !== Object.prototype) throw new FieldsHeadlessError("invalid-definition", "must be a plain object", field);
	return parsed;
}
function positive(value, field) {
	const n = Number(value);
	if (!Number.isSafeInteger(n) || n < 1) throw new FieldsHeadlessError("integrity", "must be a positive integer", field);
	return n;
}
function bool(value) {
	return value === true || value === 1;
}
function serializable(value, field = "schema", depth = 0) {
	if (depth > 24) throw new FieldsHeadlessError("invalid-definition", "schema exceeds maximum depth", field);
	if (value === null || typeof value === "string" || typeof value === "boolean") return value;
	if (typeof value === "number") {
		if (!Number.isFinite(value)) throw new FieldsHeadlessError("invalid-definition", "schema contains non-finite number", field);
		return value;
	}
	if (Array.isArray(value)) return Object.freeze(value.map((item, index) => serializable(item, `${field}.${index}`, depth + 1)));
	if (typeof value === "object") {
		const out = {};
		for (const key of Object.keys(value).sort()) {
			const child = value[key];
			if (child !== void 0) out[key] = serializable(child, `${field}.${key}`, depth + 1);
		}
		return Object.freeze(out);
	}
	throw new FieldsHeadlessError("invalid-definition", "schema contains unsupported value", field);
}
function sanitizeCustom(value, registry) {
	const row = plain(value, "field"), type = String(row.type), copy = { ...row };
	if (!registry.has(type)) throw new FieldsHeadlessError("invalid-registry", `unregistered field type ${type}`, "field.type");
	if (type === "group" || type === "repeater") {
		const s = plain(row.settings, "field.settings"), fields = s.fields;
		if (!Array.isArray(fields)) throw new FieldsHeadlessError("invalid-definition", "nested fields are malformed", "field.settings.fields");
		copy.settings = {
			...s,
			fields: fields.map((child) => sanitizeCustom(child, registry))
		};
	}
	if (type === "flexible") {
		const s = plain(row.settings, "field.settings"), layouts = s.layouts;
		if (!Array.isArray(layouts)) throw new FieldsHeadlessError("invalid-definition", "layouts are malformed", "field.settings.layouts");
		copy.settings = {
			...s,
			layouts: layouts.map((raw) => {
				const layout = plain(raw, "layout"), fields = layout.fields;
				if (!Array.isArray(fields)) throw new FieldsHeadlessError("invalid-definition", "layout fields are malformed", "layout.fields");
				return {
					...layout,
					fields: fields.map((child) => sanitizeCustom(child, registry))
				};
			})
		};
	}
	return registry.builtInTypes.has(type) ? copy : {
		...copy,
		type: "text",
		settings: {}
	};
}
function validateFieldTree(value, registry) {
	const raw = plain(value, "field"), type = String(raw.type), descriptor = registry.resolve(type);
	if (!descriptor) throw new FieldsHeadlessError("invalid-registry", `unregistered field type ${type}`, "field.type");
	if (descriptor.parseDefinition(registry.builtInTypes.has(type) ? sanitizeCustom(raw, registry) : raw, FIELD_DEFINITION_LIMITS).type !== type) throw new FieldsHeadlessError("invalid-registry", "descriptor changed immutable type identity", "field.type");
	if (type === "group" || type === "repeater") for (const child of plain(raw.settings, "field.settings").fields) validateFieldTree(child, registry);
	if (type === "flexible") for (const layoutRaw of plain(raw.settings, "field.settings").layouts) for (const child of plain(layoutRaw, "layout").fields) validateFieldTree(child, registry);
}
function parseGroup(value, registry) {
	const raw = plain(value, "group"), fields = raw.fields;
	if (!Array.isArray(fields)) throw new FieldsHeadlessError("invalid-definition", "group fields are malformed", "fields");
	for (const field of fields) validateFieldTree(field, registry);
	const structural = parseFieldGroupDefinition({
		...raw,
		fields: fields.map((field) => sanitizeCustom(field, registry))
	});
	return Object.freeze({
		...structural,
		fields: Object.freeze(fields.map((field) => Object.freeze({ ...plain(field, "field") })))
	});
}
var ADMIN_TYPES = /* @__PURE__ */ new Set([
	"message",
	"accordion",
	"tab"
]);
function publicChildFields(fields, registry) {
	return Object.freeze(fields.map((field) => fieldSchema(field, registry)).filter((field) => field !== null));
}
function structuredValueSchema(field, registry) {
	if (field.type === "group") {
		const settings = field.settings;
		return Object.freeze({
			type: "group",
			nullable: false,
			constraints: serializable({
				...settings.layout ? { layout: settings.layout } : {},
				fields: publicChildFields(settings.fields, registry)
			}, "field.group.constraints")
		});
	}
	if (field.type === "repeater") {
		const settings = field.settings;
		const publicKeys = new Set(publicChildFields(settings.fields, registry).map((child) => child.key)), fields = publicChildFields(settings.fields, registry);
		return Object.freeze({
			type: "repeater",
			nullable: false,
			constraints: serializable({
				fields,
				...settings.layout ? { layout: settings.layout } : {},
				...settings.min === void 0 ? {} : { min: settings.min },
				...settings.max === void 0 ? {} : { max: settings.max },
				...settings.collapsedBy && publicKeys.has(settings.collapsedBy) ? { collapsedBy: settings.collapsedBy } : {},
				...settings.pagination ? { pagination: { pageSize: settings.pagination.pageSize } } : {}
			}, "field.repeater.constraints")
		});
	}
	if (field.type === "flexible") {
		const settings = field.settings;
		return Object.freeze({
			type: "flexible",
			nullable: false,
			constraints: serializable({
				layouts: settings.layouts.map((layout) => ({
					key: layout.key,
					name: layout.name,
					label: layout.label,
					fields: publicChildFields(layout.fields, registry)
				})),
				...settings.min === void 0 ? {} : { min: settings.min },
				...settings.max === void 0 ? {} : { max: settings.max }
			}, "field.flexible.constraints")
		});
	}
	if (field.type === "clone") {
		const settings = field.settings;
		return Object.freeze({
			type: "clone",
			nullable: false,
			constraints: serializable({
				resolution: "host",
				...settings.display ? { display: settings.display } : {},
				...settings.prefixNames === void 0 ? {} : { prefixNames: settings.prefixNames }
			}, "field.clone.constraints")
		});
	}
	return null;
}
function fieldSchema(field, registry) {
	if (field.disabled === true || ADMIN_TYPES.has(field.type)) return null;
	let value;
	if (field.type === "password") value = Object.freeze({
		type: "object",
		nullable: false,
		readOnly: true,
		constraints: Object.freeze({ properties: Object.freeze({ configured: Object.freeze({ type: "boolean" }) }) })
	});
	else value = structuredValueSchema(field, registry) ?? (() => {
		const descriptor = registry.resolve(field.type);
		if (!descriptor) throw new FieldsHeadlessError("invalid-registry", `unregistered field type ${field.type}`);
		return descriptor.schema(field.settings);
	})();
	const formatted = Object.freeze({ oneOf: Object.freeze([
		Object.freeze({
			kind: "text",
			value: "string"
		}),
		Object.freeze({
			kind: "structured",
			value: "json"
		}),
		Object.freeze({
			kind: "sanitizedHtml",
			value: "string"
		})
	]) });
	return Object.freeze({
		key: field.key,
		name: field.name,
		label: field.label,
		type: field.type,
		required: field.required === true,
		readOnly: field.readOnly === true || field.type === "password" || value.readOnly === true,
		value: Object.freeze({
			...value,
			constraints: serializable(value.constraints, "field.constraints")
		}),
		formatted,
		...field.conditionalLogic ? { conditionalLogic: serializable(field.conditionalLogic, "field.conditionalLogic") } : {}
	});
}
function publicFields(group, registry) {
	return publicChildFields(group.fields, registry);
}
function blockTreeSchema() {
	return Object.freeze({
		version: 1,
		node: Object.freeze({ oneOf: Object.freeze([Object.freeze({
			kind: "inline",
			required: Object.freeze([
				"id",
				"type",
				"blockDefinitionRevision",
				"fieldGroups"
			]),
			children: "recursive"
		}), Object.freeze({
			kind: "reusable",
			required: Object.freeze(["id", "reusableId"])
		})]) })
	});
}
async function assertCodeRegistry(snapshot) {
	if (!snapshot) return;
	if (await fieldsRequestHash({
		version: snapshot.version,
		groups: snapshot.groups,
		optionsPages: snapshot.optionsPages,
		blocks: snapshot.blocks
	}) !== snapshot.canonicalHash) throw new FieldsHeadlessError("invalid-registry", "code registry hash mismatch");
}
async function generateFieldsHeadlessSchema(db, options = {}) {
	const registry = options.registry ?? createFieldTypeRegistry();
	await assertCodeRegistry(options.codeRegistry);
	const groupRows = await execute(db, sql`SELECT key,origin,version,active,current_revision AS "currentRevision",definition FROM field_group_definitions WHERE active=true AND (host_session_id IS NULL OR EXISTS (SELECT 1 FROM fields_import_journal j WHERE j.host_session_id=field_group_definitions.host_session_id AND j.state='published')) ORDER BY key`);
	const optionRows = await execute(db, sql`SELECT key,origin,version,active,current_revision AS "currentRevision",definition FROM field_options_definitions WHERE active=true AND (host_session_id IS NULL OR EXISTS (SELECT 1 FROM fields_import_journal j WHERE j.host_session_id=field_options_definitions.host_session_id AND j.state='published')) ORDER BY key`);
	const blockRows = await execute(db, sql`SELECT key,origin,version,active,current_revision AS "currentRevision",definition FROM field_block_definitions WHERE active=true AND (host_session_id IS NULL OR EXISTS (SELECT 1 FROM fields_import_journal j WHERE j.host_session_id=field_block_definitions.host_session_id AND j.state='published')) ORDER BY key`);
	const groupMap = /* @__PURE__ */ new Map();
	for (const row of groupRows) groupMap.set(row.key, {
		definition: parseGroup(row.definition, registry),
		version: positive(row.version, "group.version"),
		revision: positive(row.currentRevision, "group.revision"),
		active: bool(row.active),
		origin: row.origin
	});
	for (const code of options.codeRegistry?.groups ?? []) {
		const { origin: _origin, ...definition } = code;
		const parsed = parseGroup(definition, registry), previous = groupMap.get(parsed.key);
		groupMap.set(parsed.key, {
			definition: parsed,
			version: previous?.version ?? 1,
			revision: previous?.revision ?? 1,
			active: parsed.active,
			origin: "code"
		});
	}
	const groups = [...groupMap.values()].filter((item) => item.active).sort((a, b) => a.definition.key.localeCompare(b.definition.key)).map((item) => Object.freeze({
		key: item.definition.key,
		title: item.definition.title,
		version: item.version,
		revision: item.revision,
		active: item.active,
		origin: item.origin,
		location: item.definition.location,
		fields: publicFields(item.definition, registry),
		authorization: Object.freeze({
			readAction: "read",
			writeAction: "write",
			manageAction: "manageDefinitions"
		})
	}));
	const groupKeys = new Set(groups.map((group) => group.key));
	const groupDefinitions = new Map([...groupMap].map(([key, value]) => [key, value.definition]));
	const optionMap = /* @__PURE__ */ new Map();
	for (const row of optionRows) optionMap.set(row.key, {
		definition: __optionsLifecycleInternals.normalizeOptionsPage(parseJson(row.definition, "options")),
		version: positive(row.version, "options.version"),
		revision: positive(row.currentRevision, "options.revision"),
		active: bool(row.active),
		origin: row.origin
	});
	for (const code of options.codeRegistry?.optionsPages ?? []) {
		const { origin: _origin, ...definition } = code, parsed = __optionsLifecycleInternals.normalizeOptionsPage(definition), previous = optionMap.get(parsed.key);
		optionMap.set(parsed.key, {
			definition: parsed,
			version: previous?.version ?? 1,
			revision: previous?.revision ?? 1,
			active: true,
			origin: "code"
		});
	}
	const optionsPages = [...optionMap.values()].filter((item) => item.active).sort((a, b) => a.definition.key.localeCompare(b.definition.key)).map((item) => {
		const page = item.definition, fieldGroupKeys = [...groupDefinitions.values()].filter((group) => group.active && group.location.some((rules) => rules.some((rule) => rule.parameter === "optionsPage" && rule.operator === "eq" && rule.value === page.key))).map((group) => group.key).sort();
		return Object.freeze({
			key: page.key,
			title: page.title,
			version: item.version,
			revision: item.revision,
			active: item.active,
			origin: item.origin,
			...page.parentKey ? { parentKey: page.parentKey } : {},
			fieldGroupKeys: Object.freeze(fieldGroupKeys),
			authorization: Object.freeze({
				readCapability: page.readCapability,
				writeCapability: page.writeCapability,
				manageCapability: page.manageCapability
			})
		});
	});
	const blockMap = /* @__PURE__ */ new Map();
	for (const row of blockRows) blockMap.set(row.key, {
		definition: __fieldBlockLifecycleInternals.normalizeDefinition(parseJson(row.definition, "block")),
		version: positive(row.version, "block.version"),
		revision: positive(row.currentRevision, "block.revision"),
		active: bool(row.active),
		origin: row.origin
	});
	for (const code of options.codeRegistry?.blocks ?? []) {
		const { origin: _origin, ...definition } = code, parsed = __fieldBlockLifecycleInternals.normalizeDefinition(definition), previous = blockMap.get(parsed.key);
		blockMap.set(parsed.key, {
			definition: parsed,
			version: previous?.version ?? 1,
			revision: previous?.revision ?? 1,
			active: true,
			origin: "code"
		});
	}
	const blocks = [...blockMap.values()].filter((item) => item.active).sort((a, b) => a.definition.key.localeCompare(b.definition.key)).map((item) => {
		const block = item.definition;
		for (const key of block.fieldGroupKeys) if (!groupKeys.has(key)) throw new FieldsHeadlessError("integrity", `block ${block.key} references unavailable group ${key}`);
		return Object.freeze({
			key: block.key,
			title: block.title,
			version: item.version,
			revision: item.revision,
			active: item.active,
			origin: item.origin,
			fieldGroupKeys: block.fieldGroupKeys,
			...block.parent ? { parent: block.parent } : {},
			...block.ancestor ? { ancestor: block.ancestor } : {},
			...block.supports ? { supports: block.supports } : {},
			...block.templateLock === void 0 ? {} : { templateLock: block.templateLock },
			tree: blockTreeSchema()
		});
	});
	const blockKeys = new Set(blocks.map((block) => block.key));
	for (const block of blocks) {
		for (const parent of block.parent ?? []) if (!blockKeys.has(parent)) throw new FieldsHeadlessError("integrity", `block ${block.key} references unavailable parent ${parent}`);
		for (const ancestor of block.ancestor ?? []) if (!blockKeys.has(ancestor)) throw new FieldsHeadlessError("integrity", `block ${block.key} references unavailable ancestor ${ancestor}`);
	}
	const revision = Object.freeze({
		type: "object",
		required: Object.freeze([
			"id",
			"entityType",
			"entityId",
			"parentRevisionId",
			"definitionVersions",
			"values",
			"createdAt",
			"createdBy",
			"sourceVersion"
		]),
		properties: Object.freeze({
			definitionVersions: "record<string,positive-integer>",
			values: "redacted-field-value-map",
			blockDocument: "block-tree",
			password: "configured-marker-only"
		})
	});
	const errors = Object.freeze([
		"validation",
		"authorization",
		"capability",
		"conflict",
		"integrity"
	].map((category) => Object.freeze({
		category,
		fieldPath: true
	})));
	const material = {
		registryVersion: registry.version,
		...options.codeRegistry ? {
			codeRegistryVersion: options.codeRegistry.version,
			codeRegistryHash: options.codeRegistry.canonicalHash
		} : {},
		groups,
		optionsPages,
		blocks,
		revision,
		errors
	};
	return Object.freeze({
		version: await fieldsRequestHash(material),
		...material
	});
}
//#endregion
export { createFieldTypeRegistry as $, prepareRollbackFieldsImportD1 as A, resolveOptionsPages as B, getFieldsRevision as C, planFieldsImportD1 as D, planFieldsImport as E, publishFieldsImport as F, setEntityValues as G, resumeFieldsImport as H, readFlatFieldValues as I, updateOptionsPage as J, startFieldsImport as K, renderBlockDocument as L, prepareStartFieldsImportD1 as M, previewFieldBlockChange as N, preparePublishFieldsImportD1 as O, previewOptionsPageDeactivation as P, createFieldGroup as Q, resolveFieldBlocks as R, getEntityValues as S, parseFieldsImport as T, rollbackFieldsImport as U, restoreFieldsRevision as V, setBlockDocument as W, applyFieldGroupChange as X, validateBlockDocument as Y, authorizeRelationshipReplacement as Z, deleteGroup as _, parseFieldDefinition as _t, applyOptionsPageDeactivation as a, isFieldStoreError as at, generateFieldsHeadlessSchema as b, assertFieldsTransactionIdentity as c, redactFieldValueForRevision as ct, createGroup as d, restoreFieldsBackup as dt, decodeFieldValueNodes as et, createLocationResolverRegistry as f, validateFieldValue as ft, deleteEntityValues as g, fieldsSchema as gt, defineFieldGroup as h, planFieldsRecursiveEavMigration as ht, applyFieldBlockChange as i, isFieldGroupConflictError as it, prepareStagedFieldsImportGuardD1 as j, prepareResumeFieldsImportD1 as k, captureFieldsRevision as l, resolveFieldDefinitionVersion as lt, createReusableBlockResolver as m, fieldsRecursiveEavForwardMigrationSql as mt, FIELD_KEY_RE as n, fieldsBackupDestinationHash as nt, assertCanEditFields as o, isFieldValidationError as ot, createOptionsPage as p, canonicalFieldsMigrationHash as pt, updateGroup as q, FIELD_TYPES as r, isFieldAuthorizationError as rt, assertCanManageGroups as s, previewFieldGroupChange as st, DEFAULT_BLOCK_POLICY as t, encodeFieldValueNodes as tt, createFieldBlock as u, resolveFinalFieldGroups as ut, exportFields as v, parseFieldGroupDefinition as vt, listGroups as w, getBlockDocument as x, fieldsRuntimeMigrationSql as y, resolveGroups as z };
