import type { LegacyApiKeySimple } from "@toolctrl/db/api-keys.server"; import { describe, expect, test } from "vitest"; import { createServicePrincipal } from "../auth.js"; import { authorizeApiScope, createStoredApiKeyPrincipal, type ApiScopeResult } from "./scope.js"; const NOW = new Date("2026-01-15T12:00:00.000Z"); function buildApiKey(overrides: Partial = {}): LegacyApiKeySimple { return { id: "api-key-1", alias: "Production key", expires: new Date("2026-02-01T00:00:00.000Z"), tenantId: "tenant-1", active: true, entities: [ { entityId: "entity-1", create: true, read: true, update: true, delete: false, }, ], tenant: { id: "tenant-1", name: "Tenant One", slug: "tenant-one", deactivatedReason: null, }, ...overrides, }; } function authorize(apiKey: LegacyApiKeySimple, overrides: Partial[1]> = {}): ApiScopeResult { return authorizeApiScope(createStoredApiKeyPrincipal(apiKey), { tenantId: "tenant-1", entityId: "entity-1", operation: "read", now: NOW, ...overrides, }); } function expectRedactedDeny(result: ApiScopeResult, reason: string) { expect(result).toEqual({ allowed: false, principalType: "api-key", reason, code: "FORBIDDEN_API_KEY_SCOPE", }); const serialized = JSON.stringify(result); expect(serialized).not.toContain("plaintext-secret"); expect(serialized).not.toContain("hash-value"); expect(serialized).not.toContain("service-token"); } describe("authorizeApiScope", () => { test("allows service-token principals for every scoped operation", () => { const principal = createServicePrincipal(); expect( authorizeApiScope(principal, { tenantId: "other-tenant", entityId: "unknown-entity", operation: "delete", now: NOW, }), ).toEqual({ allowed: true, principalType: "service-token", }); }); test("allows active stored API keys with matching tenant, entity, and CRUD permission", () => { expect(authorize(buildApiKey(), { operation: "create" })).toEqual({ allowed: true, principalType: "api-key", }); }); test("denies inactive stored API keys", () => { expectRedactedDeny(authorize(buildApiKey({ active: false })), "api_key_inactive"); }); test("denies expired stored API keys", () => { expectRedactedDeny(authorize(buildApiKey({ expires: new Date("2026-01-01T00:00:00.000Z") })), "api_key_expired"); }); test("denies stored API keys for deactivated tenants", () => { expectRedactedDeny( authorize( buildApiKey({ tenant: { id: "tenant-1", name: "Tenant One", slug: "tenant-one", deactivatedReason: "billing_issue", }, }), ), "tenant_deactivated", ); }); test("denies stored API keys whose tenant does not match the request tenant", () => { expectRedactedDeny(authorize(buildApiKey(), { tenantId: "tenant-2" }), "tenant_mismatch"); expectRedactedDeny( authorize( buildApiKey({ tenant: { id: "tenant-2", name: "Tenant Two", slug: "tenant-two", deactivatedReason: null, }, }), ), "tenant_mismatch", ); }); test("denies stored API keys missing the requested entity permission", () => { expectRedactedDeny(authorize(buildApiKey(), { entityId: "entity-2" }), "entity_permission_missing"); }); test("denies stored API keys missing the requested CRUD operation permission", () => { expectRedactedDeny(authorize(buildApiKey(), { operation: "delete" }), "operation_permission_missing"); }); });