feat(recall): telemetryEvents — recall_shown/opened/dismissed/snoozed zod schemas (#6 v0.2.3)

- RecallShownPayload { noteId, ageDays: int>=0 } .strict()
- recall_opened/dismissed/snoozed → NoteIdPayload 재사용
- TelemetryEventSchema union 15 → 19
- 단위 +3 cases (recall_shown valid, extra field 거부, opened/dismissed/snoozed valid)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
altair823
2026-05-02 13:13:49 +09:00
parent 0eb2e6282f
commit b94e68238c
2 changed files with 37 additions and 1 deletions

View File

@@ -306,3 +306,30 @@ describe('validateEvent — tag vocab', () => {
})).toThrow();
});
});
describe('validateEvent — recall', () => {
it('accepts recall_shown event', () => {
const e = validateEvent({
ts: '2026-05-02T00:00:00.000Z',
kind: 'recall_shown',
payload: { noteId: 'n1', ageDays: 14 }
});
expect(e.kind).toBe('recall_shown');
});
it('rejects recall_shown with extra field (privacy)', () => {
expect(() => validateEvent({
ts: '2026-05-02T00:00:00.000Z',
kind: 'recall_shown',
payload: { noteId: 'n1', ageDays: 14, content: 'leak' }
})).toThrow();
});
it('accepts recall_opened/dismissed/snoozed (NoteIdPayload reused)', () => {
for (const kind of ['recall_opened', 'recall_dismissed', 'recall_snoozed'] as const) {
const e = validateEvent({ ts: '2026-05-02T00:00:00.000Z', kind, payload: { noteId: 'n1' } });
expect(e.kind).toBe(kind);
}
});
});