@pairlobby/fixtures 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/LICENSE +93 -0
  2. package/README.md +5 -0
  3. package/dist/admin-contract.d.ts +3 -0
  4. package/dist/admin-contract.d.ts.map +1 -0
  5. package/dist/admin-contract.js +63 -0
  6. package/dist/admin-contract.js.map +1 -0
  7. package/dist/auto-close-contract.d.ts +3 -0
  8. package/dist/auto-close-contract.d.ts.map +1 -0
  9. package/dist/auto-close-contract.js +204 -0
  10. package/dist/auto-close-contract.js.map +1 -0
  11. package/dist/contract.d.ts +4 -0
  12. package/dist/contract.d.ts.map +1 -0
  13. package/dist/contract.js +688 -0
  14. package/dist/contract.js.map +1 -0
  15. package/dist/fake-agent.d.ts +41 -0
  16. package/dist/fake-agent.d.ts.map +1 -0
  17. package/dist/fake-agent.js +90 -0
  18. package/dist/fake-agent.js.map +1 -0
  19. package/dist/faulty-store.d.ts +19 -0
  20. package/dist/faulty-store.d.ts.map +1 -0
  21. package/dist/faulty-store.js +54 -0
  22. package/dist/faulty-store.js.map +1 -0
  23. package/dist/group-contract.d.ts +3 -0
  24. package/dist/group-contract.d.ts.map +1 -0
  25. package/dist/group-contract.js +237 -0
  26. package/dist/group-contract.js.map +1 -0
  27. package/dist/handover-samples.d.ts +3 -0
  28. package/dist/handover-samples.d.ts.map +1 -0
  29. package/dist/handover-samples.js +23 -0
  30. package/dist/handover-samples.js.map +1 -0
  31. package/dist/harness.d.ts +635 -0
  32. package/dist/harness.d.ts.map +1 -0
  33. package/dist/harness.js +114 -0
  34. package/dist/harness.js.map +1 -0
  35. package/dist/index.d.ts +9 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +9 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/interrupt-contract.d.ts +3 -0
  40. package/dist/interrupt-contract.d.ts.map +1 -0
  41. package/dist/interrupt-contract.js +142 -0
  42. package/dist/interrupt-contract.js.map +1 -0
  43. package/dist/memory-store.d.ts +39 -0
  44. package/dist/memory-store.d.ts.map +1 -0
  45. package/dist/memory-store.js +175 -0
  46. package/dist/memory-store.js.map +1 -0
  47. package/dist/redemption-contract.d.ts +3 -0
  48. package/dist/redemption-contract.d.ts.map +1 -0
  49. package/dist/redemption-contract.js +94 -0
  50. package/dist/redemption-contract.js.map +1 -0
  51. package/dist/rejoin-contract.d.ts +3 -0
  52. package/dist/rejoin-contract.d.ts.map +1 -0
  53. package/dist/rejoin-contract.js +117 -0
  54. package/dist/rejoin-contract.js.map +1 -0
  55. package/dist/request-contract.d.ts +3 -0
  56. package/dist/request-contract.d.ts.map +1 -0
  57. package/dist/request-contract.js +215 -0
  58. package/dist/request-contract.js.map +1 -0
  59. package/package.json +40 -0
