@sellable/install 0.1.430 → 0.1.432
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/fly-customer-image/Dockerfile +1 -1
- package/lib/sellable-agent/fly-customer-image/customer-runtime.mjs +16 -13
- package/lib/sellable-agent/fly-customer-model.mjs +43 -0
- package/lib/sellable-agent/host-bootstrap.mjs +1 -1
- package/lib/sellable-agent/host-worker.mjs +1 -1
- package/lib/sellable-agent/profile-materializer.mjs +1 -1
- package/lib/sellable-agent/provisioning-adapter.mjs +4 -4
- package/package.json +1 -1
package/container/Dockerfile
CHANGED
|
@@ -3,12 +3,12 @@ FROM ${HERMES_IMAGE}
|
|
|
3
3
|
|
|
4
4
|
USER root
|
|
5
5
|
|
|
6
|
-
ARG INSTALLER_PACKAGE=@sellable/install@0.1.
|
|
6
|
+
ARG INSTALLER_PACKAGE=@sellable/install@0.1.432
|
|
7
7
|
ARG MCP_PACKAGE=@sellable/mcp@0.1.760-wip.phase143.20260727100513
|
|
8
8
|
ARG INSTALLER_INTEGRITY
|
|
9
9
|
ARG MCP_INTEGRITY=sha512-muNXHuRnLTfsnW+MQUvK+p0VBZETDKeevr70iRliXyqE3/SLrZQJLL1laJzMo+qiUs9jMXMHdKOQfQqLiwJvtg==
|
|
10
10
|
|
|
11
|
-
RUN test "${INSTALLER_PACKAGE}" = "@sellable/install@0.1.
|
|
11
|
+
RUN test "${INSTALLER_PACKAGE}" = "@sellable/install@0.1.432" \
|
|
12
12
|
&& test "${MCP_PACKAGE}" = "@sellable/mcp@0.1.760-wip.phase143.20260727100513" \
|
|
13
13
|
&& test -n "${INSTALLER_INTEGRITY}" \
|
|
14
14
|
&& test "$(npm view "${INSTALLER_PACKAGE}" dist.integrity)" = "${INSTALLER_INTEGRITY}" \
|
|
@@ -23,9 +23,9 @@ RUN test "${INSTALLER_PACKAGE}" = "@sellable/install@0.1.430" \
|
|
|
23
23
|
&& mkdir -p /opt/sellable-agent/install-root /opt/sellable-agent/mcp-root \
|
|
24
24
|
&& npm install --prefix /opt/sellable-agent/install-root --omit=dev --ignore-scripts --no-audit --no-fund "${INSTALLER_PACKAGE}" \
|
|
25
25
|
&& npm install --prefix /opt/sellable-agent/mcp-root --omit=dev --ignore-scripts --no-audit --no-fund "${MCP_PACKAGE}" \
|
|
26
|
-
&& node --input-type=module -e "import { readFileSync } from 'node:fs'; const install = JSON.parse(readFileSync('/opt/sellable-agent/install-root/node_modules/@sellable/install/package.json')); const mcp = JSON.parse(readFileSync('/opt/sellable-agent/mcp-root/node_modules/@sellable/mcp/package.json')); if (install.name !== '@sellable/install' || install.version !== '0.1.
|
|
26
|
+
&& node --input-type=module -e "import { readFileSync } from 'node:fs'; const install = JSON.parse(readFileSync('/opt/sellable-agent/install-root/node_modules/@sellable/install/package.json')); const mcp = JSON.parse(readFileSync('/opt/sellable-agent/mcp-root/node_modules/@sellable/mcp/package.json')); if (install.name !== '@sellable/install' || install.version !== '0.1.432' || mcp.name !== '@sellable/mcp' || mcp.version !== '0.1.760-wip.phase143.20260727100513') throw new Error('package identity rejected');" \
|
|
27
27
|
&& node --input-type=module -e "import { buildExternalRuntimeClosure } from '/opt/sellable-agent/install-root/node_modules/@sellable/install/lib/sellable-agent/external-runtime-builder.mjs'; const built = buildExternalRuntimeClosure({ mcpPackageRoot: '/opt/sellable-agent/mcp-root/node_modules/@sellable/mcp', mcpNodeModulesRoot: '/opt/sellable-agent/mcp-root/node_modules', hermesSourceRoot: '/opt/hermes', ownerUid: 0, ownerGid: 0 }); if (!built.closureDigest) throw new Error('runtime closure rejected');" \
|
|
28
|
-
&& node --input-type=module -e "import { chmodSync, writeFileSync } from 'node:fs'; const release = { installerPackage: '@sellable/install@0.1.
|
|
28
|
+
&& node --input-type=module -e "import { chmodSync, writeFileSync } from 'node:fs'; const release = { installerPackage: '@sellable/install@0.1.432', installerIntegrity: process.argv[1], mcpPackage: '@sellable/mcp@0.1.760-wip.phase143.20260727100513', mcpIntegrity: process.argv[2] }; writeFileSync('/opt/sellable-agent/release.json', JSON.stringify(release) + '\\n', { mode: 0o444 }); chmodSync('/opt/sellable-agent/release.json', 0o444);" "${INSTALLER_INTEGRITY}" "${MCP_INTEGRITY}" \
|
|
29
29
|
&& npm cache clean --force
|
|
30
30
|
|
|
31
31
|
COPY entrypoint.sh /usr/local/bin/sellable-agent-container-entrypoint
|
package/container/README.md
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
This image is a dedicated Agent worker/runtime boundary beside an existing Hermes dashboard. It never replaces or reconfigures the dashboard container.
|
|
4
4
|
|
|
5
5
|
Build from this directory after
|
|
6
|
-
`@sellable/install@0.1.
|
|
6
|
+
`@sellable/install@0.1.432` is
|
|
7
7
|
published:
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
10
|
docker build --platform linux/amd64 \
|
|
11
11
|
--build-arg INSTALLER_INTEGRITY='sha512-…' \
|
|
12
|
-
--tag sellable-agent-host:0.1.
|
|
12
|
+
--tag sellable-agent-host:0.1.432 .
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Create a private `bootstrap/` directory owned by root with mode `0700`. It must contain `bootstrap.json`, `provider-auth`, and `slack-app`, each owned by root with mode `0600`. `bootstrap.json` contains only non-secret identities, hashes, package integrities, and the control-plane URL. The other two files contain the provider JSON and global Slack app token whose hashes are pinned by `bootstrap.json`.
|
|
@@ -5,7 +5,7 @@ USER root
|
|
|
5
5
|
|
|
6
6
|
ARG MCP_PACKAGE=@sellable/mcp@0.1.771
|
|
7
7
|
ARG MCP_INTEGRITY=sha512-8+N7NpFenz9QYCtGqE0IVIsj9ZaKEzu3NxbIYwjWqrAMLyB5yiCKtW0+/VYrkkrjnkFrbukaIIvwHr3jDTq7eg==
|
|
8
|
-
ARG INSTALLER_PACKAGE=@sellable/install@0.1.
|
|
8
|
+
ARG INSTALLER_PACKAGE=@sellable/install@0.1.432
|
|
9
9
|
ARG HERMES_VERSION=0.19.0
|
|
10
10
|
ARG MCP_TRUST_ROOT_B64
|
|
11
11
|
ARG TIRITH_VERSION=0.3.3
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
FLY_CUSTOMER_MODEL_ID,
|
|
20
20
|
FLY_CUSTOMER_MODEL_PROVIDER,
|
|
21
21
|
FLY_CUSTOMER_MODEL_REASONING_EFFORT,
|
|
22
|
+
evaluateModelAuthReadback,
|
|
22
23
|
parseFlyCustomerModelCredential,
|
|
23
24
|
} from "../fly-customer-model.mjs";
|
|
24
25
|
import {
|
|
@@ -62,7 +63,7 @@ const RUNTIME_GENERATION = Number(
|
|
|
62
63
|
const BOOT_SESSION_ID = randomUUID();
|
|
63
64
|
const HERMES_VERSION = process.env.SELLABLE_AGENT_HERMES_VERSION ?? "0.19.0";
|
|
64
65
|
const INSTALLER_PACKAGE =
|
|
65
|
-
process.env.SELLABLE_AGENT_INSTALLER_PACKAGE ?? "@sellable/install@0.1.
|
|
66
|
+
process.env.SELLABLE_AGENT_INSTALLER_PACKAGE ?? "@sellable/install@0.1.432";
|
|
66
67
|
const MCP_PACKAGE =
|
|
67
68
|
process.env.SELLABLE_AGENT_MCP_PACKAGE ?? "@sellable/mcp@0.1.771";
|
|
68
69
|
|
|
@@ -728,25 +729,27 @@ async function proveProvisionedApplication({
|
|
|
728
729
|
} catch {
|
|
729
730
|
modelAuthReadback = null;
|
|
730
731
|
}
|
|
732
|
+
const modelAuthVerdict = evaluateModelAuthReadback(modelAuthReadback);
|
|
733
|
+
if (modelAuth.status !== 0 || !modelAuthVerdict.accepted) {
|
|
734
|
+
// Name the failed invariant: a bare rejection sent the 2026-07-28 outage
|
|
735
|
+
// hunting the credential itself when the credential was valid and only its
|
|
736
|
+
// storage shape in the root auth store had changed.
|
|
737
|
+
throw new Error(
|
|
738
|
+
`customer_model_auth_readback_rejected:${
|
|
739
|
+
modelAuth.status !== 0
|
|
740
|
+
? "probe_failed"
|
|
741
|
+
: (modelAuthVerdict.rejection ?? "unknown")
|
|
742
|
+
}`
|
|
743
|
+
);
|
|
744
|
+
}
|
|
731
745
|
if (
|
|
732
746
|
hermesVersion.status !== 0 ||
|
|
733
747
|
mcpVersion.status !== 0 ||
|
|
734
|
-
modelAuth.status !== 0 ||
|
|
735
|
-
modelAuthReadback?.provider !== FLY_CUSTOMER_MODEL_PROVIDER ||
|
|
736
|
-
modelAuthReadback?.source !== "hermes-auth-store" ||
|
|
737
|
-
modelAuthReadback?.source_class !== "root_fallback" ||
|
|
738
|
-
modelAuthReadback?.auth_mode !== "chatgpt" ||
|
|
739
|
-
modelAuthReadback?.credential_present !== true ||
|
|
740
|
-
modelAuthReadback?.local_auth_entry_count !== 0 ||
|
|
741
748
|
/Lazy-installing|pip install|npm install/i.test(
|
|
742
749
|
`${hermesVersion.stdout}\n${hermesVersion.stderr}\n${mcpVersion.stdout}\n${mcpVersion.stderr}\n${modelAuth.stdout}\n${modelAuth.stderr}`
|
|
743
750
|
)
|
|
744
751
|
) {
|
|
745
|
-
throw new Error(
|
|
746
|
-
modelAuth.status !== 0 || !modelAuthReadback
|
|
747
|
-
? "customer_model_auth_readback_rejected"
|
|
748
|
-
: "customer_runtime_binary_rejected"
|
|
749
|
-
);
|
|
752
|
+
throw new Error("customer_runtime_binary_rejected");
|
|
750
753
|
}
|
|
751
754
|
return {
|
|
752
755
|
profileDigest,
|
|
@@ -14,6 +14,49 @@ const MODEL_TOKEN_KEYS = [
|
|
|
14
14
|
"id_token",
|
|
15
15
|
"refresh_token",
|
|
16
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"];
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Decide whether the runtime's model-auth readback proves a usable, isolated
|
|
31
|
+
* Codex credential. Returns the first failed invariant so boot failures name
|
|
32
|
+
* the actual cause instead of a generic rejection.
|
|
33
|
+
*/
|
|
34
|
+
export function evaluateModelAuthReadback(readback) {
|
|
35
|
+
const reject = (rejection) => ({ accepted: false, rejection });
|
|
36
|
+
if (!readback || typeof readback !== "object" || Array.isArray(readback)) {
|
|
37
|
+
return reject("readback_unparsable");
|
|
38
|
+
}
|
|
39
|
+
if (readback.provider !== FLY_CUSTOMER_MODEL_PROVIDER) {
|
|
40
|
+
return reject("provider_mismatch");
|
|
41
|
+
}
|
|
42
|
+
if (readback.source_class !== "root_fallback") {
|
|
43
|
+
return reject("source_class_not_root_fallback");
|
|
44
|
+
}
|
|
45
|
+
if (readback.local_auth_entry_count !== 0) {
|
|
46
|
+
return reject("local_auth_entry_present");
|
|
47
|
+
}
|
|
48
|
+
if (!TRUSTED_MODEL_AUTH_SOURCES.includes(readback.source)) {
|
|
49
|
+
return reject("source_not_trusted");
|
|
50
|
+
}
|
|
51
|
+
if (readback.auth_mode !== "chatgpt") {
|
|
52
|
+
return reject("auth_mode_not_chatgpt");
|
|
53
|
+
}
|
|
54
|
+
if (readback.credential_present !== true) {
|
|
55
|
+
return reject("credential_absent");
|
|
56
|
+
}
|
|
57
|
+
return { accepted: true, rejection: null };
|
|
58
|
+
}
|
|
59
|
+
|
|
17
60
|
const exactKeys = (value, expected) =>
|
|
18
61
|
value &&
|
|
19
62
|
typeof value === "object" &&
|
|
@@ -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.432";
|
|
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}$/;
|
|
@@ -1513,7 +1513,7 @@ export function compileClaimToProfileDesired(activeClaim, config) {
|
|
|
1513
1513
|
]) ||
|
|
1514
1514
|
pinned.hermesCli !== "hermes" ||
|
|
1515
1515
|
pinned.hermesVersion !== "0.18.0" ||
|
|
1516
|
-
pinned.installerPackage !== "@sellable/install@0.1.
|
|
1516
|
+
pinned.installerPackage !== "@sellable/install@0.1.432" ||
|
|
1517
1517
|
pinned.mcpPackage !==
|
|
1518
1518
|
"@sellable/mcp@0.1.760-wip.phase143.20260727100513" ||
|
|
1519
1519
|
!Array.isArray(policy.toolInclude) ||
|
|
@@ -192,7 +192,7 @@ function validateDesired(desired) {
|
|
|
192
192
|
desired.serviceCredentialGeneration < 1 ||
|
|
193
193
|
desired.hermesCli !== "hermes" ||
|
|
194
194
|
desired.hermesVersion !== "0.18.0" ||
|
|
195
|
-
desired.installerPackage !== "@sellable/install@0.1.
|
|
195
|
+
desired.installerPackage !== "@sellable/install@0.1.432" ||
|
|
196
196
|
desired.mcpPackage !==
|
|
197
197
|
"@sellable/mcp@0.1.760-wip.phase143.20260727100513" ||
|
|
198
198
|
!Array.isArray(desired.toolInclude) ||
|
|
@@ -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.
|
|
28
|
+
export const PINNED_INSTALL_PACKAGE = "@sellable/install@0.1.432";
|
|
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.
|
|
615
|
+
manifest.installerVersion !== "0.1.432" ||
|
|
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.
|
|
829
|
+
installVersion: "0.1.432",
|
|
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.
|
|
877
|
+
installVersion: "0.1.432",
|
|
878
878
|
mcpPackage: PINNED_MCP_PACKAGE,
|
|
879
879
|
command: "hermes profile bootstrap",
|
|
880
880
|
},
|