fix(03): IN-03 re-validate outbox payload before VEVENT build, hard-fail invalid rows

This commit is contained in:
Lucas Berger
2026-06-09 11:05:50 -04:00
parent f95760e6c6
commit b8c186491b
2 changed files with 70 additions and 4 deletions
@@ -282,6 +282,29 @@ describe('runOutboxDrain — ICS building from form JSON (CR-02)', () => {
expect(setArg?.status).toBe('failed')
})
// IN-03 (iteration 2): a JSON-parseable but schema-INVALID payload (e.g. missing the
// required title) can never produce a valid VEVENT, so the row is hard-failed (no
// retry) rather than dispatched with SUMMARY:undefined.
it('IN-03: create row with schema-invalid payload (missing title) is hard-failed, never dispatched', async () => {
const { createCalendarEvent } = await import('../../src/broker/write.js')
vi.mocked(createCalendarEvent).mockResolvedValue(makeResponse(201))
// Valid JSON, but title is missing → fails outboxPayloadSchema
const badPayload = JSON.stringify({
allDay: false,
start: '2026-06-10T12:00:00',
end: '2026-06-10T13:00:00',
})
mockPendingRows = [makeRow({ payload: badPayload })]
await runOutboxDrain()
// Must NOT have dispatched a CalDAV write with an invalid VEVENT
expect(createCalendarEvent).not.toHaveBeenCalled()
const setArg = mockUpdateSet.mock.calls[0]?.[0] as { status?: string; lastError?: string }
expect(setArg?.status).toBe('failed')
expect(setArg?.lastError).toMatch(/validation/i)
})
// CR-01 (iteration 2): the edit-as-move create branch must re-apply the RRULE the
// route stashed on the payload as `_preservedRrule`, so a moved recurring series keeps
// its RRULE instead of collapsing into a single occurrence.