Workflow Architecture

Technical reference for NIVAA's shared workflow pattern. This page explains the contract used by active workflow domains, the file layout each module follows, and how routes, projections, notifications, and state transitions are expected to interact.

What counts as a workflow module

A workflow module owns a domain aggregate plus the rules that decide what may happen next. In NIVAA that means the module is responsible for aggregate loading, pure rule guards, explicit commands, read projections, and effect packaging. Route handlers should become thin adapters around these modules.

Shared Contract

LayerCanonical locationResponsibilityMust not do
Contract typesworkers_nivaa/src/lib/workflows/core/contracts.tsDefines actor/context/result/event/notification shapes shared across domains.Must not contain domain-specific branching.
Aggregate + repository<module>/aggregate.ts + <module>/repository.tsLoads the full domain state needed for one workflow decision.Must not mutate data during reads.
Guards<module>/guards.tsPure rule checks, state normalization, and precondition evaluation.Must not execute writes or notifications.
Commands<module>/commands.tsExplicit state transitions such as create/apply/approve/cancel/convert.Must not hide transitions behind route conditionals.
Projections<module>/projections.tsRead-model shaping for UI/API consumers.Must not perform hidden writes or expiry side effects.
Effects<module>/effects.tsBuilds workflow metadata, audit payloads, and notification event specs.Must not re-implement domain policy already owned by commands.
Schedulersession-workflow/scheduler.ts only where neededOwns timed sweeps such as expiry/reminder processing.Must not be replaced with write-on-read helpers.

Active Workflow Domains

WorkflowCode locationPrimary purposePrimary impacted routes / surfacesPrimary data touched
Session workflowworkers_nivaa/src/lib/workflows/session-workflow/Own appointment lifecycle, reschedule negotiation, check-in/out, parent approval/dispute, and expiry/reminders./appointments/*, /reschedule/*, tutor + parent session surfaces, check-in services, scheduler sweepsappointments, reschedule_requests, discrepancies, package ledgers, user notifications`
Tutor onboardingworkers_nivaa/src/lib/workflows/tutor-onboarding/Normalize tutor onboarding state and capability projection for workspace/postings access./intake/tutor, /admin/tutors/:id/onboarding, tutor layout, register/setup, Telegram tutor gatingusers, tutor_profiles
Family onboardingworkers_nivaa/src/lib/workflows/family-onboarding/Determine whether a parent/child set is ready for posting and what the next onboarding step is./profile/parent/me, /children/overview, /postings, parent/admin family surfacesusers, child_profiles, student_profiles
Posting workflowworkers_nivaa/src/lib/workflows/posting-workflow/Own posting creation, tutor applications, coordinator push, parent acceptance, and trial-match handoff./postings, coordinator posting views, parent posting viewspostings, posting_applications, student_profiles, matches
Trial workflowworkers_nivaa/src/lib/workflows/trial-workflow/Own trial date negotiation, invoice/payment progression, post-trial feedback, and conversion to regular sessions./trial/*, parent posting detail, tutor student flows, coordinator trial operationsmatches, trial_date_proposals, trial_invoices, trial_feedback, appointments
Notification dispatchworkers_nivaa/src/lib/notifications/Centralize inbox reads and typed notification event delivery from domain workflows./notifications, workspace shell, notification center, workflow effect dispatchuser_notifications plus telegram delivery side effects`

Execution Model

  1. 1 1. Route parses input: The HTTP route authenticates the request and parses payload/query inputs.
  2. 2 2. Aggregate loads once: The workflow repository loads the current domain state required for the operation.
  3. 3 3. Guards evaluate preconditions: The command checks access and lifecycle preconditions using pure guard functions.
  4. 4 4. Command performs the mutation: The command writes the authoritative state transition and returns a workflow result.
  5. 5 5. Effects package fanout: Audit metadata and notification event payloads are created from the workflow result.
  6. 6 6. Projections feed the UI: Read-only projections shape aggregate state into button/next-step/status payloads for web and Telegram consumers.

Non-Negotiable Rules

  • Reads must stay read-only. The session workflow already moved expiry/reminders out of projection helpers and into the scheduler.
  • One domain should have one place that decides whether a transition is valid. Routes should not duplicate domain policy.
  • Impersonation, role adaptation, and transport quirks belong at the route/auth layer, not inside workflow guards.
  • Notification fanout should emit from workflow effects or shared notification helpers, not from route-local ad hoc writes.
  • If a domain is still route-owned, document it as route-owned rather than pretending it is fully workflowized.