Auth and Access Model
This document is the definitive Tov+ specification for authentication, identity, actor linking, sessions, principals, and authorization.
1. Purpose
This document is the definitive Tov+ specification for authentication, identity, actor linking, sessions, principals, and authorization.
It is intended to unblock implementation in:
- backend server middleware and policy evaluation
- guest, vendor, dashboard, and admin app access behavior
- integration authentication
- worker/system execution context
- database records for users, links, grants, tokens, and audit
This document is security-critical. When there is conflict between convenience and security, this document chooses explicit scope, explicit linkage, and auditable authorization.
2. Core access principle
The non-negotiable system rule is:
Users authenticate. Actors authorize.
This means:
- Keycloak proves identity
- Tov+ creates or resolves the acting principal
- Tov+ maps the identity to one or more business actors where applicable
- Tov+ evaluates permissions, invitations, token restrictions, module enablement, and resource visibility
The practical consequences are:
- authentication and authorization are separate concerns
- actor identity is not replaced by a login account
- guests can be low-friction without weakening authorization
- vendors, planners, admins, integrations, and workers all enter the same central authorization flow
3. Identity model
3.1 Keycloak responsibility boundary
Keycloak is the external identity provider.
Keycloak owns:
- credential storage
- password and MFA flows
- identity verification
- SSO/federation if enabled
- primary authenticated user session issuance
- upstream identity claims such as email verification status
Keycloak does not own:
- occasion membership
- actor linking
- guest invite tokens
- vendor scoping
- integration scopes
- resource authorization
3.2 Tov+ identity boundary
Tov+ owns:
- internal user records
- mapping from external identity to internal user
- links from users to actors
- guest token issuance and revocation
- integration principals and scopes
- system principals
- all authorization and access policy evaluation
3.3 Identity objects
Tov+ distinguishes three related but different concepts:
External identity
The identity asserted by Keycloak.
Purpose:
- prove who authenticated
- carry stable external subject identifiers
Tov+ user
The internal application user.
Purpose:
- represent an authenticated person in the Tov+ platform
- aggregate linked actors across occasions
- hold internal lifecycle, support, and audit metadata
Actor
The business participant inside an occasion.
Purpose:
- represent the person, household, vendor, group, or team in occasion context
- drive authorization and business visibility
3.4 Identity linkage rules
- one Keycloak identity maps to one Tov+ user
- one Tov+ user may link to many actors
- linked actors may exist across many occasions
- actor links are explicit Tov+ records, not inferred only from email
3.5 Whether one actor can link to more than one user
Default rule:
- an actor should link to at most one active claimed user at a time
Allowed exceptions:
- a shared operational actor such as a vendor team actor may link to multiple users through membership semantics rather than direct duplicate claiming
- an organization/team actor may be accessible through multiple user-to-actor links when the actor type is group/team/vendor_organization rather than a single natural person
Forbidden pattern:
- two unrelated personal user accounts both claiming the same person actor without explicit administrative resolution
Implementation rule:
- personal actors (
person) are single-primary-user linked - non-person actors (
group,team,household,vendor organization) may have multiple linked users with scoped permissions
4. User model
4.1 Tov+ user responsibilities
The Tov+ user record owns:
- stable internal
user_id - external identity mapping
- account lifecycle state
- support/admin flags where applicable
- profile metadata needed at platform level
- linked actor references
- linked occasion participation references
4.2 Tov+ user does not replace actor
User is not the business participant model.
A user may:
- represent a planner working across many occasions
- claim a guest identity on one occasion and a vendor identity on another
- link to multiple actors in the same occasion where explicitly permitted
An actor may exist without any linked user:
- unclaimed guest
- household member without login
- vendor placeholder before invitation acceptance
4.3 User lifecycle
Typical states:
provisionedactivesuspendedclosed
Rules:
- suspension blocks authenticated access even if actor links exist
- closing a user does not delete historical actor or audit records
5. Actor linkage model
5.1 Link record purpose
User-to-actor linkage must be explicit and stored locally in Tov+.
The link record exists to answer:
- which user may act through which actor
- in which occasion the link is valid
- whether the link was guest-claimed, admin-created, or vendor-invited
- whether the link is primary, secondary, pending, or revoked
5.2 Link cardinality rules
- a user may link to many actors
- actor links are occasion-scoped even when the same real person appears across occasions
- a user may link to more than one actor in the same occasion only when product behavior requires it and permissions are explicit
Examples:
- planner user linked to planner actor on one occasion and vendor actor on another
- guest user linked to their own person actor and a household actor where household-response workflows require it
- vendor operations lead linked to both vendor organization actor and individual contact actor
5.3 Link acquisition methods
Supported methods:
- admin or planner creates link explicitly
- guest claims actor from valid guest token
- vendor accepts invite and is linked during onboarding
- support/admin resolution merges or repairs ambiguous identity links
5.4 Link verification rules
Automatic linking by email alone is not sufficient for sensitive access.
Allowed usage of email matching:
- as a candidate suggestion during claim or invite acceptance
- as a non-authoritative hint in admin tools
Required for final link activation:
- possession of valid invite/token, authenticated session, or privileged administrative action
5.5 Actor selection at request time
When a user is linked to multiple actors relevant to the request:
- Tov+ resolves the actor from request context if unambiguous
- otherwise the principal carries an active actor context chosen by the user or flow
Examples:
- dashboard request may resolve planner actor for a specific occasion
- vendor app request may resolve vendor team actor for a specific event
- claimed guest request may resolve guest actor for the occasion slug being accessed
6. Principal model
6.1 Supported principal types
Tov+ supports four principal types:
user_principalguest_principalintegration_principalsystem_principal
Each principal has:
- a stable principal type
- authenticated identity proof appropriate to that type
- contextual scope
- optional linked user and/or actor resolution
- auditable request metadata
6.2 User principal
Created by:
- successful Keycloak-authenticated login routed into Tov+
Authenticates with:
- Keycloak session or tokens
Maps to:
- exactly one Tov+ user
- zero or more linked actors depending on context
Used by:
- planners
- vendors with full login
- internal admins
- claimed guests
Authorization behavior:
- resolve Tov+ user
- resolve current occasion/event context
- resolve active actor link if required
- evaluate grants/resources/scopes
6.3 Guest principal
Created by:
- successful presentation of a valid guest invite token or QR-derived guest token
Authenticates with:
- Tov+-issued scoped guest token, optionally exchanged for a short-lived session
Maps to:
- no required Tov+ user
- one or more actor and invitation scopes embedded or referenced by the token
Used by:
- frictionless guest access before account claim
Authorization behavior:
- token restrictions are mandatory
- actor/invitation scope is restricted to the token grant
- permissions are evaluated as guest capabilities within the token's allowed resources and events
6.4 Integration principal
Created by:
- registration of an integration app in Tov+
Authenticates with:
- Tov+-issued API credential pair, signed token, or rotating secret depending on the interface pattern
Maps to:
- an integration app record
- allowed occasion/event/module/resource scopes
Used by:
- printers
- venues
- caterers
- partner systems
Authorization behavior:
- no bypass privileges
- evaluate only the integration's granted scopes and permitted resources
- every action is auditable to the integration principal
6.5 System principal
Created by:
- trusted internal worker or service runtime
Authenticates with:
- platform-managed service credentials or internal trust configuration
Maps to:
- a system actor identity for audit purposes, not a human user
Used by:
- background jobs
- reminder dispatch
- publishing generation
- webhook delivery
- integration sync handlers
Authorization behavior:
- least privilege
- system actions must still declare intended scope and operation
- workers do not implicitly act as super-admin
7. Session/token model
7.1 Session classes
Tov+ supports four session/token classes:
- authenticated user sessions
- guest access sessions
- integration credentials/sessions
- system service credentials
7.2 Authenticated user sessions
Model:
- Keycloak performs the primary login
- Tov+ exchanges or validates Keycloak identity and creates an internal application session context
Requirements:
- session identifies one Tov+ user
- session stores recent auth context metadata
- actor context may vary per request or be selected within the session
Recommended behavior:
- short-lived access token or server session
- refresh handled through Keycloak-compatible flow
- forced re-auth for high-risk admin actions if later required
7.3 Guest access sessions
Model:
- guest receives an invite link or QR token
- token is exchanged for a short-lived guest session for browser/app use
Token requirements:
- cryptographically strong random identifier or signed token
- scoped to occasion and invited actor/invitation set
- optionally scoped to event subset
- expiration timestamp
- revocation support
- minimal embedded data if self-contained
Recommended behavior:
- invite token is one-time exchangeable into a renewable short-lived guest session
- renewable guest session survives normal browser navigation but not indefinite inactivity
- session refresh requires possession of valid unexpired refresh-capable guest credential or a new invite link
7.4 Integration credentials
Model:
- Tov+ issues integration credentials bound to one integration app
Requirements:
- secret storage as hashed or envelope-encrypted server-side material
- explicit scope list
- explicit rotation and revocation support
- audit metadata on use
Recommended pattern:
- key identifier plus secret for machine auth
- optional signed JWT access token minted from the key/secret for short-lived calls
7.5 System service credentials
Model:
- internal-only credential or service identity
Requirements:
- not user-shareable
- rotated through infra controls
- limited to declared service responsibilities
7.6 Session persistence expectations
- user sessions may persist across devices through standard authenticated login, not by copying actor links
- guest sessions are device/browser-local unless the guest claims an account or reuses the invite token on another device
- claimed guest access can persist across devices once a user account is linked
- integration and system credentials are non-interactive and long-lived only with rotation controls
7.7 Local Tov+ auth/access records
Tov+ must store the following records locally because Keycloak does not own business authorization:
usersexternal_identity_mappingsuser_actor_linksaccess_grantsguest_access_tokensguest_sessionsif server-tracked sessions are usedintegration_appsintegration_credentialssystem_service_identitiesaudit_log_entriessession_metadatawhere needed for revocation, anomaly detection, or support diagnostics
Rules:
- Keycloak identity data is referenced through stable mapping, not copied as the source of truth for authorization
- user-to-actor links, guest token scopes, and integration scopes are always local Tov+ records
- audit records must outlive session expiry and account closure where legally and operationally appropriate
8. Authorization flow
8.1 Canonical authorization sequence
Every sensitive request must follow this order:
- identify the principal type
- authenticate the presented credential
- resolve the internal subject record
- resolve occasion, event, module, and resource context
- resolve linked actor or invitation scope where required
- resolve token restrictions and session constraints
- verify module installation/enablement when applicable
- evaluate permission grants and visibility rules
- return allow/deny plus effective scope metadata
8.2 Step details
Step 1: identify principal type
Determine whether the request is:
user_principalguest_principalintegration_principalsystem_principal
Mixed-mode fallback is forbidden. One request has one principal type.
Step 2: authenticate credential
Examples:
- Keycloak-backed session for user principal
- guest token/session for guest principal
- API credential for integration principal
- internal service credential for system principal
If authentication fails, stop before business context resolution.
Step 3: resolve internal subject
Resolve:
- Tov+ user for user principal
- guest token record for guest principal
- integration app record for integration principal
- service identity for system principal
Step 4: resolve context/scope
Resolve from request:
- occasion
- event if present
- module if present
- target resource if present
No permission evaluation should run with ambiguous occasion scope.
Step 5: resolve actor or invitation scope
Resolve:
- active actor link for user principal where business access depends on actor identity
- actor/invitation scope from guest token
- integration scope set for integration principal
- declared job scope for system principal
Step 6: evaluate credential restrictions
Examples:
- guest token expired
- guest token only permits event subset
- integration secret revoked
- user session suspended
Step 7: verify module state
When the request targets a module surface:
- module must be installed on the occasion
- module must be enabled on the event if event-scoped
Step 8: evaluate grants and visibility
Inputs include:
- principal type
- resolved subject
- actor link
- occasion/event/module/resource scope
- invitation state
- token restrictions
- module enablement
- resource ownership or audience visibility
Outputs include:
- allow or deny
- effective actor context
- effective scopes
- reason code for audit/debugging
8.3 Policy composition rule
Authorization is conjunctive, not role-only.
A request is allowed only if all relevant layers pass:
- authentication is valid
- principal is active
- occasion context is valid
- actor/invitation/integration scope is valid
- module state is valid
- permission grant exists
- resource visibility constraints pass
9. App-specific access behavior
9.1 Dashboard (`dash.tovplus.com`)
Primary principal:
user_principal
Expected users:
- occasion owners
- planners
- delegated helpers
- claimed vendors only if dashboard access is later explicitly supported
Rules:
- requires authenticated user session
- no guest-principal access
- actor context usually resolves to planner/helper actor for selected occasion
- broad management surfaces still respect occasion/event/module/resource grants
9.2 Admin (`admin.tovplus.com`)
Primary principal:
user_principal
Expected users:
- internal admins
- support operators
Rules:
- requires authenticated user session plus membership in the configured Keycloak platform-admin group
- platform administration is separate from ordinary occasion planner access
- platform-admin access is identity-managed in Keycloak, not stored in the Tov+ database
- any future impersonation or support-view mode must be explicit, audited, and time-bounded
9.3 Vendors (`vendors.tovplus.com`)
Primary principal:
user_principal
Expected users:
- invited vendor contacts
- vendor team members
Rules:
- requires authenticated user session after invite acceptance
- vendor actor context is mandatory for operational access
- vendor access is narrower than planner access by default
- vendor app should surface only modules/resources granted to the vendor actor in current occasion/event scope
9.4 Guests (`{occasion_slug}.tov.plus`)
Primary principals:
guest_principaluser_principalfor claimed guests
Rules:
- knowing the occasion slug is not sufficient for private access
- guest token-first flow is the default
- claimed guest sessions may reuse the same guest-visible surfaces with stronger continuity
- the guest app must present only occasion/event/module content allowed by token plus permissions
9.5 API (`api.tovplus.com`)
Primary principals:
- all four principal types depending on endpoint family
Rules:
- every endpoint documents allowed principal types
- no endpoint assumes integration access equals admin access
- user-, guest-, integration-, and system-authenticated calls go through the same authorization core with type-specific resolution
10. Guest access model
10.1 Core rule
Guest access is token-first and account-optional.
Guests should be able to:
- open invite links
- view their accessible occasion experience
- RSVP or complete forms
- view seating, gallery, FAQ, updates, or schedule summaries when granted
without mandatory account creation.
10.2 Guest invitation token model
A guest token must be scoped to:
- occasion
- target actor or invitation unit
- allowed event subset where applicable
- allowed module/resource families where necessary
- expiration policy
The token may reference:
- one actor
- a household/group invitation unit
- multiple event invitations under one occasion
Recommended representation:
- opaque invite token for delivery
- server-side token record storing scope and lifecycle
Optional implementation:
- exchange opaque token for short-lived signed guest session token after first use
10.3 What a guest can do before claim
Before claim, a guest may:
- access the occasion guest portal for their token scope
- view invited events and relevant content
- submit RSVP and forms for their allowed invitation scope
- access QR-linked experiences bound to their token scope
- revisit on the same device while the guest session remains active
Before claim, a guest may not:
- broaden access beyond the token scope
- discover unrelated events or actors
- access planner or vendor-only surfaces
- merge identities across occasions automatically
10.4 Optional guest account claim
Claim is optional and exists to improve continuity, not to gate basic access.
Claim flow:
- guest authenticates through Keycloak
- Tov+ creates or resolves the Tov+ user
- Tov+ verifies claim entitlement using the current valid guest token or equivalent proof
- guest actor is linked to the user
- future access can use
user_principalwith claimed guest actor context
10.5 Persistence across devices or browsers
Without claim:
- access persists only while the guest session or invite token remains valid
- new browser/device generally requires re-opening the invite link or QR flow
With claim:
- access persists across devices through user login because the actor link is stored in Tov+
10.6 Multiple occasions for one guest
If one real person is invited to multiple occasions:
- each occasion still has its own actor record unless later merged by a higher-level identity design
- claim may link the same user to multiple guest actors across occasions
- access remains occasion-scoped and never crosses automatically between occasions
10.7 Guest actor and RSVP unit relationship
Guest access must distinguish:
- actor identity
- invitation unit or RSVP response unit
Rules:
- actor represents the person/household/entity in the occasion
- RSVP unit may be an individual actor, household actor, or invitation group
- token scope may allow one guest principal to act for the RSVP unit it was issued for
- that permission does not imply global edit rights over every linked actor record
10.8 Guest QR access
QR access is a delivery mechanism for guest tokens, not a separate authorization model.
Rules:
- QR tokens inherit the same scoping and expiration rules as invite tokens
- high-risk QR actions should prefer short-lived or one-time exchange tokens
- printable QR content must not reveal private data if scanned by an unintended party
11. Vendor access model
11.1 Core rule
Vendors use authenticated user access, not guest-style token access, for ongoing operational work.
Vendor access is:
- invited
- actor-linked
- occasion- and event-scoped
- module- and resource-limited
11.2 Vendor invitation flow
Recommended flow:
- planner or admin creates vendor actor or vendor organization actor plus contact linkage
- Tov+ issues vendor invite
- vendor accepts invite through authenticated login or signup via Keycloak
- Tov+ creates/resolves user and links appropriate vendor actor
- vendor gains access only to granted occasion/event/module/resource scopes
11.3 Vendor actor linking
Possible patterns:
- individual vendor contact linked to person actor
- multiple users linked to a vendor organization/team actor with internal membership semantics
Rules:
- vendor actor must exist inside the occasion actor graph
- vendor permissions are attached to vendor actor scope, not to a generic global vendor role
11.4 Vendor-specific restrictions
Vendor restrictions should typically include:
- access only to assigned events
- access only to relevant modules
- access only to necessary guest data subsets
- no access to unrelated planner notes or modules
Examples:
- caterer can view meal counts and dietary constraints for assigned event
- venue manager can view seating layout outputs but not private guest notes
- photographer can upload/view gallery items for assigned events only
11.5 Vendor login vs guest login
Vendor login differs from guest login in these ways:
- vendor uses authenticated
user_principal - vendor access is intended to persist across sessions and devices
- vendor access depends on explicit actor links and grants, not invite-token-only scope
- vendor flows may still begin with an invite, but the invite culminates in durable authenticated access
12. Integration access model
12.1 Integration identity
An integration is a first-class principal with its own local Tov+ record.
Integration records should own:
- integration identifier
- display name
- credential references
- allowed scopes
- allowed endpoints/actions
- status
- audit metadata
12.2 Credential model
Recommended first-phase model:
- key identifier
- secret value
- optional derived short-lived access token
Requirements:
- rotation support
- revocation support
- hashed or encrypted-at-rest credential material
- least-privilege scope assignment
12.3 Scope model
Integration scopes may be granted at:
- platform level for infrastructure integrations only
- occasion level
- event level
- module level
- resource family level
Rules:
- integrations do not inherit human planner/admin access
- integration scopes must be explicit and minimal
- integration-specific restrictions are evaluated by the same permissions core
12.4 Preventing bypass
Integrations are prevented from bypassing permissions by:
- separate principal type
- explicit scope records
- endpoint allowlists
- central authorization checks
- full audit logging
12.5 Integration auditability
Every integration request must record:
- integration id
- credential id or key id
- requested action
- resolved scope
- authorization decision
- outcome status
13. Security and privacy constraints
13.1 Wildcard guest portal privacy
Knowledge of {occasion_slug}.tov.plus alone must never expose private occasion data.
Allowed unauthenticated content is limited to:
- explicitly public marketing or teaser content
- explicitly public occasion content if the product later supports it
Private occasion data requires:
- valid guest token
- claimed guest user session with actor linkage
- other valid authorized principal type
13.2 Token scoping
All guest and integration tokens must be narrowly scoped.
Minimum scope dimensions:
- principal type
- occasion
- event subset if applicable
- actor or invitation unit where applicable
- allowed action or endpoint family
- expiration
13.3 Expiration and revocation
Requirements:
- guest invite/session tokens must expire
- integration credentials must be revocable and rotatable
- user access must respect suspension or link revocation immediately or near-immediately
- actor-link revocation must remove future access without deleting audit history
13.4 Tenant isolation
Tov+ is logically multi-tenant at the occasion level.
Rules:
- no principal may cross occasion boundaries without explicit link and grant resolution
- resource identifiers must always be evaluated inside an occasion context
- admin-only operations must remain distinguishable from occasion-scoped actions
13.5 Admin impersonation constraints
If impersonation is added later, it must be:
- explicitly initiated
- time-bounded
- visibly indicated
- fully audited
- restricted to authorized support/admin roles
Until then, impersonation is not part of the baseline model.
14. Audit requirements
The system must audit at least:
- login and logout events for authenticated users where available
- guest token issuance, exchange, use, expiration, and revocation
- actor claim and link creation/revocation
- integration credential issuance, rotation, revocation, and use
- authorization denials for sensitive operations
- admin-level access to support or security-sensitive surfaces
- system principal execution of privileged jobs
Audit records should include:
- principal type
- subject id
- linked actor or scope id where relevant
- occasion/event/module/resource context
- action
- decision
- timestamp
- request correlation identifier
15. Final summary
Tov+ separates authentication from authorization. Keycloak proves identity for authenticated humans, while Tov+ owns users, actor links, guest tokens, integrations, system principals, grants, and final authorization. User principals, guest principals, integration principals, and system principals all enter one central authorization flow that resolves subject, occasion scope, actor or token context, module state, and permissions. Guest access remains low-friction through scoped tokens and optional claim. Vendor access uses durable authenticated user sessions with strict actor- and event-scoped access. Integrations and workers are scoped principals, not trusted bypasses.