@sellable/install 0.1.483 → 0.1.486-wip.phase169.20260804.2

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.
@@ -0,0 +1,377 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import {
3
+ chmodSync,
4
+ existsSync,
5
+ lstatSync,
6
+ mkdirSync,
7
+ readFileSync,
8
+ renameSync,
9
+ writeFileSync,
10
+ } from "node:fs";
11
+ import { dirname } from "node:path";
12
+
13
+ const SHA256 = /^[a-f0-9]{64}$/;
14
+ const SAFE_ID = /^[A-Za-z0-9_.:-]{1,256}$/;
15
+ const FINGERPRINT = /^[a-f0-9]{16,64}$/;
16
+ const SAFE_REASON = /^[a-z0-9_.:-]{1,128}$/;
17
+
18
+ function isRecord(value) {
19
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
20
+ }
21
+
22
+ function rejectIdentity() {
23
+ throw new Error("model_health_report_identity_rejected");
24
+ }
25
+
26
+ function safeOrigin(value, allowHttpLoopback) {
27
+ try {
28
+ const parsed = new URL(value);
29
+ const testHttp =
30
+ allowHttpLoopback === true &&
31
+ parsed.protocol === "http:" &&
32
+ ["127.0.0.1", "localhost", "host.docker.internal"].includes(
33
+ parsed.hostname
34
+ );
35
+ if (
36
+ (parsed.protocol !== "https:" && !testHttp) ||
37
+ parsed.username ||
38
+ parsed.password ||
39
+ parsed.pathname !== "/" ||
40
+ parsed.search ||
41
+ parsed.hash
42
+ ) {
43
+ return null;
44
+ }
45
+ return parsed.origin;
46
+ } catch {
47
+ return null;
48
+ }
49
+ }
50
+
51
+ function safeSnapshot(snapshot) {
52
+ if (
53
+ !isRecord(snapshot) ||
54
+ snapshot.schemaVersion !== "sellable-agent-model-auth-readback/v2" ||
55
+ !SAFE_ID.test(snapshot.activationId ?? "") ||
56
+ !Number.isSafeInteger(snapshot.bundleGeneration) ||
57
+ snapshot.bundleGeneration < 1 ||
58
+ !SHA256.test(snapshot.policyHash ?? "") ||
59
+ snapshot.provider !== "openai-codex" ||
60
+ !SAFE_ID.test(snapshot.model ?? "") ||
61
+ !Number.isSafeInteger(snapshot.fallbackDepth) ||
62
+ snapshot.fallbackDepth < 0 ||
63
+ snapshot.fallbackDepth > 8 ||
64
+ !["converged", "unknown"].includes(snapshot.desiredStatus) ||
65
+ !["current", "pending_start"].includes(snapshot.materializedStatus) ||
66
+ !Array.isArray(snapshot.slots) ||
67
+ snapshot.slots.length > 2 ||
68
+ !isRecord(snapshot.openrouter) ||
69
+ !FINGERPRINT.test(snapshot.openrouter.keyFingerprint ?? "") ||
70
+ !["ok", "exhausted", "dead"].includes(snapshot.openrouter.state) ||
71
+ (snapshot.activeProvider !== undefined &&
72
+ snapshot.activeProvider !== null &&
73
+ !["openai-codex", "openrouter"].includes(snapshot.activeProvider)) ||
74
+ (snapshot.activeFallbackModelId !== undefined &&
75
+ snapshot.activeFallbackModelId !== null &&
76
+ (typeof snapshot.activeFallbackModelId !== "string" ||
77
+ snapshot.activeFallbackModelId.length < 1 ||
78
+ snapshot.activeFallbackModelId.length > 256))
79
+ ) {
80
+ throw new Error("model_health_snapshot_rejected");
81
+ }
82
+ const slots = snapshot.slots.map((slot) => {
83
+ if (
84
+ !isRecord(slot) ||
85
+ !["dittto-primary", "kaigo-secondary"].includes(slot.slotId) ||
86
+ !FINGERPRINT.test(slot.grantFingerprint ?? "") ||
87
+ !Number.isFinite(Date.parse(slot.expiresAt ?? "")) ||
88
+ !["ok", "exhausted", "dead"].includes(slot.state) ||
89
+ (slot.lastErrorReason !== null &&
90
+ !SAFE_REASON.test(slot.lastErrorReason ?? "")) ||
91
+ (slot.lastErrorResetAt !== null &&
92
+ !Number.isFinite(Date.parse(slot.lastErrorResetAt ?? "")))
93
+ ) {
94
+ throw new Error("model_health_snapshot_rejected");
95
+ }
96
+ return Object.freeze({
97
+ slotId: slot.slotId,
98
+ grantFingerprint: slot.grantFingerprint,
99
+ expiresAt: new Date(slot.expiresAt).toISOString(),
100
+ state: slot.state,
101
+ lastErrorReason: slot.lastErrorReason,
102
+ lastErrorResetAt:
103
+ slot.lastErrorResetAt === null
104
+ ? null
105
+ : new Date(slot.lastErrorResetAt).toISOString(),
106
+ });
107
+ });
108
+ return Object.freeze({
109
+ activationId: snapshot.activationId,
110
+ bundleGeneration: snapshot.bundleGeneration,
111
+ policyHash: snapshot.policyHash,
112
+ provider: snapshot.provider,
113
+ model: snapshot.model,
114
+ fallbackDepth: snapshot.fallbackDepth,
115
+ desiredStatus: snapshot.desiredStatus,
116
+ materializedStatus: snapshot.materializedStatus,
117
+ slots: Object.freeze(slots),
118
+ openrouter: Object.freeze({
119
+ keyFingerprint: snapshot.openrouter.keyFingerprint,
120
+ state: snapshot.openrouter.state,
121
+ }),
122
+ activeProvider: snapshot.activeProvider ?? null,
123
+ activeFallbackModelId: snapshot.activeFallbackModelId ?? null,
124
+ });
125
+ }
126
+
127
+ function codexHealthState(slot) {
128
+ if (slot.state === "ok") return "HEALTHY";
129
+ if (slot.state === "exhausted") return "REFRESHING";
130
+ if (/revok/.test(slot.lastErrorReason ?? "")) return "REVOKED";
131
+ if (/(?:auth|unauthor|invalid|expired)/.test(slot.lastErrorReason ?? "")) {
132
+ return "REAUTH_REQUIRED";
133
+ }
134
+ return "DEAD";
135
+ }
136
+
137
+ function fallbackHealthState(snapshot) {
138
+ const allFailed =
139
+ snapshot.slots.length === 2 &&
140
+ snapshot.slots.every((slot) => slot.state === "dead") &&
141
+ snapshot.openrouter.state === "dead";
142
+ if (allFailed) return Object.freeze({ state: "ALL_FAILED", modelId: null });
143
+ if (snapshot.activeProvider === "openrouter") {
144
+ return Object.freeze({
145
+ state: "OPENROUTER_ACTIVE",
146
+ modelId:
147
+ typeof snapshot.activeFallbackModelId === "string"
148
+ ? snapshot.activeFallbackModelId
149
+ : null,
150
+ });
151
+ }
152
+ return Object.freeze({ state: "CODEX_ACTIVE", modelId: null });
153
+ }
154
+
155
+ function loadSequence(path, identity) {
156
+ if (!path || !existsSync(path)) return 0;
157
+ const stat = lstatSync(path);
158
+ if (stat.isSymbolicLink() || !stat.isFile() || (stat.mode & 0o077) !== 0) {
159
+ throw new Error("model_health_sequence_store_rejected");
160
+ }
161
+ try {
162
+ const value = JSON.parse(readFileSync(path, "utf8"));
163
+ if (
164
+ value?.schemaVersion !== "sellable-agent-model-health-sequence/v1" ||
165
+ value.runtimeGeneration !== identity.runtimeGeneration ||
166
+ value.workloadKeyHash !== identity.workloadKeyHash
167
+ ) {
168
+ return 0;
169
+ }
170
+ if (!Number.isSafeInteger(value.sequence) || value.sequence < 0) {
171
+ throw new Error("model_health_sequence_store_rejected");
172
+ }
173
+ return value.sequence;
174
+ } catch (error) {
175
+ if (
176
+ error instanceof Error &&
177
+ error.message === "model_health_sequence_store_rejected"
178
+ ) {
179
+ throw error;
180
+ }
181
+ throw new Error("model_health_sequence_store_rejected");
182
+ }
183
+ }
184
+
185
+ function persistSequence(path, identity, sequence) {
186
+ if (!path) return;
187
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
188
+ const temporary = `${path}.${process.pid}.${randomUUID()}.tmp`;
189
+ writeFileSync(
190
+ temporary,
191
+ `${JSON.stringify({
192
+ schemaVersion: "sellable-agent-model-health-sequence/v1",
193
+ runtimeGeneration: identity.runtimeGeneration,
194
+ workloadKeyHash: identity.workloadKeyHash,
195
+ sequence,
196
+ })}\n`,
197
+ { flag: "wx", mode: 0o600 }
198
+ );
199
+ chmodSync(temporary, 0o600);
200
+ renameSync(temporary, path);
201
+ chmodSync(path, 0o600);
202
+ }
203
+
204
+ export function modelHealthCadenceMs(workloadKeyHash) {
205
+ if (!SHA256.test(workloadKeyHash ?? "")) rejectIdentity();
206
+ const jitter = Number.parseInt(workloadKeyHash.slice(0, 8), 16) % 60_001;
207
+ return 240_000 + jitter;
208
+ }
209
+
210
+ export function buildModelHealthReport(input) {
211
+ if (
212
+ !["CUSTOMER", "ADMIN"].includes(input?.kind) ||
213
+ !Number.isSafeInteger(input.runtimeGeneration) ||
214
+ input.runtimeGeneration < 1 ||
215
+ !SHA256.test(input.workloadKeyHash ?? "") ||
216
+ !SAFE_ID.test(input.machineId ?? "") ||
217
+ !Number.isSafeInteger(input.sequence) ||
218
+ input.sequence < 1 ||
219
+ !Number.isFinite(Date.parse(input.observedAt ?? "")) ||
220
+ (input.kind === "ADMIN"
221
+ ? !SAFE_ID.test(input.adminRuntimeGenerationId ?? "") ||
222
+ !/^[1-9][0-9]{0,19}$/.test(input.adminRuntimeGenerationFence ?? "")
223
+ : input.adminRuntimeGenerationId !== null ||
224
+ input.adminRuntimeGenerationFence !== null)
225
+ ) {
226
+ rejectIdentity();
227
+ }
228
+ const snapshot = safeSnapshot(input.snapshot);
229
+ const slots = new Map(snapshot.slots.map((slot) => [slot.slotId, slot]));
230
+ const primary = slots.get("dittto-primary");
231
+ const secondary = slots.get("kaigo-secondary");
232
+ if (!primary || !secondary) throw new Error("model_health_snapshot_rejected");
233
+ return Object.freeze({
234
+ schemaVersion: "sellable-agent-model-health/v1",
235
+ sequence: input.sequence,
236
+ observedAt: new Date(input.observedAt).toISOString(),
237
+ machineId: input.machineId,
238
+ runtimeGeneration: input.runtimeGeneration,
239
+ workloadKeyHash: input.workloadKeyHash,
240
+ kind: input.kind,
241
+ adminRuntimeGenerationId: input.adminRuntimeGenerationId,
242
+ adminRuntimeGenerationFence: input.adminRuntimeGenerationFence,
243
+ activationId: snapshot.activationId,
244
+ bundleGeneration: snapshot.bundleGeneration,
245
+ policyHash: snapshot.policyHash,
246
+ codex: Object.freeze({
247
+ primary: codexHealthState(primary),
248
+ secondary: codexHealthState(secondary),
249
+ }),
250
+ fallback: fallbackHealthState(snapshot),
251
+ });
252
+ }
253
+
254
+ /**
255
+ * @param {{
256
+ * origin: string,
257
+ * identity: Record<string, unknown>,
258
+ * observe: () => unknown,
259
+ * authorize: (body: unknown) => string,
260
+ * fetchImpl?: typeof fetch,
261
+ * now?: () => Date,
262
+ * onError?: (error: unknown) => void,
263
+ * setIntervalImpl?: typeof setInterval,
264
+ * clearIntervalImpl?: typeof clearInterval,
265
+ * allowHttpLoopback?: boolean,
266
+ * sequencePath?: string | null,
267
+ * }} input
268
+ */
269
+ export function createModelHealthReporter({
270
+ origin,
271
+ identity,
272
+ observe,
273
+ authorize,
274
+ fetchImpl = fetch,
275
+ now = () => new Date(),
276
+ onError = () => {},
277
+ setIntervalImpl = setInterval,
278
+ clearIntervalImpl = clearInterval,
279
+ allowHttpLoopback = false,
280
+ sequencePath = null,
281
+ }) {
282
+ const endpoint = safeOrigin(origin, allowHttpLoopback);
283
+ if (
284
+ !endpoint ||
285
+ !isRecord(identity) ||
286
+ typeof observe !== "function" ||
287
+ typeof authorize !== "function" ||
288
+ typeof fetchImpl !== "function" ||
289
+ typeof now !== "function" ||
290
+ (sequencePath !== null &&
291
+ (typeof sequencePath !== "string" || !sequencePath))
292
+ ) {
293
+ rejectIdentity();
294
+ }
295
+ // Validate the workload binding before any timer or network side effect.
296
+ const cadenceMs = modelHealthCadenceMs(identity.workloadKeyHash);
297
+ buildModelHealthReport({
298
+ ...identity,
299
+ sequence: 1,
300
+ observedAt: now().toISOString(),
301
+ snapshot: observe(),
302
+ });
303
+ let sequence = loadSequence(sequencePath, identity);
304
+ let inFlight = null;
305
+ let timer = null;
306
+ let stopped = false;
307
+
308
+ const emit = (_transition = "periodic") => {
309
+ if (stopped)
310
+ return Promise.reject(new Error("model_health_reporter_stopped"));
311
+ if (inFlight) return inFlight;
312
+ const nextSequence = sequence + 1;
313
+ const snapshot = observe();
314
+ const body = buildModelHealthReport({
315
+ ...identity,
316
+ sequence: nextSequence,
317
+ observedAt: now().toISOString(),
318
+ snapshot,
319
+ });
320
+ persistSequence(sequencePath, identity, nextSequence);
321
+ sequence = nextSequence;
322
+ const authorization = authorize(body);
323
+ if (
324
+ typeof authorization !== "string" ||
325
+ !authorization.startsWith("Worker ")
326
+ ) {
327
+ return Promise.reject(new Error("model_health_report_unsigned"));
328
+ }
329
+ inFlight = (async () => {
330
+ const response = await fetchImpl(
331
+ `${endpoint}/api/v3/sellable-agent/worker/model-health`,
332
+ {
333
+ method: "POST",
334
+ headers: { authorization, "content-type": "application/json" },
335
+ body: JSON.stringify(body),
336
+ signal: AbortSignal.timeout(20_000),
337
+ }
338
+ );
339
+ let result;
340
+ try {
341
+ result = await response.json();
342
+ } catch {
343
+ throw new Error("model_health_report_response_rejected");
344
+ }
345
+ if (!response.ok || result?.accepted !== true) {
346
+ throw new Error("model_health_report_rejected");
347
+ }
348
+ return Object.freeze({ accepted: true, sequence });
349
+ })().finally(() => {
350
+ inFlight = null;
351
+ });
352
+ return inFlight;
353
+ };
354
+
355
+ return Object.freeze({
356
+ cadenceMs,
357
+ emit,
358
+ async start(transition = "materialized") {
359
+ try {
360
+ return await emit(transition);
361
+ } finally {
362
+ if (!timer && !stopped) {
363
+ timer = setIntervalImpl(() => {
364
+ emit("periodic").catch(onError);
365
+ }, cadenceMs);
366
+ timer?.unref?.();
367
+ }
368
+ }
369
+ },
370
+ async stop() {
371
+ stopped = true;
372
+ if (timer) clearIntervalImpl(timer);
373
+ timer = null;
374
+ await inFlight;
375
+ },
376
+ });
377
+ }
@@ -197,7 +197,7 @@ function validateDesired(desired) {
197
197
  desired.serviceCredentialGeneration < 1 ||
198
198
  desired.hermesCli !== "hermes" ||
199
199
  desired.hermesVersion !== "0.18.0" ||
200
- desired.installerPackage !== "@sellable/install@0.1.483" ||
200
+ desired.installerPackage !== "@sellable/install@0.1.486-wip.phase169.20260804.2" ||
201
201
  desired.mcpPackage !==
202
202
  "@sellable/mcp@0.1.760-wip.phase143.20260727100513" ||
203
203
  !Array.isArray(desired.toolInclude) ||
@@ -2023,6 +2023,9 @@ const NATIVE_SLACK_KEYS = [
2023
2023
  "membershipGeneration",
2024
2024
  "serviceCredentialGeneration",
2025
2025
  "modelCredentialGeneration",
2026
+ "modelActivationId",
2027
+ "modelBundleGeneration",
2028
+ "modelPolicyHash",
2026
2029
  "runtimeGeneration",
2027
2030
  "selectedChannelIds",
2028
2031
  "defaultChannelId",
@@ -2062,8 +2065,12 @@ function validateNativeSlackDesired(desired) {
2062
2065
  "membershipGeneration",
2063
2066
  "serviceCredentialGeneration",
2064
2067
  "modelCredentialGeneration",
2068
+ "modelBundleGeneration",
2065
2069
  "runtimeGeneration",
2066
2070
  ].some((key) => !Number.isSafeInteger(desired[key]) || desired[key] < 1) ||
2071
+ desired.modelCredentialGeneration !== desired.modelBundleGeneration ||
2072
+ !SAFE_ID.test(desired.modelActivationId ?? "") ||
2073
+ !SHA256.test(desired.modelPolicyHash ?? "") ||
2067
2074
  !Array.isArray(desired.selectedChannelIds) ||
2068
2075
  desired.selectedChannelIds.length < 1 ||
2069
2076
  desired.selectedChannelIds.some(
@@ -2117,6 +2124,9 @@ function nativeSlackCustomerFiles(desired) {
2117
2124
  membershipGeneration: desired.membershipGeneration,
2118
2125
  serviceCredentialGeneration: desired.serviceCredentialGeneration,
2119
2126
  modelCredentialGeneration: desired.modelCredentialGeneration,
2127
+ modelActivationId: desired.modelActivationId,
2128
+ modelBundleGeneration: desired.modelBundleGeneration,
2129
+ modelPolicyHash: desired.modelPolicyHash,
2120
2130
  runtimeGeneration: desired.runtimeGeneration,
2121
2131
  selectedChannelIds: [...desired.selectedChannelIds],
2122
2132
  memberAllowlist: [...desired.memberAllowlist],
@@ -2140,7 +2150,9 @@ function nativeSlackCustomerFiles(desired) {
2140
2150
  provider: FLY_CUSTOMER_MODEL_PROVIDER,
2141
2151
  default: FLY_CUSTOMER_MODEL_ID,
2142
2152
  reasoning_effort: FLY_CUSTOMER_MODEL_REASONING_EFFORT,
2143
- generation: desired.modelCredentialGeneration,
2153
+ generation: desired.modelBundleGeneration,
2154
+ activation_id: desired.modelActivationId,
2155
+ policy_hash: desired.modelPolicyHash,
2144
2156
  },
2145
2157
  slack: {
2146
2158
  require_mention: true,
@@ -2237,6 +2249,9 @@ function nativeSlackManifest(desired, files) {
2237
2249
  membershipGeneration: desired.membershipGeneration,
2238
2250
  serviceCredentialGeneration: desired.serviceCredentialGeneration,
2239
2251
  modelCredentialGeneration: desired.modelCredentialGeneration,
2252
+ modelActivationId: desired.modelActivationId,
2253
+ modelBundleGeneration: desired.modelBundleGeneration,
2254
+ modelPolicyHash: desired.modelPolicyHash,
2240
2255
  runtimeGeneration: desired.runtimeGeneration,
2241
2256
  installerPackage: desired.installerPackage,
2242
2257
  mcpPackage: desired.mcpPackage,
@@ -25,7 +25,7 @@ import { fileURLToPath } from "node:url";
25
25
  import { deriveContainedProfileId } from "./profile-materializer.mjs";
26
26
 
27
27
  export const PROVISIONING_ACTION = "PROVISION_HERMES_PROFILE";
28
- export const PINNED_INSTALL_PACKAGE = "@sellable/install@0.1.483";
28
+ export const PINNED_INSTALL_PACKAGE = "@sellable/install@0.1.486-wip.phase169.20260804.2";
29
29
  export const PINNED_MCP_PACKAGE =
30
30
  "@sellable/mcp@0.1.760-wip.phase143.20260727100513";
31
31
 
@@ -612,7 +612,7 @@ function inspectProvisionedProfile({
612
612
  !matchesReadback(manifest, request) ||
613
613
  manifest.serviceCredentialReference !== serviceCredentialReference ||
614
614
  manifest.installerPackage !== PINNED_INSTALL_PACKAGE ||
615
- manifest.installerVersion !== "0.1.483" ||
615
+ manifest.installerVersion !== "0.1.486-wip.phase169.20260804.2" ||
616
616
  manifest.mcpPackage !== PINNED_MCP_PACKAGE ||
617
617
  manifest.credentialKeyVersion !== credentialKeyVersion ||
618
618
  !/^[a-f0-9]{16}$/.test(manifest.credentialFingerprint) ||
@@ -826,7 +826,7 @@ function successReceipt({
826
826
  subject: `agent-profile:${observed.profileId}`,
827
827
  cli: {
828
828
  installPackage: PINNED_INSTALL_PACKAGE,
829
- installVersion: "0.1.483",
829
+ installVersion: "0.1.486-wip.phase169.20260804.2",
830
830
  mcpPackage: PINNED_MCP_PACKAGE,
831
831
  command: "hermes profile bootstrap",
832
832
  },
@@ -874,7 +874,7 @@ function failure(code, stages, extra = {}, request = null) {
874
874
  : "agent-profile:unbound",
875
875
  cli: {
876
876
  installPackage: PINNED_INSTALL_PACKAGE,
877
- installVersion: "0.1.483",
877
+ installVersion: "0.1.486-wip.phase169.20260804.2",
878
878
  mcpPackage: PINNED_MCP_PACKAGE,
879
879
  command: "hermes profile bootstrap",
880
880
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/install",
3
- "version": "0.1.483",
3
+ "version": "0.1.486-wip.phase169.20260804.2",
4
4
  "type": "module",
5
5
  "description": "One-command installer for Sellable MCP in Claude Code, Codex, and Hermes",
6
6
  "bin": {