maestro/src/engine/browser-session-auth.test.ts
2026-06-03 05:08:00 +00:00

96 lines
2.7 KiB
TypeScript

import { describe, it, expect, beforeEach } from 'vitest';
import type { AuditInput } from '../db/browser-session-repo.js';
import { assertProfileOwner } from './browser-session-auth.js';
interface FakeRepo {
audit: (input: AuditInput) => void;
rows: AuditInput[];
}
function makeFakeRepo(): FakeRepo {
const rows: AuditInput[] = [];
return {
rows,
audit(input: AuditInput) {
rows.push(input);
},
};
}
describe('assertProfileOwner — fail-closed owner enforcement', () => {
let fake: FakeRepo;
beforeEach(() => {
fake = makeFakeRepo();
});
it('passes when job.ownerId equals profile.ownerId', () => {
expect(() =>
assertProfileOwner(
{ id: 7, ownerId: 'user-a' },
{ id: 'job-1', ownerId: 'user-a' },
fake,
),
).not.toThrow();
expect(fake.rows.length).toBe(0);
});
it('throws and audits when job.ownerId is null (legacy / dev-mode jobs)', () => {
expect(() =>
assertProfileOwner(
{ id: 7, ownerId: 'user-a' },
{ id: 'job-1', ownerId: null },
fake,
),
).toThrow('Browser session profile owner mismatch');
expect(fake.rows).toHaveLength(1);
expect(fake.rows[0]).toMatchObject({
actorUserId: null,
ownerId: 'user-a',
profileId: 7,
action: 'use',
result: 'error',
jobId: 'job-1',
});
expect(fake.rows[0]!.reason).toContain('job.owner=null');
expect(fake.rows[0]!.reason).toContain('profile.owner=user-a');
});
it('throws and audits when job.ownerId is undefined', () => {
expect(() =>
assertProfileOwner(
{ id: 7, ownerId: 'user-a' },
{ id: 'job-2', ownerId: undefined },
fake,
),
).toThrow('Browser session profile owner mismatch');
expect(fake.rows).toHaveLength(1);
expect(fake.rows[0]!.reason).toContain('job.owner=null');
});
it('throws and audits when job.ownerId is empty string', () => {
expect(() =>
assertProfileOwner(
{ id: 7, ownerId: 'user-a' },
{ id: 'job-3', ownerId: '' },
fake,
),
).toThrow('Browser session profile owner mismatch');
expect(fake.rows).toHaveLength(1);
});
it('throws and audits when job.ownerId differs from profile.ownerId', () => {
expect(() =>
assertProfileOwner(
{ id: 9, ownerId: 'user-a' },
{ id: 'job-4', ownerId: 'user-b' },
fake,
),
).toThrow('Browser session profile owner mismatch');
expect(fake.rows).toHaveLength(1);
expect(fake.rows[0]!.reason).toContain('job.owner=user-b');
expect(fake.rows[0]!.reason).toContain('profile.owner=user-a');
expect(fake.rows[0]!.actorUserId).toBe('user-b');
});
});