Beds read the catalogue: a shared loader, eight beds converted, the rest declared
catalogueModule() in the harness reads a module's manifest from the catalogue and rewrites only what the lab must: the build section goes, each artifact becomes the image the machine holds, images are pinned, and a bed may declare a host-port remap or a lab-local address. confluence, gitlab, openai-consumer, audit-logger, ollama, local-model-consumer, model-usage, mosquitto, anthropic-manager and anthropic-consumer now install the catalogue's manifest. A unit test refuses any inline copy naming a catalogue module unless the bed is declared with its reason; the declared list is the debt (novox/hq 04-ISSUES/073).
This commit is contained in:
@@ -49,7 +49,7 @@ import { loadScenario } from "../../src/declaration/parse.ts";
|
||||
import { raise } from "../../src/lifecycle/raise.ts";
|
||||
import { destroy, exec } from "../../src/lifecycle/operate.ts";
|
||||
import { hostBinaryPath, HOST_PATH } from "../../src/lifecycle/place.ts";
|
||||
import { labIsUsable, destroyAll, foundationBundle, onTheMachine } from "./harness.ts";
|
||||
import { labIsUsable, destroyAll, foundationBundle, onTheMachine, catalogueModule, catalogueIsPresent } from "./harness.ts";
|
||||
import type { HeldImage } from "../../src/pinning.ts";
|
||||
|
||||
const capability = await labIsUsable();
|
||||
@@ -62,7 +62,7 @@ const skip = !capability.usable
|
||||
? "MESH_LAB_HOST_BINARY is not set to a built mesh-host"
|
||||
: !bundle || !existsSync(bundle)
|
||||
? "MESH_LAB_BUNDLE is not set to a foundation bundle (mesh-host examples/)"
|
||||
: false;
|
||||
: catalogueIsPresent();
|
||||
|
||||
const SCENARIO = "anthropic-bed";
|
||||
const MACHINE = "anchor";
|
||||
@@ -194,8 +194,6 @@ after(async () => {
|
||||
test("model access refreshes on the manager node and delivers only the access token, never the refresh token", {
|
||||
skip, timeout: 1_500_000,
|
||||
}, async () => {
|
||||
const managerImage = pinned("mesh-runtime-anthropic-manager");
|
||||
const consumerImage = pinned("mesh-runtime-anthropic-consumer");
|
||||
|
||||
// --- the licence, and the manager as its holder ------------------------------------------------
|
||||
// The manager module is a HOLDER, named the licence's manager. It is delivered the refresh token;
|
||||
@@ -207,37 +205,15 @@ test("model access refreshes on the manager node and delivers only the access to
|
||||
await mesh(`licence use personal ${MACHINE} anthropic-manager`);
|
||||
|
||||
// --- the manager module, deployed so the host delivers its bound facts --------------------------
|
||||
// Inline manifest mirroring the committed module.json: model-access holder, refresh token bound as a
|
||||
// sealed secret, no node-key mount. The scheduled container installs as present state (ADR 0053);
|
||||
// the test drives adopt/refresh directly for a deterministic flow rather than waiting on cron.
|
||||
const managerManifest = JSON.stringify({
|
||||
module: "anthropic-manager",
|
||||
version: "1",
|
||||
requires: ["model-access"],
|
||||
binds: { "model-access": "/var/lib/mesh/anthropic-manager/model.json" },
|
||||
secrets: { "model-access": "/var/lib/mesh/anthropic-manager/refresh-token" },
|
||||
"own-secrets": { broker: "/var/lib/mesh/anthropic-manager/broker" },
|
||||
emits: ["module.anthropic-manager.usage.read"],
|
||||
resources: [
|
||||
{ id: "mesh-state", type: "directory", path: "/var/lib/mesh/anthropic-manager", mode: "0700" },
|
||||
{ id: "out", type: "directory", path: "/var/lib/mesh/anthropic-manager/out", mode: "0700" },
|
||||
{
|
||||
id: "refresh", type: "container", name: "mesh-anthropic-manager-refresh",
|
||||
image: managerImage, network: "host", schedule: "*/9 * * * *",
|
||||
args: ["run", "/app/modules/anthropic-manager/dist/refresh/index.js"],
|
||||
volumes: ["/var/lib/mesh/anthropic-manager:/run/state"],
|
||||
env: {
|
||||
MESH_ANTHROPIC_LICENCE: "personal",
|
||||
MESH_ANTHROPIC_TOKEN_ENDPOINT: "http://127.0.0.1:9099/token",
|
||||
MESH_ANTHROPIC_USAGE_ENDPOINT: "http://127.0.0.1:9099/usage",
|
||||
MESH_MODEL_ACCESS_SECRET_FILE: "/run/state/refresh-token",
|
||||
MESH_MODEL_ACCESS_BIND_FILE: "/run/state/model.json",
|
||||
MESH_ANTHROPIC_ACCESS_OUT: "/run/state/out/access-token",
|
||||
MESH_ANTHROPIC_GRANT_OUT: "/run/state/out/grant.json",
|
||||
MESH_ANTHROPIC_USAGE_OUT: "/run/state/out/usage.json",
|
||||
},
|
||||
},
|
||||
],
|
||||
// The catalogue's own manifest (novox/hq 04-ISSUES/073): model-access holder, refresh token bound
|
||||
// as a sealed secret, no node-key mount. The scheduled container installs as present state (ADR
|
||||
// 0053); the test drives adopt/refresh directly for a deterministic flow rather than waiting on
|
||||
// cron. The one lab rewrite: the OAuth endpoints point at the stub this bed raises below.
|
||||
const managerManifest = catalogueModule("anthropic-manager", held, {
|
||||
env: { refresh: {
|
||||
MESH_ANTHROPIC_TOKEN_ENDPOINT: "http://127.0.0.1:9099/token",
|
||||
MESH_ANTHROPIC_USAGE_ENDPOINT: "http://127.0.0.1:9099/usage",
|
||||
} },
|
||||
});
|
||||
await must(`printf %s ${quote(managerManifest)} > /tmp/anthropic-manager.json && docker cp /tmp/anthropic-manager.json mesh-controller:/anthropic-manager.json`);
|
||||
await mesh(`module add /anthropic-manager.json`);
|
||||
@@ -329,32 +305,8 @@ test("model access refreshes on the manager node and delivers only the access to
|
||||
assert.match(submitted, /sealed to 1 holder/, submitted);
|
||||
|
||||
// --- 5. deliver: deploy the consumer and push; it gets the sealed access token -------------------
|
||||
const consumerManifest = JSON.stringify({
|
||||
module: "anthropic-consumer",
|
||||
version: "1",
|
||||
requires: ["model-access"],
|
||||
binds: { "model-access": "/var/lib/anthropic-consumer/model.json" },
|
||||
secrets: { "model-access": "/var/lib/anthropic-consumer/access-token" },
|
||||
"own-secrets": { broker: "/var/lib/mesh/anthropic-consumer/broker" },
|
||||
emits: ["module.anthropic-consumer.usage.session"],
|
||||
resources: [
|
||||
{ id: "mesh-state", type: "directory", path: "/var/lib/mesh/anthropic-consumer", mode: "0700" },
|
||||
{ id: "state", type: "directory", path: "/var/lib/anthropic-consumer", mode: "0700" },
|
||||
{ id: "claude-home", type: "directory", path: "/var/lib/anthropic-consumer/claude", mode: "0700" },
|
||||
{
|
||||
id: "apply", type: "container", name: "mesh-anthropic-consumer-apply",
|
||||
image: consumerImage, network: "host", schedule: "*/9 * * * *",
|
||||
args: ["run", "/app/modules/anthropic-consumer/dist/apply/index.js"],
|
||||
volumes: ["/var/lib/anthropic-consumer:/run/state"],
|
||||
env: {
|
||||
MESH_MODEL_ACCESS_SECRET_FILE: "/run/state/access-token",
|
||||
MESH_MODEL_ACCESS_BIND_FILE: "/run/state/model.json",
|
||||
MESH_CLAUDE_CREDENTIALS_FILE: "/run/state/claude/.credentials.json",
|
||||
MESH_CLAUDE_IDENTITY_FILE: "/run/state/claude/.claude.json",
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
// The catalogue's own manifest (novox/hq 04-ISSUES/073).
|
||||
const consumerManifest = catalogueModule("anthropic-consumer", held);
|
||||
await must(`printf %s ${quote(consumerManifest)} > /tmp/anthropic-consumer.json && docker cp /tmp/anthropic-consumer.json mesh-controller:/anthropic-consumer.json`);
|
||||
await mesh(`module add /anthropic-consumer.json`);
|
||||
await mesh(`module issue anthropic-consumer --node ${MACHINE}`);
|
||||
|
||||
Reference in New Issue
Block a user