import { describe, expect, it } from "vitest";
import { missingPermissions, type Permission } from "#lib/auth/scopes.ts";
const KNOT = "did:web:knot.example.com";
const write: Permission = {
resource: "repo",
collection: "sh.tangled.repo.collaboratorAcceptance",
actions: ["create", "update"]
};
const call: Permission = {
resource: "rpc",
lxm: "sh.tangled.repo.acceptCollaboration",
aud: KNOT
};
const wanted = [write, call];
const handle: Permission = { resource: "identity", attr: "handle" };
const covering: [string, readonly Permission[]][] = [
["repo:sh.tangled.repo.collaboratorAcceptance", [write]],
["repo?collection=sh.tangled.repo.collaboratorAcceptance", [write]],
["repo:*", [write]],
[
"repo:sh.tangled.repo.collaboratorAcceptance?action=create&action=update&action=delete",
[write]
],
["rpc:sh.tangled.repo.acceptCollaboration?aud=*", [call]],
[`rpc?lxm=sh.tangled.repo.acceptCollaboration&aud=${KNOT}`, [call]],
[
`rpc:sh.tangled.repo.acceptCollaboration?aud=${KNOT}%23tangled_knot`,
[{ ...call, aud: `${KNOT}#tangled_knot` }]
],
[`rpc:*?aud=${KNOT}`, [call]],
["identity:handle", [handle]],
["identity:*", [handle]],
["identity?attr=handle", [handle]],
["atproto include:sh.tangled.authKnot", wanted],
["atproto transition:generic", wanted]
];
const coveringNothing: [string, readonly Permission[]][] = [
["repo", [write]],
["repo:", [write]],
["repo?action=create", [write]],
["repo:sh.tangled.knot.member", [write]],
["repo:sh.tangled.repo.collaboratorAcceptance?action=create", [write]],
["rpc:sh.tangled.repo.acceptCollaboration", [call]],
["rpc?lxm=sh.tangled.repo.acceptCollaboration", [call]],
["rpc:sh.tangled.knot.*?aud=*", [call]],
["rpc:sh.tangled.knot.addMember?aud=*", wanted],
["", wanted],
["identity", [handle]],
["identity:", [handle]],
["atproto repo:* rpc:*?aud=*", [handle]],
["atproto repo:sh.tangled.knot repo:sh.tangled.knot.member blob:*/*", wanted]
];
describe("a granted scope", () => {
it.each(covering)("covers %s", (granted, permissions) => {
expect(missingPermissions(granted, permissions)).toEqual([]);
});
it.each(coveringNothing)("covers nothing under %s", (granted, missing) => {
expect(missingPermissions(granted, missing)).toEqual(missing);
});
it("covers its own audience and nobody else's", () => {
const mine = `rpc?lxm=sh.tangled.repo.acceptCollaboration&aud=${KNOT}`;
const theirs = "rpc?lxm=sh.tangled.repo.acceptCollaboration&aud=did:web:other.example";
expect(missingPermissions(mine, [call])).toEqual([]);
expect(missingPermissions(theirs, [call])).toEqual([call]);
});
});