@ouro.bot/cli 0.1.0-alpha.733 → 0.1.0-alpha.734
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.json +25 -0
- package/deploy/unraid/Dockerfile +27 -0
- package/deploy/unraid/README.txt +1368 -0
- package/deploy/unraid/audit-container-spec.sh +4 -0
- package/deploy/unraid/container-runtime.json +1 -0
- package/deploy/unraid/sanctuary-acceptance-adapter.sh +37 -0
- package/deploy/unraid/sanctuary-acceptance-contract.json +200 -0
- package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
- package/deploy/unraid/sanctuary-deployment-target.mjs +705 -0
- package/deploy/unraid/sanctuary-safe-rename.py +24 -0
- package/deploy/unraid/sanctuary-unit16-host-broker.mjs +1777 -0
- package/deploy/unraid/sanctuary-unit16-run.sh +502 -0
- package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
- package/deploy/unraid/sanctuary.ouro/agent.json +24 -0
- package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
- package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
- package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
- package/deploy/unraid/sanctuary.ouro/provider-readiness.json +18 -0
- package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +3 -0
- package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +3 -0
- package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +3 -0
- package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +5 -0
- package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +7 -0
- package/deploy/unraid/sanctuary.ouro/tool-profiles.json +21 -0
- package/deploy/unraid/sanctuary.xml +25 -0
- package/dist/heart/approval-files.js +113 -0
- package/dist/heart/approval-store.js +168 -9
- package/dist/heart/auth/auth-flow.js +17 -1
- package/dist/heart/autonomy-budget.js +44 -1
- package/dist/heart/awaiting/await-scheduler.js +6 -2
- package/dist/heart/config.js +8 -0
- package/dist/heart/core.js +117 -132
- package/dist/heart/daemon/cli-exec.js +73 -1
- package/dist/heart/daemon/cli-help.js +5 -0
- package/dist/heart/daemon/cli-parse.js +6 -4
- package/dist/heart/daemon/container-credential-bootstrap.js +185 -0
- package/dist/heart/daemon/container-healthcheck.js +94 -0
- package/dist/heart/daemon/container-runtime.js +84 -0
- package/dist/heart/daemon/container-spec-auditor-main.js +156 -0
- package/dist/heart/daemon/container-spec-auditor.js +156 -0
- package/dist/heart/daemon/daemon-bootstrap-startup.js +41 -0
- package/dist/heart/daemon/daemon-entry.js +116 -28
- package/dist/heart/daemon/daemon-health.js +10 -0
- package/dist/heart/daemon/daemon.js +92 -5
- package/dist/heart/daemon/runtime-logging.js +6 -0
- package/dist/heart/daemon/runtime-mode.js +13 -2
- package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2365 -0
- package/dist/heart/daemon/sanctuary-acceptance-harness.js +1624 -0
- package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
- package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +985 -0
- package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
- package/dist/heart/daemon/sanctuary-scheduler-origin.js +126 -0
- package/dist/heart/daemon/sense-manager.js +25 -6
- package/dist/heart/daemon/supercronic-supervisor.js +267 -0
- package/dist/heart/habits/habit-scheduler.js +7 -3
- package/dist/heart/identity.js +13 -3
- package/dist/heart/provider-credentials.js +9 -1
- package/dist/heart/provider-models.js +8 -0
- package/dist/heart/provider-ping.js +5 -2
- package/dist/heart/providers/openai-compatible.js +177 -0
- package/dist/heart/runtime-credentials.js +217 -8
- package/dist/heart/sense-truth.js +2 -0
- package/dist/heart/tool-approval.js +1 -0
- package/dist/heart/turn-context.js +8 -0
- package/dist/mind/prompt.js +9 -0
- package/dist/nerves/coverage/source-scanner.js +4 -4
- package/dist/nerves/index.js +75 -9
- package/dist/nerves/runtime.js +12 -0
- package/dist/repertoire/tool-arguments.js +39 -0
- package/dist/repertoire/tools-unraid.js +353 -0
- package/dist/repertoire/tools.js +19 -1
- package/dist/repertoire/unraid-client.js +155 -0
- package/dist/repertoire/unraid-restart.js +130 -0
- package/dist/senses/private-runtime-worker.js +3 -2
- package/dist/senses/sanctuary-grounding.js +118 -0
- package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
- package/dist/senses/sanctuary-health-acceptance-probe.js +772 -0
- package/dist/senses/sanctuary-health-runner.js +146 -0
- package/dist/senses/sanctuary-health.js +447 -0
- package/dist/senses/sanctuary-interactive-control.js +306 -0
- package/dist/senses/sanctuary-runtime.js +206 -0
- package/dist/senses/shared-turn.js +11 -3
- package/dist/senses/telegram-approval-runtime.js +526 -0
- package/dist/senses/telegram-audit-ledger.js +220 -0
- package/dist/senses/telegram-client.js +1471 -0
- package/dist/senses/telegram-entry.js +80 -0
- package/dist/senses/telegram.js +1232 -0
- package/npm-shrinkwrap.json +6558 -0
- package/package.json +4 -2
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.boundDirectoryEntryPath = boundDirectoryEntryPath;
|
|
37
|
+
exports.secureRenameBoundInodeSync = secureRenameBoundInodeSync;
|
|
38
|
+
exports.readSanctuaryAcceptanceMarker = readSanctuaryAcceptanceMarker;
|
|
39
|
+
exports.writeSanctuaryAcceptanceMarker = writeSanctuaryAcceptanceMarker;
|
|
40
|
+
exports.clearSanctuaryAcceptanceMarker = clearSanctuaryAcceptanceMarker;
|
|
41
|
+
exports.quarantineSanctuaryAcceptanceMarker = quarantineSanctuaryAcceptanceMarker;
|
|
42
|
+
exports.sanctuaryAcceptanceEventMeta = sanctuaryAcceptanceEventMeta;
|
|
43
|
+
exports.publishSanctuaryAcceptanceGateStatus = publishSanctuaryAcceptanceGateStatus;
|
|
44
|
+
exports.clearSanctuaryAcceptanceGateStatus = clearSanctuaryAcceptanceGateStatus;
|
|
45
|
+
exports.runWithSanctuaryAcceptanceApproval = runWithSanctuaryAcceptanceApproval;
|
|
46
|
+
exports.readSanctuaryAcceptanceApproval = readSanctuaryAcceptanceApproval;
|
|
47
|
+
const fs = __importStar(require("node:fs"));
|
|
48
|
+
const path = __importStar(require("node:path"));
|
|
49
|
+
const node_async_hooks_1 = require("node:async_hooks");
|
|
50
|
+
const node_crypto_1 = require("node:crypto");
|
|
51
|
+
const node_child_process_1 = require("node:child_process");
|
|
52
|
+
const identity_1 = require("../identity");
|
|
53
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
54
|
+
const SHA256 = /^[0-9a-f]{64}$/u;
|
|
55
|
+
const acceptanceApproval = new node_async_hooks_1.AsyncLocalStorage();
|
|
56
|
+
const DEFAULT_GATE_STATUS_PATH = "/evidence/current-scenario-gate.json";
|
|
57
|
+
const SAFE_RENAME_HELPER = path.resolve(__dirname, "../../../deploy/unraid/sanctuary-safe-rename.py");
|
|
58
|
+
function requireBasename(name) {
|
|
59
|
+
if (name.length === 0 || name === "." || name === ".." || path.basename(name) !== name || name.includes("/") || name.includes("\0")) {
|
|
60
|
+
throw new Error("acceptance quarantine coordinates must be basenames");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function boundDirectoryEntryPath(directoryHandle, directoryPath, name) {
|
|
64
|
+
requireBasename(name);
|
|
65
|
+
return process.platform === "linux" ? `/proc/self/fd/${directoryHandle}/${name}` : path.join(directoryPath, name);
|
|
66
|
+
}
|
|
67
|
+
function secureRenameBoundInodeSync(sourceDirectoryHandle, sourceName, destinationDirectoryHandle, destinationName, expected) {
|
|
68
|
+
requireBasename(sourceName);
|
|
69
|
+
requireBasename(destinationName);
|
|
70
|
+
const result = (0, node_child_process_1.spawnSync)("/usr/bin/python3", [SAFE_RENAME_HELPER, sourceName, destinationName, String(expected.dev), String(expected.ino)], {
|
|
71
|
+
cwd: "/", encoding: "utf8", timeout: 5_000, maxBuffer: 16 * 1024,
|
|
72
|
+
env: { PATH: "/usr/bin:/bin" }, stdio: ["ignore", "ignore", "pipe", sourceDirectoryHandle, destinationDirectoryHandle],
|
|
73
|
+
});
|
|
74
|
+
if (result.error || result.status !== 0)
|
|
75
|
+
throw new Error("acceptance quarantine bound rename failed");
|
|
76
|
+
}
|
|
77
|
+
function markerPath(agentName, configuredAgentRoot) {
|
|
78
|
+
return path.join(configuredAgentRoot ?? (0, identity_1.getAgentRoot)(agentName), "state", "acceptance", "active-scenario.json");
|
|
79
|
+
}
|
|
80
|
+
function parseMarker(value) {
|
|
81
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
82
|
+
throw new Error("acceptance marker is corrupt");
|
|
83
|
+
const marker = value;
|
|
84
|
+
if (JSON.stringify(Object.keys(marker).sort()) !== JSON.stringify(["label", "scenarioHandleDigest", "schemaVersion", "startedAt"])) {
|
|
85
|
+
throw new Error("acceptance marker is corrupt");
|
|
86
|
+
}
|
|
87
|
+
if (marker.schemaVersion !== "sanctuary-acceptance-marker-v1"
|
|
88
|
+
|| typeof marker.label !== "string" || marker.label.length === 0
|
|
89
|
+
|| typeof marker.scenarioHandleDigest !== "string" || !SHA256.test(marker.scenarioHandleDigest)
|
|
90
|
+
|| typeof marker.startedAt !== "string" || new Date(marker.startedAt).toISOString() !== marker.startedAt) {
|
|
91
|
+
throw new Error("acceptance marker is corrupt");
|
|
92
|
+
}
|
|
93
|
+
return marker;
|
|
94
|
+
}
|
|
95
|
+
function readSanctuaryAcceptanceMarker(agentName, configuredAgentRoot) {
|
|
96
|
+
if (agentName !== "sanctuary")
|
|
97
|
+
return null;
|
|
98
|
+
const filePath = markerPath(agentName, configuredAgentRoot);
|
|
99
|
+
let raw;
|
|
100
|
+
try {
|
|
101
|
+
raw = fs.readFileSync(filePath, "utf8");
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
if (error.code === "ENOENT")
|
|
105
|
+
return null;
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
return parseMarker(JSON.parse(raw));
|
|
109
|
+
}
|
|
110
|
+
function writeSanctuaryAcceptanceMarker(agentName, marker, configuredAgentRoot) {
|
|
111
|
+
if (agentName !== "sanctuary")
|
|
112
|
+
throw new Error("acceptance markers are restricted to Sanctuary");
|
|
113
|
+
const parsed = parseMarker(marker);
|
|
114
|
+
const filePath = markerPath(agentName, configuredAgentRoot);
|
|
115
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 });
|
|
116
|
+
const temporary = `${filePath}.${process.pid}.tmp`;
|
|
117
|
+
fs.writeFileSync(temporary, `${JSON.stringify(parsed)}\n`, { encoding: "utf8", mode: 0o600, flag: "wx" });
|
|
118
|
+
fs.renameSync(temporary, filePath);
|
|
119
|
+
fs.chmodSync(filePath, 0o600);
|
|
120
|
+
(0, runtime_1.emitNervesEvent)({ component: "daemon", event: "daemon.sanctuary_acceptance_marker_written", message: "Sanctuary acceptance marker published", meta: { label: parsed.label, scenarioHandleDigest: parsed.scenarioHandleDigest } });
|
|
121
|
+
}
|
|
122
|
+
function clearSanctuaryAcceptanceMarker(agentName, scenarioHandleDigest, configuredAgentRoot) {
|
|
123
|
+
if (!SHA256.test(scenarioHandleDigest))
|
|
124
|
+
throw new Error("scenario handle digest is invalid");
|
|
125
|
+
const current = readSanctuaryAcceptanceMarker(agentName, configuredAgentRoot);
|
|
126
|
+
if (!current)
|
|
127
|
+
return;
|
|
128
|
+
if (current.scenarioHandleDigest !== scenarioHandleDigest)
|
|
129
|
+
throw new Error("acceptance marker ownership mismatch");
|
|
130
|
+
fs.unlinkSync(markerPath(agentName, configuredAgentRoot));
|
|
131
|
+
(0, runtime_1.emitNervesEvent)({ component: "daemon", event: "daemon.sanctuary_acceptance_marker_cleared", message: "Sanctuary acceptance marker cleared", meta: { scenarioHandleDigest } });
|
|
132
|
+
}
|
|
133
|
+
function quarantineSanctuaryAcceptanceMarker(agentName, configuredAgentRoot) {
|
|
134
|
+
if (agentName !== "sanctuary")
|
|
135
|
+
throw new Error("acceptance markers are restricted to Sanctuary");
|
|
136
|
+
const filePath = markerPath(agentName, configuredAgentRoot);
|
|
137
|
+
const sourceParent = path.dirname(filePath);
|
|
138
|
+
const quarantineRoot = path.join(sourceParent, "quarantine");
|
|
139
|
+
let markerPathMetadata;
|
|
140
|
+
try {
|
|
141
|
+
markerPathMetadata = fs.lstatSync(filePath);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
if (error.code === "ENOENT")
|
|
145
|
+
return null;
|
|
146
|
+
throw error;
|
|
147
|
+
}
|
|
148
|
+
const sourceParentHandle = fs.openSync(sourceParent, fs.constants.O_RDONLY | fs.constants.O_DIRECTORY | fs.constants.O_NOFOLLOW);
|
|
149
|
+
let markerHandle = null;
|
|
150
|
+
let quarantineHandle = null;
|
|
151
|
+
const rejectedPath = path.join(sourceParent, `.quarantine-rejected-${(0, node_crypto_1.randomUUID)()}`);
|
|
152
|
+
const quarantinePath = path.join(quarantineRoot, `active-scenario-${(0, node_crypto_1.randomUUID)()}.json`);
|
|
153
|
+
try {
|
|
154
|
+
const sourceParentMetadata = fs.fstatSync(sourceParentHandle);
|
|
155
|
+
const sourceParentPathMetadata = fs.lstatSync(sourceParent);
|
|
156
|
+
if (!sourceParentMetadata.isDirectory() || !sourceParentPathMetadata.isDirectory()
|
|
157
|
+
|| sourceParentMetadata.dev !== sourceParentPathMetadata.dev || sourceParentMetadata.ino !== sourceParentPathMetadata.ino)
|
|
158
|
+
throw new Error("acceptance marker parent changed during quarantine");
|
|
159
|
+
const boundMarkerPath = boundDirectoryEntryPath(sourceParentHandle, sourceParent, path.basename(filePath));
|
|
160
|
+
const boundQuarantineRoot = boundDirectoryEntryPath(sourceParentHandle, sourceParent, path.basename(quarantineRoot));
|
|
161
|
+
const boundRejectedPath = boundDirectoryEntryPath(sourceParentHandle, sourceParent, path.basename(rejectedPath));
|
|
162
|
+
if (markerPathMetadata.isFile())
|
|
163
|
+
markerHandle = fs.openSync(boundMarkerPath, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW);
|
|
164
|
+
if (markerHandle !== null) {
|
|
165
|
+
const markerMetadata = fs.fstatSync(markerHandle);
|
|
166
|
+
markerPathMetadata = fs.lstatSync(boundMarkerPath);
|
|
167
|
+
if (!markerMetadata.isFile() || !markerPathMetadata.isFile() || markerMetadata.dev !== markerPathMetadata.dev || markerMetadata.ino !== markerPathMetadata.ino)
|
|
168
|
+
throw new Error("acceptance marker changed during quarantine");
|
|
169
|
+
}
|
|
170
|
+
let quarantineExists = false;
|
|
171
|
+
let rejectedMetadata = null;
|
|
172
|
+
try {
|
|
173
|
+
const existing = fs.lstatSync(boundQuarantineRoot);
|
|
174
|
+
if (!existing.isDirectory()) {
|
|
175
|
+
secureRenameBoundInodeSync(sourceParentHandle, path.basename(quarantineRoot), sourceParentHandle, path.basename(rejectedPath), existing);
|
|
176
|
+
const rejected = fs.lstatSync(boundRejectedPath);
|
|
177
|
+
if (rejected.dev !== existing.dev || rejected.ino !== existing.ino)
|
|
178
|
+
throw new Error("acceptance marker quarantine rejection changed during move");
|
|
179
|
+
rejectedMetadata = rejected;
|
|
180
|
+
}
|
|
181
|
+
else
|
|
182
|
+
quarantineExists = true;
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
if (error.code !== "ENOENT")
|
|
186
|
+
throw error;
|
|
187
|
+
}
|
|
188
|
+
if (!quarantineExists)
|
|
189
|
+
fs.mkdirSync(boundQuarantineRoot, { mode: 0o700 });
|
|
190
|
+
quarantineHandle = fs.openSync(boundQuarantineRoot, fs.constants.O_RDONLY | fs.constants.O_DIRECTORY | fs.constants.O_NOFOLLOW);
|
|
191
|
+
const quarantineMetadata = fs.fstatSync(quarantineHandle);
|
|
192
|
+
const quarantinePathMetadata = fs.lstatSync(boundQuarantineRoot);
|
|
193
|
+
if (!quarantineMetadata.isDirectory() || !quarantinePathMetadata.isDirectory()
|
|
194
|
+
|| quarantineMetadata.dev !== quarantinePathMetadata.dev || quarantineMetadata.ino !== quarantinePathMetadata.ino)
|
|
195
|
+
throw new Error("acceptance marker quarantine root changed");
|
|
196
|
+
fs.fchmodSync(quarantineHandle, 0o700);
|
|
197
|
+
if (rejectedMetadata) {
|
|
198
|
+
secureRenameBoundInodeSync(sourceParentHandle, path.basename(rejectedPath), quarantineHandle, path.basename(rejectedPath).slice(1), rejectedMetadata);
|
|
199
|
+
}
|
|
200
|
+
const finalMarkerPathMetadata = fs.lstatSync(boundMarkerPath);
|
|
201
|
+
if (finalMarkerPathMetadata.dev !== markerPathMetadata.dev || finalMarkerPathMetadata.ino !== markerPathMetadata.ino)
|
|
202
|
+
throw new Error("acceptance marker changed before quarantine move");
|
|
203
|
+
secureRenameBoundInodeSync(sourceParentHandle, path.basename(filePath), quarantineHandle, path.basename(quarantinePath), markerPathMetadata);
|
|
204
|
+
const movedMarkerMetadata = fs.lstatSync(boundDirectoryEntryPath(quarantineHandle, quarantineRoot, path.basename(quarantinePath)));
|
|
205
|
+
if (movedMarkerMetadata.dev !== markerPathMetadata.dev || movedMarkerMetadata.ino !== markerPathMetadata.ino)
|
|
206
|
+
throw new Error("acceptance marker changed during quarantine move");
|
|
207
|
+
if (markerHandle !== null)
|
|
208
|
+
fs.fsyncSync(markerHandle);
|
|
209
|
+
fs.fsyncSync(sourceParentHandle);
|
|
210
|
+
fs.fsyncSync(quarantineHandle);
|
|
211
|
+
}
|
|
212
|
+
finally {
|
|
213
|
+
if (quarantineHandle !== null)
|
|
214
|
+
fs.closeSync(quarantineHandle);
|
|
215
|
+
if (markerHandle !== null)
|
|
216
|
+
fs.closeSync(markerHandle);
|
|
217
|
+
fs.closeSync(sourceParentHandle);
|
|
218
|
+
}
|
|
219
|
+
(0, runtime_1.emitNervesEvent)({ component: "daemon", event: "daemon.sanctuary_acceptance_marker_quarantined", message: "Sanctuary acceptance marker was quarantined", meta: { quarantinePath } });
|
|
220
|
+
return quarantinePath;
|
|
221
|
+
}
|
|
222
|
+
function sanctuaryAcceptanceEventMeta(agentName) {
|
|
223
|
+
const marker = readSanctuaryAcceptanceMarker(agentName);
|
|
224
|
+
return marker ? { scenarioHandleDigest: marker.scenarioHandleDigest } : {};
|
|
225
|
+
}
|
|
226
|
+
function parseGateStatus(value) {
|
|
227
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
228
|
+
throw new Error("acceptance gate status is invalid");
|
|
229
|
+
const status = value;
|
|
230
|
+
if (JSON.stringify(Object.keys(status).sort()) !== JSON.stringify(["gate", "label", "phase", "startedAt"]))
|
|
231
|
+
throw new Error("acceptance gate status is invalid");
|
|
232
|
+
if (typeof status.label !== "string" || status.label.length === 0
|
|
233
|
+
|| typeof status.gate !== "string" || status.gate.length === 0
|
|
234
|
+
|| (status.phase !== "waiting" && status.phase !== "complete")
|
|
235
|
+
|| typeof status.startedAt !== "string" || new Date(status.startedAt).toISOString() !== status.startedAt) {
|
|
236
|
+
throw new Error("acceptance gate status is invalid");
|
|
237
|
+
}
|
|
238
|
+
return status;
|
|
239
|
+
}
|
|
240
|
+
function publishSanctuaryAcceptanceGateStatus(status, filePath = DEFAULT_GATE_STATUS_PATH) {
|
|
241
|
+
const parsed = parseGateStatus(status);
|
|
242
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o755 });
|
|
243
|
+
const temporary = `${filePath}.${process.pid}.tmp`;
|
|
244
|
+
fs.writeFileSync(temporary, `${JSON.stringify(parsed)}\n`, { encoding: "utf8", mode: 0o644, flag: "wx" });
|
|
245
|
+
fs.renameSync(temporary, filePath);
|
|
246
|
+
fs.chmodSync(filePath, 0o644);
|
|
247
|
+
(0, runtime_1.emitNervesEvent)({ component: "daemon", event: "daemon.sanctuary_acceptance_gate_status_written", message: "Sanctuary acceptance gate status published", meta: { label: parsed.label, gate: parsed.gate, phase: parsed.phase } });
|
|
248
|
+
}
|
|
249
|
+
function clearSanctuaryAcceptanceGateStatus(filePath = DEFAULT_GATE_STATUS_PATH) {
|
|
250
|
+
try {
|
|
251
|
+
fs.unlinkSync(filePath);
|
|
252
|
+
}
|
|
253
|
+
catch (error) {
|
|
254
|
+
if (error.code !== "ENOENT")
|
|
255
|
+
throw error;
|
|
256
|
+
}
|
|
257
|
+
(0, runtime_1.emitNervesEvent)({ component: "daemon", event: "daemon.sanctuary_acceptance_gate_status_cleared", message: "Sanctuary acceptance gate status cleared", meta: { path: filePath } });
|
|
258
|
+
}
|
|
259
|
+
function runWithSanctuaryAcceptanceApproval(value, operation) {
|
|
260
|
+
if (!value.approvalId || !SHA256.test(value.argumentDigest))
|
|
261
|
+
throw new Error("acceptance approval context is invalid");
|
|
262
|
+
return acceptanceApproval.run({ ...value }, operation);
|
|
263
|
+
}
|
|
264
|
+
function readSanctuaryAcceptanceApproval() {
|
|
265
|
+
const value = acceptanceApproval.getStore();
|
|
266
|
+
return value ? { ...value } : null;
|
|
267
|
+
}
|