@sellable/install 0.1.484 → 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.
- package/container/Dockerfile +4 -4
- package/container/README.md +2 -2
- package/lib/sellable-agent/admin-runtime-reconciler.mjs +1 -5
- package/lib/sellable-agent/fly-admin-image/Dockerfile +4 -0
- package/lib/sellable-agent/fly-admin-image/admin-runtime.mjs +327 -86
- package/lib/sellable-agent/fly-customer-image/Dockerfile +2 -2
- package/lib/sellable-agent/fly-customer-image/customer-runtime.mjs +224 -70
- package/lib/sellable-agent/fly-customer-image/model-auth-store.mjs +6 -143
- package/lib/sellable-agent/fly-customer-model.mjs +16 -157
- package/lib/sellable-agent/host-bootstrap.mjs +1 -1
- package/lib/sellable-agent/host-worker.mjs +1 -1
- package/lib/sellable-agent/model-auth-reconciler.mjs +574 -0
- package/lib/sellable-agent/model-health-reporter.mjs +377 -0
- package/lib/sellable-agent/profile-materializer.mjs +17 -2
- package/lib/sellable-agent/provisioning-adapter.mjs +4 -4
- package/package.json +1 -1
|
@@ -1,161 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
MODEL_AUTH_DEFAULT_MODEL,
|
|
3
|
+
MODEL_AUTH_PROVIDER,
|
|
4
|
+
MODEL_AUTH_REASONING_EFFORT,
|
|
5
|
+
evaluateModelAuthReadback,
|
|
6
|
+
parseModelAuthRuntimeCredential,
|
|
7
|
+
} from "./model-auth-reconciler.mjs";
|
|
4
8
|
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"tokens",
|
|
10
|
-
];
|
|
11
|
-
const MODEL_TOKEN_KEYS = [
|
|
12
|
-
"access_token",
|
|
13
|
-
"account_id",
|
|
14
|
-
"id_token",
|
|
15
|
-
"refresh_token",
|
|
16
|
-
];
|
|
17
|
-
/**
|
|
18
|
-
* Credential sources that count as "resolved from this runtime's own root auth
|
|
19
|
-
* store". `hermes-auth-store` is the seeded singleton under `providers`;
|
|
20
|
-
* `credential_pool` is the pooled entry — which this module seeds itself (see
|
|
21
|
-
* `hermesRootAuthJson` below) and which `hermes auth add` also writes when an
|
|
22
|
-
* operator re-authenticates an expired Codex token. Both live in the same root
|
|
23
|
-
* auth.json, so neither weakens isolation: that guarantee is carried by
|
|
24
|
-
* `source_class === "root_fallback"` and `local_auth_entry_count === 0`, which
|
|
25
|
-
* together prove no profile-local auth.json is shadowing the root store.
|
|
26
|
-
*/
|
|
27
|
-
const TRUSTED_MODEL_AUTH_SOURCES = ["hermes-auth-store", "credential_pool"];
|
|
9
|
+
export const FLY_CUSTOMER_MODEL_PROVIDER = MODEL_AUTH_PROVIDER;
|
|
10
|
+
export const FLY_CUSTOMER_MODEL_ID = MODEL_AUTH_DEFAULT_MODEL;
|
|
11
|
+
export const FLY_CUSTOMER_MODEL_REASONING_EFFORT =
|
|
12
|
+
MODEL_AUTH_REASONING_EFFORT;
|
|
28
13
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
*
|
|
34
|
-
* @param {unknown} readback
|
|
35
|
-
* @param {{ sourceFingerprint: string, generation: number } | null} [expected]
|
|
36
|
-
*/
|
|
37
|
-
export function evaluateModelAuthReadback(readback, expected = null) {
|
|
38
|
-
const reject = (rejection) => ({ accepted: false, rejection });
|
|
39
|
-
if (!readback || typeof readback !== "object" || Array.isArray(readback)) {
|
|
40
|
-
return reject("readback_unparsable");
|
|
41
|
-
}
|
|
42
|
-
if (readback.provider !== FLY_CUSTOMER_MODEL_PROVIDER) {
|
|
43
|
-
return reject("provider_mismatch");
|
|
44
|
-
}
|
|
45
|
-
if (readback.source_class !== "root_fallback") {
|
|
46
|
-
return reject("source_class_not_root_fallback");
|
|
47
|
-
}
|
|
48
|
-
if (readback.local_auth_entry_count !== 0) {
|
|
49
|
-
return reject("local_auth_entry_present");
|
|
50
|
-
}
|
|
51
|
-
if (!TRUSTED_MODEL_AUTH_SOURCES.includes(readback.source)) {
|
|
52
|
-
return reject("source_not_trusted");
|
|
53
|
-
}
|
|
54
|
-
if (readback.auth_mode !== "chatgpt") {
|
|
55
|
-
return reject("auth_mode_not_chatgpt");
|
|
56
|
-
}
|
|
57
|
-
if (readback.credential_present !== true) {
|
|
58
|
-
return reject("credential_absent");
|
|
59
|
-
}
|
|
60
|
-
if (expected && readback.source_fingerprint !== expected.sourceFingerprint) {
|
|
61
|
-
return reject("source_fingerprint_mismatch");
|
|
62
|
-
}
|
|
63
|
-
if (expected && readback.credential_generation !== expected.generation) {
|
|
64
|
-
return reject("credential_generation_mismatch");
|
|
65
|
-
}
|
|
66
|
-
return { accepted: true, rejection: null };
|
|
14
|
+
// Kept as the package's stable import name while the on-wire credential is
|
|
15
|
+
// upgraded from a singleton full grant to the v2 access-only runtime bundle.
|
|
16
|
+
export function parseFlyCustomerModelCredential(secret, options) {
|
|
17
|
+
return parseModelAuthRuntimeCredential(secret, options);
|
|
67
18
|
}
|
|
68
19
|
|
|
69
|
-
|
|
70
|
-
value &&
|
|
71
|
-
typeof value === "object" &&
|
|
72
|
-
!Array.isArray(value) &&
|
|
73
|
-
Object.keys(value).length === expected.length &&
|
|
74
|
-
Object.keys(value).every((key) => expected.includes(key));
|
|
75
|
-
const bounded = (value, minimum, maximum) =>
|
|
76
|
-
typeof value === "string" &&
|
|
77
|
-
value.length >= minimum &&
|
|
78
|
-
value.length <= maximum &&
|
|
79
|
-
!value.includes("\0");
|
|
80
|
-
|
|
81
|
-
export function parseFlyCustomerModelCredential(secret) {
|
|
82
|
-
if (
|
|
83
|
-
typeof secret !== "string" ||
|
|
84
|
-
!secret ||
|
|
85
|
-
Buffer.byteLength(secret, "utf8") > 64 * 1024
|
|
86
|
-
) {
|
|
87
|
-
throw new Error("customer_model_credential_rejected");
|
|
88
|
-
}
|
|
89
|
-
let value;
|
|
90
|
-
try {
|
|
91
|
-
value = JSON.parse(secret);
|
|
92
|
-
} catch {
|
|
93
|
-
throw new Error("customer_model_credential_rejected");
|
|
94
|
-
}
|
|
95
|
-
if (
|
|
96
|
-
!exactKeys(value, MODEL_CREDENTIAL_KEYS) ||
|
|
97
|
-
value.auth_mode !== "chatgpt" ||
|
|
98
|
-
value.OPENAI_API_KEY !== null ||
|
|
99
|
-
!bounded(value.last_refresh, 10, 128) ||
|
|
100
|
-
Number.isNaN(Date.parse(value.last_refresh)) ||
|
|
101
|
-
!exactKeys(value.tokens, MODEL_TOKEN_KEYS) ||
|
|
102
|
-
!bounded(value.tokens.id_token, 32, 32 * 1024) ||
|
|
103
|
-
!bounded(value.tokens.access_token, 32, 32 * 1024) ||
|
|
104
|
-
!bounded(value.tokens.refresh_token, 32, 16 * 1024) ||
|
|
105
|
-
!bounded(value.tokens.account_id, 1, 512)
|
|
106
|
-
) {
|
|
107
|
-
throw new Error("customer_model_credential_rejected");
|
|
108
|
-
}
|
|
109
|
-
const authJson = JSON.stringify({
|
|
110
|
-
auth_mode: "chatgpt",
|
|
111
|
-
OPENAI_API_KEY: null,
|
|
112
|
-
tokens: {
|
|
113
|
-
id_token: value.tokens.id_token,
|
|
114
|
-
access_token: value.tokens.access_token,
|
|
115
|
-
refresh_token: value.tokens.refresh_token,
|
|
116
|
-
account_id: value.tokens.account_id,
|
|
117
|
-
},
|
|
118
|
-
last_refresh: value.last_refresh,
|
|
119
|
-
});
|
|
120
|
-
const hermesRootAuthJson = JSON.stringify({
|
|
121
|
-
version: 1,
|
|
122
|
-
providers: {
|
|
123
|
-
"openai-codex": {
|
|
124
|
-
tokens: {
|
|
125
|
-
id_token: value.tokens.id_token,
|
|
126
|
-
access_token: value.tokens.access_token,
|
|
127
|
-
refresh_token: value.tokens.refresh_token,
|
|
128
|
-
account_id: value.tokens.account_id,
|
|
129
|
-
},
|
|
130
|
-
last_refresh: value.last_refresh,
|
|
131
|
-
auth_mode: "chatgpt",
|
|
132
|
-
},
|
|
133
|
-
},
|
|
134
|
-
credential_pool: {
|
|
135
|
-
"openai-codex": [
|
|
136
|
-
{
|
|
137
|
-
id: "sellable-control-plane",
|
|
138
|
-
label: "Sellable Codex OAuth",
|
|
139
|
-
auth_type: "oauth",
|
|
140
|
-
source: "device_code",
|
|
141
|
-
access_token: value.tokens.access_token,
|
|
142
|
-
refresh_token: value.tokens.refresh_token,
|
|
143
|
-
id_token: value.tokens.id_token,
|
|
144
|
-
account_id: value.tokens.account_id,
|
|
145
|
-
last_refresh: value.last_refresh,
|
|
146
|
-
priority: 0,
|
|
147
|
-
request_count: 0,
|
|
148
|
-
},
|
|
149
|
-
],
|
|
150
|
-
},
|
|
151
|
-
active_provider: "openai-codex",
|
|
152
|
-
});
|
|
153
|
-
return Object.freeze({
|
|
154
|
-
provider: FLY_CUSTOMER_MODEL_PROVIDER,
|
|
155
|
-
model: FLY_CUSTOMER_MODEL_ID,
|
|
156
|
-
reasoningEffort: FLY_CUSTOMER_MODEL_REASONING_EFFORT,
|
|
157
|
-
authJson,
|
|
158
|
-
hermesRootAuthJson,
|
|
159
|
-
testAccessToken: value.tokens.access_token,
|
|
160
|
-
});
|
|
161
|
-
}
|
|
20
|
+
export { evaluateModelAuthReadback };
|
|
@@ -38,7 +38,7 @@ import { installAgentHostServices } from "./service-installer.mjs";
|
|
|
38
38
|
const PACKAGE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
|
|
39
39
|
const VERSION = "sellable-agent-host-bootstrap/v1";
|
|
40
40
|
const RECEIPT_VERSION = "sellable-agent-host-registration/v1";
|
|
41
|
-
const INSTALLER_PACKAGE = "@sellable/install@0.1.
|
|
41
|
+
const INSTALLER_PACKAGE = "@sellable/install@0.1.486-wip.phase169.20260804.2";
|
|
42
42
|
const MCP_PACKAGE = "@sellable/mcp@0.1.760-wip.phase143.20260727100513";
|
|
43
43
|
const HERMES_VERSION = "0.18.0";
|
|
44
44
|
const SHA256 = /^[a-f0-9]{64}$/;
|
|
@@ -1540,7 +1540,7 @@ export function compileClaimToProfileDesired(activeClaim, config) {
|
|
|
1540
1540
|
]) ||
|
|
1541
1541
|
pinned.hermesCli !== "hermes" ||
|
|
1542
1542
|
pinned.hermesVersion !== "0.18.0" ||
|
|
1543
|
-
pinned.installerPackage !== "@sellable/install@0.1.
|
|
1543
|
+
pinned.installerPackage !== "@sellable/install@0.1.486-wip.phase169.20260804.2" ||
|
|
1544
1544
|
pinned.mcpPackage !==
|
|
1545
1545
|
"@sellable/mcp@0.1.760-wip.phase143.20260727100513" ||
|
|
1546
1546
|
!Array.isArray(policy.toolInclude) ||
|