Files
0pt/tests/document-workbench/project-access.test.ts
admin e3c4bc28c3
CI (SIAX Cloud) / integration (push) Skipped
CI (SIAX Cloud) / sonar (push) Skipped
CI (SIAX Cloud) / sonar (pull_request) Skipped
masterplan-lock / check (pull_request) Successful in 6s
masterplan-lock / check (push) Successful in 6s
CI (SIAX Cloud) / security (push) Successful in 14s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 19s
CI (SIAX Cloud) / security (pull_request) Successful in 21s
Security Scan (SIAX Cloud) / security (push) Successful in 25s
CI (SIAX Cloud) / integration (pull_request) Successful in 29s
CI (SIAX Cloud) / quality (pull_request) Successful in 51s
CI (SIAX Cloud) / quality (push) Successful in 1m29s
feat(workbench): live LiteLLM gateway adapter + explicit project grants
- createInf0Gateway prefers the live OpenAI-compatible LiteLLM gateway and
  falls back to the native INF0 surface; admission stays local and fail-closed.
- Project authorization: OpenFGA when configured, otherwise a validated
  server-owned OPT_PROJECT_GRANTS list (deny by default).
- Tests for the gateway adapter, the factory and grants.
2026-11-02 14:50:50 +01:00

46 lines
2.0 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import {
createProjectAuthorizer,
parseProjectGrants,
projectAuthorizationConfigured,
} from '../../src/document-workbench/project-access';
const scope = { tenantId: 't_0pt', projectId: 'prj_alpha', actorId: 'user_1' };
describe('project authorization', () => {
it('fails closed when neither OpenFGA nor explicit grants are configured', async () => {
const env = {} as unknown as NodeJS.ProcessEnv;
expect(projectAuthorizationConfigured(env)).toBe(false);
await expect(createProjectAuthorizer(env)(scope)).resolves.toBe(false);
});
it('honours an exact actor grant and rejects a different actor or project', async () => {
const env = {
OPT_PROJECT_GRANTS: JSON.stringify([{ tenantId: 't_0pt', projectId: 'prj_alpha', actorId: 'user_1' }]),
} as unknown as NodeJS.ProcessEnv;
const authorize = createProjectAuthorizer(env);
await expect(authorize(scope)).resolves.toBe(true);
await expect(authorize({ ...scope, actorId: 'user_2' })).resolves.toBe(false);
await expect(authorize({ ...scope, projectId: 'prj_beta' })).resolves.toBe(false);
await expect(authorize({ ...scope, tenantId: 't_other' })).resolves.toBe(false);
});
it('supports a tenant-wide wildcard actor', async () => {
const env = {
OPT_PROJECT_GRANTS: JSON.stringify([{ tenantId: 't_0pt', projectId: 'prj_alpha', actorId: '*' }]),
} as unknown as NodeJS.ProcessEnv;
await expect(createProjectAuthorizer(env)({ ...scope, actorId: 'anyone' })).resolves.toBe(true);
});
it('treats an invalid grant document as unconfigured', () => {
expect(parseProjectGrants('{not json')).toBeUndefined();
expect(parseProjectGrants(JSON.stringify([]))).toBeUndefined();
expect(parseProjectGrants(JSON.stringify([{ tenantId: 't', projectId: 'p' }]))).toBeUndefined();
expect(
projectAuthorizationConfigured({
OPT_PROJECT_GRANTS: 'not-json',
} as unknown as NodeJS.ProcessEnv),
).toBe(false);
});
});