feat(poll): enforce auditable lifecycle transitions
This commit is contained in:
24
README.md
24
README.md
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user