globalThis.process ??= {};
globalThis.process.env ??= {};
import { r as __exportAll } from "./rolldown-runtime_-UtK6b3T.mjs";
import { Tt as sql, f as getTransactionIdentity, n as d1AssertPreviousChanges } from "./d1_DTqC4o_t.mjs";
import { l as jsonError, u as jsonOk } from "./crypto_CY2zBtG3.mjs";
import { A as resolveContentTypes, C as prepareStartContentImportD1, E as publishContentImport, F as startContentImport, N as resumeContentImport, P as rollbackContentImport, S as prepareStagedContentImportGuardD1, _ as planContentImport, b as prepareResumeContentImportD1, d as exportContent, g as parseContentImport, h as normalizeContentTypeDefinition, r as canonicalContentMigrationHash, u as createDbContentImportJournal, x as prepareRollbackContentImportD1, y as preparePublishContentImportD1 } from "./dist_YU938xCs.mjs";
import { r as getMutationDb } from "./db_BQ9NAt8x.mjs";
import { $ as createFieldTypeRegistry, A as prepareRollbackFieldsImportD1, D as planFieldsImportD1, E as planFieldsImport, F as publishFieldsImport, H as resumeFieldsImport, K as startFieldsImport, M as prepareStartFieldsImportD1, O as preparePublishFieldsImportD1, T as parseFieldsImport, U as rollbackFieldsImport, j as prepareStagedFieldsImportGuardD1, k as prepareResumeFieldsImportD1, pt as canonicalFieldsMigrationHash, v as exportFields } from "./dist_BBLvfyU8.mjs";
import { c as assertCsrf, i as requireAdmin } from "./auth_B0DWM0G6.mjs";
import { i as contentModelAdminFieldsContext } from "./content-model-admin_DmJQq0qW.mjs";
import { n as adminContentPrincipal } from "./content-model-editor_A7KaA6-n.mjs";
import { env } from "cloudflare:workers";
//#region src/lib/content-model-import.ts
var ContentModelImportError = class extends Error {
	code;
	detail;
	field;
	actual;
	maximum;
	name = "ContentModelImportError";
	constructor(code, detail, field, actual, maximum) {
		super(`content model import ${code}: ${detail}`);
		this.code = code;
		this.detail = detail;
		this.field = field;
		this.actual = actual;
		this.maximum = maximum;
	}
};
var fail = (code, detail) => {
	throw new ContentModelImportError(code, detail);
};
function d1InvocationLimit(actual) {
	return new ContentModelImportError("limit", `combined import requires ${actual} D1 queries in this invocation; maximum is 50. Reduce the import scope or batch size and retry`, "d1InvocationQueries", actual, 50);
}
function createContentModelD1InvocationBudget() {
	let queries = 0;
	return Object.freeze({
		used: () => queries,
		consume: (count = 1) => {
			const next = queries + count;
			if (next > 50) throw d1InvocationLimit(next);
			queries = next;
		}
	});
}
function budgetedD1Client(db, budget) {
	return Object.freeze({
		execute: async (query) => {
			budget.consume();
			return db.execute(query);
		},
		prepare: (query) => db.prepare(query)
	});
}
async function runContentModelImportMutation(capability, invocationBudget, postgresOperation, d1Operation) {
	if (capability.dialect === "postgres") return capability.db.transaction((tx) => postgresOperation(tx));
	if (!d1Operation) throw new ContentModelImportError("unsupported-capability", "combined content/fields import requires a D1 prepared contribution");
	const contribution = await d1Operation(budgetedD1Client(capability.db, invocationBudget));
	invocationBudget.consume(contribution.items.length);
	await capability.db.batch(contribution.items);
	return contribution.result;
}
var HOST_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;
var bounded = (value, field, max = 512) => {
	if (typeof value !== "string" || value.length < 1 || value.length > max) fail("validation", `${field} must be a bounded string`);
	return value;
};
var hostSessionId = (value, field = "staging.hostSessionId") => {
	const id = bounded(value, field, 128);
	if (!HOST_SESSION_UUID_RE.test(id)) fail("validation", `${field} must be a UUID`);
	return id;
};
var stableStrings = (values, field) => {
	const result = [...new Set(values.map((value) => bounded(value, field, 256)))].sort();
	if (result.length < 1) fail("validation", `${field} must not be empty`);
	return Object.freeze(result);
};
function normalizeContentModelImportScope(scope) {
	return Object.freeze({
		tenantKey: bounded(scope.tenantKey, "scope.tenantKey", 256),
		contentTypeKeys: stableStrings(scope.contentTypeKeys, "scope.contentTypeKeys"),
		fieldsEntityTypes: stableStrings(scope.fieldsEntityTypes, "scope.fieldsEntityTypes")
	});
}
function projectContentModelScope(scopeInput, entityTypeMap) {
	const scope = normalizeContentModelImportScope(scopeInput);
	bounded(entityTypeMap.version, "entityTypeMap.version", 256);
	bounded(entityTypeMap.canonicalHash, "entityTypeMap.canonicalHash", 128);
	const selectedFields = new Set(scope.fieldsEntityTypes);
	const claimedFields = /* @__PURE__ */ new Set();
	for (const typeKey of scope.contentTypeKeys) {
		const mapped = bounded(entityTypeMap.forContentType(typeKey), `entityTypeMap.${typeKey}`, 256);
		if (!selectedFields.has(mapped)) fail("validation", `content type ${typeKey} maps outside selected fields entity types`);
		if (claimedFields.has(mapped)) fail("validation", `multiple content types map to fields entity type ${mapped}`);
		claimedFields.add(mapped);
	}
	return {
		scope,
		content: Object.freeze({
			tenantKey: scope.tenantKey,
			typeKeys: scope.contentTypeKeys
		}),
		fields: Object.freeze({
			tenantKey: scope.tenantKey,
			entityTypes: scope.fieldsEntityTypes
		})
	};
}
function selectedEntityTypeMappings(scope, entityTypeMap) {
	const entries = scope.contentTypeKeys.map((typeKey) => [typeKey, bounded(entityTypeMap.forContentType(typeKey), `entityTypeMap.${typeKey}`, 256)]);
	return Object.freeze(Object.fromEntries(entries));
}
function assertPrincipal(principal) {
	if (bounded(principal.id, "principal.id", 512) !== principal.content.id || principal.fields.id !== principal.id) fail("authorization", "content and fields principals do not share one host identity");
}
function fieldsContextFor(deps, principal) {
	return Object.freeze({
		...deps.fieldsContext,
		principal: principal.fields
	});
}
function hostAuthInput(plan) {
	return Object.freeze({
		scope: plan.scope,
		contentRequiredAuthority: plan.contentPlan.requiredAuthority,
		fieldsRequiredAuthority: plan.fieldsPlan.requiredAuthority,
		expectedPolicyVersion: plan.authorizationPolicyVersion,
		expectedContentPolicyVersion: plan.contentPlan.authorizationPolicyVersion,
		expectedFieldsPolicyVersion: plan.fieldsPlan.authorizationPolicyVersion
	});
}
async function authorizeHost(tx, deps, principal, action, input) {
	assertPrincipal(principal);
	try {
		const result = await deps.authorization.assert(tx, principal, action, input);
		if (!result?.policyVersion) fail("authorization", "host policy version is unavailable");
		if (input.expectedPolicyVersion !== void 0 && result.policyVersion !== input.expectedPolicyVersion) fail("authorization", "host policy version changed");
		return result.policyVersion;
	} catch (error) {
		if (error instanceof ContentModelImportError) throw error;
		return fail("authorization", "content model import is unavailable");
	}
}
function fieldsAuthorization(context) {
	const authorization = context.authorization;
	if (!context.principal || !authorization || typeof authorization.assert !== "function" || typeof authorization.assertDefinitionMigration !== "function") return fail("authorization", "fields import authorization is unavailable");
	return authorization;
}
async function authorizePackagesBeforeLookup(tx, deps, principal, action, input) {
	const projected = projectContentModelScope(input.scope, deps.entityTypeMap);
	const views = {
		content: tx,
		fields: tx
	};
	try {
		const content = await deps.contentAuthorization.assert(views.content, principal.content, action, {
			scope: projected.content,
			requiredAuthority: input.contentRequiredAuthority,
			...input.expectedContentPolicyVersion === void 0 ? {} : { expectedPolicyVersion: input.expectedContentPolicyVersion }
		});
		if (!content?.policyVersion || input.expectedContentPolicyVersion !== void 0 && content.policyVersion !== input.expectedContentPolicyVersion) fail("authorization", "content package policy version changed");
		const authorization = fieldsAuthorization(fieldsContextFor(deps, principal));
		await authorization.assert(principal.fields, "manageDefinitions", {
			entityType: "fields-import-scope",
			entityId: projected.fields.tenantKey
		});
		const migration = await authorization.assertDefinitionMigration(principal.fields, projected.fields.entityTypes);
		for (const entityType of projected.fields.entityTypes) await authorization.assert(principal.fields, "write", {
			entityType,
			entityId: "*"
		});
		if (!migration?.policyVersion || input.expectedFieldsPolicyVersion !== void 0 && migration.policyVersion !== input.expectedFieldsPolicyVersion) fail("authorization", "fields package policy version changed");
	} catch (error) {
		if (error instanceof ContentModelImportError) throw error;
		return fail("authorization", "content model import is unavailable");
	}
}
function transactionViews(tx) {
	getTransactionIdentity(tx);
	return {
		content: tx,
		fields: tx
	};
}
function planHashMaterial(plan) {
	return plan;
}
async function assertPlanIdentity(plan) {
	const { planHash, ...rest } = plan;
	if (await canonicalContentMigrationHash(planHashMaterial(rest)) !== planHash) fail("integrity", "host plan hash is invalid");
}
function fieldsManifestEntityTypes(parsed) {
	const result = /* @__PURE__ */ new Set();
	for (const item of parsed.manifest.entities ?? []) result.add(item.sourceRef.entityType);
	for (const item of parsed.manifest.revisions ?? []) result.add(item.sourceRef.entityType);
	for (const item of parsed.manifest.blockDocuments ?? []) result.add(item.sourceRef.entityType);
	for (const item of parsed.manifest.omissions) result.add(item.sourceRef.entityType);
	if ((parsed.manifest.options?.length ?? 0) > 0 || parsed.manifest.definitions.optionsPages.length > 0) result.add("options");
	for (const group of parsed.manifest.definitions.groups) for (const rules of group.location) for (const rule of rules) if (rule.parameter === "entityType" && rule.operator === "eq" && typeof rule.value === "string" && rule.value.length > 0) result.add(rule.value);
	return result;
}
function assertFieldsScopeNamedByManifest(scope, mappings, parsed) {
	const mapped = new Set(Object.values(mappings)), named = fieldsManifestEntityTypes(parsed);
	for (const entityType of scope.fieldsEntityTypes) if (!mapped.has(entityType) && !named.has(entityType)) fail("validation", `fields entity type ${entityType} is not named by the content map or fields manifest`);
}
async function planContentModelImport(tx, deps, principal, input) {
	const views = {
		content: tx,
		fields: tx
	};
	const projected = projectContentModelScope(input.scope, deps.entityTypeMap);
	const entityTypeMappings = selectedEntityTypeMappings(projected.scope, deps.entityTypeMap);
	assertFieldsScopeNamedByManifest(projected.scope, entityTypeMappings, input.parsedFields);
	if (input.staging.visibility !== "hiddenUntilPublish") fail("validation", "staging must remain hiddenUntilPublish");
	hostSessionId(input.staging.hostSessionId);
	await authorizeHost(tx, deps, principal, "plan", Object.freeze({
		scope: projected.scope,
		contentRequiredAuthority: Object.freeze([]),
		fieldsRequiredAuthority: Object.freeze([])
	}));
	const contentPlan = await planContentImport(views.content, deps.contentAuthorization, principal.content, input.contentBundle, {
		scope: projected.content,
		conflictPolicy: input.contentConflictPolicy
	});
	const fieldsPlan = "prepare" in tx ? await planFieldsImportD1(views.fields, projected.fields, input.parsedFields, input.fieldsConflictPolicy, deps.fieldsRemappers, deps.fieldsRegistry, deps.codeRegistry, fieldsContextFor(deps, principal)) : await planFieldsImport(views.fields, projected.fields, input.parsedFields, input.fieldsConflictPolicy, deps.fieldsRemappers, deps.fieldsRegistry, deps.codeRegistry, fieldsContextFor(deps, principal));
	const policy = await authorizeHost(tx, deps, principal, "plan", Object.freeze({
		scope: projected.scope,
		contentRequiredAuthority: contentPlan.requiredAuthority,
		fieldsRequiredAuthority: fieldsPlan.requiredAuthority
	}));
	if (deps.codeRegistry.version !== fieldsPlan.codeRegistryVersion || deps.codeRegistry.canonicalHash !== fieldsPlan.codeRegistryHash) fail("stale-plan", "fields code registry changed during host planning");
	const manifestHash = await canonicalContentMigrationHash({
		content: contentPlan.manifestHash,
		fields: fieldsPlan.manifestHash
	});
	const destinationVersion = await canonicalContentMigrationHash({
		content: contentPlan.destinationCorpusVersion,
		fields: fieldsPlan.valueCorpusVersion
	});
	const rest = Object.freeze({
		manifestHash,
		destinationVersion,
		scope: projected.scope,
		contentScope: projected.content,
		fieldsScope: projected.fields,
		contentPlan,
		fieldsPlan,
		contentBundle: input.contentBundle,
		staging: Object.freeze(input.staging),
		authorizationPolicyVersion: policy,
		entityTypeMapVersion: deps.entityTypeMap.version,
		entityTypeMapHash: deps.entityTypeMap.canonicalHash,
		entityTypeMappings,
		codeRegistryVersion: deps.codeRegistry.version,
		codeRegistryHash: deps.codeRegistry.canonicalHash
	});
	return Object.freeze({
		planHash: await canonicalContentMigrationHash(planHashMaterial(rest)),
		...rest
	});
}
var jsonRecord = (value, field) => {
	let parsed = value;
	if (typeof value === "string") try {
		parsed = JSON.parse(value);
	} catch {
		return fail("integrity", `${field} contains invalid JSON`);
	}
	if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) fail("integrity", `${field} is malformed`);
	return parsed;
};
var storedString = (value, field, max = 4096) => {
	if (typeof value !== "string" || value.length < 1 || value.length > max) return fail("integrity", `${field} is malformed`);
	return value;
};
var storedInteger = (value, field) => {
	const number = Number(value);
	if (!Number.isSafeInteger(number) || number < 0) return fail("integrity", `${field} is malformed`);
	return number;
};
var storedStringArray = (value, field) => {
	if (!Array.isArray(value)) return fail("integrity", `${field} is malformed`);
	return Object.freeze(value.map((item, index) => storedString(item, `${field}.${index}`, 512)));
};
var storedStringRecord = (value, field) => {
	const row = jsonRecord(value, field), out = {};
	for (const [key, value] of Object.entries(row)) out[storedString(key, `${field}.key`, 512)] = storedString(value, `${field}.${key}`, 512);
	return Object.freeze(out);
};
function storedHostScope(value, field) {
	const row = jsonRecord(value, field), raw = Object.freeze({
		tenantKey: storedString(row.tenantKey, `${field}.tenantKey`, 256),
		contentTypeKeys: storedStringArray(row.contentTypeKeys, `${field}.contentTypeKeys`),
		fieldsEntityTypes: storedStringArray(row.fieldsEntityTypes, `${field}.fieldsEntityTypes`)
	}), normalized = normalizeContentModelImportScope(raw);
	if (JSON.stringify(raw) !== JSON.stringify(normalized)) fail("integrity", `${field} is not canonical`);
	return normalized;
}
function storedContentScope(value, field) {
	const row = jsonRecord(value, field);
	return Object.freeze({
		tenantKey: storedString(row.tenantKey, `${field}.tenantKey`, 256),
		typeKeys: storedStringArray(row.typeKeys, `${field}.typeKeys`)
	});
}
function storedFieldsScope(value, field) {
	const row = jsonRecord(value, field);
	return Object.freeze({
		tenantKey: storedString(row.tenantKey, `${field}.tenantKey`, 256),
		entityTypes: storedStringArray(row.entityTypes, `${field}.entityTypes`)
	});
}
function storedStaging(value, field) {
	const row = jsonRecord(value, field), visibility = row.visibility;
	if (visibility !== "hiddenUntilPublish") return fail("integrity", `${field}.visibility is malformed`);
	return Object.freeze({
		hostSessionId: hostSessionId(storedString(row.hostSessionId, `${field}.hostSessionId`, 128), `${field}.hostSessionId`),
		visibility
	});
}
function storedContentAuthority(value, field) {
	if (!Array.isArray(value)) return fail("integrity", `${field} is malformed`);
	return Object.freeze(value.map((raw, index) => {
		const row = jsonRecord(raw, `${field}.${index}`);
		return Object.freeze({
			typeKey: storedString(row.typeKey, `${field}.${index}.typeKey`, 256),
			branches: storedStringArray(row.branches, `${field}.${index}.branches`)
		});
	}));
}
function storedFieldsAuthority(value, field) {
	if (!Array.isArray(value)) return fail("integrity", `${field} is malformed`);
	return Object.freeze(value.map((raw, index) => {
		const row = jsonRecord(raw, `${field}.${index}`);
		return Object.freeze({
			entityType: storedString(row.entityType, `${field}.${index}.entityType`, 256),
			branches: storedStringArray(row.branches, `${field}.${index}.branches`)
		});
	}));
}
function storedContentConflict(value, field) {
	const row = jsonRecord(value, field), category = row.category;
	if (category !== "validation" && category !== "authorization" && category !== "notFound" && category !== "conflict" && category !== "capability" && category !== "integrity") return fail("integrity", `${field}.category is malformed`);
	return Object.freeze({
		code: storedString(row.code, `${field}.code`, 256),
		category,
		message: storedString(row.message, `${field}.message`, 4096),
		...row.fieldPath === void 0 ? {} : { fieldPath: storedString(row.fieldPath, `${field}.fieldPath`, 1024) }
	});
}
function storedContentPlan(value) {
	const row = jsonRecord(value, "host plan.contentPlan"), policy = row.conflictPolicy;
	if (policy !== "reject" && policy !== "preserve" && policy !== "mappedReplacement") return fail("integrity", "host plan.contentPlan.conflictPolicy is malformed");
	if (!Array.isArray(row.conflicts)) return fail("integrity", "host plan.contentPlan.conflicts is malformed");
	return Object.freeze({
		planHash: storedString(row.planHash, "host plan.contentPlan.planHash", 128),
		manifestHash: storedString(row.manifestHash, "host plan.contentPlan.manifestHash", 128),
		destinationCorpusVersion: storedString(row.destinationCorpusVersion, "host plan.contentPlan.destinationCorpusVersion", 128),
		authorizationPolicyVersion: storedString(row.authorizationPolicyVersion, "host plan.contentPlan.authorizationPolicyVersion", 512),
		scope: storedContentScope(row.scope, "host plan.contentPlan.scope"),
		conflictPolicy: policy,
		requiredAuthority: storedContentAuthority(row.requiredAuthority, "host plan.contentPlan.requiredAuthority"),
		counts: jsonRecord(row.counts, "host plan.contentPlan.counts"),
		mappings: storedStringRecord(row.mappings, "host plan.contentPlan.mappings"),
		conflicts: Object.freeze(row.conflicts.map((item, index) => storedContentConflict(item, `host plan.contentPlan.conflicts.${index}`))),
		estimatedBytes: storedInteger(row.estimatedBytes, "host plan.contentPlan.estimatedBytes")
	});
}
function storedFieldsPlan(value) {
	const row = jsonRecord(value, "host plan.fieldsPlan"), policy = row.policy;
	if (policy !== "reject" && policy !== "preserveDestination" && policy !== "replaceMapped") return fail("integrity", "host plan.fieldsPlan.policy is malformed");
	if (!Array.isArray(row.conflicts) || !Array.isArray(row.omissions)) return fail("integrity", "host plan.fieldsPlan arrays are malformed");
	jsonRecord(row.manifest, "host plan.fieldsPlan.manifest");
	return Object.freeze({
		...row,
		planId: storedString(row.planId, "host plan.fieldsPlan.planId", 128),
		manifestHash: storedString(row.manifestHash, "host plan.fieldsPlan.manifestHash", 128),
		registryVersion: storedString(row.registryVersion, "host plan.fieldsPlan.registryVersion", 128),
		codeRegistryVersion: storedString(row.codeRegistryVersion, "host plan.fieldsPlan.codeRegistryVersion", 128),
		codeRegistryHash: storedString(row.codeRegistryHash, "host plan.fieldsPlan.codeRegistryHash", 128),
		valueCorpusVersion: storedString(row.valueCorpusVersion, "host plan.fieldsPlan.valueCorpusVersion", 128),
		authorizationPolicyVersion: storedString(row.authorizationPolicyVersion, "host plan.fieldsPlan.authorizationPolicyVersion", 512),
		scope: storedFieldsScope(row.scope, "host plan.fieldsPlan.scope"),
		requiredAuthority: storedFieldsAuthority(row.requiredAuthority, "host plan.fieldsPlan.requiredAuthority"),
		mappings: storedStringRecord(row.mappings, "host plan.fieldsPlan.mappings"),
		policy
	});
}
function storedHostPlan(value) {
	const row = jsonRecord(value, "host plan");
	jsonRecord(row.contentBundle, "host plan.contentBundle");
	return Object.freeze({
		planHash: storedString(row.planHash, "host plan.planHash", 128),
		manifestHash: storedString(row.manifestHash, "host plan.manifestHash", 128),
		destinationVersion: storedString(row.destinationVersion, "host plan.destinationVersion", 128),
		scope: storedHostScope(row.scope, "host plan.scope"),
		contentScope: storedContentScope(row.contentScope, "host plan.contentScope"),
		fieldsScope: storedFieldsScope(row.fieldsScope, "host plan.fieldsScope"),
		contentPlan: storedContentPlan(row.contentPlan),
		fieldsPlan: storedFieldsPlan(row.fieldsPlan),
		contentBundle: row.contentBundle,
		staging: storedStaging(row.staging, "host plan.staging"),
		authorizationPolicyVersion: storedString(row.authorizationPolicyVersion, "host plan.authorizationPolicyVersion", 512),
		entityTypeMapVersion: storedString(row.entityTypeMapVersion, "host plan.entityTypeMapVersion", 256),
		entityTypeMapHash: storedString(row.entityTypeMapHash, "host plan.entityTypeMapHash", 128),
		codeRegistryVersion: storedString(row.codeRegistryVersion, "host plan.codeRegistryVersion", 256),
		codeRegistryHash: storedString(row.codeRegistryHash, "host plan.codeRegistryHash", 128),
		entityTypeMappings: storedStringRecord(row.entityTypeMappings, "host plan.entityTypeMappings")
	});
}
function storedContentSession(value) {
	const row = jsonRecord(value, "host session.content"), state = row.state;
	if (![
		"validated",
		"applying",
		"staged",
		"published",
		"failed",
		"rolledBack",
		"reversing",
		"reversed"
	].includes(String(state))) return fail("integrity", "host session.content.state is malformed");
	const nextSection = row.nextSection;
	if (nextSection !== null && ![
		"type",
		"status",
		"taxonomy",
		"term",
		"entry",
		"revision"
	].includes(String(nextSection))) return fail("integrity", "host session.content.nextSection is malformed");
	return Object.freeze({
		...row,
		id: storedString(row.id, "host session.content.id", 512),
		planHash: storedString(row.planHash, "host session.content.planHash", 128),
		manifestHash: storedString(row.manifestHash, "host session.content.manifestHash", 128),
		state,
		staging: storedStaging(row.staging, "host session.content.staging"),
		scope: storedContentScope(row.scope, "host session.content.scope"),
		authorizationPolicyVersion: storedString(row.authorizationPolicyVersion, "host session.content.authorizationPolicyVersion", 512),
		destinationCorpusVersion: storedString(row.destinationCorpusVersion, "host session.content.destinationCorpusVersion", 128),
		journalVersion: storedString(row.journalVersion, "host session.content.journalVersion", 64),
		nextSection,
		nextOffset: storedInteger(row.nextOffset, "host session.content.nextOffset"),
		appliedBatches: storedInteger(row.appliedBatches, "host session.content.appliedBatches")
	});
}
function storedFieldsJournal(value) {
	const row = jsonRecord(value, "host session.fields"), state = row.state;
	if (![
		"planned",
		"applying",
		"staged",
		"published",
		"rollingBack",
		"rolledBack",
		"reversing",
		"reversed",
		"failed"
	].includes(String(state))) return fail("integrity", "host session.fields.state is malformed");
	const nextSection = row.nextSection;
	if (nextSection !== null && ![
		"definitions",
		"optionsPages",
		"blocks",
		"entities",
		"revisions",
		"options",
		"blockDocuments"
	].includes(String(nextSection))) return fail("integrity", "host session.fields.nextSection is malformed");
	return Object.freeze({
		...row,
		importId: storedString(row.importId, "host session.fields.importId", 512),
		version: storedString(row.version, "host session.fields.version", 64),
		planId: storedString(row.planId, "host session.fields.planId", 128),
		manifestHash: storedString(row.manifestHash, "host session.fields.manifestHash", 128),
		codeRegistryVersion: storedString(row.codeRegistryVersion, "host session.fields.codeRegistryVersion", 256),
		codeRegistryHash: storedString(row.codeRegistryHash, "host session.fields.codeRegistryHash", 128),
		staging: storedStaging(row.staging, "host session.fields.staging"),
		scope: storedFieldsScope(row.scope, "host session.fields.scope"),
		authorizationPolicyVersion: storedString(row.authorizationPolicyVersion, "host session.fields.authorizationPolicyVersion", 512),
		state,
		nextSection,
		nextOffset: storedInteger(row.nextOffset, "host session.fields.nextOffset")
	});
}
var resultRows = (value) => {
	if (Array.isArray(value)) return value;
	const rows = value?.rows;
	if (Array.isArray(rows)) return rows;
	return fail("integrity", "database adapter returned invalid rows");
};
async function executeRows(db, query) {
	return resultRows(await db.execute(query));
}
function sessionFromStored(value) {
	const row = jsonRecord(value, "host session"), state = row.state;
	if (![
		"applying",
		"staged",
		"published",
		"failed",
		"rolledBack",
		"reversing",
		"reversed"
	].includes(String(state))) return fail("integrity", "host session.state is malformed");
	return Object.freeze({
		sessionId: storedString(row.sessionId, "host session.sessionId", 512),
		scope: storedHostScope(row.scope, "host session.scope"),
		authorizationPolicyVersion: storedString(row.authorizationPolicyVersion, "host session.authorizationPolicyVersion", 512),
		version: storedString(row.version, "host session.version", 64),
		planHash: storedString(row.planHash, "host session.planHash", 128),
		state,
		staging: storedStaging(row.staging, "host session.staging"),
		content: storedContentSession(row.content),
		fields: storedFieldsJournal(row.fields)
	});
}
function assertStoredJournalEvidence(row, payload) {
	const { plan, session } = payload;
	if (row.sessionId !== session.sessionId || row.planHash !== plan.planHash || row.manifestHash !== plan.manifestHash || row.destinationVersion !== plan.destinationVersion || row.contentPlanHash !== plan.contentPlan.planHash || row.fieldsPlanId !== plan.fieldsPlan.planId || row.contentManifestHash !== plan.contentPlan.manifestHash || row.fieldsManifestHash !== plan.fieldsPlan.manifestHash || row.authorizationPolicyVersion !== plan.authorizationPolicyVersion || row.codeRegistryVersion !== plan.codeRegistryVersion || row.codeRegistryHash !== plan.codeRegistryHash || row.entityTypeMapVersion !== plan.entityTypeMapVersion || row.entityTypeMapHash !== plan.entityTypeMapHash || row.state !== session.state || String(row.version) !== session.version || row.contentImportId !== session.content.id || row.fieldsImportId !== session.fields.importId || !sameStaging(session.staging, plan.staging)) fail("integrity", "host journal columns differ from persisted payload evidence");
}
async function readHostJournal(db, sessionId) {
	const row = (await executeRows(db, sql`SELECT session_id AS "sessionId",plan_hash AS "planHash",manifest_hash AS "manifestHash",destination_version AS "destinationVersion",content_plan_hash AS "contentPlanHash",fields_plan_id AS "fieldsPlanId",content_manifest_hash AS "contentManifestHash",fields_manifest_hash AS "fieldsManifestHash",authorization_policy_version AS "authorizationPolicyVersion",code_registry_version AS "codeRegistryVersion",code_registry_hash AS "codeRegistryHash",entity_type_map_version AS "entityTypeMapVersion",entity_type_map_hash AS "entityTypeMapHash",state,version,content_import_id AS "contentImportId",fields_import_id AS "fieldsImportId",payload FROM content_model_import_journal WHERE session_id=${sessionId} LIMIT 1`))[0];
	if (!row) return null;
	const raw = jsonRecord(row.payload, "host journal payload");
	if (!raw.plan || !raw.session) fail("integrity", "host journal payload is incomplete");
	const payload = {
		plan: storedHostPlan(raw.plan),
		session: sessionFromStored(raw.session)
	};
	assertStoredJournalEvidence(row, payload);
	return {
		row,
		payload
	};
}
async function readHostReceipt(db, operationId) {
	return (await executeRows(db, sql`SELECT session_id AS "sessionId",kind,request_hash AS "requestHash",principal_id AS "principalId",state,result FROM content_model_operation_receipts WHERE operation_id=${operationId} LIMIT 1`))[0] ?? null;
}
function combinedState(content, fields) {
	if (content.state === "failed" || fields.state === "failed") return "failed";
	if (content.state === "published" || fields.state === "published") {
		if (content.state === "published" && fields.state === "published") return "published";
		return fail("integrity", "package publication states diverged");
	}
	if (content.state === "rolledBack" || fields.state === "rolledBack" || fields.state === "rollingBack") {
		if (content.state === "rolledBack" && fields.state === "rolledBack") return "rolledBack";
		return fail("integrity", "package rollback states diverged");
	}
	if (content.state === "reversed" || fields.state === "reversed" || content.state === "reversing" || fields.state === "reversing") {
		if (content.state === "reversed" && fields.state === "reversed") return "reversed";
		return fail("integrity", "package reverse states diverged");
	}
	if (content.state === "staged" && fields.state === "staged") return "staged";
	const contentApplying = content.state === "validated" || content.state === "applying" || content.state === "staged";
	const fieldsApplying = fields.state === "planned" || fields.state === "applying" || fields.state === "staged";
	if (contentApplying && fieldsApplying) return "applying";
	return fail("integrity", "package import states are not representable by the host coordinator");
}
function sameStaging(left, right) {
	return left.hostSessionId === right.hostSessionId && left.visibility === right.visibility;
}
function makeSession(plan, version, content, fields) {
	const sessionId = plan.staging.hostSessionId;
	if (!sameStaging(content.staging, plan.staging) || !sameStaging(fields.staging, plan.staging)) fail("integrity", "package staging descriptors differ from host plan");
	if (content.id !== sessionId || fields.importId !== sessionId) fail("integrity", "package import identities differ from host session identity");
	return Object.freeze({
		sessionId,
		scope: plan.scope,
		authorizationPolicyVersion: plan.authorizationPolicyVersion,
		version,
		planHash: plan.planHash,
		state: combinedState(content, fields),
		staging: plan.staging,
		content,
		fields
	});
}
function contentCommand(plan, session, operationId) {
	return Object.freeze({
		operationId,
		expectedPlanHash: plan.contentPlan.planHash,
		expectedManifestHash: plan.contentPlan.manifestHash,
		scope: plan.contentPlan.scope,
		requiredAuthority: plan.contentPlan.requiredAuthority,
		expectedAuthorizationPolicyVersion: plan.contentPlan.authorizationPolicyVersion,
		expectedJournalVersion: session.journalVersion,
		expectedSection: session.nextSection,
		expectedOffset: session.nextOffset
	});
}
function fieldsCommand(plan, journal, operationId, start = false) {
	return Object.freeze({
		operationId,
		expectedPlanId: plan.fieldsPlan.planId,
		expectedManifestHash: plan.fieldsPlan.manifestHash,
		scope: plan.fieldsPlan.scope,
		expectedJournalVersion: start ? null : journal.version,
		expectedSection: start ? null : journal.nextSection,
		expectedOffset: start ? null : journal.nextOffset
	});
}
function hostRequestHash(kind, principal, value) {
	return canonicalContentMigrationHash({
		kind,
		principalIds: {
			host: principal.id,
			content: principal.content.id,
			fields: principal.fields.id
		},
		value
	});
}
async function replayHostReceipt(tx, operationId, sessionId, kind, requestHash, principalId) {
	const receipt = await readHostReceipt(tx, operationId);
	if (!receipt) return null;
	if (receipt.sessionId !== sessionId || receipt.kind !== kind || receipt.requestHash !== requestHash || receipt.principalId !== principalId || receipt.state !== "committed") fail("conflict", "host operation id was already used with different evidence");
	const session = sessionFromStored(receipt.result);
	if (session.sessionId !== sessionId) fail("integrity", "host receipt result differs from receipt session identity");
	return session;
}
async function insertPendingHostReceipt(tx, sessionId, operationId, kind, requestHash, principalId) {
	const now = (/* @__PURE__ */ new Date()).toISOString();
	return (await executeRows(tx, sql`INSERT INTO content_model_operation_receipts (operation_id,session_id,kind,request_hash,principal_id,state,result,created_at,updated_at) VALUES (${operationId},${sessionId},${kind},${requestHash},${principalId},'pending',${JSON.stringify({})},${now},${now}) ON CONFLICT (operation_id) DO NOTHING RETURNING operation_id AS "operationId"`)).length === 1;
}
async function claimPendingHostReceipt(tx, sessionId, operationId, kind, requestHash, principalId) {
	if (await insertPendingHostReceipt(tx, sessionId, operationId, kind, requestHash, principalId)) return null;
	const replay = await replayHostReceipt(tx, operationId, sessionId, kind, requestHash, principalId);
	if (replay) return replay;
	return fail("conflict", "host operation id was already claimed with different or incomplete evidence");
}
async function commitHostReceipt(tx, operationId, result) {
	if ((await executeRows(tx, sql`UPDATE content_model_operation_receipts SET state='committed',result=${JSON.stringify(result)},updated_at=${(/* @__PURE__ */ new Date()).toISOString()} WHERE operation_id=${operationId} AND state='pending' RETURNING operation_id AS "operationId"`)).length !== 1) fail("integrity", "host receipt claim disappeared");
}
async function claimHostSession(tx, plan) {
	const now = (/* @__PURE__ */ new Date()).toISOString(), payload = JSON.stringify({ plan });
	if ((await executeRows(tx, sql`INSERT INTO content_model_import_journal (session_id,plan_hash,manifest_hash,destination_version,content_plan_hash,fields_plan_id,content_manifest_hash,fields_manifest_hash,authorization_policy_version,code_registry_version,code_registry_hash,entity_type_map_version,entity_type_map_hash,state,version,content_import_id,fields_import_id,payload,created_at,updated_at) VALUES (${plan.staging.hostSessionId},${plan.planHash},${plan.manifestHash},${plan.destinationVersion},${plan.contentPlan.planHash},${plan.fieldsPlan.planId},${plan.contentPlan.manifestHash},${plan.fieldsPlan.manifestHash},${plan.authorizationPolicyVersion},${plan.codeRegistryVersion},${plan.codeRegistryHash},${plan.entityTypeMapVersion},${plan.entityTypeMapHash},'applying',0,NULL,NULL,${payload},${now},${now}) ON CONFLICT (session_id) DO NOTHING RETURNING session_id AS "sessionId"`)).length !== 1) fail("conflict", "host staging session id is already claimed");
}
async function persistHostSession(tx, plan, session) {
	const payload = JSON.stringify({
		plan,
		session
	});
	if ((await executeRows(tx, sql`UPDATE content_model_import_journal SET state=${session.state},content_import_id=${session.content.id},fields_import_id=${session.fields.importId},payload=${payload},updated_at=${(/* @__PURE__ */ new Date()).toISOString()} WHERE session_id=${session.sessionId} AND plan_hash=${plan.planHash} AND manifest_hash=${plan.manifestHash} AND version=${Number(session.version)} RETURNING session_id AS "sessionId"`)).length !== 1) fail("stale-journal", "host journal claim was lost");
}
async function claimHostCommand(tx, sessionId, principal, command, kind) {
	const operationId = bounded(command.operationId, "command.operationId", 512);
	const requestHash = await hostRequestHash(kind, principal, command);
	const replay = await replayHostReceipt(tx, operationId, sessionId, kind, requestHash, principal.id);
	if (replay) return {
		version: replay.version,
		replay,
		requestHash
	};
	const claimedReplay = await claimPendingHostReceipt(tx, sessionId, operationId, kind, requestHash, principal.id);
	if (claimedReplay) return {
		version: claimedReplay.version,
		replay: claimedReplay,
		requestHash
	};
	const expected = Number(command.expectedVersion);
	if (!Number.isSafeInteger(expected) || expected < 0) fail("validation", "expectedVersion must be a nonnegative integer string");
	const row = (await executeRows(tx, sql`
    UPDATE content_model_import_journal
    SET version=version+1, updated_at=${(/* @__PURE__ */ new Date()).toISOString()}
    WHERE session_id=${sessionId} AND plan_hash=${command.expectedPlanHash} AND manifest_hash=${command.expectedManifestHash} AND version=${expected}
    RETURNING version,payload
  `))[0];
	if (!row) fail("stale-journal", "host journal coordinate changed");
	const payload = jsonRecord(row.payload, "host journal payload");
	if (!payload.plan || !payload.session) fail("integrity", "host journal payload is incomplete");
	const plan = storedHostPlan(payload.plan), session = sessionFromStored(payload.session);
	return {
		version: String(row.version),
		replay: null,
		requestHash,
		plan,
		session
	};
}
function sameStrings(left, right) {
	return JSON.stringify([...left].sort()) === JSON.stringify([...right].sort());
}
function sameContentAuthority(left, right) {
	const normalize = (value) => [...value].map((item) => ({
		typeKey: item.typeKey,
		branches: [...item.branches].sort()
	})).sort((a, b) => a.typeKey.localeCompare(b.typeKey));
	return JSON.stringify(normalize(left)) === JSON.stringify(normalize(right));
}
function sameFieldsAuthority(left, right) {
	const normalize = (value) => [...value].map((item) => ({
		entityType: item.entityType,
		branches: [...item.branches].sort()
	})).sort((a, b) => a.entityType.localeCompare(b.entityType));
	return JSON.stringify(normalize(left)) === JSON.stringify(normalize(right));
}
function assertCommandEvidence(plan, command) {
	const scope = normalizeContentModelImportScope(command.scope);
	if (command.expectedPlanHash !== plan.planHash) fail("conflict", "command plan hash differs from host plan");
	if (command.expectedManifestHash !== plan.manifestHash) fail("conflict", "command manifest hash differs from host plan");
	if (scope.tenantKey !== plan.scope.tenantKey || !sameStrings(scope.contentTypeKeys, plan.scope.contentTypeKeys) || !sameStrings(scope.fieldsEntityTypes, plan.scope.fieldsEntityTypes)) fail("authorization", "command scope differs from host plan");
	if (!sameContentAuthority(command.contentRequiredAuthority, plan.contentPlan.requiredAuthority) || !sameFieldsAuthority(command.fieldsRequiredAuthority, plan.fieldsPlan.requiredAuthority)) fail("authorization", "command authority differs from host plan");
	if (command.expectedAuthorizationPolicyVersion !== plan.authorizationPolicyVersion) fail("authorization", "command host policy version differs from host plan");
	if (command.expectedContentAuthorizationPolicyVersion !== plan.contentPlan.authorizationPolicyVersion) fail("authorization", "command content policy version differs from content plan");
	if (command.expectedFieldsAuthorizationPolicyVersion !== plan.fieldsPlan.authorizationPolicyVersion) fail("authorization", "command fields policy version differs from fields plan");
}
function assertRuntimeBindings(deps, plan) {
	if (deps.entityTypeMap.version !== plan.entityTypeMapVersion || deps.entityTypeMap.canonicalHash !== plan.entityTypeMapHash) fail("stale-plan", "entity-type mapping changed");
	if (deps.codeRegistry.version !== plan.codeRegistryVersion || deps.codeRegistry.canonicalHash !== plan.codeRegistryHash) fail("stale-plan", "fields code registry changed");
	projectContentModelScope(plan.scope, deps.entityTypeMap);
	if (JSON.stringify(selectedEntityTypeMappings(plan.scope, deps.entityTypeMap)) !== JSON.stringify(plan.entityTypeMappings)) fail("stale-plan", "selected entity-type mapping changed");
}
async function validateContinuationReplay(tx, deps, sessionId, command, replay) {
	const stored = await readHostJournal(tx, sessionId);
	if (!stored) throw new ContentModelImportError("authorization", "combined import session is unavailable");
	const plan = stored.payload.plan;
	await assertPlanIdentity(plan);
	assertCommandEvidence(plan, command);
	assertRuntimeBindings(deps, plan);
	if (replay.sessionId !== stored.payload.session.sessionId || replay.planHash !== plan.planHash || !sameStaging(replay.staging, plan.staging)) fail("integrity", "host replay receipt differs from persisted import identity");
	return replay;
}
function startFieldsCommand(plan, operationId) {
	return Object.freeze({
		operationId,
		expectedPlanId: plan.fieldsPlan.planId,
		expectedManifestHash: plan.fieldsPlan.manifestHash,
		scope: plan.fieldsPlan.scope,
		expectedJournalVersion: null,
		expectedSection: null,
		expectedOffset: null
	});
}
function hostEvent(kind, operationId, session, plan, principal) {
	return Object.freeze({
		id: crypto.randomUUID(),
		version: 1,
		kind,
		operationId,
		sessionId: session.sessionId,
		planHash: session.planHash,
		manifestHash: plan.manifestHash,
		principalIds: Object.freeze({
			content: principal.content.id,
			fields: principal.fields.id
		}),
		scope: session.scope,
		authorizationPolicyVersion: session.authorizationPolicyVersion
	});
}
function contentD1Event(kind, operationId, session, principal, counts) {
	return Object.freeze({
		id: crypto.randomUUID(),
		version: 1,
		kind,
		operationId,
		sessionId: session.id,
		planHash: session.planHash,
		manifestHash: session.manifestHash,
		principalId: principal.id,
		scope: session.scope,
		authorizationPolicyVersion: session.authorizationPolicyVersion,
		affectedCounts: counts
	});
}
function fieldsD1Event(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 d1LifecycleInput(phase, operationId, result, plan, principal, host, contentKind, fieldsKind = "batchStaged", contentCounts = plan.contentPlan.counts) {
	return Object.freeze({
		phase,
		...host ? { host } : {},
		...contentKind ? { content: contentD1Event(contentKind, `${operationId}:content`, result.content, principal.content, contentCounts) } : {},
		fields: fieldsD1Event(fieldsKind, `${operationId}:fields`, result.fields, plan.fieldsPlan, principal.fields.id)
	});
}
async function assertHostEffectsParticipate(tx, deps) {
	try {
		await deps.effects.audit.assertParticipates(tx);
		await deps.effects.outbox.assertParticipates(tx);
	} catch (error) {
		if (error instanceof ContentModelImportError) throw error;
		throw new ContentModelImportError("unsupported-capability", "host import effects cannot participate in the combined transaction");
	}
}
async function emitHostEvent(tx, deps, event) {
	await deps.effects.audit.record(tx, event);
	await deps.effects.outbox.enqueue(tx, event);
}
async function validateStartReplay(tx, deps, plan, replay) {
	const stored = await readHostJournal(tx, replay.sessionId);
	if (!stored) throw new ContentModelImportError("authorization", "combined import session is unavailable");
	await assertPlanIdentity(stored.payload.plan);
	assertRuntimeBindings(deps, stored.payload.plan);
	if (stored.payload.plan.planHash !== plan.planHash || stored.payload.plan.manifestHash !== plan.manifestHash || !sameStaging(stored.payload.plan.staging, plan.staging)) fail("conflict", "host start replay differs from supplied plan identity");
	if (await canonicalContentMigrationHash(stored.payload.session) !== await canonicalContentMigrationHash(replay)) fail("integrity", "host start replay receipt differs from persisted session");
	return replay;
}
async function startContentModelImport(tx, deps, principal, plan, operationIdInput) {
	const views = transactionViews(tx);
	await assertPlanIdentity(plan);
	assertRuntimeBindings(deps, plan);
	if (plan.contentPlan.conflicts.length || plan.fieldsPlan.conflicts.length) fail("conflict", "host plan contains unresolved package conflicts");
	const operationId = bounded(operationIdInput, "operationId", 512);
	const authorizationInput = hostAuthInput(plan);
	if (await authorizeHost(tx, deps, principal, "start", authorizationInput) !== plan.authorizationPolicyVersion) fail("authorization", "host policy version changed");
	await authorizePackagesBeforeLookup(tx, deps, principal, "start", authorizationInput);
	const requestHash = await hostRequestHash("started", principal, plan);
	const replay = await replayHostReceipt(tx, operationId, plan.staging.hostSessionId, "started", requestHash, principal.id);
	if (replay) return validateStartReplay(tx, deps, plan, replay);
	const claimedReplay = await claimPendingHostReceipt(tx, plan.staging.hostSessionId, operationId, "started", requestHash, principal.id);
	if (claimedReplay) return validateStartReplay(tx, deps, plan, claimedReplay);
	await claimHostSession(tx, plan);
	const session = makeSession(plan, "0", await startContentImport(views.content, deps.contentJournal, deps.contentAuthorization, principal.content, plan.contentBundle, {
		plan: plan.contentPlan,
		staging: plan.staging,
		operationId: `${operationId}:content`
	}), await startFieldsImport(views.fields, plan.fieldsPlan, plan.staging, startFieldsCommand(plan, `${operationId}:fields`), deps.fieldsRegistry, deps.codeRegistry, fieldsContextFor(deps, principal), deps.effects.fields));
	await persistHostSession(tx, plan, session);
	await commitHostReceipt(tx, operationId, session);
	return session;
}
async function authorizeCommandBeforeLookup(tx, deps, principal, action, command) {
	const scope = normalizeContentModelImportScope(command.scope);
	const input = Object.freeze({
		scope,
		contentRequiredAuthority: command.contentRequiredAuthority,
		fieldsRequiredAuthority: command.fieldsRequiredAuthority,
		expectedPolicyVersion: command.expectedAuthorizationPolicyVersion,
		expectedContentPolicyVersion: command.expectedContentAuthorizationPolicyVersion,
		expectedFieldsPolicyVersion: command.expectedFieldsAuthorizationPolicyVersion
	});
	if (await authorizeHost(tx, deps, principal, action, input) !== command.expectedAuthorizationPolicyVersion) fail("authorization", "host policy version changed");
	await authorizePackagesBeforeLookup(tx, deps, principal, action === "planReverse" ? "reversePublished" : action, input);
}
async function resumeContentModelImport(tx, deps, principal, sessionIdInput, command, fieldsBatchSize = 100) {
	const views = transactionViews(tx), sessionId = bounded(sessionIdInput, "sessionId", 512);
	await authorizeCommandBeforeLookup(tx, deps, principal, "resume", command);
	const claim = await claimHostCommand(tx, sessionId, principal, command, "resumed");
	if (claim.replay) return validateContinuationReplay(tx, deps, sessionId, command, claim.replay);
	const plan = claim.plan, previous = claim.session;
	if (!plan || !previous) throw new ContentModelImportError("integrity", "host resume claim lost payload");
	await assertPlanIdentity(plan);
	assertCommandEvidence(plan, command);
	assertRuntimeBindings(deps, plan);
	if (previous.state !== "applying") fail("stale-journal", "combined import is not resumable");
	let content = previous.content, fields = previous.fields;
	if (content.state !== "staged") content = await resumeContentImport(views.content, deps.contentJournal, deps.contentAuthorization, principal.content, plan.contentBundle, content.id, contentCommand(plan, content, `${command.operationId}:content`));
	if (fields.state !== "staged") fields = await resumeFieldsImport(views.fields, fields.importId, fieldsBatchSize, fieldsCommand(plan, fields, `${command.operationId}:fields`), deps.fieldsRegistry, deps.codeRegistry, fieldsContextFor(deps, principal), deps.effects.fields);
	const session = makeSession(plan, claim.version, content, fields);
	await persistHostSession(tx, plan, session);
	await commitHostReceipt(tx, command.operationId, session);
	return session;
}
async function publishContentModelImport(tx, deps, principal, sessionIdInput, command) {
	const views = transactionViews(tx), sessionId = bounded(sessionIdInput, "sessionId", 512);
	await authorizeCommandBeforeLookup(tx, deps, principal, "publish", command);
	await assertHostEffectsParticipate(tx, deps);
	const claim = await claimHostCommand(tx, sessionId, principal, command, "published");
	if (claim.replay) return validateContinuationReplay(tx, deps, sessionId, command, claim.replay);
	const plan = claim.plan, previous = claim.session;
	if (!plan || !previous) throw new ContentModelImportError("integrity", "host publish claim lost payload");
	await assertPlanIdentity(plan);
	assertCommandEvidence(plan, command);
	assertRuntimeBindings(deps, plan);
	if (previous.state !== "staged" || previous.content.state !== "staged" || previous.fields.state !== "staged") fail("stale-journal", "both package imports must be staged before publication");
	const content = await publishContentImport(views.content, deps.contentJournal, deps.contentAuthorization, deps.effects.content, principal.content, previous.content.id, contentCommand(plan, previous.content, `${command.operationId}:content`));
	const fields = await publishFieldsImport(views.fields, previous.fields.importId, fieldsCommand(plan, previous.fields, `${command.operationId}:fields`), deps.fieldsRegistry, deps.codeRegistry, fieldsContextFor(deps, principal), deps.effects.fields);
	const session = makeSession(plan, claim.version, content, fields);
	if (session.state !== "published") fail("integrity", "package publication states diverged");
	await persistHostSession(tx, plan, session);
	await emitHostEvent(tx, deps, hostEvent("published", command.operationId, session, plan, principal));
	await commitHostReceipt(tx, command.operationId, session);
	return session;
}
async function rollbackContentModelImport(tx, deps, principal, sessionIdInput, command) {
	const views = transactionViews(tx), sessionId = bounded(sessionIdInput, "sessionId", 512);
	await authorizeCommandBeforeLookup(tx, deps, principal, "rollback", command);
	await assertHostEffectsParticipate(tx, deps);
	const claim = await claimHostCommand(tx, sessionId, principal, command, "rolledBack");
	if (claim.replay) return validateContinuationReplay(tx, deps, sessionId, command, claim.replay);
	const plan = claim.plan, previous = claim.session;
	if (!plan || !previous) throw new ContentModelImportError("integrity", "host rollback claim lost payload");
	await assertPlanIdentity(plan);
	assertCommandEvidence(plan, command);
	assertRuntimeBindings(deps, plan);
	if (![
		"planned",
		"applying",
		"staged"
	].includes(previous.state)) fail("stale-journal", "combined import cannot be rolled back from its current state");
	const content = await rollbackContentImport(views.content, deps.contentJournal, deps.contentAuthorization, deps.effects.content, principal.content, previous.content.id, contentCommand(plan, previous.content, `${command.operationId}:content`));
	const fields = await rollbackFieldsImport(views.fields, previous.fields.importId, fieldsCommand(plan, previous.fields, `${command.operationId}:fields`), deps.fieldsRegistry, deps.codeRegistry, fieldsContextFor(deps, principal), deps.effects.fields);
	const session = makeSession(plan, claim.version, content, fields);
	if (session.state !== "rolledBack") fail("integrity", "package rollback states diverged");
	await persistHostSession(tx, plan, session);
	await emitHostEvent(tx, deps, hostEvent("rolledBack", command.operationId, session, plan, principal));
	await commitHostReceipt(tx, command.operationId, session);
	return session;
}
var d1Guard = (db) => db.prepare(d1AssertPreviousChanges(1));
function hostInsert(db, plan, session) {
	const now = (/* @__PURE__ */ new Date()).toISOString();
	return [db.prepare(sql`INSERT INTO content_model_import_journal (session_id,plan_hash,manifest_hash,destination_version,content_plan_hash,fields_plan_id,content_manifest_hash,fields_manifest_hash,authorization_policy_version,code_registry_version,code_registry_hash,entity_type_map_version,entity_type_map_hash,state,version,content_import_id,fields_import_id,payload,created_at,updated_at) VALUES (${session.sessionId},${plan.planHash},${plan.manifestHash},${plan.destinationVersion},${plan.contentPlan.planHash},${plan.fieldsPlan.planId},${plan.contentPlan.manifestHash},${plan.fieldsPlan.manifestHash},${plan.authorizationPolicyVersion},${plan.codeRegistryVersion},${plan.codeRegistryHash},${plan.entityTypeMapVersion},${plan.entityTypeMapHash},${session.state},${Number(session.version)},${session.content.id},${session.fields.importId},${JSON.stringify({
		plan,
		session
	})},${now},${now})`), d1Guard(db)];
}
function hostUpdate(db, plan, previous, result) {
	const observedPayload = JSON.stringify({
		plan,
		session: previous
	});
	return [db.prepare(sql`UPDATE content_model_import_journal SET state=${result.state},version=${Number(result.version)},content_import_id=${result.content.id},fields_import_id=${result.fields.importId},payload=${JSON.stringify({
		plan,
		session: result
	})},updated_at=${(/* @__PURE__ */ new Date()).toISOString()} WHERE session_id=${previous.sessionId} AND plan_hash=${plan.planHash} AND manifest_hash=${plan.manifestHash} AND destination_version=${plan.destinationVersion} AND content_plan_hash=${plan.contentPlan.planHash} AND fields_plan_id=${plan.fieldsPlan.planId} AND content_manifest_hash=${plan.contentPlan.manifestHash} AND fields_manifest_hash=${plan.fieldsPlan.manifestHash} AND authorization_policy_version=${plan.authorizationPolicyVersion} AND code_registry_version=${plan.codeRegistryVersion} AND code_registry_hash=${plan.codeRegistryHash} AND entity_type_map_version=${plan.entityTypeMapVersion} AND entity_type_map_hash=${plan.entityTypeMapHash} AND version=${Number(previous.version)} AND state=${previous.state} AND content_import_id=${previous.content.id} AND fields_import_id=${previous.fields.importId} AND json(payload)=json(${observedPayload})`), d1Guard(db)];
}
function hostReceipt(db, sessionId, operationId, kind, hash, principalId, result) {
	const now = (/* @__PURE__ */ new Date()).toISOString();
	return [db.prepare(sql`INSERT INTO content_model_operation_receipts (operation_id,session_id,kind,request_hash,principal_id,state,result,created_at,updated_at) VALUES (${operationId},${sessionId},${kind},${hash},${principalId},'committed',${JSON.stringify(result)},${now},${now})`), d1Guard(db)];
}
async function replayD1(db, operationId, sessionId, kind, hash, principalId) {
	const row = await readHostReceipt(db, operationId);
	if (!row) return null;
	if (row.sessionId !== sessionId || row.kind !== kind || row.requestHash !== hash || row.principalId !== principalId || row.state !== "committed") fail("conflict", "host operation id was already used with different evidence");
	const result = sessionFromStored(row.result), guard = db.prepare(sql`SELECT CASE WHEN EXISTS (SELECT 1 FROM content_model_operation_receipts WHERE operation_id=${operationId} AND session_id=${sessionId} AND kind=${kind} AND request_hash=${hash} AND principal_id=${principalId} AND state='committed' AND json(result)=json(${JSON.stringify(result)})) THEN 1 ELSE json_extract('not-json','$') END AS ok`);
	return Object.freeze({
		items: Object.freeze([guard]),
		result
	});
}
async function authorizeD1(db, deps, principal, action, input) {
	assertPrincipal(principal);
	try {
		const result = await deps.authorization.assert(db, principal, action, input);
		if (!result?.policyVersion || input.expectedPolicyVersion !== void 0 && result.policyVersion !== input.expectedPolicyVersion) fail("authorization", "host policy version changed");
	} catch (error) {
		if (error instanceof ContentModelImportError) throw error;
		fail("authorization", "content model import is unavailable");
	}
}
async function effectsD1(db, deps, input) {
	const prepare = deps.effects.prepareD1;
	if (!prepare) return fail("unsupported-capability", "content, fields, audit, and outbox effects cannot participate in the D1 batch");
	const items = await prepare(db, input);
	if (items.length < 1) fail("unsupported-capability", "D1 lifecycle effects returned no prepared statements");
	return Object.freeze([...items]);
}
function hostStartReplayGuard(db, plan, result) {
	return db.prepare(sql`SELECT CASE WHEN EXISTS (SELECT 1 FROM content_model_import_journal WHERE session_id=${result.sessionId} AND plan_hash=${plan.planHash} AND manifest_hash=${plan.manifestHash} AND destination_version=${plan.destinationVersion} AND content_plan_hash=${plan.contentPlan.planHash} AND fields_plan_id=${plan.fieldsPlan.planId} AND content_manifest_hash=${plan.contentPlan.manifestHash} AND fields_manifest_hash=${plan.fieldsPlan.manifestHash} AND authorization_policy_version=${plan.authorizationPolicyVersion} AND code_registry_version=${plan.codeRegistryVersion} AND code_registry_hash=${plan.codeRegistryHash} AND entity_type_map_version=${plan.entityTypeMapVersion} AND entity_type_map_hash=${plan.entityTypeMapHash} AND state=${result.state} AND version=${Number(result.version)} AND content_import_id=${result.content.id} AND fields_import_id=${result.fields.importId} AND json(payload)=json(${JSON.stringify({
		plan,
		session: result
	})})) THEN 1 ELSE json_extract('not-json','$') END AS ok`);
}
async function prepareStartContentModelImportD1(db, deps, principal, plan, operationIdInput) {
	await assertPlanIdentity(plan);
	assertRuntimeBindings(deps, plan);
	if (plan.contentPlan.conflicts.length || plan.fieldsPlan.conflicts.length) fail("conflict", "host plan contains unresolved package conflicts");
	const operationId = bounded(operationIdInput, "operationId", 512), auth = hostAuthInput(plan);
	await authorizeD1(db, deps, principal, "start", auth);
	await authorizePackagesBeforeLookup(db, deps, principal, "start", auth);
	const hash = await hostRequestHash("started", principal, plan);
	const replay = await replayD1(db, operationId, plan.staging.hostSessionId, "started", hash, principal.id);
	const content = await prepareStartContentImportD1(db, deps.contentAuthorization, principal.content, plan.contentBundle, {
		plan: plan.contentPlan,
		staging: plan.staging,
		operationId: `${operationId}:content`
	});
	const fields = await prepareStartFieldsImportD1(db, plan.fieldsPlan, plan.staging, startFieldsCommand(plan, `${operationId}:fields`), deps.fieldsRegistry, deps.codeRegistry, fieldsContextFor(deps, principal));
	const result = makeSession(plan, "0", content.result, fields.result);
	if (replay) {
		if (await canonicalContentMigrationHash(replay.result) !== await canonicalContentMigrationHash(result)) fail("integrity", "host start replay differs from package replay evidence");
		return Object.freeze({
			items: Object.freeze([
				...replay.items,
				...content.items,
				...fields.items,
				hostStartReplayGuard(db, plan, result)
			]),
			result
		});
	}
	const lifecycleItems = await effectsD1(db, deps, d1LifecycleInput("start", operationId, result, plan, principal, void 0, void 0, "started"));
	return Object.freeze({
		items: Object.freeze([
			...hostReceipt(db, result.sessionId, operationId, "started", hash, principal.id, result),
			...content.items,
			...fields.items,
			...hostInsert(db, plan, result),
			...lifecycleItems
		]),
		result
	});
}
async function prepareResumeContentModelImportD1(db, deps, principal, sessionIdInput, command, fieldsBatchSize = 100) {
	const sessionId = bounded(sessionIdInput, "sessionId", 512);
	const authorizationInput = Object.freeze({
		scope: normalizeContentModelImportScope(command.scope),
		contentRequiredAuthority: command.contentRequiredAuthority,
		fieldsRequiredAuthority: command.fieldsRequiredAuthority,
		expectedPolicyVersion: command.expectedAuthorizationPolicyVersion,
		expectedContentPolicyVersion: command.expectedContentAuthorizationPolicyVersion,
		expectedFieldsPolicyVersion: command.expectedFieldsAuthorizationPolicyVersion
	});
	await authorizeD1(db, deps, principal, "resume", authorizationInput);
	await authorizePackagesBeforeLookup(db, deps, principal, "resume", authorizationInput);
	const operationId = bounded(command.operationId, "command.operationId", 512);
	const requestHash = await hostRequestHash("resumed", principal, command);
	const receipt = await readHostReceipt(db, operationId);
	const stored = await readHostJournal(db, sessionId);
	if (!stored) throw new ContentModelImportError("authorization", "combined import session is unavailable");
	const plan = stored.payload.plan;
	await assertPlanIdentity(plan);
	assertCommandEvidence(plan, command);
	assertRuntimeBindings(deps, plan);
	let previous;
	let committedResult;
	let receiptItems;
	if (receipt) {
		if (receipt.sessionId !== sessionId || receipt.kind !== "resumed" || receipt.requestHash !== requestHash || receipt.principalId !== principal.id || receipt.state !== "committed") fail("conflict", "host operation id was already used with different evidence");
		const rawResult = jsonRecord(receipt.result, "host resume receipt result");
		previous = sessionFromStored(rawResult.resumePrevious);
		committedResult = sessionFromStored(rawResult);
		if (await canonicalContentMigrationHash(stored.payload.session) !== await canonicalContentMigrationHash(committedResult)) fail("integrity", "host resume replay differs from persisted session");
		receiptItems = [db.prepare(sql`SELECT CASE WHEN EXISTS (SELECT 1 FROM content_model_operation_receipts WHERE operation_id=${operationId} AND session_id=${sessionId} AND kind='resumed' AND request_hash=${requestHash} AND principal_id=${principal.id} AND state='committed' AND json(result)=json(${JSON.stringify(rawResult)})) THEN 1 ELSE json_extract('not-json','$') END AS ok`)];
	} else {
		previous = stored.payload.session;
		if (previous.version !== command.expectedVersion) fail("stale-journal", "host journal coordinate changed");
		receiptItems = [];
	}
	if (previous.state !== "applying") fail("stale-journal", "combined import is not resumable");
	const content = previous.content.state === "staged" ? await prepareStagedContentImportGuardD1(db, deps.contentAuthorization, principal.content, previous.content.id, contentCommand(plan, previous.content, `${operationId}:content`)) : await prepareResumeContentImportD1(db, deps.contentAuthorization, principal.content, plan.contentBundle, previous.content.id, contentCommand(plan, previous.content, `${operationId}:content`));
	const fields = previous.fields.state === "staged" ? await prepareStagedFieldsImportGuardD1(db, previous.fields.importId, fieldsCommand(plan, previous.fields, `${operationId}:fields`), deps.fieldsRegistry, deps.codeRegistry, fieldsContextFor(deps, principal)) : await prepareResumeFieldsImportD1(db, previous.fields.importId, fieldsBatchSize, fieldsCommand(plan, previous.fields, `${operationId}:fields`), deps.fieldsRegistry, deps.codeRegistry, fieldsContextFor(deps, principal));
	const result = makeSession(plan, String(Number(previous.version) + 1), content.result, fields.result);
	if (result.state !== "applying" && result.state !== "staged") fail("integrity", "package resume states diverged");
	if (committedResult) {
		if (await canonicalContentMigrationHash(result) !== await canonicalContentMigrationHash(committedResult)) fail("integrity", "host resume replay differs from package replay evidence");
		const receiptGuard = receiptItems[0];
		if (!receiptGuard) fail("integrity", "host resume replay guard is unavailable");
		return Object.freeze({
			items: Object.freeze([
				receiptGuard,
				...content.items,
				...fields.items,
				hostStartReplayGuard(db, plan, result)
			]),
			result
		});
	}
	const now = (/* @__PURE__ */ new Date()).toISOString();
	const receiptResult = Object.freeze({
		...result,
		resumePrevious: previous
	});
	const lifecycleItems = previous.fields.state === "staged" ? Object.freeze([]) : await effectsD1(db, deps, d1LifecycleInput("resume", operationId, result, plan, principal));
	return Object.freeze({
		items: Object.freeze([
			db.prepare(sql`INSERT INTO content_model_operation_receipts (operation_id,session_id,kind,request_hash,principal_id,state,result,created_at,updated_at) VALUES (${operationId},${sessionId},'resumed',${requestHash},${principal.id},'committed',${JSON.stringify(receiptResult)},${now},${now})`),
			d1Guard(db),
			...hostUpdate(db, plan, previous, result),
			...content.items,
			...fields.items,
			...lifecycleItems
		]),
		result
	});
}
async function preparePublishContentModelImportD1(db, deps, principal, sessionIdInput, command) {
	const sessionId = bounded(sessionIdInput, "sessionId", 512);
	const authorizationInput = Object.freeze({
		scope: normalizeContentModelImportScope(command.scope),
		contentRequiredAuthority: command.contentRequiredAuthority,
		fieldsRequiredAuthority: command.fieldsRequiredAuthority,
		expectedPolicyVersion: command.expectedAuthorizationPolicyVersion,
		expectedContentPolicyVersion: command.expectedContentAuthorizationPolicyVersion,
		expectedFieldsPolicyVersion: command.expectedFieldsAuthorizationPolicyVersion
	});
	await authorizeD1(db, deps, principal, "publish", authorizationInput);
	await authorizePackagesBeforeLookup(db, deps, principal, "publish", authorizationInput);
	const operationId = bounded(command.operationId, "command.operationId", 512);
	const requestHash = await hostRequestHash("published", principal, command);
	const replay = await replayD1(db, operationId, sessionId, "published", requestHash, principal.id);
	const stored = await readHostJournal(db, sessionId);
	if (!stored) throw new ContentModelImportError("authorization", "combined import session is unavailable");
	const plan = stored.payload.plan;
	await assertPlanIdentity(plan);
	assertCommandEvidence(plan, command);
	assertRuntimeBindings(deps, plan);
	if (replay) {
		if (await canonicalContentMigrationHash(stored.payload.session) !== await canonicalContentMigrationHash(replay.result)) fail("integrity", "host publish replay differs from persisted session");
		const { publishedCorpusVersion: _publishedCorpusVersion, ...contentResultBefore } = replay.result.content;
		const priorContentVersion = Number(replay.result.content.journalVersion) - 1;
		const priorFieldsVersion = Number(replay.result.fields.version) - 1;
		if (!Number.isSafeInteger(priorContentVersion) || priorContentVersion < 0 || !Number.isSafeInteger(priorFieldsVersion) || priorFieldsVersion < 0) fail("integrity", "published package replay versions are malformed");
		const contentBefore = Object.freeze({
			...contentResultBefore,
			state: "staged",
			journalVersion: String(priorContentVersion)
		});
		const fieldsBefore = Object.freeze({
			...replay.result.fields,
			state: "staged",
			version: String(priorFieldsVersion)
		});
		const content = await preparePublishContentImportD1(db, deps.contentAuthorization, principal.content, sessionId, contentCommand(plan, contentBefore, `${operationId}:content`));
		const fields = await preparePublishFieldsImportD1(db, sessionId, fieldsCommand(plan, fieldsBefore, `${operationId}:fields`), deps.fieldsRegistry, deps.codeRegistry, fieldsContextFor(deps, principal));
		if (await canonicalContentMigrationHash(content.result) !== await canonicalContentMigrationHash(replay.result.content) || await canonicalContentMigrationHash(fields.result) !== await canonicalContentMigrationHash(replay.result.fields)) fail("integrity", "host publish replay differs from package replay evidence");
		return Object.freeze({
			items: Object.freeze([
				...replay.items,
				...content.items,
				...fields.items,
				hostStartReplayGuard(db, plan, replay.result)
			]),
			result: replay.result
		});
	}
	const previous = stored.payload.session;
	if (previous.version !== command.expectedVersion) fail("stale-journal", "host journal coordinate changed");
	if (previous.state !== "staged" || previous.content.state !== "staged" || previous.fields.state !== "staged") fail("stale-journal", "both package imports must be staged before publication");
	const content = await preparePublishContentImportD1(db, deps.contentAuthorization, principal.content, sessionId, contentCommand(plan, previous.content, `${operationId}:content`));
	const fields = await preparePublishFieldsImportD1(db, sessionId, fieldsCommand(plan, previous.fields, `${operationId}:fields`), deps.fieldsRegistry, deps.codeRegistry, fieldsContextFor(deps, principal));
	if (content.result.state !== "published" || fields.result.state !== "published") fail("integrity", "package publication states diverged");
	const result = makeSession(plan, String(Number(previous.version) + 1), content.result, fields.result);
	if (result.state !== "published") fail("integrity", "package publication states diverged");
	const lifecycleItems = await effectsD1(db, deps, d1LifecycleInput("publish", operationId, result, plan, principal, hostEvent("published", operationId, result, plan, principal), "published", "published", content.affectedCounts ?? fail("integrity", "content publish contribution has no semantic affected counts")));
	return Object.freeze({
		items: Object.freeze([
			...hostReceipt(db, sessionId, operationId, "published", requestHash, principal.id, result),
			...hostUpdate(db, plan, previous, result),
			...content.items,
			...fields.items,
			...lifecycleItems
		]),
		result
	});
}
async function prepareRollbackContentModelImportD1(db, deps, principal, sessionIdInput, command) {
	const sessionId = bounded(sessionIdInput, "sessionId", 512);
	const authorizationInput = Object.freeze({
		scope: normalizeContentModelImportScope(command.scope),
		contentRequiredAuthority: command.contentRequiredAuthority,
		fieldsRequiredAuthority: command.fieldsRequiredAuthority,
		expectedPolicyVersion: command.expectedAuthorizationPolicyVersion,
		expectedContentPolicyVersion: command.expectedContentAuthorizationPolicyVersion,
		expectedFieldsPolicyVersion: command.expectedFieldsAuthorizationPolicyVersion
	});
	await authorizeD1(db, deps, principal, "rollback", authorizationInput);
	await authorizePackagesBeforeLookup(db, deps, principal, "rollback", authorizationInput);
	const operationId = bounded(command.operationId, "command.operationId", 512);
	const requestHash = await hostRequestHash("rolledBack", principal, command);
	const receipt = await readHostReceipt(db, operationId);
	if (receipt) {
		if (receipt.sessionId !== sessionId || receipt.kind !== "rolledBack" || receipt.requestHash !== requestHash || receipt.principalId !== principal.id || receipt.state !== "committed") fail("conflict", "host operation id was already used with different evidence");
		const rawResult = jsonRecord(receipt.result, "host rollback receipt result");
		const previous = sessionFromStored(rawResult.rollbackPrevious);
		const result = sessionFromStored(rawResult);
		const stored = await readHostJournal(db, sessionId);
		if (!stored) throw new ContentModelImportError("integrity", "host rollback replay session is unavailable");
		if (await canonicalContentMigrationHash(stored.payload.session) !== await canonicalContentMigrationHash(result)) fail("integrity", "host rollback replay differs from persisted session");
		const plan = stored.payload.plan;
		await assertPlanIdentity(plan);
		assertCommandEvidence(plan, command);
		assertRuntimeBindings(deps, plan);
		const content = await prepareRollbackContentImportD1(db, deps.contentAuthorization, principal.content, previous.content.id, contentCommand(plan, previous.content, `${operationId}:content`));
		const fields = await prepareRollbackFieldsImportD1(db, previous.fields.importId, fieldsCommand(plan, previous.fields, `${operationId}:fields`), deps.fieldsRegistry, deps.codeRegistry, fieldsContextFor(deps, principal));
		if (await canonicalContentMigrationHash(content.result) !== await canonicalContentMigrationHash(result.content) || await canonicalContentMigrationHash(fields.result) !== await canonicalContentMigrationHash(result.fields)) fail("integrity", "host rollback replay differs from package replay evidence");
		const receiptGuard = db.prepare(sql`SELECT CASE WHEN EXISTS (SELECT 1 FROM content_model_operation_receipts WHERE operation_id=${operationId} AND session_id=${sessionId} AND kind='rolledBack' AND request_hash=${requestHash} AND principal_id=${principal.id} AND state='committed' AND json(result)=json(${JSON.stringify(rawResult)})) THEN 1 ELSE json_extract('not-json','$') END AS ok`);
		return Object.freeze({
			items: Object.freeze([
				receiptGuard,
				...content.items,
				...fields.items,
				hostStartReplayGuard(db, plan, result)
			]),
			result
		});
	}
	const stored = await readHostJournal(db, sessionId);
	if (!stored) throw new ContentModelImportError("authorization", "combined import session is unavailable");
	const plan = stored.payload.plan;
	const previous = stored.payload.session;
	await assertPlanIdentity(plan);
	assertCommandEvidence(plan, command);
	assertRuntimeBindings(deps, plan);
	if (previous.version !== command.expectedVersion) fail("stale-journal", "host journal coordinate changed");
	if (previous.state !== "applying" && previous.state !== "staged") fail("stale-journal", "combined import cannot be rolled back from its current state");
	const content = await prepareRollbackContentImportD1(db, deps.contentAuthorization, principal.content, previous.content.id, contentCommand(plan, previous.content, `${operationId}:content`));
	const fields = await prepareRollbackFieldsImportD1(db, previous.fields.importId, fieldsCommand(plan, previous.fields, `${operationId}:fields`), deps.fieldsRegistry, deps.codeRegistry, fieldsContextFor(deps, principal));
	if (content.result.state !== "rolledBack" || fields.result.state !== "rolledBack") fail("integrity", "package rollback states diverged");
	const result = makeSession(plan, String(Number(previous.version) + 1), content.result, fields.result);
	if (result.state !== "rolledBack") fail("integrity", "package rollback states diverged");
	const now = (/* @__PURE__ */ new Date()).toISOString();
	const receiptResult = Object.freeze({
		...result,
		rollbackPrevious: previous
	});
	const lifecycleItems = await effectsD1(db, deps, d1LifecycleInput("rollback", operationId, result, plan, principal, hostEvent("rolledBack", operationId, result, plan, principal), "rolledBack", "rolledBack", content.affectedCounts ?? fail("integrity", "content rollback contribution has no semantic affected counts")));
	return Object.freeze({
		items: Object.freeze([
			db.prepare(sql`INSERT INTO content_model_operation_receipts (operation_id,session_id,kind,request_hash,principal_id,state,result,created_at,updated_at) VALUES (${operationId},${sessionId},'rolledBack',${requestHash},${principal.id},'committed',${JSON.stringify(receiptResult)},${now},${now})`),
			d1Guard(db),
			...hostUpdate(db, plan, previous, result),
			...content.items,
			...fields.items,
			...lifecycleItems
		]),
		result
	});
}
//#endregion
//#region src/lib/content-model-transfer.ts
var ContentModelTransferError = class extends Error {
	code;
	name = "ContentModelTransferError";
	constructor(code, detail, options) {
		super(`content model transfer ${code}: ${detail}`, options);
		this.code = code;
	}
};
var ContentModelTransferCleanupError = class extends ContentModelTransferError {
	sessionId;
	importError;
	cleanupError;
	name = "ContentModelTransferCleanupError";
	constructor(sessionId, importError, cleanupError) {
		super("import-failed", `import failed and automatic cleanup failed for session ${sessionId}`, { cause: importError });
		this.sessionId = sessionId;
		this.importError = importError;
		this.cleanupError = cleanupError;
	}
};
var CONTENT_LIMITS = Object.freeze({
	maxBytes: 2e7,
	maxDefinitions: 1e4,
	maxEntries: 1e5,
	maxRevisions: 2e5,
	batchSize: 100
});
var FIELDS_LIMITS = Object.freeze({
	maxBytes: 2e7,
	maxDefinitions: 1e4,
	maxEntities: 1e5,
	maxRevisions: 2e5,
	maxBlockNodes: 1e6,
	maxDepth: 32
});
var POLICY = "mod-cms-transfer-v1";
function text(value, field, max = 128) {
	if (typeof value !== "string" || !value.trim() || value.length > max) throw new ContentModelTransferError("validation", `${field} must be a bounded string`);
	return value.trim();
}
function object(value, field) {
	if (typeof value !== "object" || value === null || Array.isArray(value)) throw new ContentModelTransferError("validation", `${field} must be an object`);
	return value;
}
async function codeRegistry() {
	const version = "mod-cms-code-v1", groups = Object.freeze([]), optionsPages = Object.freeze([]), blocks = Object.freeze([]), canonicalHash = await canonicalFieldsMigrationHash({
		version,
		groups,
		optionsPages,
		blocks
	});
	return Object.freeze({
		version,
		canonicalHash,
		groups,
		optionsPages,
		blocks
	});
}
var remappers = {
	entity: async (value) => value,
	user: async (value) => value,
	media: async (value) => value,
	term: async (value) => value,
	reusableBlock: async (value) => value
};
function entryIds(bundle) {
	const ids = [];
	for (const value of bundle.entries) {
		const row = object(value, "content.entries");
		ids.push(text(row.id, "content.entries.id", 128));
	}
	return Object.freeze(ids);
}
async function append(tx, kind, event) {
	getTransactionIdentity(tx);
	const now = (/* @__PURE__ */ new Date()).toISOString();
	await tx.execute(sql`INSERT INTO content_model_admin_outbox (id,kind,payload,created_at) VALUES (${crypto.randomUUID()},${kind},${JSON.stringify(event)},${now})`);
}
function importPrincipal(userId, matrix) {
	const contentCapabilities = /* @__PURE__ */ new Set(["content.manage"]);
	for (const row of Object.values(matrix)) for (const values of Object.values(row)) for (const capability of values) contentCapabilities.add(capability);
	return Object.freeze({
		id: userId,
		content: Object.freeze({
			id: userId,
			capabilities: contentCapabilities
		}),
		fields: Object.freeze({
			id: userId,
			capabilities: /* @__PURE__ */ new Set(["fields.manage"])
		})
	});
}
function importedTypeDefinitions(bundle) {
	const result = /* @__PURE__ */ new Map();
	for (const item of bundle.types) {
		const row = object(item, "content.types"), definition = normalizeContentTypeDefinition(object(row.definition, "content.types.definition"));
		if (typeof row.key !== "string" || row.key !== definition.key) throw new ContentModelTransferError("integrity", "content type bundle key differs from its definition");
		result.set(definition.key, definition);
	}
	return result;
}
var BRANCHES = Object.freeze([
	"manageType",
	"migrateAll",
	"manageTerms",
	"create",
	"read",
	"readPrivate",
	"readProtected",
	"editOwn",
	"editOthers",
	"editPrivate",
	"editPublished",
	"publish",
	"deleteOwn",
	"deleteOthers",
	"deletePrivate",
	"deletePublished"
]);
function capabilityMatrix(current, incoming) {
	const keys = [.../* @__PURE__ */ new Set([...current.map((type) => type.key), ...incoming.keys()])].sort(), matrix = {};
	for (const key of keys) {
		const candidates = [current.find((type) => type.key === key)?.capabilities, incoming.get(key)?.capabilities].filter((value) => value !== void 0), row = {};
		for (const branch of BRANCHES) row[branch] = Object.freeze([...new Set(candidates.map((caps) => caps[branch]).filter((value) => typeof value === "string" && value.length > 0))].sort());
		matrix[key] = Object.freeze(row);
	}
	return Object.freeze(matrix);
}
function contentAuthorizationFor(bundle) {
	const incoming = importedTypeDefinitions(bundle);
	return Object.freeze({ assert: async (tx, principal, _action, input) => {
		if (!principal.capabilities.has("content.manage")) throw new ContentModelTransferError("import-failed", "content import authority is unavailable");
		const matrix = capabilityMatrix(await resolveContentTypes(tx), incoming);
		for (const required of input.requiredAuthority) {
			const row = matrix[required.typeKey];
			if (!row) throw new ContentModelTransferError("import-failed", "content import type authority is unavailable");
			for (const branch of required.branches) if (!row[branch]?.some((capability) => principal.capabilities.has(capability))) throw new ContentModelTransferError("import-failed", `content import branch ${required.typeKey}.${branch} is unavailable`);
		}
		const policyVersion = await canonicalContentMigrationHash({
			policy: POLICY,
			matrix
		});
		if (input.expectedPolicyVersion !== void 0 && input.expectedPolicyVersion !== policyVersion) throw new ContentModelTransferError("import-failed", "content import policy changed");
		return Object.freeze({ policyVersion });
	} });
}
async function importDependencies(userId, contentAuthorization) {
	const registry = createFieldTypeRegistry(), code = await codeRegistry(), fieldsContext = contentModelAdminFieldsContext(userId), entityTypeMap = Object.freeze({
		version: "mod-cms-content-v1",
		canonicalHash: await canonicalContentMigrationHash({
			version: "mod-cms-content-v1",
			content: "content"
		}),
		forContentType: (_typeKey) => "content"
	});
	return Object.freeze({
		authorization: Object.freeze({ assert: async (_tx, principal, _action, input) => {
			if (!principal.content.capabilities.has("content.manage") || !principal.fields.capabilities.has("fields.manage")) throw new ContentModelTransferError("import-failed", "host import authority is unavailable");
			if (input.expectedPolicyVersion !== void 0 && input.expectedPolicyVersion !== POLICY) throw new ContentModelTransferError("import-failed", "host import policy changed");
			return Object.freeze({ policyVersion: POLICY });
		} }),
		contentAuthorization,
		contentJournal: createDbContentImportJournal(),
		fieldsContext,
		fieldsRegistry: registry,
		codeRegistry: code,
		fieldsRemappers: Object.freeze(remappers),
		entityTypeMap,
		effects: Object.freeze({
			content: {
				audit: { record: async (tx, event) => append(tx, "transfer:content:audit", event) },
				outbox: { enqueue: async (tx, event) => append(tx, "transfer:content:outbox", event) }
			},
			fields: {
				audit: async (tx, event) => append(tx, "transfer:fields:audit", event),
				enqueue: async (tx, event) => append(tx, "transfer:fields:outbox", event)
			},
			prepareD1: (db, input) => {
				const now = (/* @__PURE__ */ new Date()).toISOString(), items = [], events = Object.freeze([
					...input.content ? [["transfer:content:audit", input.content], ["transfer:content:outbox", input.content]] : [],
					["transfer:fields:audit", input.fields],
					["transfer:fields:outbox", input.fields],
					...input.host ? [["transfer:host:audit", input.host], ["transfer:host:outbox", input.host]] : []
				]);
				for (const [kind, payload] of events) items.push(db.prepare(sql`INSERT INTO content_model_admin_outbox (id,kind,payload,created_at) VALUES (${crypto.randomUUID()},${kind},${JSON.stringify(payload)},${now})`), db.prepare(d1AssertPreviousChanges(1)));
				return Object.freeze(items);
			},
			audit: {
				assertParticipates: (tx) => {
					getTransactionIdentity(tx);
				},
				record: async (tx, event) => append(tx, "transfer:host:audit", event)
			},
			outbox: {
				assertParticipates: (tx) => {
					getTransactionIdentity(tx);
				},
				enqueue: async (tx, event) => append(tx, "transfer:host:outbox", event)
			}
		})
	});
}
function command(plan, session, operationId) {
	return Object.freeze({
		operationId,
		expectedPlanHash: plan.planHash,
		expectedManifestHash: plan.manifestHash,
		expectedVersion: session.version,
		scope: plan.scope,
		contentRequiredAuthority: plan.contentPlan.requiredAuthority,
		fieldsRequiredAuthority: plan.fieldsPlan.requiredAuthority,
		expectedAuthorizationPolicyVersion: plan.authorizationPolicyVersion,
		expectedContentAuthorizationPolicyVersion: plan.contentPlan.authorizationPolicyVersion,
		expectedFieldsAuthorizationPolicyVersion: plan.fieldsPlan.authorizationPolicyVersion
	});
}
async function exportContentModelTransfer(env, userId, typeKeyInput) {
	const typeKey = text(typeKeyInput, "typeKey"), capability = getMutationDb(env);
	if (capability.dialect !== "postgres") throw new ContentModelTransferError("unsupported-capability", "native content-model export requires a callback transaction with the current package export seam");
	return capability.db.transaction(async (tx) => {
		const types = await resolveContentTypes(tx), type = types.find((candidate) => candidate.key === typeKey && candidate.active);
		if (!type || !type.canExport) throw new ContentModelTransferError("validation", "content type is unavailable for export");
		const principal = adminContentPrincipal(userId, types), content = await exportContent(tx, principal, {
			typeKeys: [typeKey],
			includeRevisions: true,
			limits: CONTENT_LIMITS
		}, { audit: { recordOverride: async () => {} } }), ids = entryIds(content), fields = await exportFields(tx, {
			entities: ids.map((id) => Object.freeze({
				entityType: "content",
				entityId: id
			})),
			includeRevisions: true,
			includeOptions: true,
			includeBlocks: true
		}, contentModelAdminFieldsContext(userId));
		return Object.freeze({
			version: 1,
			generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
			typeKey,
			content,
			fields
		});
	});
}
async function importContentModelTransfer(env, userId, input) {
	const raw = object(input, "bundle");
	if (raw.version !== 1) throw new ContentModelTransferError("validation", "bundle version must be 1");
	const typeKey = text(raw.typeKey, "bundle.typeKey"), contentBytes = new TextEncoder().encode(JSON.stringify(raw.content)), fieldsBytes = new TextEncoder().encode(JSON.stringify(raw.fields)), content = await parseContentImport(contentBytes, CONTENT_LIMITS), registry = createFieldTypeRegistry(), parsedFields = await parseFieldsImport(fieldsBytes, FIELDS_LIMITS, registry);
	if (content.types.length !== 1 || object(content.types[0], "content.types.0").key !== typeKey) throw new ContentModelTransferError("validation", "bundle must contain exactly its declared content type");
	const capability = getMutationDb(env), invocationBudget = createContentModelD1InvocationBudget();
	const scope = Object.freeze({
		tenantKey: "mod-cms",
		contentTypeKeys: Object.freeze([typeKey]),
		fieldsEntityTypes: Object.freeze(["content"])
	}), staging = Object.freeze({
		hostSessionId: crypto.randomUUID(),
		visibility: "hiddenUntilPublish"
	}), incoming = importedTypeDefinitions(content), { principal, deps, plan } = await runContentModelImportMutation(capability, invocationBudget, async (tx) => {
		const principal = importPrincipal(userId, capabilityMatrix(await resolveContentTypes(tx), incoming)), deps = await importDependencies(userId, contentAuthorizationFor(content)), plan = await planContentModelImport(tx, deps, principal, {
			scope,
			contentBundle: content,
			parsedFields,
			contentConflictPolicy: "mappedReplacement",
			fieldsConflictPolicy: "replaceMapped",
			staging
		});
		return Object.freeze({
			principal,
			deps,
			plan
		});
	}, async (db) => {
		const principal = importPrincipal(userId, capabilityMatrix(await resolveContentTypes(db), incoming)), deps = await importDependencies(userId, contentAuthorizationFor(content)), plan = await planContentModelImport(db, deps, principal, {
			scope,
			contentBundle: content,
			parsedFields,
			contentConflictPolicy: "mappedReplacement",
			fieldsConflictPolicy: "replaceMapped",
			staging
		});
		return Object.freeze({
			items: Object.freeze([db.prepare(sql`SELECT 1`)]),
			result: Object.freeze({
				principal,
				deps,
				plan
			})
		});
	});
	let session = await runContentModelImportMutation(capability, invocationBudget, (tx) => startContentModelImport(tx, deps, principal, plan, `transfer:start:${staging.hostSessionId}`), (db) => prepareStartContentModelImportD1(db, deps, principal, plan, `transfer:start:${staging.hostSessionId}`)), index = 0;
	try {
		while (session.state === "applying") {
			if (++index > 1e4) throw new ContentModelTransferError("import-failed", "import exceeded bounded resume count");
			session = await runContentModelImportMutation(capability, invocationBudget, (tx) => resumeContentModelImport(tx, deps, principal, session.sessionId, command(plan, session, `transfer:resume:${staging.hostSessionId}:${index}`), 100), (db) => prepareResumeContentModelImportD1(db, deps, principal, session.sessionId, command(plan, session, `transfer:resume:${staging.hostSessionId}:${index}`), 100));
		}
		if (session.state !== "staged") throw new ContentModelTransferError("import-failed", `import stopped in ${session.state}`);
		session = await runContentModelImportMutation(capability, invocationBudget, (tx) => publishContentModelImport(tx, deps, principal, session.sessionId, command(plan, session, `transfer:publish:${staging.hostSessionId}`)), (db) => preparePublishContentModelImportD1(db, deps, principal, session.sessionId, command(plan, session, `transfer:publish:${staging.hostSessionId}`)));
	} catch (error) {
		if (session.state === "applying" || session.state === "staged") {
			const rollbackCommand = command(plan, session, `transfer:rollback:${staging.hostSessionId}`);
			try {
				await runContentModelImportMutation(capability, invocationBudget, (tx) => rollbackContentModelImport(tx, deps, principal, session.sessionId, rollbackCommand), (db) => prepareRollbackContentModelImportD1(db, deps, principal, session.sessionId, rollbackCommand));
			} catch (cleanupError) {
				throw new ContentModelTransferCleanupError(session.sessionId, error, cleanupError);
			}
		}
		throw error;
	}
	if (session.state !== "published") throw new ContentModelTransferError("import-failed", `import publish stopped in ${session.state}`);
	return Object.freeze({
		planHash: plan.planHash,
		sessionId: session.sessionId,
		state: "published"
	});
}
//#endregion
//#region src/pages/api/admin/content-model/transfer.ts
var transfer_exports = /* @__PURE__ */ __exportAll({
	GET: () => GET,
	POST: () => POST,
	prerender: () => false
});
function map(error) {
	const name = error.name;
	if (name === "InvalidSessionError") return jsonError(401, "unauthorized", "content transfer unavailable");
	if (name === "RoleDeniedError" || name === "CsrfError") return jsonError(403, "forbidden", "content transfer unavailable");
	if (error instanceof ContentModelTransferError) {
		if (error.code === "unsupported-capability") return jsonError(409, "unsupported_capability", error.message);
		if (error.code === "integrity" || error.code === "import-failed") return jsonError(409, "transfer_conflict", error.message);
		return jsonError(400, "validation_error", error.message);
	}
	const code = error.code;
	if (name === "ContentImportError" || name === "FieldsImportError" || name === "ContentExportError") {
		if (code === "authorization" || code === "forbidden") return jsonError(403, "forbidden", "content transfer unavailable");
		if (code === "conflict" || code === "stale-plan" || code === "stale-journal" || code === "integrity") return jsonError(409, "transfer_conflict", "content transfer conflicted");
		return jsonError(400, "validation_error", error instanceof Error ? error.message : "invalid content transfer");
	}
	console.error("content model transfer failed", error);
	return jsonError(500, "internal_error", "internal error");
}
var GET = async ({ request, url, cookies }) => {
	try {
		const { actor } = await requireAdmin(request, env, cookies), type = url.searchParams.get("type");
		if (!type) return jsonError(400, "validation_error", "type is required");
		const bundle = await exportContentModelTransfer(env, actor.id, type);
		return new Response(JSON.stringify(bundle), {
			status: 200,
			headers: {
				"Content-Type": "application/json",
				"Cache-Control": "no-store",
				"Content-Disposition": `attachment; filename="mod-cms-${bundle.typeKey}-${bundle.generatedAt}.json"`
			}
		});
	} catch (error) {
		return map(error);
	}
};
var POST = async ({ request, cookies }) => {
	try {
		const { actor, authMode } = await requireAdmin(request, env, cookies);
		assertCsrf(request, {
			authMode,
			siteOrigin: env.SITE_ORIGIN
		});
		const contentLength = Number(request.headers.get("content-length") ?? 0);
		if (Number.isFinite(contentLength) && contentLength > 25e6) return jsonError(413, "payload_too_large", "transfer bundle exceeds 25000000 bytes");
		const text = await request.text();
		if (new TextEncoder().encode(text).byteLength > 25e6) return jsonError(413, "payload_too_large", "transfer bundle exceeds 25000000 bytes");
		let body;
		try {
			body = JSON.parse(text);
		} catch {
			return jsonError(400, "validation_error", "invalid JSON");
		}
		return jsonOk(await importContentModelTransfer(env, actor.id, body));
	} catch (error) {
		return map(error);
	}
};
//#endregion
//#region \0virtual:astro:page:src/pages/api/admin/content-model/transfer@_@ts
var page = () => transfer_exports;
//#endregion
export { page };
