@sellable/install 0.1.465 → 0.1.467
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-admin-image/Dockerfile +4 -0
- package/lib/sellable-agent/fly-admin-image/admin-runtime.mjs +169 -17
- package/lib/sellable-agent/fly-customer-image/Dockerfile +1 -1
- package/lib/sellable-agent/fly-customer-image/customer-runtime.mjs +1 -1
- 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.467
|
|
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.467" \
|
|
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.465" \
|
|
|
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.467' || 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.467', 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.467` 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.467 .
|
|
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`.
|
|
@@ -64,18 +64,22 @@ RUN set -eux; \
|
|
|
64
64
|
COPY fly-admin-image/admin-runtime.mjs /usr/local/lib/sellable-agent/admin-runtime/admin-runtime.mjs
|
|
65
65
|
COPY fly-admin-image/start-admin-runtime /usr/local/lib/sellable-agent/admin-runtime/start-admin-runtime
|
|
66
66
|
COPY fly-runtime-identity.mjs /usr/local/lib/sellable-agent/fly-runtime-identity.mjs
|
|
67
|
+
COPY hermes-bridge.mjs /usr/local/lib/sellable-agent/hermes-bridge.mjs
|
|
67
68
|
COPY hermes-memory-snapshot.mjs /usr/local/lib/sellable-agent/hermes-memory-snapshot.mjs
|
|
68
69
|
COPY hermes-memory-dirty.mjs /opt/sellable/bin/hermes-memory-dirty
|
|
69
70
|
COPY hermes-memory-reconcile.sh /opt/sellable/share/hermes-memory-reconcile.sh
|
|
70
71
|
COPY fly-admin-image/rootfs/ /
|
|
71
72
|
|
|
72
73
|
RUN node --input-type=module -e \
|
|
74
|
+
'import { installHermesAgentBridge, HERMES_AGENT_BRIDGE_DEDICATED_V019_CONTRACT } from "/usr/local/lib/sellable-agent/hermes-bridge.mjs"; installHermesAgentBridge({ sourceRoot: "/opt/hermes", contract: HERMES_AGENT_BRIDGE_DEDICATED_V019_CONTRACT });' \
|
|
75
|
+
&& node --input-type=module -e \
|
|
73
76
|
'await import("/usr/local/lib/sellable-agent/fly-runtime-identity.mjs");' \
|
|
74
77
|
&& chmod 0755 /etc \
|
|
75
78
|
&& chmod 0555 \
|
|
76
79
|
/usr/local/lib/sellable-agent/admin-runtime/admin-runtime.mjs \
|
|
77
80
|
/usr/local/lib/sellable-agent/admin-runtime/start-admin-runtime \
|
|
78
81
|
/usr/local/lib/sellable-agent/fly-runtime-identity.mjs \
|
|
82
|
+
/usr/local/lib/sellable-agent/hermes-bridge.mjs \
|
|
79
83
|
/usr/local/lib/sellable-agent/hermes-memory-snapshot.mjs \
|
|
80
84
|
/opt/sellable/bin/hermes-memory-dirty \
|
|
81
85
|
/etc/s6-overlay/s6-rc.d/admin-runtime/run \
|
|
@@ -37,7 +37,10 @@ import {
|
|
|
37
37
|
promoteAdminProfileAtomically,
|
|
38
38
|
stageAdminProfile,
|
|
39
39
|
} from "../admin-artifact/node_modules/@sellable/admin-install/lib/hermes-admin-profile-factory.mjs";
|
|
40
|
-
import {
|
|
40
|
+
import {
|
|
41
|
+
evaluateModelAuthReadback,
|
|
42
|
+
parseFlyCustomerModelCredential,
|
|
43
|
+
} from "../admin-artifact/node_modules/@sellable/install/lib/sellable-agent/fly-customer-model.mjs";
|
|
41
44
|
import {
|
|
42
45
|
buildAgentServiceEnvironment,
|
|
43
46
|
buildNativeHermesLaunch,
|
|
@@ -83,6 +86,7 @@ const RUNTIME_ROOT = join(DATA_ROOT, ".sellable-agent", "admin-runtime");
|
|
|
83
86
|
const DELIVERY_ROOT = join(RUNTIME_ROOT, "delivery");
|
|
84
87
|
const SECRET_ROOT = "/run/sellable-agent/admin-runtime";
|
|
85
88
|
const HERMES = "/opt/hermes/.venv/bin/hermes";
|
|
89
|
+
const HERMES_PYTHON = "/opt/hermes/.venv/bin/python";
|
|
86
90
|
const NODE = "/usr/local/bin/node";
|
|
87
91
|
const ADMIN_INSTALL_PACKAGE_ROOT = join(
|
|
88
92
|
ARTIFACT_ROOT,
|
|
@@ -893,8 +897,90 @@ async function consumeRuntimeSecrets({ claim, exchange, client }) {
|
|
|
893
897
|
|
|
894
898
|
function installRuntimeSecrets({ claim, secrets }) {
|
|
895
899
|
privateDirectory(SECRET_ROOT);
|
|
900
|
+
const modelAuthority = claim?.runtimeContract?.model;
|
|
901
|
+
const modelEnvelope = claim?.secretEnvelopes?.modelCodex;
|
|
902
|
+
if (
|
|
903
|
+
modelAuthority?.provider !== "codex" ||
|
|
904
|
+
!Number.isSafeInteger(modelAuthority.credentialGeneration) ||
|
|
905
|
+
modelAuthority.credentialGeneration < 1 ||
|
|
906
|
+
!/^[a-f0-9]{16}$/.test(modelAuthority.credentialFingerprint ?? "") ||
|
|
907
|
+
modelAuthority.credentialGeneration !== modelEnvelope?.generation ||
|
|
908
|
+
modelAuthority.credentialFingerprint !== modelEnvelope?.fingerprint ||
|
|
909
|
+
!/^[A-Za-z0-9_-]{1,128}$/.test(claim?.operation?.profileId ?? "")
|
|
910
|
+
) {
|
|
911
|
+
throw new Error("admin_model_auth_identity_rejected");
|
|
912
|
+
}
|
|
896
913
|
const model = parseFlyCustomerModelCredential(secrets.modelCodex);
|
|
897
|
-
|
|
914
|
+
const rootAuthPath = join(DATA_ROOT, "auth.json");
|
|
915
|
+
const localAuthPath = join(
|
|
916
|
+
PROFILES_ROOT,
|
|
917
|
+
claim.operation.profileId,
|
|
918
|
+
"auth.json"
|
|
919
|
+
);
|
|
920
|
+
const identityPath = join(RUNTIME_ROOT, "model-auth-identity.json");
|
|
921
|
+
const validateAuthFile = (path) => {
|
|
922
|
+
const stat = lstatSync(path);
|
|
923
|
+
if (stat.isSymbolicLink() || !stat.isFile() || (stat.mode & 0o077) !== 0) {
|
|
924
|
+
throw new Error("admin_model_auth_store_rejected");
|
|
925
|
+
}
|
|
926
|
+
};
|
|
927
|
+
if (existsSync(localAuthPath)) {
|
|
928
|
+
validateAuthFile(localAuthPath);
|
|
929
|
+
rmSync(localAuthPath, { force: true });
|
|
930
|
+
}
|
|
931
|
+
let priorCredentialGeneration = null;
|
|
932
|
+
if (existsSync(identityPath)) {
|
|
933
|
+
validateAuthFile(identityPath);
|
|
934
|
+
let priorIdentity;
|
|
935
|
+
try {
|
|
936
|
+
priorIdentity = JSON.parse(readFileSync(identityPath, "utf8"));
|
|
937
|
+
} catch {
|
|
938
|
+
throw new Error("admin_model_auth_identity_rejected");
|
|
939
|
+
}
|
|
940
|
+
if (
|
|
941
|
+
priorIdentity?.schemaVersion !== "sellable-admin-model-auth/v1" ||
|
|
942
|
+
priorIdentity.provider !== "codex" ||
|
|
943
|
+
!Number.isSafeInteger(priorIdentity.credentialGeneration) ||
|
|
944
|
+
priorIdentity.credentialGeneration < 1 ||
|
|
945
|
+
!/^[a-f0-9]{16}$/.test(priorIdentity.credentialFingerprint ?? "") ||
|
|
946
|
+
Object.keys(priorIdentity).sort().join("\0") !==
|
|
947
|
+
[
|
|
948
|
+
"credentialFingerprint",
|
|
949
|
+
"credentialGeneration",
|
|
950
|
+
"provider",
|
|
951
|
+
"schemaVersion",
|
|
952
|
+
]
|
|
953
|
+
.sort()
|
|
954
|
+
.join("\0")
|
|
955
|
+
) {
|
|
956
|
+
throw new Error("admin_model_auth_identity_rejected");
|
|
957
|
+
}
|
|
958
|
+
priorCredentialGeneration = priorIdentity.credentialGeneration;
|
|
959
|
+
}
|
|
960
|
+
const replaceRootAuth =
|
|
961
|
+
priorCredentialGeneration === null ||
|
|
962
|
+
priorCredentialGeneration !== modelAuthority.credentialGeneration ||
|
|
963
|
+
!existsSync(rootAuthPath);
|
|
964
|
+
if (existsSync(rootAuthPath)) {
|
|
965
|
+
validateAuthFile(rootAuthPath);
|
|
966
|
+
if (replaceRootAuth) rmSync(rootAuthPath, { force: true });
|
|
967
|
+
}
|
|
968
|
+
if (replaceRootAuth) {
|
|
969
|
+
atomicPrivateFile(rootAuthPath, model.hermesRootAuthJson);
|
|
970
|
+
} else {
|
|
971
|
+
// Hermes may refresh the pooled OAuth record in place. Preserve that
|
|
972
|
+
// native state until the server advances the credential generation.
|
|
973
|
+
chmodSync(rootAuthPath, 0o600);
|
|
974
|
+
}
|
|
975
|
+
atomicPrivateFile(
|
|
976
|
+
identityPath,
|
|
977
|
+
`${JSON.stringify({
|
|
978
|
+
schemaVersion: "sellable-admin-model-auth/v1",
|
|
979
|
+
provider: "codex",
|
|
980
|
+
credentialGeneration: modelAuthority.credentialGeneration,
|
|
981
|
+
credentialFingerprint: modelAuthority.credentialFingerprint,
|
|
982
|
+
})}\n`
|
|
983
|
+
);
|
|
898
984
|
atomicPrivateFile(join(SECRET_ROOT, "slack-app"), `${secrets.slackApp}\n`);
|
|
899
985
|
atomicPrivateFile(join(SECRET_ROOT, "slack-bot"), `${secrets.slackBot}\n`);
|
|
900
986
|
const slackSecretFile = join(SECRET_ROOT, "profile-slack.env");
|
|
@@ -922,15 +1008,73 @@ function installRuntimeSecrets({ claim, secrets }) {
|
|
|
922
1008
|
})}\n`
|
|
923
1009
|
);
|
|
924
1010
|
return {
|
|
925
|
-
rootAuthPath
|
|
1011
|
+
rootAuthPath,
|
|
926
1012
|
productConfigPath,
|
|
927
1013
|
slackSecretFile,
|
|
928
1014
|
};
|
|
929
1015
|
}
|
|
930
1016
|
|
|
1017
|
+
function proveAdminModelAuth(profile) {
|
|
1018
|
+
const environment = {
|
|
1019
|
+
...process.env,
|
|
1020
|
+
HOME: DATA_ROOT,
|
|
1021
|
+
HERMES_HOME: profile.profileHome,
|
|
1022
|
+
SELLABLE_HERMES_PROFILE_ID: profile.profile,
|
|
1023
|
+
NO_COLOR: "1",
|
|
1024
|
+
};
|
|
1025
|
+
delete environment.OPENAI_BASE_URL;
|
|
1026
|
+
delete environment.OPENAI_API_KEY;
|
|
1027
|
+
delete environment.OPENROUTER_API_KEY;
|
|
1028
|
+
const probe = spawnSync(
|
|
1029
|
+
HERMES_PYTHON,
|
|
1030
|
+
[
|
|
1031
|
+
"-c",
|
|
1032
|
+
[
|
|
1033
|
+
"import json",
|
|
1034
|
+
"from hermes_constants import get_default_hermes_root, get_hermes_home",
|
|
1035
|
+
"from hermes_cli.auth import resolve_codex_runtime_credentials",
|
|
1036
|
+
"value = resolve_codex_runtime_credentials(refresh_if_expiring=False)",
|
|
1037
|
+
'root_auth = get_default_hermes_root() / "auth.json"',
|
|
1038
|
+
'local_auth = get_hermes_home() / "auth.json"',
|
|
1039
|
+
'print(json.dumps({"provider": value.get("provider"), "source": value.get("source"), "source_class": "root_fallback" if root_auth.is_file() and not local_auth.exists() else "unexpected", "auth_mode": value.get("auth_mode"), "credential_present": bool(value.get("api_key")), "local_auth_entry_count": 0 if not local_auth.exists() else 1}))',
|
|
1040
|
+
].join(";"),
|
|
1041
|
+
],
|
|
1042
|
+
{
|
|
1043
|
+
env: environment,
|
|
1044
|
+
encoding: "utf8",
|
|
1045
|
+
timeout: TIMEOUT_MS,
|
|
1046
|
+
maxBuffer: 64 * 1024,
|
|
1047
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1048
|
+
}
|
|
1049
|
+
);
|
|
1050
|
+
let readback = null;
|
|
1051
|
+
try {
|
|
1052
|
+
readback = JSON.parse(probe.stdout ?? "");
|
|
1053
|
+
} catch {
|
|
1054
|
+
readback = null;
|
|
1055
|
+
}
|
|
1056
|
+
const verdict = evaluateModelAuthReadback(readback);
|
|
1057
|
+
if (probe.status !== 0 || probe.error || !verdict.accepted) {
|
|
1058
|
+
throw new Error(
|
|
1059
|
+
`admin_model_auth_readback_rejected:${
|
|
1060
|
+
probe.status !== 0 || probe.error
|
|
1061
|
+
? "probe_failed"
|
|
1062
|
+
: (verdict.rejection ?? "unknown")
|
|
1063
|
+
}`
|
|
1064
|
+
);
|
|
1065
|
+
}
|
|
1066
|
+
return Object.freeze({
|
|
1067
|
+
provider: readback.provider,
|
|
1068
|
+
source: readback.source,
|
|
1069
|
+
sourceClass: readback.source_class,
|
|
1070
|
+
authMode: readback.auth_mode,
|
|
1071
|
+
credentialPresent: readback.credential_present,
|
|
1072
|
+
localAuthEntryCount: readback.local_auth_entry_count,
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1075
|
+
|
|
931
1076
|
function clearRuntimeSecrets() {
|
|
932
1077
|
for (const name of [
|
|
933
|
-
"auth.json",
|
|
934
1078
|
"slack-app",
|
|
935
1079
|
"slack-bot",
|
|
936
1080
|
"profile-slack.env",
|
|
@@ -1479,6 +1623,7 @@ function completionReceipt({
|
|
|
1479
1623
|
recovery,
|
|
1480
1624
|
observedLifecycle,
|
|
1481
1625
|
memorySnapshot,
|
|
1626
|
+
modelAuth,
|
|
1482
1627
|
}) {
|
|
1483
1628
|
const identity = operationIdentity(claim, exchange);
|
|
1484
1629
|
const routeGenerationDigest = flyRuntimeDigest(
|
|
@@ -1517,7 +1662,7 @@ function completionReceipt({
|
|
|
1517
1662
|
package: sha256(JSON.stringify(packageSpecs())),
|
|
1518
1663
|
config: operation.profileContract.digest,
|
|
1519
1664
|
content: operation.profileContract.digest,
|
|
1520
|
-
process: sha256(JSON.stringify(profile.servers)),
|
|
1665
|
+
process: sha256(JSON.stringify({ servers: profile.servers, modelAuth })),
|
|
1521
1666
|
};
|
|
1522
1667
|
return {
|
|
1523
1668
|
...identity,
|
|
@@ -1538,6 +1683,7 @@ function completionReceipt({
|
|
|
1538
1683
|
{ code: "DUAL_MCP_PROVEN", status: "TRUE" },
|
|
1539
1684
|
{ code: "SETTINGS_GENERATION_PROVEN", status: "TRUE" },
|
|
1540
1685
|
{ code: "RECOVERY_GENERATION_PROVEN", status: "TRUE" },
|
|
1686
|
+
{ code: "MODEL_AUTH_PROVEN", status: "TRUE" },
|
|
1541
1687
|
{ code: "SLACK_TRAFFIC_DISABLED", status: "TRUE" },
|
|
1542
1688
|
{ code: "NO_BOOT_INSTALL", status: "TRUE" },
|
|
1543
1689
|
],
|
|
@@ -1547,6 +1693,7 @@ function completionReceipt({
|
|
|
1547
1693
|
`hermes-memory-${
|
|
1548
1694
|
memorySnapshot.ok ? memorySnapshot.status : memorySnapshot.code
|
|
1549
1695
|
}`.toLowerCase(),
|
|
1696
|
+
`model-auth-${modelAuth.sourceClass}`,
|
|
1550
1697
|
],
|
|
1551
1698
|
adminRuntimeProof,
|
|
1552
1699
|
};
|
|
@@ -1753,23 +1900,24 @@ export async function runAdminCanary() {
|
|
|
1753
1900
|
for (const [name, value] of Object.entries(fixtureFiles)) {
|
|
1754
1901
|
atomicPrivateFile(join(sourceRoot, name), value);
|
|
1755
1902
|
}
|
|
1756
|
-
const rootAuthPath = join(
|
|
1903
|
+
const rootAuthPath = join(DATA_ROOT, "auth.json");
|
|
1757
1904
|
const productConfigPath = join(SECRET_ROOT, "canary-product-config.json");
|
|
1758
1905
|
rmSync(rootAuthPath, { force: true });
|
|
1759
1906
|
rmSync(productConfigPath, { force: true });
|
|
1760
|
-
const
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1907
|
+
const canaryModel = parseFlyCustomerModelCredential(
|
|
1908
|
+
JSON.stringify({
|
|
1909
|
+
OPENAI_API_KEY: null,
|
|
1910
|
+
auth_mode: "chatgpt",
|
|
1911
|
+
last_refresh: "2026-07-29T00:00:00.000Z",
|
|
1912
|
+
tokens: {
|
|
1913
|
+
access_token: "phase158-canary-oauth-access-token-placeholder",
|
|
1914
|
+
account_id: "phase158-canary-account",
|
|
1915
|
+
id_token: "phase158-canary-oauth-id-token-placeholder",
|
|
1916
|
+
refresh_token: "phase158-canary-oauth-refresh-token-placeholder",
|
|
1770
1917
|
},
|
|
1771
|
-
})
|
|
1918
|
+
})
|
|
1772
1919
|
);
|
|
1920
|
+
atomicPrivateFile(rootAuthPath, canaryModel.hermesRootAuthJson);
|
|
1773
1921
|
atomicPrivateFile(
|
|
1774
1922
|
productConfigPath,
|
|
1775
1923
|
`${JSON.stringify({
|
|
@@ -1936,6 +2084,7 @@ export async function runAdminCanary() {
|
|
|
1936
2084
|
byteLength: soulBytes.byteLength,
|
|
1937
2085
|
},
|
|
1938
2086
|
});
|
|
2087
|
+
const modelAuth = proveAdminModelAuth(profile);
|
|
1939
2088
|
const observedSettings = settingsProof(
|
|
1940
2089
|
settingsRoot,
|
|
1941
2090
|
transition.settingsDigest
|
|
@@ -1956,6 +2105,7 @@ export async function runAdminCanary() {
|
|
|
1956
2105
|
profileFactory: "stageAdminProfile",
|
|
1957
2106
|
profileDigest: profileContract.digest,
|
|
1958
2107
|
servers: profile.servers,
|
|
2108
|
+
modelAuth,
|
|
1959
2109
|
settings: observedSettings,
|
|
1960
2110
|
adminHome: profile.adminHome,
|
|
1961
2111
|
transition,
|
|
@@ -2247,6 +2397,7 @@ async function runAdminProduction() {
|
|
|
2247
2397
|
slack: nativeSlackProfileInput(claim, installed),
|
|
2248
2398
|
agentServiceEnv: adminAgentServiceEnvironment(claim),
|
|
2249
2399
|
});
|
|
2400
|
+
const modelAuth = proveAdminModelAuth(profile);
|
|
2250
2401
|
const memorySnapshot = await flushHermesSnapshot({
|
|
2251
2402
|
client,
|
|
2252
2403
|
profileId: profile.profile,
|
|
@@ -2282,6 +2433,7 @@ async function runAdminProduction() {
|
|
|
2282
2433
|
recovery,
|
|
2283
2434
|
observedLifecycle: desiredLifecycle,
|
|
2284
2435
|
memorySnapshot,
|
|
2436
|
+
modelAuth,
|
|
2285
2437
|
});
|
|
2286
2438
|
operationHeartbeat.assertHealthy();
|
|
2287
2439
|
const candidateLaunch =
|
|
@@ -5,7 +5,7 @@ USER root
|
|
|
5
5
|
|
|
6
6
|
ARG MCP_PACKAGE=@sellable/mcp@0.1.789-wip.phase159.20260729223403
|
|
7
7
|
ARG MCP_INTEGRITY=sha512-KoheQcAQe/c8xzhF3R1ls6nQd11bcQqM3ykOUlzzNX5kykO7rO8RR2KsOvomwMv2Nn5VzvZZx6rGrle/6woKfw==
|
|
8
|
-
ARG INSTALLER_PACKAGE=@sellable/install@0.1.
|
|
8
|
+
ARG INSTALLER_PACKAGE=@sellable/install@0.1.467
|
|
9
9
|
ARG TUS_JS_CLIENT_VERSION=4.3.1
|
|
10
10
|
ARG HERMES_VERSION=0.19.0
|
|
11
11
|
ARG MCP_TRUST_ROOT_B64
|
|
@@ -69,7 +69,7 @@ const RUNTIME_GENERATION = Number(
|
|
|
69
69
|
const BOOT_SESSION_ID = randomUUID();
|
|
70
70
|
const HERMES_VERSION = process.env.SELLABLE_AGENT_HERMES_VERSION ?? "0.19.0";
|
|
71
71
|
const INSTALLER_PACKAGE =
|
|
72
|
-
process.env.SELLABLE_AGENT_INSTALLER_PACKAGE ?? "@sellable/install@0.1.
|
|
72
|
+
process.env.SELLABLE_AGENT_INSTALLER_PACKAGE ?? "@sellable/install@0.1.467";
|
|
73
73
|
const MCP_PACKAGE =
|
|
74
74
|
process.env.SELLABLE_AGENT_MCP_PACKAGE ??
|
|
75
75
|
"@sellable/mcp@0.1.789-wip.phase159.20260729223403";
|
|
@@ -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.467";
|
|
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.467" ||
|
|
1544
1544
|
pinned.mcpPackage !==
|
|
1545
1545
|
"@sellable/mcp@0.1.760-wip.phase143.20260727100513" ||
|
|
1546
1546
|
!Array.isArray(policy.toolInclude) ||
|
|
@@ -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.
|
|
200
|
+
desired.installerPackage !== "@sellable/install@0.1.467" ||
|
|
201
201
|
desired.mcpPackage !==
|
|
202
202
|
"@sellable/mcp@0.1.760-wip.phase143.20260727100513" ||
|
|
203
203
|
!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.467";
|
|
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.467" ||
|
|
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.467",
|
|
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.467",
|
|
878
878
|
mcpPackage: PINNED_MCP_PACKAGE,
|
|
879
879
|
command: "hermes profile bootstrap",
|
|
880
880
|
},
|