# Periods and cadence

Read the date rules and keys used by the current notification workflow.

## Due-date rules

| Cadence Key | Due day |
| --- | --- |
| daily | Every day |
| daily-working-days | Days listed in By Day |
| weekly | Monday |
| biweekly | Monday in even ISO weeks (configured parity 0) |
| monthly | First day of the month |
| quarterly | January, April, July and October 1 |
| semiannual | January and July 1 |
| annual | January 1 |
| on-demand or unknown key | Never sent by the daily scheduler |

Both schedule and cadence must be Active. Event Schedule is not parsed by this workflow. Calendar rules are explicit code, not inferred from Repeat Frequency.

## Identity of a response

Period Key Format formats the date using YYYY, MM, DD, [W]WW, [Q]Q and [H]. Weekly formats use ISO week-year. Occurrence Key is `scheduleRecordId:periodKey`; Submission Key is `occurrenceKey|membershipRecordId`. Use the membership-specific key for collection, since one occurrence can request several memberships. Display names and target values are not keys.

## Timezone and late responses

The daily cron is 09:00 in the inherited n8n instance timezone; the workflow does not explicitly set it. Config.timezone is America/Chicago for due-date calculation and response display. The cache schedule explicitly uses America/Recife. runDate defaults to the n8n current date and can be overridden by the daily webhook; this is an operational control, not a public input.

An old Slack item retains its period in private context, while Observation Date is the submission time. The daily workflow only computes the requested run date: there is no automatic backlog sweep. The parser enforces no response cutoff. A late edit reads the schedule’s current target and unit, so changing a schedule can affect an old response; snapshotting target versions is an implementation gap.