@@ -0,0 +1,94 @@
1
+ //! Crash injection around invite redemption. The gate is that every interleaving
2
+ //! produces at most one membership, and that an authorized retry recovers the
3
+ //! same one rather than forking a second.
4
+ import { ProtocolError, newCredential, newId } from '@pairlobby/protocol';
5
+ import { RoomService } from '@pairlobby/server-core';
6
+ import { afterEach, beforeEach, describe, expect, test } from 'vitest';
7
+ import { FaultyStore } from './faulty-store.js';
8
+ export function runRedemptionContract(label, makeStore) {
9
+ describe(label, () => {
10
+ let store;
11
+ let service;
12
+ let roomId;
13
+ let controllerCredential;
14
+ let code;
15
+ const joiner = { displayName: 'codex', kind: 'agent' };
16
+ beforeEach(async () => {
17
+ store = new FaultyStore(makeStore());
18
+ service = new RoomService(store, () => 1_700_000_000_000);
19
+ controllerCredential = newCredential('controller');
20
+ const created = await service.createRoom({
21
+ name: 'recovery-room',
22
+ controllerCredential,
23
+ participantCredential: newCredential('participant'),
24
+ displayName: 'claude',
25
+ kind: 'agent'
26
+ });
27
+ roomId = created.roomId;
28
+ code = created.invite.code;
29
+ });
30
+ afterEach(() => store.close());
31
+ async function participantCount() {
32
+ return (await service.snapshot(roomId, controllerCredential)).participants.length;
33
+ }
34
+ test('test_a_crash_creating_membership_leaves_a_resumable_reservation', async () => {
35
+ const attemptId = newId('attempt');
36
+ const participantCredential = newCredential('participant');
37
+ store.faults.failNextApply = true;
38
+ await expect(service.redeemInvite({ code, attemptId, participantCredential, ...joiner })).rejects.toThrow('injected store failure');
39
+ expect(await participantCount()).toBe(1);
40
+ const recovered = await service.redeemInvite({ code, attemptId, participantCredential, ...joiner });
41
+ expect(recovered.replayed).toBe(false);
42
+ expect(await participantCount()).toBe(2);
43
+ });
44
+ test('test_a_crash_before_the_invite_is_marked_consumed_recovers_the_same_member', async () => {
45
+ const attemptId = newId('attempt');
46
+ const participantCredential = newCredential('participant');
47
+ store.faults.failNextCompleteInvite = true;
48
+ await expect(service.redeemInvite({ code, attemptId, participantCredential, ...joiner })).rejects.toThrow('injected crash');
49
+ expect(await participantCount()).toBe(2);
50
+ const recovered = await service.redeemInvite({ code, attemptId, participantCredential, ...joiner });
51
+ expect(recovered.replayed).toBe(true);
52
+ expect(await participantCount()).toBe(2);
53
+ });
54
+ test('test_a_stranger_cannot_claim_an_invite_reserved_by_another_attempt', async () => {
55
+ const participantCredential = newCredential('participant');
56
+ store.faults.failNextApply = true;
57
+ await expect(service.redeemInvite({ code, attemptId: newId('attempt'), participantCredential, ...joiner })).rejects.toThrow('injected store failure');
58
+ // The reservation survives the crash, so the code is not available to anyone else.
59
+ await expect(service.redeemInvite({ code, attemptId: newId('attempt'), participantCredential: newCredential('participant'), displayName: 'stranger', kind: 'agent' })).rejects.toMatchObject({ code: 'invite_already_redeemed' });
60
+ expect(await participantCount()).toBe(1);
61
+ });
62
+ // This proves the service serializes correctly *given* an atomic `reserveInvite`.
63
+ // A single-threaded fixture cannot prove the store's own isolation under real
64
+ // concurrency; that belongs in the load runs.
65
+ test('test_concurrent_attempts_on_one_invite_yield_exactly_one_member', async () => {
66
+ const attempts = Array.from({ length: 8 }, () => ({ code, attemptId: newId('attempt'), participantCredential: newCredential('participant'), ...joiner }));
67
+ const results = await Promise.allSettled(attempts.map((attempt) => service.redeemInvite(attempt)));
68
+ expect(results.filter((result) => result.status === 'fulfilled')).toHaveLength(1);
69
+ for (const result of results.filter((candidate) => candidate.status === 'rejected')) {
70
+ expect(result.reason).toBeInstanceOf(ProtocolError);
71
+ expect(result.reason.code).toBe('invite_already_redeemed');
72
+ }
73
+ expect(await participantCount()).toBe(2);
74
+ });
75
+ test('test_retrying_a_completed_redemption_never_creates_a_second_member', async () => {
76
+ const attemptId = newId('attempt');
77
+ const participantCredential = newCredential('participant');
78
+ const first = await service.redeemInvite({ code, attemptId, participantCredential, ...joiner });
79
+ for (let index = 0; index < 5; index += 1) {
80
+ const retry = await service.redeemInvite({ code, attemptId, participantCredential, ...joiner });
81
+ expect(retry.participantId).toBe(first.participantId);
82
+ expect(retry.replayed).toBe(true);
83
+ }
84
+ expect(await participantCount()).toBe(2);
85
+ });
86
+ test('test_each_invite_admits_one_member_so_a_second_agent_needs_its_own', async () => {
87
+ await service.redeemInvite({ code, attemptId: newId('attempt'), participantCredential: newCredential('participant'), ...joiner });
88
+ const second = await service.mintInvite(roomId, controllerCredential, 'member');
89
+ await service.redeemInvite({ code: second.code, attemptId: newId('attempt'), participantCredential: newCredential('participant'), displayName: 'gemini', kind: 'agent' });
90
+ expect(await participantCount()).toBe(3);
91
+ });
92
+ });
93
+ }
94
+ //# sourceMappingURL=redemption-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redemption-contract.js","sourceRoot":"","sources":["../src/redemption-contract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { StoreFactory } from './contract.js';
2
+ export declare function runRejoinContract(label: string, makeStore: StoreFactory): void;
3
+ //# sourceMappingURL=rejoin-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rejoin-contract.d.ts","sourceRoot":"","sources":["../src/rejoin-contract.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,eAAe,CAAC;AAIhD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,GAAG,IAAI,CAwH9E"}
@@ -0,0 +1,117 @@
1
+ import { afterEach, beforeEach, describe, expect, test } from 'vitest';
2
+ import { DEFAULT_ROOM_POLICY, newCredential, newId } from '@pairlobby/protocol';
3
+ import { RoomService } from '@pairlobby/server-core';
4
+ import { fixedClock } from './harness.js';
5
+ export function runRejoinContract(label, makeStore) {
6
+ describe(`${label} / saved-session rejoin`, () => {
7
+ let store;
8
+ let clock;
9
+ let service;
10
+ let room;
11
+ let owner;
12
+ let controller;
13
+ beforeEach(async () => {
14
+ store = makeStore();
15
+ clock = fixedClock();
16
+ service = new RoomService(store, clock.now);
17
+ owner = newCredential('participant');
18
+ controller = newCredential('controller');
19
+ room = await service.createRoom({ name: 'rejoin', displayName: 'owner', kind: 'human', participantCredential: owner, controllerCredential: controller, policy: { ...DEFAULT_ROOM_POLICY, maxParticipants: 2 } });
20
+ });
21
+ afterEach(() => store.close?.());
22
+ test('restores the same owner identity and makes retries harmless', async () => {
23
+ await service.leave(room.roomId, owner);
24
+ const snapshot = await service.rejoin(room.roomId, owner);
25
+ expect(snapshot.participants).toHaveLength(1);
26
+ expect(snapshot.participants[0]).toMatchObject({ participantId: room.participantId, displayName: 'owner', kind: 'human', role: 'member', left: false });
27
+ expect((await service.rejoin(room.roomId, owner)).latestSeq).toBe(snapshot.latestSeq);
28
+ await service.send(room.roomId, owner, { type: 'message', payload: { text: 'back again', priority: 'normal' }, idempotencyKey: newId('event') });
29
+ await expect(service.rejoin(room.roomId, controller)).rejects.toMatchObject({ code: 'unauthorized' });
30
+ await expect(service.rejoin(room.roomId, 'unknown')).rejects.toMatchObject({ code: 'unauthorized' });
31
+ });
32
+ test('preserves guest permissions and agent session, mute and pause state', async () => {
33
+ const memberCredential = newCredential('participant');
34
+ const sessionId = newId('session');
35
+ const member = await service.redeemInvite({ code: room.invite.code, displayName: 'agent', kind: 'agent', sessionId, participantCredential: memberCredential, attemptId: newId('attempt') });
36
+ await service.setMuted(room.roomId, controller, member.participantId, true);
37
+ await service.control(room.roomId, controller, member.participantId, true);
38
+ await service.leave(room.roomId, memberCredential);
39
+ const snapshot = await service.rejoin(room.roomId, memberCredential);
40
+ expect(snapshot.participants.find((participant) => participant.participantId === member.participantId)).toMatchObject({ left: false, muted: true, paused: true, role: 'member' });
41
+ expect((await store.loadRoom(room.roomId)).participants.find((participant) => participant.participantId === member.participantId).sessionId).toBe(sessionId);
42
+ await service.leave(room.roomId, memberCredential);
43
+ const invitation = await service.mintInvite(room.roomId, controller, 'guest');
44
+ const guestCredential = newCredential('participant');
45
+ const guest = await service.redeemInvite({ code: invitation.code, displayName: 'observer', kind: 'human', participantCredential: guestCredential, attemptId: newId('attempt') });
46
+ await service.leave(room.roomId, guestCredential);
47
+ expect((await service.rejoin(room.roomId, guestCredential)).participants.find((participant) => participant.participantId === guest.participantId)).toMatchObject({ left: false, role: 'guest' });
48
+ await expect(service.send(room.roomId, guestCredential, { type: 'message', payload: { text: 'forbidden', priority: 'normal' }, idempotencyKey: newId('event') })).rejects.toMatchObject({ code: 'unauthorized' });
49
+ });
50
+ test('a saved credential does not bypass room locks, capacity or revocation', async () => {
51
+ const memberCredential = newCredential('participant');
52
+ const member = await service.redeemInvite({ code: room.invite.code, displayName: 'member', kind: 'human', participantCredential: memberCredential, attemptId: newId('attempt') });
53
+ await service.leave(room.roomId, memberCredential);
54
+ await service.setLocked(room.roomId, controller, true);
55
+ await expect(service.rejoin(room.roomId, memberCredential)).rejects.toMatchObject({ code: 'room_locked' });
56
+ await service.setLocked(room.roomId, controller, false);
57
+ const invitation = await service.mintInvite(room.roomId, controller, 'member');
58
+ await service.redeemInvite({ code: invitation.code, displayName: 'another', kind: 'human', participantCredential: newCredential('participant'), attemptId: newId('attempt') });
59
+ await expect(service.rejoin(room.roomId, memberCredential)).rejects.toMatchObject({ code: 'participant_limit_reached' });
60
+ await service.revoke(room.roomId, controller, member.participantId);
61
+ await expect(service.rejoin(room.roomId, memberCredential)).rejects.toMatchObject({ code: 'participant_revoked' });
62
+ });
63
+ test('closed and expired rooms cannot be rejoined', async () => {
64
+ await service.leave(room.roomId, owner);
65
+ await service.setExpiry(room.roomId, controller, clock.now() + 1000);
66
+ await service.close(room.roomId, controller);
67
+ await expect(service.rejoin(room.roomId, owner)).rejects.toMatchObject({ code: 'room_closed' });
68
+ clock.advance(1001);
69
+ await expect(service.rejoin(room.roomId, owner)).rejects.toMatchObject({ code: 'room_expired' });
70
+ });
71
+ test('self rename preserves identity, controls and existing requests across rejoin', async () => {
72
+ const credential = newCredential('participant');
73
+ const sessionId = newId('session');
74
+ const agent = await service.redeemInvite({ code: room.invite.code, displayName: 'agent', kind: 'agent', sessionId, participantCredential: credential, attemptId: newId('attempt') });
75
+ const request = await service.send(room.roomId, owner, { type: 'message', recipientId: agent.participantId, payload: { text: 'hello', priority: 'normal' }, idempotencyKey: newId('event') });
76
+ await service.control(room.roomId, controller, agent.participantId, true);
77
+ const before = (await store.loadRoom(room.roomId)).participants.find((participant) => participant.participantId === agent.participantId);
78
+ const snapshot = await service.renameSelf(room.roomId, credential, { name: 'Review Agent', source: 'room' });
79
+ expect(snapshot.participants.find((participant) => participant.participantId === agent.participantId)).toMatchObject({ displayName: 'Review Agent', nameSource: 'room', kind: 'agent', role: 'member', paused: true });
80
+ const after = (await store.loadRoom(room.roomId)).participants.find((participant) => participant.participantId === agent.participantId);
81
+ expect(after).toEqual({ ...before, displayName: 'Review Agent', nameSource: 'room' });
82
+ expect((await service.request(room.roomId, owner, request.event.eventId)).to).toBe(agent.participantId);
83
+ const events = (await service.read(room.roomId, owner, 0, 100)).events;
84
+ expect(events.at(-1)).toMatchObject({ type: 'participant.renamed', senderId: agent.participantId, payload: { previousName: 'agent', name: 'Review Agent' } });
85
+ await service.leave(room.roomId, credential);
86
+ expect((await service.rejoin(room.roomId, credential)).participants.find((participant) => participant.participantId === agent.participantId)).toMatchObject({ displayName: 'Review Agent', nameSource: 'room' });
87
+ });
88
+ test('profile names follow the default until a room name is explicitly chosen', async () => {
89
+ await service.renameSelf(room.roomId, owner, { name: 'New default', source: 'profile' });
90
+ const renamed = await service.renameSelf(room.roomId, owner, { name: 'New default', source: 'room' });
91
+ const repeated = await service.renameSelf(room.roomId, owner, { name: 'New default', source: 'room' });
92
+ expect(repeated.latestSeq).toBe(renamed.latestSeq);
93
+ const later = await service.renameSelf(room.roomId, owner, { name: 'Later default', source: 'profile' });
94
+ expect(later.latestSeq).toBe(renamed.latestSeq);
95
+ expect(later.participants[0]).toMatchObject({ displayName: 'New default', nameSource: 'room' });
96
+ });
97
+ test('self rename cannot bypass controller, guest, mute or revoked restrictions', async () => {
98
+ const input = { name: 'new', source: 'room' };
99
+ await expect(service.renameSelf(room.roomId, controller, input)).rejects.toMatchObject({ code: 'unauthorized' });
100
+ const invite = await service.mintInvite(room.roomId, controller, 'guest');
101
+ const guestCredential = newCredential('participant');
102
+ const guest = await service.redeemInvite({ code: invite.code, displayName: 'observer', kind: 'human', participantCredential: guestCredential, attemptId: newId('attempt') });
103
+ await expect(service.renameSelf(room.roomId, guestCredential, input)).rejects.toMatchObject({ code: 'unauthorized' });
104
+ await service.revoke(room.roomId, controller, guest.participantId);
105
+ await expect(service.renameSelf(room.roomId, guestCredential, input)).rejects.toMatchObject({ code: 'participant_revoked' });
106
+ await service.setMuted(room.roomId, controller, room.participantId, true);
107
+ await expect(service.renameSelf(room.roomId, owner, input)).rejects.toMatchObject({ code: 'participant_muted' });
108
+ });
109
+ test('invalid names cannot enter the transcript or change a membership', async () => {
110
+ for (const name of ['', ' ', 'x'.repeat(65), 'All', 'hello\nworld', 'bad\u001b[2J']) {
111
+ await expect(service.renameSelf(room.roomId, owner, { name, source: 'room' })).rejects.toMatchObject({ code: 'invalid_request' });
112
+ }
113
+ expect((await service.snapshot(room.roomId, owner)).participants[0].displayName).toBe('owner');
114
+ });
115
+ });
116
+ }
117
+ //# sourceMappingURL=rejoin-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rejoin-contract.js","sourceRoot":"","sources":["../src/rejoin-contract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { StoreFactory } from './contract.js';
2
+ export declare function runRequestContract(label: string, makeStore: StoreFactory): void;
3
+ //# sourceMappingURL=request-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-contract.d.ts","sourceRoot":"","sources":["../src/request-contract.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,eAAe,CAAC;AAIhD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,QA2NxE"}
@@ -0,0 +1,215 @@
1
+ import { afterEach, beforeEach, describe, expect, test } from 'vitest';
2
+ import { DEFAULT_ROOM_POLICY, newCredential, newId, requestState } from '@pairlobby/protocol';
3
+ import { RoomService } from '@pairlobby/server-core';
4
+ import { FaultyStore } from './faulty-store.js';
5
+ export function runRequestContract(label, makeStore) {
6
+ describe(`${label} / durable message obligations`, () => {
7
+ let store, service, roomId, alice, bob, aliceId, bobId, controller;
8
+ beforeEach(async () => {
9
+ store = makeStore();
10
+ service = new RoomService(store);
11
+ alice = newCredential('participant');
12
+ bob = newCredential('participant');
13
+ controller = newCredential('controller');
14
+ const room = await service.createRoom({
15
+ name: 'delivery',
16
+ displayName: 'alice',
17
+ kind: 'agent',
18
+ participantCredential: alice,
19
+ controllerCredential: controller
20
+ });
21
+ roomId = room.roomId;
22
+ aliceId = room.participantId;
23
+ bobId = (await service.redeemInvite({ code: room.invite.code, displayName: 'bob', kind: 'agent', participantCredential: bob, attemptId: newId('attempt') }))
24
+ .participantId;
25
+ });
26
+ afterEach(() => store.close?.());
27
+ const ask = (text) => service.send(roomId, alice, { type: 'message', recipientId: bobId, payload: { text, priority: 'normal' }, idempotencyKey: newId('event') });
28
+ const answer = (id, text = 'I do not know', progress = false) => service.send(roomId, bob, {
29
+ type: 'message',
30
+ recipientId: aliceId,
31
+ replyTo: id,
32
+ payload: { text, priority: 'normal', responseStage: progress ? 'progress' : 'final' },
33
+ idempotencyKey: newId('event')
34
+ });
35
+ test('every request survives newer requests and unthreaded chatter', async () => {
36
+ const first = await ask('first'), second = await ask('second');
37
+ await service.send(roomId, bob, { type: 'message', recipientId: aliceId, payload: { text: 'unrelated', priority: 'normal' }, idempotencyKey: newId('event') });
38
+ const pending = await service.requests(roomId, bob, 0, 100, bobId);
39
+ expect(pending.requests.map((r) => r.eventId)).toEqual([first.event.eventId, second.event.eventId]);
40
+ });
41
+ test('quoted follow-ups create new obligations and preserve the earlier final answer', async () => {
42
+ const question = await ask('original question');
43
+ await service.acknowledgeMessage(roomId, bob, question.event.eventId);
44
+ const response = await answer(question.event.eventId, 'original answer');
45
+ const request = { type: 'message', recipientId: bobId, quoteOf: response.event.eventId, payload: { text: 'explain further', priority: 'normal' }, idempotencyKey: newId('event') };
46
+ const followup = await service.send(roomId, alice, request);
47
+ expect(followup.event).toMatchObject({ quoteOf: response.event.eventId, replyTo: null, payload: { text: 'explain further' } });
48
+ const obligation = await service.request(roomId, bob, followup.event.eventId);
49
+ expect(obligation.requiresReply).toBe(true);
50
+ expect(obligation.text).toContain('original answer');
51
+ expect(obligation.text).toContain('explain further');
52
+ expect((await service.request(roomId, alice, question.event.eventId)).responseEventId).toBe(response.event.eventId);
53
+ expect((await service.send(roomId, alice, request)).deduplicated).toBe(true);
54
+ await expect(service.send(roomId, alice, { ...request, quoteOf: question.event.eventId })).rejects.toMatchObject({ code: 'idempotency_conflict' });
55
+ expect((await new RoomService(store).read(roomId, alice, 0, 100)).events.at(-1)?.quoteOf).toBe(response.event.eventId);
56
+ });
57
+ test('quotes cannot point outside retained message history, bypass reply rules or complete somebody else’s request', async () => {
58
+ const question = await ask('unanswered question');
59
+ const quote = { type: 'message', quoteOf: question.event.eventId, payload: { text: 'context', priority: 'normal' }, idempotencyKey: newId('event') };
60
+ await service.send(roomId, alice, quote);
61
+ expect((await service.request(roomId, bob, question.event.eventId)).responseEventId).toBeNull();
62
+ const system = (await service.read(roomId, alice, 0, 100)).events[0];
63
+ for (const quoteOf of [newId('event'), system.eventId]) {
64
+ await expect(service.send(roomId, alice, { ...quote, quoteOf, idempotencyKey: newId('event') })).rejects.toMatchObject({ code: 'invalid_request' });
65
+ }
66
+ await expect(service.send(roomId, alice, { ...quote, replyTo: question.event.eventId, idempotencyKey: newId('event') })).rejects.toMatchObject({ code: 'invalid_request' });
67
+ });
68
+ test('senders cannot acknowledge themselves, and a final reply requires the recipients receipt', async () => {
69
+ const { event } = await ask('work');
70
+ await expect(service.acknowledgeMessage(roomId, alice, event.eventId)).rejects.toMatchObject({ code: 'unauthorized' });
71
+ await expect(answer(event.eventId)).rejects.toMatchObject({ code: 'invalid_request' });
72
+ await service.acknowledgeMessage(roomId, bob, event.eventId);
73
+ await expect(service.send(roomId, alice, {
74
+ type: 'message',
75
+ replyTo: event.eventId,
76
+ recipientId: bobId,
77
+ payload: { text: 'forged answer', priority: 'normal' },
78
+ idempotencyKey: newId('event')
79
+ })).rejects.toMatchObject({ code: 'unauthorized' });
80
+ expect((await service.requests(roomId, bob)).requests).toHaveLength(1);
81
+ });
82
+ test('human and agent readers have separate receipts without satisfying another recipients obligation', async () => {
83
+ const invite = await service.mintInvite(roomId, alice, 'member');
84
+ const humanCredential = newCredential('participant');
85
+ const human = await service.redeemInvite({ code: invite.code, displayName: 'human', kind: 'human', participantCredential: humanCredential, attemptId: newId('attempt') });
86
+ const { event } = await ask('agent to agent');
87
+ await service.acknowledgeMessage(roomId, humanCredential, event.eventId);
88
+ expect((await service.request(roomId, alice, event.eventId)).receivedAt).toBeNull();
89
+ await expect(answer(event.eventId)).rejects.toMatchObject({ code: 'invalid_request' });
90
+ await service.acknowledgeMessage(roomId, bob, event.eventId);
91
+ await service.acknowledgeMessage(roomId, humanCredential, event.eventId);
92
+ const receipts = (await service.read(roomId, alice, 0, 100)).events.filter((entry) => entry.type === 'message.received' && entry.payload.eventId === event.eventId);
93
+ expect(receipts.map((entry) => entry.senderId)).toEqual([human.participantId, bobId]);
94
+ const reply = await answer(event.eventId);
95
+ await service.acknowledgeMessage(roomId, alice, reply.event.eventId);
96
+ expect((await service.request(roomId, bob, reply.event.eventId)).receivedAt).not.toBeNull();
97
+ expect((await service.requests(roomId, alice)).requests).toHaveLength(0);
98
+ });
99
+ test('broadcast receipts are idempotent per reader and never create reply obligations', async () => {
100
+ const { event } = await service.send(roomId, alice, { type: 'message', payload: { text: 'everyone', priority: 'normal' }, idempotencyKey: newId('event') });
101
+ await service.acknowledgeMessage(roomId, bob, event.eventId);
102
+ await service.send(roomId, bob, { type: 'message.received', payload: { eventId: event.eventId }, idempotencyKey: newId('event') });
103
+ const receipts = (await service.read(roomId, alice, 0, 100)).events.filter((entry) => entry.type === 'message.received');
104
+ expect(receipts).toHaveLength(1);
105
+ expect((await service.requests(roomId, bob)).requests).toHaveLength(0);
106
+ store.dropHistoryBefore(roomId, receipts[0].seq + 1);
107
+ await new RoomService(store).acknowledgeMessage(roomId, bob, event.eventId);
108
+ expect((await service.read(roomId, bob, 0, 100)).events).toHaveLength(0);
109
+ });
110
+ test('muted agents can confirm receipt but cannot send or reply, and revocation blocks receipts', async () => {
111
+ const { event } = await ask('read while muted');
112
+ await service.setMuted(roomId, controller, bobId, true);
113
+ await service.acknowledgeMessage(roomId, bob, event.eventId);
114
+ expect((await service.request(roomId, alice, event.eventId)).receivedAt).not.toBeNull();
115
+ await expect(answer(event.eventId)).rejects.toMatchObject({ code: 'participant_muted' });
116
+ await expect(service.send(roomId, bob, { type: 'message', payload: { text: 'blocked', priority: 'normal' }, idempotencyKey: newId('event') })).rejects.toMatchObject({ code: 'participant_muted' });
117
+ await expect(service.acknowledgeMessage(roomId, alice, event.eventId)).rejects.toMatchObject({ code: 'unauthorized' });
118
+ await service.revoke(roomId, controller, bobId);
119
+ await expect(service.acknowledgeMessage(roomId, bob, event.eventId)).rejects.toMatchObject({ code: 'participant_revoked' });
120
+ });
121
+ test('receipts reject system events, missing messages and guest writers', async () => {
122
+ const joined = (await service.read(roomId, alice, 0, 100)).events[0];
123
+ await expect(service.acknowledgeMessage(roomId, bob, joined.eventId)).rejects.toMatchObject({ code: 'invalid_request' });
124
+ await expect(service.acknowledgeMessage(roomId, bob, newId('event'))).rejects.toMatchObject({ code: 'invalid_request' });
125
+ const invite = await service.mintInvite(roomId, alice, 'guest');
126
+ const guestCredential = newCredential('participant');
127
+ await service.redeemInvite({ code: invite.code, displayName: 'guest', kind: 'human', participantCredential: guestCredential, attemptId: newId('attempt') });
128
+ const { event } = await ask('work');
129
+ await expect(service.acknowledgeMessage(roomId, guestCredential, event.eventId)).rejects.toMatchObject({ code: 'unauthorized' });
130
+ });
131
+ test('an unrelated event using a receipt key cannot fabricate successful acknowledgement', async () => {
132
+ const { event } = await ask('work');
133
+ await service.send(roomId, alice, { type: 'message', payload: { text: 'collision', priority: 'normal' }, idempotencyKey: `receipt-${event.eventId}-${bobId}` });
134
+ await expect(service.acknowledgeMessage(roomId, bob, event.eventId)).rejects.toMatchObject({ code: 'idempotency_conflict' });
135
+ expect((await service.request(roomId, alice, event.eventId)).receivedAt).toBeNull();
136
+ });
137
+ test('receipt and progress do not complete a request; a refusal closes exactly one', async () => {
138
+ const first = await ask('first'), second = await ask('second');
139
+ await service.acknowledgeMessage(roomId, bob, first.event.eventId);
140
+ await answer(first.event.eventId, 'Working on it', true);
141
+ expect((await service.requests(roomId, bob)).requests).toHaveLength(2);
142
+ await answer(first.event.eventId, 'I refuse this request');
143
+ expect((await service.requests(roomId, bob)).requests.map((r) => r.eventId)).toEqual([second.event.eventId]);
144
+ expect((await service.requests(roomId, alice, 0, 100, aliceId)).requests).toHaveLength(0);
145
+ });
146
+ test('unanswered requests and acknowledgements survive transcript pruning', async () => {
147
+ const { event } = await ask('do not forget');
148
+ await service.acknowledgeMessage(roomId, bob, event.eventId);
149
+ store.dropHistoryBefore(roomId, event.seq + 2);
150
+ const restarted = new RoomService(store);
151
+ expect((await restarted.requests(roomId, bob)).requests[0].text).toBe('do not forget');
152
+ await restarted.acknowledgeMessage(roomId, bob, event.eventId);
153
+ await answer(event.eventId);
154
+ expect((await restarted.requests(roomId, bob)).requests).toHaveLength(0);
155
+ });
156
+ test('a failed commit cannot acknowledge or close the obligation', async () => {
157
+ const { event } = await ask('work');
158
+ const faulty = new FaultyStore(store);
159
+ const failing = new RoomService(faulty);
160
+ faulty.faults.failNextApply = true;
161
+ await expect(failing.acknowledgeMessage(roomId, bob, event.eventId)).rejects.toThrow();
162
+ expect((await service.request(roomId, alice, event.eventId)).receivedAt).toBeNull();
163
+ await service.acknowledgeMessage(roomId, bob, event.eventId);
164
+ faulty.faults.failNextApply = true;
165
+ await expect(failing.send(roomId, bob, {
166
+ type: 'message',
167
+ recipientId: aliceId,
168
+ replyTo: event.eventId,
169
+ payload: { text: 'answer', priority: 'normal' },
170
+ idempotencyKey: newId('event')
171
+ })).rejects.toThrow();
172
+ expect((await service.requests(roomId, alice)).requests).toHaveLength(1);
173
+ });
174
+ test('ordinary work quota cannot prevent a receipt and final reply', async () => {
175
+ const a = newCredential('participant'), b = newCredential('participant');
176
+ const room = await service.createRoom({
177
+ name: 'reserved replies',
178
+ displayName: 'a',
179
+ kind: 'agent',
180
+ participantCredential: a,
181
+ controllerCredential: newCredential('controller'),
182
+ policy: { ...DEFAULT_ROOM_POLICY, maxRetainedEvents: 3 }
183
+ });
184
+ const member = await service.redeemInvite({ code: room.invite.code, displayName: 'b', kind: 'agent', participantCredential: b, attemptId: newId('attempt') });
185
+ const sent = await service.send(room.roomId, a, {
186
+ type: 'message',
187
+ recipientId: member.participantId,
188
+ payload: { text: 'last allowed request', priority: 'normal' },
189
+ idempotencyKey: newId('event')
190
+ });
191
+ await service.acknowledgeMessage(room.roomId, b, sent.event.eventId);
192
+ await service.send(room.roomId, b, {
193
+ type: 'message',
194
+ recipientId: room.participantId,
195
+ replyTo: sent.event.eventId,
196
+ payload: { text: 'I cannot do it', priority: 'normal' },
197
+ idempotencyKey: newId('event')
198
+ });
199
+ expect((await service.requests(room.roomId, a)).requests).toHaveLength(0);
200
+ });
201
+ test('adapter failure is visible but never forged as an agent answer', async () => {
202
+ const { event } = await ask('work');
203
+ await service.send(roomId, bob, { type: 'message.delivery_failed', payload: { eventId: event.eventId, reason: 'Runtime disconnected' }, idempotencyKey: newId('event') });
204
+ const failed = await service.request(roomId, alice, event.eventId);
205
+ expect(requestState(failed)).toBe('failed');
206
+ expect(failed.receivedAt).toBeNull();
207
+ expect(failed.responseEventId).toBeNull();
208
+ expect((await service.requests(roomId, alice)).requests).toHaveLength(1);
209
+ await service.acknowledgeMessage(roomId, bob, event.eventId);
210
+ await answer(event.eventId);
211
+ expect(requestState(await service.request(roomId, alice, event.eventId))).toBe('answered');
212
+ });
213
+ });
214
+ }
215
+ //# sourceMappingURL=request-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-contract.js","sourceRoot":"","sources":["../src/request-contract.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@pairlobby/fixtures",
3
+ "version": "0.11.0",
4
+ "description": "PairLobby fixtures: part of the PairLobby room protocol and relay",
5
+ "license": "Elastic-2.0",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "LICENSE",
18
+ "README.md"
19
+ ],
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/PairLobby/app.git",
23
+ "directory": "fixtures"
24
+ },
25
+ "homepage": "https://pairlobby.com",
26
+ "engines": {
27
+ "node": ">=22"
28
+ },
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "dependencies": {
33
+ "@pairlobby/protocol": "0.11.0",
34
+ "@pairlobby/room-core": "0.11.0",
35
+ "@pairlobby/server-core": "0.11.0"
36
+ },
37
+ "peerDependencies": {
38
+ "vitest": ">=4.1.0"
39
+ }
40
+ }