fix(agent): bound push suppression to observed browser attention
This commit is contained in:
@@ -70,17 +70,88 @@ test('first source bootstrap never alerts history; later durable candidates debo
|
||||
const restarted = new AgentPushCoordinator({ ...f.manager.options, warmupMs: 0 }); await restarted.tick(); assert.equal(f.sent.length, 1);
|
||||
});
|
||||
|
||||
test('all tabs veto: visible focused idle, recent interaction and unknown connections; leases eventually expire', async () => {
|
||||
const f = await fixture(), tab1 = randomUUID(), tab2 = randomUUID(), unknown = randomUUID();
|
||||
test('all tabs veto while focused; hidden heartbeats and stale sequences cannot extend short transition grace', async () => {
|
||||
const f = await fixture(), tab1 = randomUUID(), tab2 = randomUUID();
|
||||
await f.manager.presence(tab1, { sequence: 1, visibility: 'hidden', focused: false, interacted: false });
|
||||
await f.manager.presence(tab2, { sequence: 1, visibility: 'visible', focused: true, interacted: false });
|
||||
f.candidate(); await f.manager.tick(); f.advance(2_000); await f.manager.tick(); assert.equal(f.sent.length, 0, 'focused but idle still vetoes');
|
||||
let receipt = await prisma.agentPushDelivery.findFirstOrThrow();
|
||||
assert.equal(receipt.lastSuppressionReason, 'foreground_focused'); assert.equal(receipt.lastSuppressionClientKind, 'web');
|
||||
await f.manager.presence(tab2, { sequence: 2, visibility: 'hidden', focused: false, interacted: true });
|
||||
f.advance(2_000); await f.manager.tick(); assert.equal(f.sent.length, 0, 'recent input vetoes blur');
|
||||
await f.manager.presence(tab2, { sequence: 1, visibility: 'visible', focused: true, interacted: false });
|
||||
assert.equal((await prisma.agentPushPresence.findUniqueOrThrow({ where: { id: tab2 } })).sequence, 2);
|
||||
await f.manager.connect(unknown); f.advance(31_000); await f.manager.tick(); assert.equal(f.sent.length, 0, 'unknown authenticated socket vetoes');
|
||||
f.advance(61_000); await f.manager.tick(); assert.equal(f.sent.length, 1, 'expired stale sessions retire');
|
||||
await f.manager.presence(tab2, { sequence: 3, visibility: 'hidden', focused: false, interacted: true });
|
||||
f.advance(4_000); await f.manager.tick(); assert.equal(f.sent.length, 1, 'hidden receipts do not renew attention');
|
||||
receipt = await prisma.agentPushDelivery.findFirstOrThrow();
|
||||
assert.equal(receipt.lastSuppressionReason, 'inactive_grace'); assert.ok(receipt.lastSuppressedAt);
|
||||
});
|
||||
|
||||
test('blur and visible recent interaction have short grace; fresh focus renews a live lease', async () => {
|
||||
const f = await fixture(), tab = randomUUID();
|
||||
await f.manager.presence(tab, { sequence: 1, visibility: 'visible', focused: true, interacted: false });
|
||||
f.candidate(); await f.manager.tick(); f.advance(2_000);
|
||||
await f.manager.presence(tab, { sequence: 2, visibility: 'visible', focused: false, interacted: true });
|
||||
await f.manager.tick(); assert.equal(f.sent.length, 0);
|
||||
assert.equal((await prisma.agentPushDelivery.findFirstOrThrow()).lastSuppressionReason, 'recent_interaction');
|
||||
f.advance(3_000); await f.manager.presence(tab, { sequence: 3, visibility: 'visible', focused: false, interacted: false });
|
||||
f.advance(3_000); await f.manager.tick(); assert.equal(f.sent.length, 1);
|
||||
await f.manager.presence(tab, { sequence: 4, visibility: 'visible', focused: true, interacted: false });
|
||||
f.candidate('12'); await f.manager.tick(); f.advance(45_000);
|
||||
await f.manager.presence(tab, { sequence: 5, visibility: 'visible', focused: true, interacted: false });
|
||||
f.advance(20_000); await f.manager.tick(); assert.equal(f.sent.length, 1, 'fresh foreground heartbeat extends attention');
|
||||
f.advance(41_000); await f.manager.tick(); assert.equal(f.sent.length, 2, 'stale focus expires');
|
||||
});
|
||||
|
||||
test('anonymous introduction grace survives heartbeat, new UUID reconnects and coordinator restart without renewing', async () => {
|
||||
const f = await fixture(), connection = randomUUID();
|
||||
await f.manager.connect(connection); f.candidate(); await f.manager.tick(); f.advance(2_000); await f.manager.tick();
|
||||
assert.equal(f.sent.length, 0);
|
||||
const first = await prisma.agentPushCoordinator.findUniqueOrThrow({ where: { id: 'root' } });
|
||||
assert.equal((await prisma.agentPushDelivery.findFirstOrThrow()).lastSuppressionReason, 'unknown_client_grace');
|
||||
await f.manager.heartbeat(connection); await f.manager.disconnect(connection);
|
||||
await f.manager.connect(randomUUID(), 'web', randomUUID()); f.advance(4_000); await f.manager.tick(); assert.equal(f.sent.length, 1);
|
||||
f.candidate('12'); await f.manager.tick(); f.advance(2_000);
|
||||
const restarted = new AgentPushCoordinator({ ...f.manager.options, warmupMs: 0 });
|
||||
await restarted.connect(randomUUID()); await restarted.tick(); assert.equal(f.sent.length, 2);
|
||||
assert.deepEqual((await prisma.agentPushCoordinator.findUniqueOrThrow({ where: { id: 'root' } })).unknownSince, first.unknownSince);
|
||||
// Spending the anonymous budget never disables an independent authenticated browser lease.
|
||||
await f.manager.presence(randomUUID(), { sequence: 1, visibility: 'visible', focused: true, interacted: false });
|
||||
f.candidate('13'); await f.manager.tick(); f.advance(2_000); await f.manager.tick(); assert.equal(f.sent.length, 2);
|
||||
});
|
||||
|
||||
test('expired observed web lease is inactive with a live socket; transport heartbeat preserves attribution and never recreates it', async () => {
|
||||
const f = await fixture(), tab = randomUUID(), connection = randomUUID(), native = randomUUID();
|
||||
await f.manager.presence(tab, { sequence: 1, visibility: 'visible', focused: true, interacted: false });
|
||||
await f.manager.connect(connection, 'web', tab); await f.manager.connect(native, 'native');
|
||||
f.candidate(); await f.manager.tick(); f.advance(61_000);
|
||||
await f.manager.heartbeat(connection); await f.manager.heartbeat(native); await f.manager.tick(); assert.equal(f.sent.length, 1);
|
||||
assert.equal((await prisma.agentPushCoordinator.findUniqueOrThrow({ where: { id: 'root' } })).unknownSince, null);
|
||||
const row = await prisma.agentPushConnection.findUniqueOrThrow({ where: { id: connection } });
|
||||
assert.equal(row.kind, 'web'); assert.equal(row.sessionId, tab);
|
||||
assert.equal((await prisma.agentPushConnection.findUniqueOrThrow({ where: { id: native } })).kind, 'native');
|
||||
await f.manager.disconnect(native); await f.manager.heartbeat(native);
|
||||
assert.equal(await prisma.agentPushConnection.findUnique({ where: { id: native } }), null);
|
||||
await f.manager.presence(tab, { sequence: 2, visibility: 'hidden', focused: false, interacted: false });
|
||||
assert.equal((await prisma.agentPushPresence.findUniqueOrThrow({ where: { id: tab } })).inactiveUntil, null, 'stale focus cannot start fresh grace');
|
||||
});
|
||||
|
||||
test('presence classification cannot borrow a session from a different credential generation', async () => {
|
||||
const f = await fixture(), tab = randomUUID();
|
||||
await f.manager.presence(tab, { sequence: 1, visibility: 'hidden', focused: false, interacted: false });
|
||||
await prisma.agentPushPresence.update({ where: { id: tab }, data: { ownerEpoch: 'another-generation' } });
|
||||
await f.manager.connect(randomUUID(), 'web', tab); f.candidate(); await f.manager.tick(); f.advance(2_000); await f.manager.tick();
|
||||
assert.equal(f.sent.length, 0); assert.equal((await prisma.agentPushDelivery.findFirstOrThrow()).lastSuppressionReason, 'unknown_client_grace');
|
||||
});
|
||||
|
||||
test('read at final context refresh cancels without a send and preserves the prior suppression evidence', async () => {
|
||||
const f = await fixture(); await f.manager.connect(randomUUID()); f.candidate(); await f.manager.tick(); f.advance(2_000); await f.manager.tick();
|
||||
const prior = await prisma.agentPushDelivery.findFirstOrThrow(), original = f.manager.options.context; let calls = 0;
|
||||
f.manager.options.context = async (...args) => { if (++calls === 2) await f.manager.advanceRead('11', f.source); return original(...args); };
|
||||
f.advance(4_000); await f.manager.tick();
|
||||
const receipt = await prisma.agentPushDelivery.findFirstOrThrow();
|
||||
assert.equal(f.sent.length, 0); assert.equal(receipt.attempts, 0); assert.equal(receipt.outcome, 'read');
|
||||
assert.equal(receipt.lastSuppressionReason, prior.lastSuppressionReason); assert.deepEqual(receipt.lastSuppressedAt, prior.lastSuppressedAt);
|
||||
});
|
||||
|
||||
test('instrumented hidden web socket is inactive; missing lease and native-runtime unknown veto', async () => {
|
||||
|
||||
Reference in New Issue
Block a user