@ouro.bot/cli 0.1.0-alpha.732 → 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/README.md +1 -1
- package/changelog.json +34 -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 +74 -2
- package/dist/heart/daemon/cli-help.js +6 -1
- 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/doctor.js +56 -7
- 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/mailroom/blob-store.js +97 -19
- package/dist/mailroom/cache-sync-cli.js +5 -1
- package/dist/mailroom/core.js +23 -8
- package/dist/mailroom/hosted-cache-sync.js +179 -44
- package/dist/mailroom/search-cache.js +109 -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,220 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.TELEGRAM_ACCEPTANCE_AUDIT_HEAD_RELATIVE_PATH = exports.TELEGRAM_ACCEPTANCE_AUDIT_RELATIVE_PATH = void 0;
|
|
7
|
+
exports.verifyTelegramAuditLedger = verifyTelegramAuditLedger;
|
|
8
|
+
exports.createTelegramAuditLedger = createTelegramAuditLedger;
|
|
9
|
+
const node_crypto_1 = require("node:crypto");
|
|
10
|
+
const node_fs_1 = require("node:fs");
|
|
11
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
12
|
+
const redact_1 = require("../nerves/redact");
|
|
13
|
+
const runtime_1 = require("../nerves/runtime");
|
|
14
|
+
const SCHEMA = "sanctuary-telegram-audit-chain-v1";
|
|
15
|
+
const GENESIS_MAC = "0".repeat(64);
|
|
16
|
+
const SHA256 = /^[0-9a-f]{64}$/u;
|
|
17
|
+
const MAX_BYTES = 32 * 1024 * 1024;
|
|
18
|
+
const MAX_ROWS = 100_000;
|
|
19
|
+
const MAX_ROW_BYTES = 64 * 1024;
|
|
20
|
+
const LEVELS = new Set(["debug", "info", "warn", "error"]);
|
|
21
|
+
const ROW_KEYS = ["component", "event", "level", "message", "meta", "previousMac", "rowMac", "schemaVersion", "sequence", "trace_id", "ts"].sort();
|
|
22
|
+
const HEAD_KEYS = ["headMac", "lastMac", "recordCount", "schemaVersion"].sort();
|
|
23
|
+
exports.TELEGRAM_ACCEPTANCE_AUDIT_RELATIVE_PATH = node_path_1.default.join("state", "acceptance", "telegram-audit-chain.ndjson");
|
|
24
|
+
exports.TELEGRAM_ACCEPTANCE_AUDIT_HEAD_RELATIVE_PATH = node_path_1.default.join("state", "acceptance", "telegram-audit-chain.head.json");
|
|
25
|
+
function canonicalJson(value) {
|
|
26
|
+
if (Array.isArray(value))
|
|
27
|
+
return `[${value.map(canonicalJson).join(",")}]`;
|
|
28
|
+
if (value && typeof value === "object") {
|
|
29
|
+
const record = value;
|
|
30
|
+
return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(record[key])}`).join(",")}}`;
|
|
31
|
+
}
|
|
32
|
+
const rendered = JSON.stringify(value);
|
|
33
|
+
if (rendered === undefined)
|
|
34
|
+
throw new Error("Telegram audit ledger contains an unsupported value");
|
|
35
|
+
return rendered;
|
|
36
|
+
}
|
|
37
|
+
function rowMac(identityKey, row) {
|
|
38
|
+
return (0, node_crypto_1.createHmac)("sha256", identityKey).update(`ouroboros.telegram.audit-row.v1\0${canonicalJson(row)}`, "utf8").digest("hex");
|
|
39
|
+
}
|
|
40
|
+
function headMac(identityKey, recordCount, lastMac) {
|
|
41
|
+
return (0, node_crypto_1.createHmac)("sha256", identityKey).update(`ouroboros.telegram.audit-head.v1\0${recordCount}\0${lastMac}`, "utf8").digest("hex");
|
|
42
|
+
}
|
|
43
|
+
function canonicalIso(value) {
|
|
44
|
+
return typeof value === "string" && value.length <= 30 && Number.isFinite(Date.parse(value)) && new Date(Date.parse(value)).toISOString() === value;
|
|
45
|
+
}
|
|
46
|
+
function object(value, label) {
|
|
47
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
48
|
+
throw new Error(`${label} is invalid`);
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
function parseJson(raw, label) {
|
|
52
|
+
try {
|
|
53
|
+
return JSON.parse(raw);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
throw new Error(`${label} JSON is invalid`, { cause: error });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function containsPrivateMaterial(raw, privateValues) {
|
|
60
|
+
return privateValues.some((value) => value.length >= 5 && raw.includes(value))
|
|
61
|
+
|| /\b\d{5,16}:[A-Za-z0-9_-]{20,}\b/u.test(raw)
|
|
62
|
+
|| /"(?:authorized_?user_?id|authorized_?chat_?id|transport_?user_?id|transport_?chat_?id|user_?id|chat_?id|update_?id|message_?id)"\s*:\s*"?\d{1,20}"?/iu.test(raw);
|
|
63
|
+
}
|
|
64
|
+
function parseHead(raw, identityKey) {
|
|
65
|
+
if (Buffer.byteLength(raw) > 4 * 1024)
|
|
66
|
+
throw new Error("Telegram audit head exceeds its bound");
|
|
67
|
+
const value = object(parseJson(raw, "Telegram audit head"), "Telegram audit head");
|
|
68
|
+
if (JSON.stringify(Object.keys(value).sort()) !== JSON.stringify(HEAD_KEYS)
|
|
69
|
+
|| value.schemaVersion !== SCHEMA
|
|
70
|
+
|| !Number.isSafeInteger(value.recordCount) || Number(value.recordCount) < 0 || Number(value.recordCount) > MAX_ROWS
|
|
71
|
+
|| typeof value.lastMac !== "string" || !SHA256.test(value.lastMac)
|
|
72
|
+
|| typeof value.headMac !== "string" || !SHA256.test(value.headMac)
|
|
73
|
+
|| value.headMac !== headMac(identityKey, Number(value.recordCount), value.lastMac))
|
|
74
|
+
throw new Error("Telegram audit head MAC is invalid");
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
function verifyTelegramAuditLedger(options) {
|
|
78
|
+
if (Buffer.byteLength(options.ledgerRaw) > MAX_BYTES)
|
|
79
|
+
throw new Error("Telegram audit ledger exceeds its bound");
|
|
80
|
+
const lines = options.ledgerRaw.split("\n").filter(Boolean);
|
|
81
|
+
if (lines.length > MAX_ROWS || lines.some((line) => Buffer.byteLength(line) > MAX_ROW_BYTES))
|
|
82
|
+
throw new Error("Telegram audit ledger exceeds its bound");
|
|
83
|
+
const head = parseHead(options.headRaw, options.identityKey);
|
|
84
|
+
let previousMac = GENESIS_MAC;
|
|
85
|
+
const events = lines.map((line, index) => {
|
|
86
|
+
if (containsPrivateMaterial(line, options.privateValues ?? []))
|
|
87
|
+
throw new Error("Telegram audit ledger contains private material");
|
|
88
|
+
const value = object(parseJson(line, "Telegram audit ledger row"), "Telegram audit ledger row");
|
|
89
|
+
if (JSON.stringify(Object.keys(value).sort()) !== JSON.stringify(ROW_KEYS)
|
|
90
|
+
|| value.schemaVersion !== SCHEMA || value.sequence !== index + 1 || value.previousMac !== previousMac
|
|
91
|
+
|| !canonicalIso(value.ts) || typeof value.level !== "string" || !LEVELS.has(value.level)
|
|
92
|
+
|| typeof value.event !== "string" || value.event.length < 1 || value.event.length > 256
|
|
93
|
+
|| typeof value.component !== "string" || value.component.length < 1 || value.component.length > 128
|
|
94
|
+
|| typeof value.trace_id !== "string" || value.trace_id.length < 1 || value.trace_id.length > 256
|
|
95
|
+
|| typeof value.message !== "string" || value.message.length > 4_096
|
|
96
|
+
|| !value.meta || typeof value.meta !== "object" || Array.isArray(value.meta)
|
|
97
|
+
|| typeof value.rowMac !== "string" || !SHA256.test(value.rowMac))
|
|
98
|
+
throw new Error("Telegram audit ledger row is invalid");
|
|
99
|
+
const unsigned = Object.fromEntries(Object.entries(value).filter(([key]) => key !== "rowMac"));
|
|
100
|
+
if (value.rowMac !== rowMac(options.identityKey, unsigned))
|
|
101
|
+
throw new Error("Telegram audit ledger row MAC is invalid");
|
|
102
|
+
previousMac = value.rowMac;
|
|
103
|
+
return { event: value.event, at: Date.parse(value.ts), meta: value.meta };
|
|
104
|
+
});
|
|
105
|
+
if (head.recordCount !== lines.length || head.lastMac !== previousMac)
|
|
106
|
+
throw new Error("Telegram audit head does not match the append-only ledger");
|
|
107
|
+
return events;
|
|
108
|
+
}
|
|
109
|
+
function writeHead(filePath, directory, head) {
|
|
110
|
+
const temporary = `${filePath}.tmp-${process.pid}-${(0, node_crypto_1.randomUUID)()}`;
|
|
111
|
+
(0, node_fs_1.writeFileSync)(temporary, `${JSON.stringify(head)}\n`, { flag: "wx", mode: 0o600 });
|
|
112
|
+
const file = (0, node_fs_1.openSync)(temporary, "r");
|
|
113
|
+
try {
|
|
114
|
+
(0, node_fs_1.fsyncSync)(file);
|
|
115
|
+
}
|
|
116
|
+
finally {
|
|
117
|
+
(0, node_fs_1.closeSync)(file);
|
|
118
|
+
}
|
|
119
|
+
(0, node_fs_1.renameSync)(temporary, filePath);
|
|
120
|
+
const directoryHandle = (0, node_fs_1.openSync)(directory, "r");
|
|
121
|
+
try {
|
|
122
|
+
(0, node_fs_1.fsyncSync)(directoryHandle);
|
|
123
|
+
}
|
|
124
|
+
finally {
|
|
125
|
+
(0, node_fs_1.closeSync)(directoryHandle);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function createTelegramAuditLedger(options) {
|
|
129
|
+
const directory = node_path_1.default.join(options.root, "state", "acceptance");
|
|
130
|
+
const ledgerPath = node_path_1.default.join(options.root, exports.TELEGRAM_ACCEPTANCE_AUDIT_RELATIVE_PATH);
|
|
131
|
+
const headPath = node_path_1.default.join(options.root, exports.TELEGRAM_ACCEPTANCE_AUDIT_HEAD_RELATIVE_PATH);
|
|
132
|
+
(0, node_fs_1.mkdirSync)(directory, { recursive: true, mode: 0o700 });
|
|
133
|
+
if ((0, node_fs_1.existsSync)(ledgerPath) !== (0, node_fs_1.existsSync)(headPath))
|
|
134
|
+
throw new Error("Telegram audit ledger/head presence mismatch");
|
|
135
|
+
if (!(0, node_fs_1.existsSync)(ledgerPath)) {
|
|
136
|
+
(0, node_fs_1.writeFileSync)(ledgerPath, "", { flag: "wx", mode: 0o600 });
|
|
137
|
+
writeHead(headPath, directory, { schemaVersion: SCHEMA, recordCount: 0, lastMac: GENESIS_MAC, headMac: headMac(options.identityKey, 0, GENESIS_MAC) });
|
|
138
|
+
}
|
|
139
|
+
let records = verifyTelegramAuditLedger({ ledgerRaw: (0, node_fs_1.readFileSync)(ledgerPath, "utf8"), headRaw: (0, node_fs_1.readFileSync)(headPath, "utf8"), identityKey: options.identityKey, privateValues: options.privateValues });
|
|
140
|
+
let currentHead = parseHead((0, node_fs_1.readFileSync)(headPath, "utf8"), options.identityKey);
|
|
141
|
+
const maxBytes = options._maxBytes ?? MAX_BYTES;
|
|
142
|
+
let failure;
|
|
143
|
+
(0, runtime_1.emitNervesEvent)({
|
|
144
|
+
component: "senses",
|
|
145
|
+
event: "senses.telegram_audit_ledger_ready",
|
|
146
|
+
message: "Telegram acceptance audit ledger is verified",
|
|
147
|
+
meta: { recordCount: currentHead.recordCount },
|
|
148
|
+
});
|
|
149
|
+
return {
|
|
150
|
+
ledgerPath,
|
|
151
|
+
headPath,
|
|
152
|
+
append(event) {
|
|
153
|
+
if (failure)
|
|
154
|
+
throw failure;
|
|
155
|
+
try {
|
|
156
|
+
const original = JSON.stringify(event);
|
|
157
|
+
if (containsPrivateMaterial(original, options.privateValues ?? []))
|
|
158
|
+
throw new Error("Telegram audit event contains private material");
|
|
159
|
+
const redacted = JSON.parse((0, redact_1.redactString)(JSON.stringify((0, redact_1.redactLogEntry)(event))));
|
|
160
|
+
const unsigned = {
|
|
161
|
+
schemaVersion: SCHEMA,
|
|
162
|
+
sequence: currentHead.recordCount + 1,
|
|
163
|
+
previousMac: currentHead.lastMac,
|
|
164
|
+
ts: redacted.ts,
|
|
165
|
+
level: redacted.level,
|
|
166
|
+
event: redacted.event,
|
|
167
|
+
component: redacted.component,
|
|
168
|
+
trace_id: redacted.trace_id,
|
|
169
|
+
message: redacted.message,
|
|
170
|
+
meta: redacted.meta,
|
|
171
|
+
};
|
|
172
|
+
const row = { ...unsigned, rowMac: rowMac(options.identityKey, unsigned) };
|
|
173
|
+
const serialized = JSON.stringify(row);
|
|
174
|
+
if (Buffer.byteLength(serialized) > MAX_ROW_BYTES || currentHead.recordCount >= MAX_ROWS
|
|
175
|
+
|| Buffer.byteLength((0, node_fs_1.readFileSync)(ledgerPath)) + Buffer.byteLength(serialized) + 1 > maxBytes)
|
|
176
|
+
throw new Error("Telegram audit ledger exceeds its bound");
|
|
177
|
+
(0, node_fs_1.appendFileSync)(ledgerPath, `${serialized}\n`, { encoding: "utf8", mode: 0o600 });
|
|
178
|
+
const ledgerHandle = (0, node_fs_1.openSync)(ledgerPath, "r");
|
|
179
|
+
try {
|
|
180
|
+
(0, node_fs_1.fsyncSync)(ledgerHandle);
|
|
181
|
+
}
|
|
182
|
+
finally {
|
|
183
|
+
(0, node_fs_1.closeSync)(ledgerHandle);
|
|
184
|
+
}
|
|
185
|
+
currentHead = {
|
|
186
|
+
schemaVersion: SCHEMA,
|
|
187
|
+
recordCount: row.sequence,
|
|
188
|
+
lastMac: row.rowMac,
|
|
189
|
+
headMac: headMac(options.identityKey, row.sequence, row.rowMac),
|
|
190
|
+
};
|
|
191
|
+
writeHead(headPath, directory, currentHead);
|
|
192
|
+
records = [...records, { event: row.event, at: Date.parse(row.ts), meta: row.meta }];
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
failure = error instanceof Error ? error : new Error(String(error));
|
|
196
|
+
throw failure;
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
poison(error) {
|
|
200
|
+
failure ??= error;
|
|
201
|
+
throw failure;
|
|
202
|
+
},
|
|
203
|
+
assertHealthy() {
|
|
204
|
+
if (failure)
|
|
205
|
+
throw failure;
|
|
206
|
+
records = verifyTelegramAuditLedger({ ledgerRaw: (0, node_fs_1.readFileSync)(ledgerPath, "utf8"), headRaw: (0, node_fs_1.readFileSync)(headPath, "utf8"), identityKey: options.identityKey, privateValues: options.privateValues });
|
|
207
|
+
currentHead = parseHead((0, node_fs_1.readFileSync)(headPath, "utf8"), options.identityKey);
|
|
208
|
+
},
|
|
209
|
+
assertCapacity(additionalRows = 1) {
|
|
210
|
+
if (!Number.isSafeInteger(additionalRows) || additionalRows < 1)
|
|
211
|
+
throw new Error("Telegram audit capacity reservation is invalid");
|
|
212
|
+
if (failure)
|
|
213
|
+
throw failure;
|
|
214
|
+
if (currentHead.recordCount + additionalRows > MAX_ROWS
|
|
215
|
+
|| Buffer.byteLength((0, node_fs_1.readFileSync)(ledgerPath)) + additionalRows * (MAX_ROW_BYTES + 1) > maxBytes) {
|
|
216
|
+
throw new Error("Telegram audit ledger lacks reserved capacity");
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
}
|