feat(poll): enforce auditable lifecycle transitions

This commit is contained in:
2026-07-20 18:18:20 +02:00
parent f4d5cac40d
commit 65e2d1fd65
14 changed files with 1161 additions and 68 deletions

View File

@@ -63,6 +63,30 @@ Poll stores the shared poll/options/responses/result summary. Scheduling owns
the domain workflow around rooms, calendars, free/busy checks, reminders,
appointment creation, and optional Workflow integration.
## Poll lifecycle
Poll configures its lifecycle through the separate, pure transition engine in
`backend/transitions.py`. The default policy is:
- `draft``open` or `archived`
- `open``draft`, `closed`, or `archived`
- `closed``open`, `decided`, or `archived`
- `decided``open`, `decided` (an explicit re-decision), or `archived`
- `archived` → the status from which the Poll was archived
Reopening and archiving preserve responses, close history, and decision
metadata. Every applied transition has a Poll-owned lifecycle audit record.
Re-deciding always appends a record and supersedes the current decision. An
exact retry carrying the same `Idempotency-Key` is a no-op and returns the
original transition record; reusing that key for a different action or option
is rejected. Without an idempotency identity, a repeated transition is invalid
except for the deliberately auditable `decided``decided` action.
Poll API representations expose every lifecycle action with its availability
and, when unavailable, the policy reason. Management clients can use the
`GET /poll/polls/{poll_id}/transitions` endpoint to read the durable history
instead of duplicating the matrix in their UI.
## Development Install
```bash