194 lines
10 KiB
JavaScript
194 lines
10 KiB
JavaScript
"use strict";
|
|
|
|
const test = require("node:test");
|
|
const assert = require("node:assert/strict");
|
|
const fs = require("node:fs");
|
|
const os = require("node:os");
|
|
const path = require("node:path");
|
|
const { WorkOrderManager } = require("./workorder-manager");
|
|
|
|
const persona = { pid: "ICE-GL-ZY001", name: "铸渊" };
|
|
|
|
test("defaults keep approval links and sessions alive for three hours", () => {
|
|
const manager = new WorkOrderManager();
|
|
assert.equal(manager.approvalTtl, 3 * 60 * 60);
|
|
assert.equal(manager.sessionTtl, 3 * 60 * 60);
|
|
assert.equal(manager.maxSessionLifetime, 24 * 60 * 60);
|
|
});
|
|
|
|
test("approval link is single use and the session is claimed once", () => {
|
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "lake-lamp-authz-"));
|
|
try {
|
|
const manager = new WorkOrderManager({ stateFile: path.join(dir, "state.json"), sessionTtl: 3600 });
|
|
const created = manager.request({ persona, target: "JD-FD-PRIMARY", scope: "server-login", action: "read-navigation-map", allowedActions: ["read-navigation-map", "inspect-services"] }, 100);
|
|
assert.equal(manager.inspectHandoff(created.handoffToken, 101).ok, true);
|
|
const issued = manager.issueApproval(created.handoffToken, 101);
|
|
assert.equal(issued.ok, true);
|
|
assert.equal(manager.inspectApproval(issued.approvalToken, 101).ok, true);
|
|
assert.equal(manager.approve(issued.approvalToken, 102).ok, true);
|
|
assert.equal(manager.approve(issued.approvalToken, 103).ok, false);
|
|
|
|
const claimed = manager.claim(created.id, created.claimToken, 104);
|
|
assert.equal(claimed.ok, true);
|
|
assert.equal(claimed.expiresIn, 3600);
|
|
assert.equal(
|
|
manager.verifySession(claimed.sessionToken, persona, "JD-FD-PRIMARY", "server-login", "read-navigation-map", 106).session.approvalChannel,
|
|
"email",
|
|
);
|
|
assert.equal(manager.claim(created.id, created.claimToken, 105).ok, false);
|
|
assert.equal(manager.verifySession(claimed.sessionToken, persona, "JD-FD-PRIMARY", "server-login", "read-navigation-map", 106).ok, true);
|
|
assert.equal(manager.verifySession(claimed.sessionToken, persona, "JD-FD-PRIMARY", "server-login", "inspect-services", 106).ok, true);
|
|
} finally {
|
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("session is bound to one persona target scope and action", () => {
|
|
const manager = new WorkOrderManager({ sessionTtl: 3600 });
|
|
const created = manager.request({ persona, target: "BS-GZ-006", scope: "server-ops", action: "read-navigation-map" }, 100);
|
|
const issued = manager.issueApproval(created.handoffToken, 101);
|
|
manager.approve(issued.approvalToken, 101);
|
|
const claimed = manager.claim(created.id, created.claimToken, 102);
|
|
|
|
assert.equal(manager.verifySession(claimed.sessionToken, persona, "BS-GZ-006", "server-ops", "read-navigation-map", 103).ok, true);
|
|
assert.equal(manager.verifySession(claimed.sessionToken, persona, "JD-FD-PRIMARY", "server-ops", "read-navigation-map", 103).reason, "target_mismatch");
|
|
assert.equal(manager.verifySession(claimed.sessionToken, { pid: "OTHER" }, "BS-GZ-006", "server-ops", "read-navigation-map", 103).reason, "persona_mismatch");
|
|
assert.equal(manager.verifySession(claimed.sessionToken, persona, "BS-GZ-006", "repo-push", "read-navigation-map", 103).reason, "scope_mismatch");
|
|
assert.equal(manager.verifySession(claimed.sessionToken, persona, "BS-GZ-006", "server-ops", "push-repository", 103).reason, "action_mismatch");
|
|
});
|
|
|
|
test("plaintext approval claim and session tokens are never persisted", () => {
|
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "lake-lamp-authz-"));
|
|
try {
|
|
const stateFile = path.join(dir, "state.json");
|
|
const manager = new WorkOrderManager({ stateFile });
|
|
const created = manager.request({ persona, target: "JD-FD-PRIMARY", scope: "repo-push", action: "push-repository" }, 100);
|
|
const issued = manager.issueApproval(created.handoffToken, 101);
|
|
manager.approve(issued.approvalToken, 101);
|
|
const claimed = manager.claim(created.id, created.claimToken, 102);
|
|
const state = fs.readFileSync(stateFile, "utf8");
|
|
for (const secret of [created.handoffToken, issued.approvalToken, created.claimToken, claimed.sessionToken]) assert.equal(state.includes(secret), false);
|
|
} finally {
|
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("expired work orders and sessions fail closed", () => {
|
|
const manager = new WorkOrderManager({ approvalTtl: 10, sessionTtl: 20 });
|
|
const created = manager.request({ persona, target: "JD-FD-PRIMARY", scope: "server-login", action: "read-navigation-map" }, 100);
|
|
assert.equal(manager.issueApproval(created.handoffToken, 111).reason, "request_expired");
|
|
|
|
const fresh = manager.request({ persona, target: "JD-FD-PRIMARY", scope: "server-login", action: "read-navigation-map" }, 200);
|
|
const issued = manager.issueApproval(fresh.handoffToken, 201);
|
|
manager.approve(issued.approvalToken, 201);
|
|
const claimed = manager.claim(fresh.id, fresh.claimToken, 202);
|
|
assert.equal(manager.verifySession(claimed.sessionToken, persona, "JD-FD-PRIMARY", "server-login", "read-navigation-map", 223).reason, "session_expired");
|
|
});
|
|
|
|
test("an active session renews without changing target scope or actions", () => {
|
|
const manager = new WorkOrderManager({ sessionTtl: 100, maxSessionLifetime: 500 });
|
|
const created = manager.request({ persona, target: "BS-SG-001", scope: "server-ops", action: "read-navigation-map", allowedActions: ["read-navigation-map", "health-check"] }, 100);
|
|
const issued = manager.issueApproval(created.handoffToken, 101);
|
|
manager.approve(issued.approvalToken, 101);
|
|
const claimed = manager.claim(created.id, created.claimToken, 102);
|
|
const renewed = manager.renewSession(claimed.sessionToken, persona, "BS-SG-001", "server-ops", 150);
|
|
assert.equal(renewed.ok, true);
|
|
assert.equal(renewed.expiresAt, 250);
|
|
assert.equal(manager.renewSession(claimed.sessionToken, persona, "BS-SG-002", "server-ops", 160).reason, "target_mismatch");
|
|
assert.equal(manager.verifySession(claimed.sessionToken, persona, "BS-SG-001", "server-ops", "health-check", 249).ok, true);
|
|
});
|
|
|
|
test("verified bound activity automatically renews without expanding authority", () => {
|
|
const resource = `HLCC-STAGE@${"d".repeat(40)}`;
|
|
const manager = new WorkOrderManager({ sessionTtl: 100, maxSessionLifetime: 500 });
|
|
const created = manager.request({
|
|
persona,
|
|
target: "JD-FD-PRIMARY",
|
|
scope: "server-ops",
|
|
action: "provision-approved-architecture",
|
|
resource,
|
|
}, 100);
|
|
const issued = manager.issueApproval(created.handoffToken, 101);
|
|
manager.approve(issued.approvalToken, 101);
|
|
const claimed = manager.claim(created.id, created.claimToken, 102);
|
|
|
|
const active = manager.verifySession(
|
|
claimed.sessionToken,
|
|
persona,
|
|
"JD-FD-PRIMARY",
|
|
"server-ops",
|
|
"provision-approved-architecture",
|
|
150,
|
|
resource,
|
|
);
|
|
assert.equal(active.ok, true);
|
|
assert.equal(active.autoRenewed, true);
|
|
assert.equal(active.session.expiresAt, 250);
|
|
assert.equal(manager.verifySession(
|
|
claimed.sessionToken,
|
|
persona,
|
|
"JD-FD-PRIMARY",
|
|
"server-ops",
|
|
"provision-approved-architecture",
|
|
160,
|
|
`OTHER@${"e".repeat(40)}`,
|
|
).reason, "resource_mismatch");
|
|
});
|
|
|
|
test("public handoff can send one approval email and can recover from mail failure", () => {
|
|
const manager = new WorkOrderManager({ approvalTtl: 60 });
|
|
const created = manager.request({ persona, target: "JD-FD-PRIMARY", scope: "repo-push", action: "push-repository" }, 100);
|
|
const first = manager.issueApproval(created.handoffToken, 101);
|
|
assert.equal(first.ok, true);
|
|
assert.equal(manager.issueApproval(created.handoffToken, 102).reason, "approval_email_already_sent");
|
|
assert.equal(manager.failApprovalEmail(created.handoffToken), true);
|
|
const retry = manager.issueApproval(created.handoffToken, 103);
|
|
assert.equal(retry.ok, true);
|
|
assert.notEqual(retry.approvalToken, first.approvalToken);
|
|
assert.equal(manager.inspectApproval(first.approvalToken, 104).ok, false);
|
|
assert.equal(manager.inspectApproval(retry.approvalToken, 104).ok, true);
|
|
});
|
|
|
|
test("a broadcast console lists and approves only its bound pending cards", () => {
|
|
const manager = new WorkOrderManager({ approvalTtl: 60 });
|
|
const first = manager.request({
|
|
persona,
|
|
target: "JD-FD-PRIMARY",
|
|
scope: "server-login",
|
|
action: "read-navigation-map",
|
|
}, 100);
|
|
const second = manager.request({
|
|
persona: { pid: "AWEN-TECH", name: "阿文" },
|
|
target: "JD-FD-PRIMARY",
|
|
scope: "server-ops",
|
|
action: "inspect-services",
|
|
}, 100);
|
|
manager.bindApprover(first.handoffToken, "owner");
|
|
manager.bindApprover(second.handoffToken, "awen");
|
|
|
|
const cards = manager.pendingForApprover("owner", 101);
|
|
assert.equal(cards.length, 1);
|
|
assert.equal(cards[0].id, first.id);
|
|
assert.equal(cards[0].state, "pending");
|
|
assert.equal(manager.approveById(first.id, "awen", 102).reason, "authorizer_mismatch");
|
|
assert.equal(manager.approveById(first.id, "owner", 102).ok, true);
|
|
assert.equal(manager.pendingForApprover("owner", 103).length, 0);
|
|
const claimed = manager.claim(first.id, first.claimToken, 104);
|
|
assert.equal(claimed.ok, true);
|
|
assert.equal(
|
|
manager.verifySession(claimed.sessionToken, persona, "JD-FD-PRIMARY", "server-login", "read-navigation-map", 105).session.approvalChannel,
|
|
"guanghu_router",
|
|
);
|
|
});
|
|
|
|
test("session cannot switch an approved architecture resource", () => {
|
|
const resource = `GLS-0231-JD-LAN-01-INITIAL-PROVISION-20260720@${"b".repeat(40)}`;
|
|
const manager = new WorkOrderManager({ sessionTtl: 3600 });
|
|
const created = manager.request({ persona, target: "JD-FD-PRIMARY", scope: "server-ops", action: "provision-approved-architecture", resource }, 100);
|
|
const issued = manager.issueApproval(created.handoffToken, 101);
|
|
manager.approve(issued.approvalToken, 101);
|
|
const claimed = manager.claim(created.id, created.claimToken, 102);
|
|
assert.equal(claimed.resource, resource);
|
|
assert.equal(manager.verifySession(claimed.sessionToken, persona, "JD-FD-PRIMARY", "server-ops", "provision-approved-architecture", 103, resource).ok, true);
|
|
assert.equal(manager.verifySession(claimed.sessionToken, persona, "JD-FD-PRIMARY", "server-ops", "provision-approved-architecture", 103, `OTHER@${"c".repeat(40)}`).reason, "resource_mismatch");
|
|
});
|