import { describe, expect, it } from 'vitest' import { createMemoryDb, migrateSchema, closeDb, createUser, getUserById, getUserPermissions, setUserAccess, updateUser, deleteUser, createRefreshSession, revokeRefreshSession, revokeSessionById, revokeAllSessionsForUser, enablePortalRevocations, } from '../src/index.js' const target = 'https://mm.example.invalid/_internal/mcp/portal/revocations' describe('integrated portal revocation outbox', () => { it('opts in explicitly and retains deletion event independently of user FK', () => { const { db, sqlite } = createMemoryDb(); migrateSchema(sqlite) try { const user = createUser(db, {email:'owned@example.invalid',name:'owned',passwordHash:'synthetic',isAdmin:false}) setUserAccess(db,user.id,['mm'],['old']) expect(sqlite.prepare('SELECT count(*) AS n FROM portal_revocation_outbox').get()).toEqual({n:0}) enablePortalRevocations(db,target) setUserAccess(db,user.id,['mm'],['new']); deleteUser(db,user.id) const rows = sqlite.prepare('SELECT body FROM portal_revocation_outbox ORDER BY sequence').all() as {body:string}[] expect(rows.map(row=>JSON.parse(row.body).type)).toEqual(['permissions.changed','user.disabled']) for (const row of rows) expect(JSON.parse(row.body)).toMatchObject({version:2,userId:user.id}) expect(getUserById(db,user.id)).toBeUndefined() } finally { closeDb(sqlite) } }) it('enqueue failure prevents success of every genuine access/disable/delete/session mutation', () => { const { db, sqlite } = createMemoryDb(); migrateSchema(sqlite) try { const user = createUser(db,{email:'atomic@example.invalid',name:'owned',passwordHash:'synthetic',isAdmin:false}) setUserAccess(db,user.id,['mm'],['old']) const session = createRefreshSession(db,user.id,'owned-refresh',new Date(Date.now()+60000)) enablePortalRevocations(db,target) sqlite.exec("CREATE TRIGGER deny_revocation BEFORE INSERT ON portal_revocation_outbox BEGIN SELECT RAISE(ABORT,'OWNED_ENQUEUE_FAILURE'); END") for (const mutation of [ ()=>setUserAccess(db,user.id,[],[]), ()=>updateUser(db,user.id,{isAdmin:true}), ()=>updateUser(db,user.id,{disabled:true}), ()=>deleteUser(db,user.id), ()=>revokeSessionById(db,session), ()=>revokeRefreshSession(db,'owned-refresh'), ()=>revokeAllSessionsForUser(db,user.id), ]) { expect(mutation).toThrow('OWNED_ENQUEUE_FAILURE') expect(getUserById(db,user.id)).toMatchObject({isAdmin:false,disabled:false}) expect(getUserPermissions(db,user.id)).toEqual(['old']) expect(sqlite.prepare('SELECT revoked_at FROM refresh_sessions WHERE id=?').get(session)).toEqual({revoked_at:null}) expect(sqlite.prepare('SELECT count(*) AS n FROM portal_revocation_outbox').get()).toEqual({n:0}) } } finally { closeDb(sqlite) } }) })