test/issues-ownerless-access.test.js
Rama main · réplica de lectura del repositorio original.
var test = require("node:test");
var assert = require("node:assert/strict");
var fs = require("node:fs");
var os = require("node:os");
var path = require("node:path");
var attachService = require("../lib/issues-service").attachIssuesService;
var attachProject = require("../lib/project-issues").attachProjectIssues;
function fixture(t) {
var directory = fs.mkdtempSync(path.join(os.tmpdir(), "clay-ownerless-"));
t.after(function () { fs.rmSync(directory, { recursive: true, force: true }); });
var user = { id: "member" };
var session = { localId: 1, ownerId: user.id, vendor: "codex" };
var status = { slug: "app", path: directory, projectKnowledgeId: "pk_ownerless", projectOwnerId: null };
var sessions = new Map([[1, session]]);
var project = { getStatus: function () { return status; }, getSessionManager: function () { return { sessions: sessions }; } };
var projects = new Map([["app", project]]);
var access = true;
var service = attachService({
getProjects: function () { return projects; },
isMultiUser: function () { return true; },
findUserById: function (id) { return id === user.id ? user : null; },
canAccessProject: function (id) { return access && id === user.id; },
baseDir: directory,
});
var controller = attachProject({ service: service, projectSlug: "app", getClients: function () { return []; } });
return { service: service, controller: controller, session: session, status: status,
revoke: function () { access = false; } };
}
test("ownerless project exposes Driver tools that create, read and update without granting deletion", async function (t) {
var f = fixture(t);
var defs = f.controller.getDynamicToolDefs(f.session);
function tool(name) { return defs.find(function (item) { return item.name === name; }); }
assert.ok(tool("create_issue"));
var created = await tool("create_issue").handler({ title: "Ownerless project regression" });
assert.notEqual(created.isError, true);
var entry = JSON.parse(created.content[0].text);
var read = await tool("read_issue").handler({ ref: entry.ref });
assert.equal(JSON.parse(read.content[0].text).title, entry.title);
var updated = await tool("update_issue").handler({ ref: entry.ref, expectedRevision: 1, status: "in_progress" });
assert.equal(JSON.parse(updated.content[0].text).revision, 2);
var human = f.service.bindUser({ projectSlug: "app", userId: "member" });
assert.equal(human.canDelete, false);
assert.throws(function () { human.removeIssue({ ref: entry.ref, expectedRevision: 2 }); }, /project owner/);
assert.throws(function () { human.createIssue({ title: "Human write" }); }, /cannot create issues directly/);
assert.equal(f.status.projectOwnerId, null);
f.revoke();
assert.equal(f.controller.getDynamicToolDefs(f.session).length, 0);
var stale = await tool("read_issue").handler({ ref: entry.ref });
assert.equal(stale.isError, true);
assert.equal(f.service.bindUser({ projectSlug: "app", userId: "member" }), null);
});
test("ownerless access still rejects unauthorized users, workers and stale sessions", function (t) {
var f = fixture(t);
assert.equal(f.service.bindUser({ projectSlug: "app", userId: "unknown" }), null);
var forged = Object.assign({}, f.session);
assert.equal(f.service.bindProjectSession({ projectSlug: "app", session: forged }), null);
f.session.ownerId = null;
assert.equal(f.controller.getDynamicToolDefs(f.session).length, 0);
f.session.ownerId = "member";
f.session.sessionProvenance = { kind: "worker" };
assert.equal(f.controller.getDynamicToolDefs(f.session).length, 0);
delete f.session.sessionProvenance;
f.session.hidden = true;
assert.equal(f.controller.getDynamicToolDefs(f.session).length, 0);
f.session.hidden = false;
f.revoke();
assert.equal(f.controller.getDynamicToolDefs(f.session).length, 0);
});
test("absent ownership is allowed but dangling and malformed ownership remains rejected", function (t) {
var f = fixture(t);
delete f.status.projectOwnerId;
assert.ok(f.service.bindProjectSession({ projectSlug: "app", session: f.session }));
["missing-user", "", 123].forEach(function (owner) {
f.status.projectOwnerId = owner;
assert.equal(f.controller.getDynamicToolDefs(f.session).length, 0);
});
});