@sellable/install
Version:
One-command installer for Sellable MCP in Claude Code, Codex, and Hermes
824 lines (797 loc) • 27.9 kB
JavaScript
import { createHash, randomUUID } from "node:crypto";
import {
chmodSync,
closeSync,
constants,
existsSync,
fstatSync,
fsyncSync,
lstatSync,
mkdirSync,
openSync,
readFileSync,
readdirSync,
realpathSync,
renameSync,
rmSync,
writeFileSync,
} from "node:fs";
import { basename, dirname, isAbsolute, join } from "node:path";
import { withProfileSoulLock } from "./fly-soul-bridge.mjs";
import { ensureHermesNamedCron } from "./hermes-memory-snapshot.mjs";
export const DEFAULT_PROFILE_RECONCILE_RECEIPT =
".sellable-agent/default-profile-reconcile.json";
export const DEFAULT_PROFILE_RECONCILE_SCHEMA =
"sellable-agent-default-profile-reconcile/v1";
const BUNDLE_SCHEMA = "sellable-agent-default-profile-bundle/v1";
const ID = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;
const MANAGED_ID = /^[a-z0-9][a-z0-9-]{0,63}$/;
const SHA256 = /^[a-f0-9]{64}$/;
const FENCE = /^[1-9][0-9]{0,19}$/;
const STAGE_PREFIX = ".sellable-default-stage-";
const MAX_BYTES = 1024 * 1024;
const ADMIN_MATERIALIZER_ANCHOR = "skills/sellable-admin/SKILL.md";
const ADMIN_NAMESPACE_RECEIPT_SCHEMA =
"sellable-admin-skill-namespace-receipt/v1";
// Immutable shared skill bytes shipped at 9878ec7a (@sellable/install 0.1.758).
// A partial upgrade can leave these legacy copies outside its older receipt.
// Operation d99cebfe proved that Hermes rejects their duplicate native names.
// Only these known bytes, current bundle bytes, or receipt-proven bytes may
// be retired; unknown customer content must still fail closed.
const LEGACY_PUBLIC_SKILL_DIGESTS = Object.freeze({
"create-campaign":
"0c1e7d514f6ff15c433fe6e9625c3b226ac9cd0add8e0590b10ca99ef0fa427b",
"refill-sends":
"2d0896a8024e0a3fee0ff8cf040ea6acdc8bca3292cddb48b41b4ac9f4b4065a",
"campaign-daily-review":
"2b0abf90d283835362d81bdcbd1759cbd2bc1048bddee3f2805466882f55320e",
"campaign-daily-results":
"bd12c54601285819cc70e54f0e41a04aba4a072664c1ce7a425d4be62188780c",
"campaign-weekly-review":
"09690edac84758ee3d874791d6235874577ac7d300192ef30328f003b641083d",
});
const legacyManagedSkillPath = (entry) =>
`skills/sellable-defaults/${entry.id}/SKILL.md`;
const canonicalPublicSkillPath = (entry) =>
`skills/sellable/${entry.nativeName}/SKILL.md`;
const acceptedSkillPath = (entry) =>
entry.path === legacyManagedSkillPath(entry) ||
(entry.nativeName === `sellable-${entry.id}` &&
entry.path === canonicalPublicSkillPath(entry));
const sha256 = (value) => createHash("sha256").update(value).digest("hex");
const canonicalJson = (value) => {
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
if (value && typeof value === "object") {
return `{${Object.keys(value)
.sort()
.map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`)
.join(",")}}`;
}
return JSON.stringify(value);
};
const refused = (code) => ({ ok: false, status: "REFUSED", code });
export function buildDefaultProfileProjection({
kind,
claim,
env = process.env,
imageBundle,
fixtureTarget,
} = {}) {
const operation = claim?.operation;
const authority = claim?.runtimeAuthority;
if (
authority?.bundleVersion === undefined &&
authority?.bundleDigest === undefined
) {
return null;
}
const verifiedImage = imageBundle ?? {
bundleVersion: Number(
env.SELLABLE_AGENT_DEFAULT_PROFILE_BUNDLE_VERSION ?? ""
),
bundleDigest: env.SELLABLE_AGENT_DEFAULT_PROFILE_BUNDLE_DIGEST ?? "",
};
if (
!["CUSTOMER", "ADMIN"].includes(kind) ||
!Number.isSafeInteger(verifiedImage.bundleVersion) ||
verifiedImage.bundleVersion < 1 ||
!SHA256.test(verifiedImage.bundleDigest)
) {
throw new Error("default_profile_image_bundle_rejected");
}
if (
!operation ||
!Number.isSafeInteger(authority?.authorityGeneration) ||
authority.authorityGeneration < 1 ||
authority.bundleVersion !== verifiedImage.bundleVersion ||
authority.bundleDigest !== verifiedImage.bundleDigest
) {
throw new Error("default_profile_bundle_identity_rejected");
}
const verifiedFixture =
fixtureTarget ??
(env.SELLABLE_AGENT_DEFAULT_PROFILE_FIXTURE_TEST_ONLY === "1"
? {
testOnly: true,
workspaceId:
env.SELLABLE_AGENT_DEFAULT_PROFILE_FIXTURE_WORKSPACE_ID ?? "",
agentId: env.SELLABLE_AGENT_DEFAULT_PROFILE_FIXTURE_AGENT_ID ?? "",
}
: undefined);
const exactFixture =
verifiedFixture?.testOnly === true &&
verifiedFixture.workspaceId === operation.workspaceId &&
verifiedFixture.agentId === operation.agentId
? { ...verifiedFixture }
: undefined;
return {
kind,
profileId: operation.profileId,
workspaceId: operation.workspaceId,
agentId: operation.agentId,
operationId: operation.id,
authorityGeneration: authority.authorityGeneration,
fence: String(operation.fence),
...verifiedImage,
...(exactFixture ? { fixtureTarget: exactFixture } : {}),
};
}
export function bindDefaultProfileProbeCron({
activeProjection,
profileRoot,
job,
bootId,
} = {}) {
if (!activeProjection?.fixtureTarget) return { changed: false };
if (
!isAbsolute(profileRoot ?? "") ||
!ID.test(bootId ?? "") ||
!ID.test(job?.id ?? "") ||
job.name !== "sellable-default-probe"
) {
throw new Error("default_profile_cron_binding_rejected");
}
const scriptPath = join(profileRoot, "scripts", "sellable-default-probe.sh");
const binding = {
operationId: activeProjection.operationId,
bootId,
bundleDigest: activeProjection.bundleDigest,
nonce: sha256(
`${activeProjection.operationId}\0${bootId}\0${activeProjection.bundleDigest}`
).slice(0, 32),
jobId: job.id,
name: job.name,
};
const script = `#!/bin/sh
set -eu
exec /opt/hermes/.venv/bin/python3 - ${JSON.stringify(profileRoot)} <<'PY'
import json, os, sys, time
root = sys.argv[1]
binding = json.loads(${JSON.stringify(JSON.stringify(binding))})
binding["firedAt"] = int(time.time() * 1000)
marker_root = os.path.join(root, ".sellable-agent", "cron-markers")
os.makedirs(marker_root, mode=0o700, exist_ok=True)
target = os.path.join(marker_root, binding["name"] + ".json")
stage = target + ".tmp"
with open(stage, "w", encoding="utf-8") as handle:
json.dump(binding, handle, separators=(",", ":"))
handle.write("\\n")
os.chmod(stage, 0o600)
os.replace(stage, target)
PY
`;
const changed =
!existsSync(scriptPath) || readFileSync(scriptPath, "utf8") !== script;
if (changed) atomicWrite(scriptPath, script, 0o700);
return { changed, binding };
}
function readRegular(path, maxBytes = MAX_BYTES) {
const link = lstatSync(path);
if (
link.isSymbolicLink() ||
!link.isFile() ||
link.nlink !== 1 ||
link.size > maxBytes
)
throw new Error("default_profile_file_rejected");
const fd = openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW);
try {
const opened = fstatSync(fd);
if (
!opened.isFile() ||
opened.dev !== link.dev ||
opened.ino !== link.ino ||
opened.nlink !== 1 ||
opened.size !== link.size
) {
throw new Error("default_profile_file_rejected");
}
return readFileSync(fd);
} finally {
closeSync(fd);
}
}
function adminSkillNamespaceReceiptHash(profileRoot) {
const namespaceRoot = join(profileRoot, "skills", "sellable-admin");
if (
!existsSync(namespaceRoot) ||
lstatSync(namespaceRoot).isSymbolicLink() ||
!lstatSync(namespaceRoot).isDirectory() ||
realpathSync(namespaceRoot) !== namespaceRoot
) {
throw new Error("default_profile_admin_skill_namespace_rejected");
}
const names = readdirSync(namespaceRoot).sort();
if (names.length < 1 || names.length > 64) {
throw new Error("default_profile_admin_skill_namespace_rejected");
}
let totalBytes = 0;
const entries = names.map((name) => {
if (!MANAGED_ID.test(name)) {
throw new Error("default_profile_admin_skill_namespace_rejected");
}
const directory = join(namespaceRoot, name);
if (
lstatSync(directory).isSymbolicLink() ||
!lstatSync(directory).isDirectory() ||
realpathSync(directory) !== directory
) {
throw new Error("default_profile_admin_skill_namespace_rejected");
}
const relativePath = `skills/sellable-admin/${name}/SKILL.md`;
const content = readRegular(join(directory, "SKILL.md"), 64 * 1024);
totalBytes += content.byteLength;
if (totalBytes > MAX_BYTES) {
throw new Error("default_profile_admin_skill_namespace_rejected");
}
return { path: relativePath, sha256: sha256(content) };
});
return sha256(
canonicalJson({
schemaVersion: ADMIN_NAMESPACE_RECEIPT_SCHEMA,
entries,
})
);
}
function materializerReceiptHash(profileRoot, path) {
const target = join(profileRoot, ...path.split("/"));
if (path === ADMIN_MATERIALIZER_ANCHOR && !existsSync(target)) {
return adminSkillNamespaceReceiptHash(profileRoot);
}
return sha256(readRegular(target, 64 * 1024));
}
export function buildDefaultProfileMaterializerReceipt({
profileId,
profileRoot,
materializerReceipts,
} = {}) {
const allowed = new Set([
"SOUL.md",
"skills/sellable/SKILL.md",
ADMIN_MATERIALIZER_ANCHOR,
]);
if (
!ID.test(profileId ?? "") ||
!isAbsolute(profileRoot ?? "") ||
!Array.isArray(materializerReceipts) ||
materializerReceipts.length < 1 ||
materializerReceipts.length > allowed.size ||
new Set(materializerReceipts).size !== materializerReceipts.length ||
materializerReceipts.some((path) => !allowed.has(path))
) {
throw new Error("default_profile_materializer_receipt_rejected");
}
return {
profileId,
fileHashes: Object.fromEntries(
materializerReceipts.map((path) => [
path,
materializerReceiptHash(profileRoot, path),
])
),
};
}
export function verifyDefaultProfileMaterializerReceipt({
profileRoot,
materializerReceipts,
materializerReceipt,
} = {}) {
if (
!ID.test(materializerReceipt?.profileId ?? "") ||
!materializerReceipt?.fileHashes ||
Array.isArray(materializerReceipt.fileHashes)
) {
return false;
}
try {
const current = buildDefaultProfileMaterializerReceipt({
profileId: materializerReceipt.profileId,
profileRoot,
materializerReceipts,
});
return materializerReceipts.every(
(path) =>
SHA256.test(materializerReceipt.fileHashes[path] ?? "") &&
materializerReceipt.fileHashes[path] === current.fileHashes[path]
);
} catch {
return false;
}
}
function atomicWrite(path, bytes, mode) {
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
const stage = join(
dirname(path),
`${STAGE_PREFIX}${basename(path)}-${process.pid}-${randomUUID()}`
);
writeFileSync(stage, bytes, { flag: "wx", mode });
chmodSync(stage, mode);
const fd = openSync(stage, constants.O_RDONLY);
try {
fsyncSync(fd);
} finally {
closeSync(fd);
}
renameSync(stage, path);
}
function readBundle(bundleRoot) {
if (
!isAbsolute(bundleRoot ?? "") ||
!existsSync(bundleRoot) ||
lstatSync(bundleRoot).isSymbolicLink() ||
!lstatSync(bundleRoot).isDirectory() ||
realpathSync(bundleRoot) !== bundleRoot
) {
throw new Error("default_profile_bundle_rejected");
}
const manifest = JSON.parse(
readRegular(join(bundleRoot, "manifest.json")).toString("utf8")
);
if (
manifest?.schemaVersion !== BUNDLE_SCHEMA ||
!["CUSTOMER", "ADMIN"].includes(manifest.kind) ||
!Number.isSafeInteger(manifest.bundleVersion) ||
manifest.bundleVersion < 1 ||
!SHA256.test(manifest.bundleDigest ?? "") ||
!Array.isArray(manifest.materializerReceipts) ||
!Array.isArray(manifest.files)
) {
throw new Error("default_profile_bundle_rejected");
}
const files = manifest.files.map((entry) => {
const expectedPath =
entry?.type === "cron" ? `crons/${entry?.name}.json` : null;
if (
!MANAGED_ID.test(entry?.id ?? "") ||
!["skill", "cron"].includes(entry.type) ||
entry.ownership !== "system_managed" ||
!["SHARED", "CUSTOMER", "ADMIN", "FIXTURE"].includes(entry.kind) ||
entry.mode !== "0444" ||
(entry.type === "skill"
? !acceptedSkillPath(entry)
: entry.path !== expectedPath) ||
!SHA256.test(entry.sha256 ?? "") ||
(entry.type === "skill" && !MANAGED_ID.test(entry.nativeName ?? "")) ||
(entry.type === "cron" &&
(!MANAGED_ID.test(entry.name ?? "") ||
!entry.name.startsWith("sellable-default-")))
) {
throw new Error("default_profile_bundle_rejected");
}
const content = readRegular(
join(bundleRoot, ...entry.path.split("/")),
64 * 1024
);
if (sha256(content) !== entry.sha256)
throw new Error("default_profile_bundle_rejected");
return { ...entry, content: content.toString("utf8") };
});
const { bundleDigest, ...unsignedManifest } = manifest;
if (
sha256(canonicalJson({ manifest: unsignedManifest, files })) !==
bundleDigest
)
throw new Error("default_profile_bundle_rejected");
return { manifest, files };
}
function activeEntries(bundle, projection) {
if (
bundle.manifest.kind !== projection.kind ||
bundle.manifest.bundleVersion !== projection.bundleVersion ||
bundle.manifest.bundleDigest !== projection.bundleDigest
) {
throw new Error("default_profile_projection_mismatch");
}
const target = projection.fixtureTarget;
const fixtureAllowed =
target?.testOnly === true &&
target.workspaceId === projection.workspaceId &&
target.agentId === projection.agentId;
return bundle.files
.filter((entry) => entry.kind !== "FIXTURE" || fixtureAllowed)
.sort(
(left, right) =>
(left.type === "skill" ? 0 : 1) - (right.type === "skill" ? 0 : 1) ||
left.path.localeCompare(right.path)
);
}
function validateProjection(value) {
return Boolean(
value &&
["CUSTOMER", "ADMIN"].includes(value.kind) &&
["profileId", "workspaceId", "agentId", "operationId"].every((key) =>
ID.test(value[key] ?? "")
) &&
Number.isSafeInteger(value.authorityGeneration) &&
value.authorityGeneration > 0 &&
FENCE.test(value.fence ?? "") &&
Number.isSafeInteger(value.bundleVersion) &&
value.bundleVersion > 0 &&
SHA256.test(value.bundleDigest ?? "")
);
}
function cronDesired(entry) {
const spec = JSON.parse(entry.content);
if (
!spec ||
Object.keys(spec).sort().join("\0") !==
"deliver\0marker\0noAgent\0schedule\0script" ||
typeof spec.schedule !== "string" ||
!/^(?:\S+\s+){4}\S+$/.test(spec.schedule) ||
!/^[a-z0-9][a-z0-9-]{0,63}\.sh$/.test(spec.script ?? "") ||
spec.noAgent !== true ||
spec.deliver !== "local" ||
!MANAGED_ID.test(spec.marker ?? "")
) {
throw new Error("default_profile_cron_spec_rejected");
}
const desired = {
name: entry.name,
enabled: true,
no_agent: true,
schedule: { kind: "cron", expr: spec.schedule },
script: spec.script,
deliver: spec.deliver,
};
return { spec, desired, sha256: sha256(canonicalJson(desired)) };
}
export async function reconcileDefaultProfileBundle({
activeProjection,
materializerReceipt,
profileRoot,
bundleRoot,
dataRoot,
withProfileLock = withProfileSoulLock,
reattestAuthority,
cronAdapter,
} = {}) {
if (activeProjection == null)
return { ok: true, status: "EMPTY", changed: false, actions: [] };
if (!validateProjection(activeProjection))
return refused("default_profile_projection_rejected");
if (
!isAbsolute(dataRoot ?? "") ||
!isAbsolute(profileRoot ?? "") ||
typeof withProfileLock !== "function" ||
typeof reattestAuthority !== "function"
) {
return refused("default_profile_reconcile_input_rejected");
}
try {
if (activeEntries(readBundle(bundleRoot), activeProjection).length === 0)
return { ok: true, status: "EMPTY", changed: false, actions: [] };
return await withProfileLock(
activeProjection.profileId,
async () => {
const authority = await reattestAuthority(activeProjection);
if (
authority?.operationId !== activeProjection.operationId ||
authority?.authorityGeneration !==
activeProjection.authorityGeneration ||
authority?.fence !== activeProjection.fence
) {
return refused("default_profile_authority_stale");
}
if (
!existsSync(profileRoot) ||
lstatSync(profileRoot).isSymbolicLink() ||
!lstatSync(profileRoot).isDirectory() ||
realpathSync(profileRoot) !== profileRoot
) {
throw new Error("default_profile_root_rejected");
}
const bundle = readBundle(bundleRoot);
const entries = activeEntries(bundle, activeProjection);
if (
materializerReceipt?.profileId !== activeProjection.profileId ||
!verifyDefaultProfileMaterializerReceipt({
profileRoot,
materializerReceipts: bundle.manifest.materializerReceipts,
materializerReceipt,
})
) {
throw new Error("default_profile_materializer_receipt_rejected");
}
const materializerReceiptSha256 = sha256(
canonicalJson(materializerReceipt)
);
const receiptPath = join(
profileRoot,
DEFAULT_PROFILE_RECONCILE_RECEIPT
);
let prior = null;
if (existsSync(receiptPath)) {
prior = JSON.parse(readRegular(receiptPath).toString("utf8"));
if (
prior?.schemaVersion !== DEFAULT_PROFILE_RECONCILE_SCHEMA ||
prior.profileId !== activeProjection.profileId ||
!Array.isArray(prior.entries)
) {
throw new Error("default_profile_receipt_rejected");
}
}
const historical = (entry) =>
prior?.entries.find(
(value) =>
value?.type === entry.type &&
value.id === entry.id &&
(entry.type !== "cron" || value.name === entry.name) &&
SHA256.test(value.sha256 ?? "")
) ?? null;
// Preflight every skill and cron spec before the first mutation.
const skillPlans = new Map();
const cronSpecs = new Map();
for (const entry of entries) {
if (entry.type === "cron") {
cronSpecs.set(entry.id, cronDesired(entry));
continue;
}
const path = join(profileRoot, ...entry.path.split("/"));
const directory = dirname(path);
const publicDirectory =
entry.path === canonicalPublicSkillPath(entry);
if (existsSync(directory)) {
const stat = lstatSync(directory);
if (stat.isSymbolicLink() || !stat.isDirectory())
throw new Error("default_profile_skill_collision");
for (const name of readdirSync(directory)) {
if (name === "SKILL.md") continue;
if (publicDirectory && name === "SOUL.md") {
const soul = lstatSync(join(directory, name));
if (soul.isSymbolicLink() || !soul.isFile() || soul.nlink !== 1)
throw new Error("default_profile_skill_collision");
continue;
}
const stage = join(directory, name);
const stageStat = lstatSync(stage);
if (
!name.startsWith(STAGE_PREFIX) ||
stageStat.isSymbolicLink() ||
!stageStat.isFile() ||
stageStat.nlink !== 1
) {
throw new Error("default_profile_skill_collision");
}
rmSync(stage);
}
}
const priorEntry = historical(entry);
const legacyPath = legacyManagedSkillPath(entry);
const priorPath =
priorEntry?.path ?? (priorEntry ? legacyPath : null);
let legacyDirectory = null;
if (
priorPath !== null &&
priorPath !== entry.path &&
priorPath !== legacyPath
) {
throw new Error("default_profile_receipt_rejected");
}
if (publicDirectory && legacyPath !== entry.path) {
const legacySkillPath = join(profileRoot, ...legacyPath.split("/"));
const candidateLegacyDirectory = dirname(legacySkillPath);
if (existsSync(candidateLegacyDirectory)) {
const stat = lstatSync(candidateLegacyDirectory);
if (stat.isSymbolicLink() || !stat.isDirectory())
throw new Error("default_profile_skill_collision");
for (const name of readdirSync(candidateLegacyDirectory)) {
if (name === "SKILL.md") continue;
const stage = join(candidateLegacyDirectory, name);
const stageStat = lstatSync(stage);
if (
!name.startsWith(STAGE_PREFIX) ||
stageStat.isSymbolicLink() ||
!stageStat.isFile() ||
stageStat.nlink !== 1
) {
throw new Error("default_profile_skill_collision");
}
rmSync(stage);
}
if (!existsSync(legacySkillPath))
throw new Error("default_profile_skill_collision");
const legacySha256 = sha256(
readRegular(legacySkillPath, 64 * 1024)
);
if (
legacySha256 !== entry.sha256 &&
legacySha256 !== priorEntry?.sha256 &&
legacySha256 !== LEGACY_PUBLIC_SKILL_DIGESTS[entry.id]
) {
throw new Error("default_profile_skill_collision");
}
legacyDirectory = candidateLegacyDirectory;
}
}
let status = "CREATED";
let write = true;
if (existsSync(path)) {
const current = sha256(readRegular(path, 64 * 1024));
if (current === entry.sha256) {
status = "REUSED";
write = false;
} else if (priorEntry?.sha256 === current) status = "UPDATED";
else throw new Error("default_profile_skill_collision");
}
if (
legacyDirectory ||
(priorPath !== null && priorPath !== entry.path)
)
status = "UPDATED";
skillPlans.set(entry.id, {
directory,
path,
status,
write,
legacyDirectory,
});
}
const actions = [];
const receiptEntries = [];
for (const entry of entries) {
if (entry.type === "skill") {
const plan = skillPlans.get(entry.id);
if (plan.write) {
mkdirSync(plan.directory, { recursive: true, mode: 0o700 });
atomicWrite(plan.path, entry.content, 0o444);
}
if (sha256(readRegular(plan.path, 64 * 1024)) !== entry.sha256)
throw new Error("default_profile_skill_readback_rejected");
if (plan.legacyDirectory)
rmSync(plan.legacyDirectory, { recursive: true, force: true });
actions.push({
type: "skill",
id: entry.id,
nativeName: entry.nativeName,
status: plan.status,
});
receiptEntries.push({
type: "skill",
id: entry.id,
path: entry.path,
sha256: entry.sha256,
});
continue;
}
if (
typeof cronAdapter?.create !== "function" ||
typeof cronAdapter?.update !== "function"
) {
throw new Error("default_profile_cron_adapter_rejected");
}
const {
spec,
desired,
sha256: desiredSha256,
} = cronSpecs.get(entry.id);
const cron = await ensureHermesNamedCron({
profileRoot,
name: entry.name,
isExpected: (job) =>
Boolean(
job?.id &&
job.name === desired.name &&
job.enabled === desired.enabled &&
job.no_agent === desired.no_agent &&
job.script === desired.script &&
job.deliver === desired.deliver &&
job.schedule?.kind === "cron" &&
job.schedule.expr === desired.schedule.expr
),
isUpdatable: (job) =>
historical(entry)?.sha256 ===
sha256(
canonicalJson({
name: job?.name,
enabled: job?.enabled,
no_agent: job?.no_agent,
schedule: job?.schedule,
script: job?.script,
deliver: job?.deliver,
})
),
create: () =>
cronAdapter.create({
profileRoot,
entry,
spec,
desired,
activeProjection,
}),
update: (existing) =>
cronAdapter.update({
profileRoot,
entry,
spec,
desired,
existing,
activeProjection,
}),
codePrefix: "default_profile_cron",
});
if (!cron.ok) throw new Error(cron.code);
const bound =
typeof cronAdapter.bind === "function"
? await cronAdapter.bind({
profileRoot,
entry,
spec,
desired,
job: cron.job,
activeProjection,
})
: { changed: false };
if (!bound || typeof bound.changed !== "boolean")
throw new Error("default_profile_cron_binding_rejected");
actions.push({
type: "cron",
id: entry.id,
name: entry.name,
status: cron.status,
bindingChanged: bound.changed,
});
receiptEntries.push({
type: "cron",
id: entry.id,
name: entry.name,
sha256: desiredSha256,
});
}
const receipt = `${canonicalJson({
schemaVersion: DEFAULT_PROFILE_RECONCILE_SCHEMA,
profileId: activeProjection.profileId,
bundleVersion: activeProjection.bundleVersion,
bundleDigest: activeProjection.bundleDigest,
materializerReceiptSha256,
entries: receiptEntries,
})}\n`;
const currentReceipt = existsSync(receiptPath)
? readRegular(receiptPath).toString("utf8")
: null;
if (currentReceipt !== receipt)
atomicWrite(receiptPath, receipt, 0o600);
const changed = actions.some(
(action) =>
action.status !== "REUSED" || action.bindingChanged === true
);
return {
ok: true,
status: changed ? "APPLIED" : "REUSED",
changed,
bundleVersion: activeProjection.bundleVersion,
bundleDigest: activeProjection.bundleDigest,
materializerReceiptSha256,
actions,
};
},
{ dataRoot }
);
} catch (error) {
const code =
error instanceof Error &&
/^default_profile_[a-z0-9_]+$/.test(error.message)
? error.message
: "default_profile_reconcile_failed";
return refused(code);
}
}