74 lines
3.7 KiB
JavaScript
74 lines
3.7 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { mkdtemp, readFile, rm } from "node:fs/promises";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import test from "node:test";
|
|
import { createFoundryAgentStore } from "./foundry-agent-store.mjs";
|
|
|
|
test("Foundry agent setup issues separate durable credentials and revoke closes both", async () => {
|
|
const dataRoot = await mkdtemp(path.join(os.tmpdir(), "nodedc-foundry-agent-store-"));
|
|
let currentTime = Date.parse("2026-07-18T12:00:00.000Z");
|
|
const store = createFoundryAgentStore({ dataRoot, now: () => currentTime });
|
|
try {
|
|
const created = await store.createAgent({
|
|
ownerId: "user_root",
|
|
ownerKey: "dcctouch@gmail.com",
|
|
name: "Foundry Codex",
|
|
});
|
|
assert.equal(created.status, "active");
|
|
assert.equal(created.deviceCount, 0);
|
|
assert.equal((await store.listAgents("another@nodedc.local")).length, 0);
|
|
|
|
const setup = await store.issueSetupCode("dcctouch@gmail.com", created.id);
|
|
const redeemed = await store.redeemSetupCode(setup.code, "Mac Pro Codex Desktop");
|
|
assert.match(redeemed.foundryToken, /^fnda_/);
|
|
assert.match(redeemed.ontologyToken, /^fndo_/);
|
|
assert.notEqual(redeemed.foundryToken, redeemed.ontologyToken);
|
|
assert.equal(redeemed.device.revokedAt, null);
|
|
assert.equal(Object.hasOwn(redeemed.device, "foundryTokenHash"), false);
|
|
assert.equal(Object.hasOwn(redeemed.device, "ontologyTokenHash"), false);
|
|
|
|
await assert.rejects(
|
|
() => store.redeemSetupCode(setup.code, "Replay"),
|
|
/setup_code_already_redeemed/,
|
|
);
|
|
|
|
const foundrySession = await store.authenticateFoundryToken(redeemed.foundryToken, { check: true });
|
|
const ontologySession = await store.authenticateOntologyToken(redeemed.ontologyToken, { check: true });
|
|
assert.equal(foundrySession.actor.actorId, "user_root");
|
|
assert.equal(ontologySession.actor.ownerKey, "dcctouch@gmail.com");
|
|
assert.equal(await store.authenticateFoundryToken(redeemed.ontologyToken), null);
|
|
assert.equal(await store.authenticateOntologyToken(redeemed.foundryToken), null);
|
|
|
|
currentTime += 3 * 365 * 24 * 60 * 60_000;
|
|
assert.ok(await store.authenticateFoundryToken(redeemed.foundryToken));
|
|
assert.ok(await store.authenticateOntologyToken(redeemed.ontologyToken));
|
|
|
|
const revoked = await store.revokeAgent("dcctouch@gmail.com", created.id);
|
|
assert.equal(revoked.status, "revoked");
|
|
assert.equal(await store.authenticateFoundryToken(redeemed.foundryToken), null);
|
|
assert.equal(await store.authenticateOntologyToken(redeemed.ontologyToken), null);
|
|
|
|
const persisted = await readFile(path.join(dataRoot, "agents.json"), "utf8");
|
|
assert.equal(persisted.includes(redeemed.foundryToken), false);
|
|
assert.equal(persisted.includes(redeemed.ontologyToken), false);
|
|
} finally {
|
|
await rm(dataRoot, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("Foundry setup codes expire and cannot cross owner boundaries", async () => {
|
|
const dataRoot = await mkdtemp(path.join(os.tmpdir(), "nodedc-foundry-agent-expiry-"));
|
|
let currentTime = Date.parse("2026-07-18T12:00:00.000Z");
|
|
const store = createFoundryAgentStore({ dataRoot, now: () => currentTime });
|
|
try {
|
|
const agent = await store.createAgent({ ownerId: "user_root", ownerKey: "owner@nodedc.local", name: "Owner agent" });
|
|
await assert.rejects(() => store.issueSetupCode("other@nodedc.local", agent.id), /foundry_agent_not_found/);
|
|
const setup = await store.issueSetupCode("owner@nodedc.local", agent.id);
|
|
currentTime += 16 * 60_000;
|
|
await assert.rejects(() => store.redeemSetupCode(setup.code, "Late device"), /setup_code_expired/);
|
|
} finally {
|
|
await rm(dataRoot, { recursive: true, force: true });
|
|
}
|
|
});
|