mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-08-14 06:47:28 +00:00
110 lines
4 KiB
TypeScript
110 lines
4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { createAccountAuditEvent, createProviderRegistry, evaluateAccountPolicy, isPolicyGatedPermission, riskBandForScore, scoreAccountActionRisk } from "./index.js";
|
|
|
|
describe("account-core", () => {
|
|
it("indexes account providers by kind and id", () => {
|
|
const registry = createProviderRegistry([
|
|
{ id: "gmail", name: "Gmail", kind: "email", authMethods: ["oauth2"], capabilities: ["email.search"] },
|
|
{ id: "mastodon", name: "Mastodon", kind: "social", authMethods: ["oauth2"], capabilities: ["social.post.publish"] }
|
|
]);
|
|
|
|
expect(registry.list("email")).toHaveLength(1);
|
|
expect(registry.require("mastodon").name).toBe("Mastodon");
|
|
});
|
|
|
|
it("keeps write and private actions policy-gated", () => {
|
|
expect(isPolicyGatedPermission("email:send")).toBe(true);
|
|
expect(isPolicyGatedPermission("social:profile:read")).toBe(false);
|
|
});
|
|
|
|
it("scores and bands risky account actions", () => {
|
|
const score = scoreAccountActionRisk({ action: "email:send", externalRecipientCount: 1, hasAttachment: true, sensitiveKeywordDetected: true });
|
|
|
|
expect(score).toBe(0.55);
|
|
expect(riskBandForScore(score)).toBe("high");
|
|
});
|
|
|
|
it("treats non-finite risk scores as critical", () => {
|
|
expect(riskBandForScore(Number.NaN)).toBe("critical");
|
|
expect(riskBandForScore(Number.POSITIVE_INFINITY)).toBe("critical");
|
|
expect(riskBandForScore(Number.NEGATIVE_INFINITY)).toBe("critical");
|
|
});
|
|
|
|
it("requires approval for gated actions with matching grants", () => {
|
|
const result = evaluateAccountPolicy({
|
|
action: "email:send",
|
|
principal: { type: "agent", id: "marketing-agent" },
|
|
grant: {
|
|
id: "grant_1",
|
|
accountId: "account_1",
|
|
principal: { type: "agent", id: "marketing-agent" },
|
|
permissions: ["email:send"],
|
|
policy: [],
|
|
createdAt: new Date(0).toISOString()
|
|
}
|
|
});
|
|
|
|
expect(result.decision).toBe("approval_required");
|
|
});
|
|
|
|
it.each([Number.NaN, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY])("fails closed for non-finite policy risk score %s", (riskScore) => {
|
|
const result = evaluateAccountPolicy({
|
|
action: "social:profile:read",
|
|
riskScore,
|
|
principal: { type: "agent", id: "reader-agent" },
|
|
grant: {
|
|
id: "grant_read",
|
|
accountId: "account_1",
|
|
principal: { type: "agent", id: "reader-agent" },
|
|
permissions: ["social:profile:read"],
|
|
policy: [],
|
|
createdAt: new Date(0).toISOString()
|
|
}
|
|
});
|
|
|
|
expect(result.riskScore).toBe(1);
|
|
expect(result.decision).toBe("deny");
|
|
});
|
|
|
|
it.each([
|
|
{ principal: { type: "agent" as const, id: "trusted-agent", trusted: true }, expected: "allow" },
|
|
{ principal: { type: "agent" as const, id: "untrusted-agent", trusted: false }, expected: "approval_required" },
|
|
{ principal: undefined, expected: "approval_required" }
|
|
])("enforces trusted-agent policies for $expected decisions", ({ principal, expected }) => {
|
|
const result = evaluateAccountPolicy({
|
|
action: "social:profile:read",
|
|
principal,
|
|
grant: {
|
|
id: "grant_trusted_agent",
|
|
accountId: "account_1",
|
|
principal: { type: "agent", id: "trusted-agent" },
|
|
permissions: ["social:profile:read"],
|
|
policy: [
|
|
{
|
|
id: "trusted_read",
|
|
resource: "social:profile",
|
|
action: "social:profile:read",
|
|
default: "allow_if_trusted_agent"
|
|
}
|
|
],
|
|
createdAt: new Date(0).toISOString()
|
|
}
|
|
});
|
|
|
|
expect(result.decision).toBe(expected);
|
|
});
|
|
|
|
it("redacts secret-like audit previews", () => {
|
|
const event = createAccountAuditEvent({
|
|
provider: "gmail",
|
|
kind: "email",
|
|
principal: { type: "user", id: "user_1" },
|
|
action: "accounts:connect",
|
|
decision: "allow",
|
|
requestPreview: { accessToken: "raw-token", provider: "gmail" }
|
|
});
|
|
|
|
expect(event.requestPreview.accessToken).toBe("[redacted]");
|
|
expect(event.requestPreview.provider).toBe("gmail");
|
|
});
|
|
});
|