docs(scheduling): document response and privacy lifecycle
This commit is contained in:
85
README.md
85
README.md
@@ -118,3 +118,88 @@ participant pages, Calendar hold cleanup after decision, and advanced scoring
|
||||
constraints such as required participants and quorum rules.
|
||||
|
||||
The active backlog lives in Gitea issues.
|
||||
|
||||
## Signed-participation policy gate
|
||||
|
||||
Scheduling persists the response policy and snapshots it onto each governed
|
||||
Poll invitation. Public access uses
|
||||
`/scheduling/public/{request_id}/{token}`; Poll's ordinary public routes reject
|
||||
these gateway-bound tokens, so callers cannot bypass Scheduling's password and
|
||||
request checks. Passwords are write-only, stored only as salted PBKDF2 hashes,
|
||||
and failed checks are throttled through Redis when configured with a bounded
|
||||
in-process fallback.
|
||||
|
||||
Poll is the transactional authority for response rules. Its governed submission
|
||||
holds the Poll-row lock while enforcing single choice, `Maybe`, participant
|
||||
email, comments, idempotency and per-option capacity. Scheduling then updates
|
||||
its participant projection in the same database transaction. Candidate-slot
|
||||
add/remove and participant-link revocation also go through the governed Poll
|
||||
capability; exact retries are idempotent, and option mutations invalidate only
|
||||
the affected answers.
|
||||
|
||||
Public submissions lock the Scheduling request and participant rows before
|
||||
entering Poll, matching organizer edit lock order and making first-use email
|
||||
binding atomic. Both authenticated and public submission paths independently
|
||||
require the Scheduling request to be collecting and its deadline not to have
|
||||
passed, so a stale or incorrectly reopened Poll projection cannot accept a
|
||||
response. Changing a request deadline transactionally updates each governed
|
||||
invitation's expiry in Poll under owner- and gateway-bound row locks. The same
|
||||
link and invitation identity survive future, past, extended, and cleared
|
||||
deadlines: a past deadline makes the link unusable, a later extension makes the
|
||||
same link usable again, and clearing the deadline removes its expiry. No raw
|
||||
replacement token crosses the PATCH response, and existing responses plus
|
||||
participant status remain attached to the same durable respondent identity.
|
||||
|
||||
Open lifecycle decision: cancellation closes the backing Poll, so submission
|
||||
fails, but an otherwise valid invitation can still resolve the reduced public
|
||||
view and show that the request was cancelled. Decide whether cancellation
|
||||
should revoke links immediately or retain that acknowledgement view for a
|
||||
bounded period; links without a deadline would otherwise remain readable.
|
||||
|
||||
If the governed capability is absent, API responses advertise that policy
|
||||
enforcement is unavailable and restricted links fail closed. Plaintext
|
||||
passwords, token hashes, response-gateway internals and the participant roster
|
||||
are not exposed by the public response model.
|
||||
|
||||
Authenticated participant list/detail projections likewise omit tenant,
|
||||
organizer, Poll and Calendar identifiers, connector metadata, invitation and
|
||||
identity bindings. Free/busy conflicts are reduced to useful time/status
|
||||
fields. Organizers and scheduling administrators retain the full management
|
||||
projection; participants retain candidate-slot revisions, their own marker and
|
||||
email, response settings, aggregates, and any roster names/statuses permitted
|
||||
by the configured privacy policy.
|
||||
|
||||
The WebUI package exposes typed clients for the public access and submission
|
||||
endpoints. A signed-out browser page cannot yet be registered by a module:
|
||||
Core's `App` renders `PublicLandingPage` directly whenever `auth` is absent and
|
||||
only mounts module route contributions inside the authenticated branch. Until
|
||||
Core gains an explicit, allowlisted `publicRoutes` contract, notification action
|
||||
URLs under `/scheduling/public/{request}/{token}` must be treated as a blocked
|
||||
frontend handoff rather than a working guest page. The token is never moved into
|
||||
query parameters, browser storage, or an authenticated API contract while that
|
||||
shell boundary is unresolved.
|
||||
|
||||
Draft saves never issue public tokens or enqueue invitation delivery, even when
|
||||
`create_participant_invitations` is left at its compatibility default. A
|
||||
collecting request may explicitly issue invitations; authenticated in-module
|
||||
responses lazily create a gateway-bound invitation and discard its token. The
|
||||
draft-to-open transition therefore supports authenticated lazy responses, but
|
||||
does not make a guest link available from the current UI. The product decision
|
||||
still open is the explicit organizer workflow for issuing or reissuing public
|
||||
links after a draft is opened and, when Mail is installed, whether that action
|
||||
should also enqueue delivery or return links for separate distribution. Until
|
||||
that workflow is agreed, opening a draft does not silently send anything.
|
||||
|
||||
## FieldLabel omission register
|
||||
|
||||
Scheduling uses the shared `FieldLabel` for form controls that need explanatory
|
||||
inline help. The only intentional omissions are:
|
||||
|
||||
- Candidate-slot and participant DataGrid cells: column headers supply the
|
||||
visible label and each interactive cell has an accessible name.
|
||||
- Per-slot availability selects: the enclosing visible slot/date text is the
|
||||
native label for that individual choice.
|
||||
|
||||
There are no other authorized Scheduling omissions. Inline help remains
|
||||
controlled by the user's shared interface setting; hiding it does not remove
|
||||
accessible labels.
|
||||
|
||||
Reference in New Issue
Block a user