C4 Architecture Model
Sanmopia architecture is documented with C4 zoom levels. C4 is the shared map; DDD, feature slices, CQRS, Supabase, Restate, SpiceDB, OPA, and OSS services are placed inside the right zoom level.
Actor names are long-term role contracts:
HeadOfficeManager, BranchOwner, Mother/FamilySponsor, and CareManager.
Source archive names, screen names, and table names belong in migration evidence
or adapter provenance only; they do not name target architecture components.
Migration docs may use the shorter actor labels HeadquartersOperator,
BranchOperator, FamilyPayer, Mother, and Caregiver when describing
legacy parity. They map to the target contracts above and should not introduce
new authorization roles.
Required Actor Coverage
Section titled “Required Actor Coverage”Every feature-level C4 or DDD note that changes command/query behavior must state which of these actor contracts can call it, read it, approve it, or only receive notifications.
| Required actor | Target contract | Primary DDD owners | Coverage rule |
|---|---|---|---|
| Mother | Mother/FamilySponsor | reservation_operations, pricing_settlement, document_reporting, customer_engagement | Owns booking, mother-visible charge/payment, service confirmations, documents, and reviews. |
| FamilyPayer | Mother/FamilySponsor plus explicit family/delegated payer grant | member_management, pricing_settlement, customer_engagement | Cannot be inferred from emergency contact or family relation text. Payment authority needs a backend grant/fact. |
| Caregiver | CareManager | caregiver_assignment, care_delivery, pricing_settlement, caregiver_management | Reads assignments, records service delivery, submits reports, acknowledges payout/service-balance facts. |
| BranchOperator | BranchOwner | branch_operations, reservation_operations, caregiver_assignment, pricing_settlement | Runs branch-scoped reservation, matching, local settlement, document, and repair commands. |
| HeadquartersOperator | HeadOfficeManager | pricing_settlement, business_reporting, branch_operations, operator_access | Owns cross-branch policy, reporting, exports, repair, and headquarters settlement workflows. |
| Settlement approver | HeadOfficeManager with settlement approval capability | pricing_settlement, business_reporting, operator_access | Approves headquarters settlement and arrears/deposit decisions. It is a capability, not a separate login role. |
C4Context
title Sanmopia Modernization - Required Actor Coverage
Person(mother, "Mother", "Reservation beneficiary and customer-facing service actor.")
Person(familyPayer, "FamilyPayer", "Delegated payer with explicit payment authority grant.")
Person(caregiver, "Caregiver", "Assigned care worker and service-report actor.")
Person(branchManager, "BranchOperator", "Branch-scoped operations and local settlement actor.")
Person(headquartersAdmin, "HeadquartersOperator", "Cross-branch policy, reporting, repair, and settlement actor.")
Person(settlementApprover, "Settlement approver", "HQ settlement approval capability holder.")
System_Boundary(sanmopia, "Sanmopia Modernization") {
System(reservationOps, "Reservation Operations", "Booking, collaboration, service calendar, command policy, lifecycle follow-up.")
System(caregiverAssignment, "Caregiver Assignment", "Matching policy, candidate snapshots, optimizer inputs, assignment decisions.")
System(careDelivery, "Care Delivery", "Attendance, service records, daily reports, customer confirmations.")
System(pricingSettlement, "Pricing Settlement", "Charges, payments, refunds, payment change, compensation, branch/HQ settlement.")
System(memberManagement, "Member Management", "Family account authority, Supabase identity, privacy lifecycle.")
System(documentReporting, "Document Reporting", "Printable documents, export grants, signed handoffs.")
System(operatorAccess, "Operator Access", "Actor capability and settlement approval permission checks.")
}
Rel(mother, reservationOps, "Submits booking and service actions")
Rel(mother, pricingSettlement, "Pays and views frozen charge/payment facts")
Rel(mother, documentReporting, "Reads allowed documents")
Rel(familyPayer, memberManagement, "Uses explicit family payment grant")
Rel(familyPayer, pricingSettlement, "Pays delegated obligations")
Rel(caregiver, caregiverAssignment, "Receives assignment decisions")
Rel(caregiver, careDelivery, "Submits service facts")
Rel(caregiver, pricingSettlement, "Acknowledges payout/service-balance facts")
Rel(branchManager, reservationOps, "Runs branch reservation workspace")
Rel(branchManager, caregiverAssignment, "Runs matching and assignment commands")
Rel(branchManager, pricingSettlement, "Runs branch settlement commands")
Rel(headquartersAdmin, pricingSettlement, "Runs HQ settlement, repair, and payment oversight")
Rel(headquartersAdmin, documentReporting, "Requests cross-branch exports")
Rel(settlementApprover, operatorAccess, "Requires settlement approval capability")
Rel(settlementApprover, pricingSettlement, "Approves HQ settlement decisions")
UpdateLayoutConfig("4", "3")
- Level 1 Context: people and external systems only.
- Level 2 Container: executable units, not Docker containers.
- Level 3 Component: bounded contexts, feature groups, and platform adapters inside one executable unit.
- Level 4 Code: aggregate, value object, command, query, policy, and port relationships for one feature slice.
Mermaid C4 support is experimental in Mermaid 11, so diagrams must stay simple,
build-tested, and backed by prose when a feature is not supported.
Large diagrams are wrapped with @beoe/pan-zoom through the Starlight
PageFrame override so C4 maps can be panned and zoomed without exporting
manual image assets.
Level 1 Context
Section titled “Level 1 Context”C4Context
title Sanmopia Modernization - System Context
Person(motherFamilySponsor, "Mother/FamilySponsor", "Books care service, pays, reads documents, reviews care records, and acts for the family.")
Person(careManager, "CareManager", "Receives assignments, delivers care, submits reports, and receives compensation.")
Person(branchOwner, "BranchOwner", "Manages local reservations, matching, benefits, settlement, and documents.")
Person(headOfficeManager, "HeadOfficeManager", "Controls policy, branch settlement, compliance, reporting, and repair.")
System(sanmopia, "Sanmopia Modernization", "Modern reservation, payment, matching, settlement, document, and reporting platform.")
System_Ext(killbill, "Kill Bill", "Payment approval, pre-registration, cancel, refund, and webhook provider.")
System_Ext(externalSettlementTargets, "External Settlement Targets", "External settlement or export recipient when required by operation.")
System_Ext(cloudflare, "Cloudflare", "Pages and edge routing for public documentation and portals.")
Rel(motherFamilySponsor, sanmopia, "Uses family service portal")
Rel(careManager, sanmopia, "Uses care manager portal")
Rel(branchOwner, sanmopia, "Uses operations portal")
Rel(headOfficeManager, sanmopia, "Uses operations portal")
Rel(sanmopia, killbill, "Verifies and changes payments")
Rel(sanmopia, externalSettlementTargets, "Sends settlement/export artifacts")
Rel(cloudflare, sanmopia, "Protects and routes web entrypoints")
UpdateLayoutConfig("3", "2")
Level 2 Container
Section titled “Level 2 Container”Container means executable unit. It does not mean a Docker service name, even when the development stage runs the unit in Docker.
C4Container
title Sanmopia Modernization - Containers
Person(motherFamilySponsor, "Mother/FamilySponsor")
Person(careManager, "CareManager")
Person(branchOwner, "BranchOwner")
Person(headOfficeManager, "HeadOfficeManager")
System_Boundary(sanmopia, "Sanmopia Modernization") {
Container(familyServicePortal, "Family Service Portal", "Astro 7, DaisyUI, Nanostores", "Mother/FamilySponsor booking, payment, document, and review UX.")
Container(careManagerPortal, "CareManager Portal", "Astro 7, DaisyUI, Nanostores", "CareManager assignment, report, schedule, and compensation UX.")
Container(operatorPortal, "Operations Portal", "Astro 7, DaisyUI, Nanostores", "BranchOwner and HeadOfficeManager operations UX.")
Container(api, "Backend API", "Python, FastAPI, Pydantic", "Contracts, commands, queries, policy checks, and adapter orchestration.")
Container(workflow, "Workflow Engine", "Restate", "Durable reservation, payment, settlement, document, and privacy workflows.")
Container(queueWorker, "Queue Worker", "Python, Supabase Queues / pgmq", "Durable notification, document, export, repair, and reconciliation work.")
Container(otelCollector, "Observability Collector", "OpenTelemetry Collector", "OTLP traces, metrics, logs, and queue/load signals.")
ContainerDb(supabase, "Supabase Platform", "Self-hosted Supabase", "Postgres, Auth, Storage, Realtime, Cron, Queues, Vector, RLS.")
Container(authz, "Relationship Authorization", "SpiceDB", "Actor-stage relationship checks.")
Container(policy, "Policy Engine", "OPA", "Law, time-window, request-context, and business-policy gates.")
Container(cms, "Admin Authoring", "Strapi", "Versioned policies, document definitions, report forms, and content.")
Container(notification, "Notification Engine", "Novu", "Dispatch workflows, provider routing, inbox, and delivery status.")
Container(docs, "Architecture Docs", "Astro Starlight, Mermaid C4", "Shared architecture, contracts, platform, and migration evidence.")
}
System_Ext(killbill, "Kill Bill", "Payment provider")
System_Ext(cloudflare, "Cloudflare Pages", "Public docs and web delivery")
Rel(motherFamilySponsor, familyServicePortal, "Books, pays, downloads")
Rel(careManager, careManagerPortal, "Accepts work, submits reports")
Rel(branchOwner, operatorPortal, "Runs branch operations")
Rel(headOfficeManager, operatorPortal, "Runs head office operations")
Rel(familyServicePortal, api, "Generated contract client", "HTTPS")
Rel(careManagerPortal, api, "Generated contract client", "HTTPS")
Rel(operatorPortal, api, "Generated contract client", "HTTPS")
Rel(operatorPortal, supabase, "Private reservation Broadcast and Presence", "WebSocket")
Rel(api, supabase, "Reads/writes business ledgers, queue messages, and Storage artifacts")
Rel(api, workflow, "Starts durable workflows")
Rel(workflow, api, "Invokes registered workflow handlers")
Rel(api, queueWorker, "Shares application processors and queue contracts")
Rel(queueWorker, supabase, "Claims, archives, retries, and dead-letters queue messages")
Rel(queueWorker, workflow, "Starts or repairs long-running workflows")
Rel(api, otelCollector, "Emits OTLP")
Rel(queueWorker, otelCollector, "Emits worker and queue OTLP")
Rel(api, authz, "Checks ReBAC capabilities")
Rel(api, policy, "Evaluates policy decisions")
Rel(api, cms, "Reads authored business definitions")
Rel(api, notification, "Triggers dispatch workflows")
Rel(api, killbill, "Pre-registers, verifies, cancels, refunds")
Rel(cloudflare, familyServicePortal, "Routes protected entry")
Rel(cloudflare, careManagerPortal, "Routes protected entry")
Rel(cloudflare, operatorPortal, "Routes protected entry")
Rel(cloudflare, docs, "Routes public docs")
UpdateLayoutConfig("4", "2")
Booking To Settlement Flow
Section titled “Booking To Settlement Flow”Current closeout work keeps payment, service-balance, receipt, and settlement state in backend ledgers. Portals render filtered projections and issue explicit commands only.
C4Container
title Booking to Payment, Service Balance Closeout, Receipt, and Settlement
Person(mother, "Mother", "Books care, pays customer-facing obligations, and reads receipts.")
Person(caregiver, "Caregiver", "Confirms payout/service-balance receipt.")
Person(branchOperator, "Branch Operator", "Confirms service balance and branch settlement facts.")
Person(hqAdmin, "HQ Admin", "Reviews HQ settlement, export, and repair flows.")
System_Boundary(sanmopia, "Sanmopia Modernization") {
Container(portals, "Actor Portals", "Astro, generated contract clients", "Mother, caregiver, branch, and HQ command/query surfaces.")
Container(api, "Backend API", "FastAPI, DDD/CQRS", "Booking, payment, closeout, receipt, and settlement commands.")
Container(workflow, "Restate Workflows", "Restate", "Booking, payment, financial lifecycle, and settlement continuation orchestration.")
ContainerDb(supabase, "Supabase", "Postgres/Auth/RLS/RPC/Storage", "Business ledgers, read models, workflow rows, signed artifacts, and RPC transactions.")
Container(killbill, "Kill Bill", "Payment provider", "Approval, verification, cancellation, refund, and provider event evidence.")
}
Rel(mother, portals, "Submit booking and payment commands")
Rel(branchOperator, portals, "Confirm service balance and branch settlement")
Rel(caregiver, portals, "Acknowledge caregiver receipt")
Rel(hqAdmin, portals, "Review settlement and exports")
Rel(portals, api, "Generated HTTPS contracts with Supabase bearer")
Rel(api, workflow, "Starts booking, payment, and financial lifecycle workflows")
Rel(workflow, api, "Calls idempotent handlers")
Rel(api, killbill, "Pre-registers and verifies payment")
Rel(api, supabase, "Persists ledgers, projections, workflow rows, and artifacts")
Rel(workflow, supabase, "Reads/writes workflow progress")
Rel(supabase, portals, "Returns RLS-scoped read models and signed handoffs")
UpdateLayoutConfig("3", "2")
Level 3 Component
Section titled “Level 3 Component”Backend components are named by business ownership. Historical controller names, screens, status codes, and table names do not define components.
C4Component
title Backend API - Components
Container(api, "Backend API", "Python, FastAPI, Pydantic", "Sanmopia command/query API.")
ContainerDb(supabase, "Supabase Platform", "Postgres/Auth/Storage/RLS", "Business ledger and read models.")
Container(workflow, "Workflow Engine", "Restate", "Durable orchestration.")
Container(authz, "Relationship Authorization", "SpiceDB", "Actor-stage relationship graph.")
Container(policy, "Policy Engine", "OPA", "Policy-as-code.")
Container(cms, "Admin Authoring", "Strapi", "Versioned business definitions.")
Container(killbill, "Kill Bill", "Payment provider", "Gateway edge.")
Container_Boundary(apiBoundary, "Backend API") {
Component(contractApi, "Contract API", "FastAPI routers, Pydantic", "Generated-client safe request and response surfaces.")
Component(reservationOps, "Reservation Operations", "DDD bounded context", "Reservation application, service calendar, change, extension, cancellation, stop.")
Component(reservationStateFollowUp, "Reservation State Transition + Side Effects", "reservation_operations domain/application slices", "Versioned state decisions, lifecycle side-effect plans, operation plans, and cross-context follow-up actions.")
Component(reservationPromotionSideEffects, "Reservation Promotion Side Effects", "pricing_settlement application slice", "Auditable promotion entitlement reset and restore plans after cancellation or service stop.")
Component(caregiverAssignment, "Caregiver Assignment", "DDD bounded context", "Caregiver matching profiles, source-parity class eligibility policy, candidate snapshots, optimizer inputs, and assignment decisions.")
Component(reservationSaga, "Reservation Orchestration", "Application saga", "Booking and financial lifecycle workflows across contexts.")
Component(pricingSettlement, "Pricing Settlement", "DDD bounded context", "Price catalogs, charge snapshots, payment changes, settlement, payout, and office closeout.")
Component(careDelivery, "Care Delivery", "DDD bounded context", "Care records, daily reports, assistant caregiver slots, customer confirmations.")
Component(memberManagement, "Member Management", "DDD bounded context", "Signup, identity, withdrawal, masking, retention, purge.")
Component(branchOperations, "Branch Operations", "DDD bounded context", "Branch profile, revisioned service-area policy publication/decision, purpose-scoped settlement accounts, account snapshots, local policy, matching scope, operator authority.")
Component(businessReporting, "Business Reporting", "DDD bounded context", "Printable documents, exports, report snapshots, delivery artifacts.")
Component(platformAdapters, "Platform Adapters", "Supabase, Restate, SpiceDB, OPA, Kill Bill, Strapi, Novu", "Infrastructure translation only.")
}
Rel(contractApi, reservationOps, "Dispatches commands and queries")
Rel(contractApi, caregiverAssignment, "Dispatches matching policy and optimizer contracts")
Rel(contractApi, pricingSettlement, "Dispatches payment and settlement APIs")
Rel(contractApi, careDelivery, "Dispatches report APIs")
Rel(contractApi, memberManagement, "Dispatches member/privacy APIs")
Rel(reservationOps, reservationStateFollowUp, "Uses transition rules and operation plans")
Rel(reservationStateFollowUp, reservationPromotionSideEffects, "Emits promotion entitlement side-effect work")
Rel(reservationPromotionSideEffects, pricingSettlement, "Uses entitlement policies")
Rel(reservationSaga, reservationOps, "Coordinates lifecycle")
Rel(reservationSaga, pricingSettlement, "Coordinates charge, payment, settlement")
Rel(reservationSaga, careDelivery, "Coordinates service delivery facts")
Rel(reservationSaga, businessReporting, "Coordinates document/report outputs")
Rel(platformAdapters, supabase, "Persists ledgers, read models, and Storage artifacts")
Rel(platformAdapters, workflow, "Starts and serves workflows")
Rel(platformAdapters, authz, "Checks relationship permissions")
Rel(platformAdapters, policy, "Evaluates policies")
Rel(platformAdapters, cms, "Reads authored definitions")
Rel(platformAdapters, killbill, "Calls gateway APIs")
UpdateLayoutConfig("3", "2")
Actor Capability Layer
Section titled “Actor Capability Layer”This diagram shows actor-facing backend surfaces. UI labels and source evidence can change; these capability groups should remain stable.
C4Component
title Backend API - Actor Capability Layer
Person(headOfficeManager, "HeadOfficeManager", "Owns platform policy, audit, reporting, and final settlement authority.")
Person(branchOwner, "BranchOwner", "Owns branch operations, service capacity, local settlement, and care-team decisions.")
Person(motherFamilySponsor, "Mother/FamilySponsor", "Owns family booking, payment, documents, confirmations, and reviews.")
Person(careManager, "CareManager", "Owns care delivery, service records, availability, credentials, and payout acknowledgement.")
Container(api, "Backend API", "Python, FastAPI, Pydantic", "Actor-scoped command/query API.")
ContainerDb(supabase, "Supabase Platform", "Postgres/Auth/Storage/RLS", "Actor projections, ledgers, and artifacts.")
Container(authz, "Relationship Authorization", "SpiceDB", "Actor-stage relationships.")
Container(policy, "Policy Engine", "OPA", "Actor-stage business policy.")
Container_Boundary(actorBoundary, "Actor Capability Layer") {
Component(actorCapabilities, "ActorStageCapabilityProjection", "CQRS read model", "Allowed commands, disabled reasons, field visibility, and audit context.")
Component(operatorFinancialLocks, "OperatorFinancialMutationLockPolicy", "reservation_operations policy/query", "Field-level locks for price version, service balance, payment date, and reservation status.")
Component(paymentProductCatalog, "PaymentProductPlanCatalog", "pricing_settlement CQRS query", "Product family, obligation, provider route, refund/conversion, settlement participation, settlement line templates, Novu workflow route keys, and virtual-account expiry.")
Component(paymentProviderRouteFee, "PaymentProviderRouteFeeSnapshot", "pricing_settlement domain snapshot", "Binds selected product plan, provider route, settlement targets, frozen customer-visible behavior, and method-fee quote at payment pre-registration.")
Component(reservationPaymentPreRegistration, "PreRegisterReservationPayment", "pricing_settlement command slice", "Loads one backend-owned waiting obligation, resolves authenticated payment authority, calls Kill Bill, and atomically links frozen evidence.")
Component(paymentActorSnapshot, "ReservationPaymentActorSnapshot", "pricing_settlement immutable snapshot", "Freezes actor, mother, branch, grant revision/scope/ceiling, payment product, amount, evidence, and authorization time.")
Component(customerChargePaymentSummary, "CustomerVisibleChargePaymentSummary", "pricing_settlement CQRS query", "Backend-owned customer charge/payment display lines, totals, payment state, receipt refs, and caller-total mismatch diagnostics.")
Component(serviceCalendarHolidayAudit, "ServiceCalendarHolidayAudit", "reservation_operations command/query slice", "Records holiday publication, branch override, duplicate-date policy decisions, and affected reservation follow-up previews from frozen service-calendar plans.")
Component(reservationOperationFollowUps, "ReservationOperationFollowUpWorkflow", "reservation_operations workflow slice", "Executes persisted follow-up actions for reservation commands without exposing source-era status ids.")
Component(reservationPromotionSideEffects, "ReservationPromotionSideEffectPlan", "pricing_settlement application slice", "Freezes promotion entitlement reset/restore commands and entitlement outbox rows for cancellation or service stop.")
Component(headOfficeOperations, "HeadOfficeManagerOperations", "Command/query slices", "Policy catalogs, settlement closeout, repair, exports, and reporting.")
Component(branchOperationsSurface, "BranchOwnerOperations", "Command/query slices", "Reservation workspace, care-team assignment, branch profile, purpose-scoped settlement accounts, snapshot handoff, local settlement, and retry state.")
Component(familyServiceSurface, "FamilyService", "Command/query slices", "Booking, payment, document access, service confirmations, partner benefits, and reviews.")
Component(familyAccountAuthority, "FamilyAccountAuthority", "member_management feature slice", "Resolves sponsor booking, delegated payment, and care-history visibility from backend-owned member profiles, family grants, and SpiceDB checks.")
Component(reservationCareHistoryAuthority, "ReservationCareHistoryAuthority", "member_management command/query slice", "Persists booking-scoped read grants and revocations through Supabase RPC plus the SpiceDB relationship outbox.")
Component(motherDailyReportReviewAuthority, "MotherDailyReportReviewAuthority", "care_delivery command guard", "Derives the booking mother and requires the separate mother-only SpiceDB mutation permission.")
Component(careManagerSurface, "CareManagerWork", "Command/query slices", "Assignments, attendance, care reports, credentials, availability, education, and payout acknowledgement.")
}
Rel(headOfficeManager, headOfficeOperations, "Runs head office commands")
Rel(branchOwner, branchOperationsSurface, "Runs branch commands")
Rel(motherFamilySponsor, familyServiceSurface, "Runs family commands")
Rel(careManager, careManagerSurface, "Runs care work commands")
Rel(familyServiceSurface, paymentProductCatalog, "Reads payment product plans")
Rel(familyServiceSurface, paymentProviderRouteFee, "Receives pre-registration fee snapshot")
Rel(familyServiceSurface, reservationPaymentPreRegistration, "Submits paymentId and idempotency key")
Rel(familyServiceSurface, customerChargePaymentSummary, "Reads backend-computed customer payable totals")
Rel(headOfficeOperations, paymentProductCatalog, "Reads operator billable plans")
Rel(headOfficeOperations, serviceCalendarHolidayAudit, "Publishes and revises service-calendar holiday policy")
Rel(branchOperationsSurface, serviceCalendarHolidayAudit, "Records branch closure overrides, withdrawal decisions, and local policy impact previews")
Rel(headOfficeOperations, reservationOperationFollowUps, "Starts operator follow-up actions")
Rel(branchOperationsSurface, reservationOperationFollowUps, "Starts branch follow-up actions")
Rel(reservationOperationFollowUps, reservationPromotionSideEffects, "Plans promotion entitlement actions")
Rel(paymentProviderRouteFee, paymentProductCatalog, "Uses selected product plan")
Rel(reservationPaymentPreRegistration, paymentProductCatalog, "Resolves backend product plan")
Rel(reservationPaymentPreRegistration, familyAccountAuthority, "Resolves exact delegated grant use")
Rel(reservationPaymentPreRegistration, paymentActorSnapshot, "Freezes authorized handoff facts")
Rel(reservationPaymentPreRegistration, authz, "Checks payment capability")
Rel(paymentActorSnapshot, supabase, "Persists immutable service-role evidence")
Rel(paymentProductCatalog, supabase, "Reads versioned active/effective catalog rows")
Rel(paymentProviderRouteFee, supabase, "Persists payment-record fee snapshot")
Rel(customerChargePaymentSummary, supabase, "Reads finalized charge snapshots and payment records")
Rel(serviceCalendarHolidayAudit, supabase, "Persists audit snapshots, reads active holiday policy versions, and reads impacted reservation candidates")
Rel(reservationPromotionSideEffects, supabase, "Persists plan snapshots and entitlement outbox rows")
Rel(serviceCalendarHolidayAudit, authz, "Checks headquarters or branch manage permission")
Rel(headOfficeOperations, actorCapabilities, "Requires capability decisions")
Rel(branchOperationsSurface, actorCapabilities, "Requires capability decisions")
Rel(headOfficeOperations, operatorFinancialLocks, "Previews reservation financial locks")
Rel(branchOperationsSurface, operatorFinancialLocks, "Previews reservation financial locks")
Rel(familyServiceSurface, actorCapabilities, "Requires capability decisions")
Rel(familyServiceSurface, familyAccountAuthority, "Requests family authority decisions")
Rel(familyServiceSurface, reservationCareHistoryAuthority, "Grants, queries, and revokes delegated read authority")
Rel(familyServiceSurface, motherDailyReportReviewAuthority, "Submits mother-only review and rating commands")
Rel(reservationCareHistoryAuthority, familyAccountAuthority, "Uses authenticated family membership and mother authority")
Rel(reservationCareHistoryAuthority, supabase, "Persists revisioned grants and relationship outbox work")
Rel(reservationCareHistoryAuthority, authz, "Checks booking-scoped care-history read permission")
Rel(motherDailyReportReviewAuthority, supabase, "Reads authoritative booking mother")
Rel(motherDailyReportReviewAuthority, authz, "Checks mother-only review mutation permission")
Rel(careManagerSurface, actorCapabilities, "Requires capability decisions")
Rel(actorCapabilities, authz, "Reads relationship facts")
Rel(actorCapabilities, policy, "Evaluates stage policy")
Rel(operatorFinancialLocks, actorCapabilities, "Uses stage capability decisions")
Rel(headOfficeOperations, supabase, "Writes ledgers and artifacts")
Rel(branchOperationsSurface, supabase, "Reads/writes branch-scoped projections")
Rel(familyServiceSurface, supabase, "Reads/writes family-scoped projections")
Rel(familyAccountAuthority, supabase, "Reads family account grants with RLS")
Rel(careManagerSurface, supabase, "Reads/writes care-manager projections")
Rel(api, actorCapabilities, "Serves actor-scoped projections")
UpdateLayoutConfig("4", "2")
Level 4 Code
Section titled “Level 4 Code”Level 4 is produced per feature slice. Keep it close to implementation and delete stale diagrams when the aggregate changes.
Reservation Operation Follow-Up and Promotion Side Effects
Section titled “Reservation Operation Follow-Up and Promotion Side Effects”classDiagram
direction LR
class ReservationOperationCommandHandler {
+handle()
}
class ReservationStateTransitionPolicy {
+decide()
}
class ReservationStateTransitionCatalog {
+effective_rules
}
class ReservationOperationPlan {
+reservation_id
+operation_command
+follow_up_actions
+state_transition_decision
}
class ReservationLifecycleSideEffectPlanPolicy {
+plan_for()
}
class ReservationLifecycleSideEffectPlan {
+reservation_id
+transition_id
+from_state
+to_state
+work_items
}
class ReservationLifecycleSideEffectWorkItem {
+kind
+target_context
+dispatch_mode
+idempotency_key
+required_revision
}
class ReservationOperationFollowUpWorkflow {
+run()
}
class PlanReservationPromotionSideEffectHandler {
+handle()
}
class PlanReservationPromotionSideEffectCommand {
+reservation_id
+side_effect_kind
+actor_kind
+actual_service_days
}
class ReservationPromotionSideEffectPlan {
+reservation_id
+side_effect_kind
+product_coupon_reset_plan
+reservation_coupon_restore_plan
+has_reservation_coupon_restores
}
class ProductCouponResetPolicy {
+plan_for()
}
class ReservationCouponRestorePolicy {
+plan_for()
}
class SupabaseReservationPromotionSideEffectPlanStore {
+save_reservation_promotion_side_effect_plan()
}
class ReservationPromotionSideEffectPlanStore {
<<port>>
+save_reservation_promotion_side_effect_plan()
}
class sanmopia_reservation_promotion_side_effect_plans {
<<Supabase table>>
+side_effect_plan_key
+reservation_id
+side_effect_kind
+plan_snapshot
+outbox_status
}
class sanmopia_promotion_entitlement_outbox_entries {
<<Supabase table>>
+side_effect_plan_key
+command_kind
+idempotency_key
+command_payload
+outbox_status
}
ReservationOperationCommandHandler ..> ReservationStateTransitionPolicy : asks before state write
ReservationStateTransitionPolicy ..> ReservationStateTransitionCatalog : selects effective rule
ReservationOperationCommandHandler ..> ReservationOperationPlan : records command outcome
ReservationOperationPlan ..> ReservationLifecycleSideEffectPlanPolicy : builds typed side-effect plan
ReservationLifecycleSideEffectPlanPolicy ..> ReservationLifecycleSideEffectPlan : returns persistable plan
ReservationLifecycleSideEffectPlan ..> ReservationLifecycleSideEffectWorkItem : contains durable work items
ReservationLifecycleSideEffectPlan ..> ReservationOperationFollowUpWorkflow : starts durable follow-up
ReservationOperationFollowUpWorkflow ..> PlanReservationPromotionSideEffectHandler : plans promotion actions
PlanReservationPromotionSideEffectHandler ..> ProductCouponResetPolicy : plans replacement entitlement
PlanReservationPromotionSideEffectHandler ..> ReservationCouponRestorePolicy : plans cancellation-only restore
PlanReservationPromotionSideEffectHandler ..> ReservationPromotionSideEffectPlan : returns persistable plan
PlanReservationPromotionSideEffectHandler ..> ReservationPromotionSideEffectPlanStore : saves plan
SupabaseReservationPromotionSideEffectPlanStore ..|> ReservationPromotionSideEffectPlanStore : implements persistence port
SupabaseReservationPromotionSideEffectPlanStore ..> sanmopia_reservation_promotion_side_effect_plans : upserts plan snapshot
SupabaseReservationPromotionSideEffectPlanStore ..> sanmopia_promotion_entitlement_outbox_entries : upserts idempotent commands
Source evidence for this boundary: reservation status changes and stop/cancel
branches in source-refs/sanmopia-admin/application/models/Reservation_model.php:1769-1916
and source-refs/sanmopia_web/application/models/Reservation_model.php:989-1112,
product entitlement reset evidence in
source-refs/sanmopia-admin/application/models/Coupon_model.php:63-157, and
used reservation entitlement restore evidence in
source-refs/sanmopia-admin/application/models/Coupon_model.php:935-958 plus
source-refs/sanmopia_web/application/models/Coupon_model.php:530-553. Target
component names stay ReservationStateTransitionPolicy,
ReservationLifecycleSideEffectPlan,
ReservationOperationFollowUpWorkflow, and
ReservationPromotionSideEffectPlan; source status numbers, table names, and
payment-provider vocabulary remain evidence or adapter data only.
classDiagram
direction LR
class OpenBranchSettlementBoardCommand {
+settlement_id
+branch_id
+settlement_date
+settlement_period_start
+settlement_period_end
}
class BranchSettlementCalculationQuery {
+branch_profile_id
+settlement_period_start
+settlement_period_end
}
class BranchSettlementCalculationSnapshot {
+branch_profile_id
+origin_evidence_lines
+branch_receivable_total_krw
+branch_payable_total_krw
+net_balance_krw
+to_opening_line_items()
}
class BranchSettlementCalculationEvidenceLine {
+line_kind
+direction
+amount_krw
+policy_version_label
+origin_financial_ledger_line_id
+origin_snapshot_kind
+origin_snapshot_id
+calculation_basis
+recognized_on
}
class PromotionalCouponCost {
+snapshot_id
+branch_profile_id
+promotional_coupon_cost
+recognized_on
}
class VoucherServiceCommissionCatalog {
+rate_versions
+commission_for()
}
class VoucherServiceCommission {
+eligible_reservation_count
+amount_krw
+policy_version
+as_branch_settlement_line_item()
}
class BranchSettlementDeliveryFeeCatalog {
+rate_versions
+fee_for()
}
class BranchSettlementDeliveryFee {
+delivery_required
+amount_krw
+policy_version
+as_branch_settlement_line_item()
}
class FrozenSettlementManualAdjustmentLine {
+catalog_version_key
+quantity
+unit_amount_krw
+line_direction
+lineage_reference_key
+total_amount_krw
+as_branch_settlement_line_item()
}
class BranchSettlementCommandHandler {
+open_board()
+confirm_branch_deposit()
+review()
}
class BranchSettlementBoard {
+settlement_id
+branch_id
+settlement_date
+status
+line_items
+net_balance_krw
}
class BranchSettlementOperatorDashboard {
<<query model>>
+settlement_count
+settlement_status_counts
+branch_receivable_total_krw
+branch_payable_total_krw
}
class BranchProfile {
+branch_profile_id
+origin_branch_reference
+is_active
+branch_settlement_participation
+can_participate_in_branch_settlement
}
class BranchSettlementStatusCounts {
+awaiting_branch_deposit
+awaiting_confirmation
+settled
+reconciliation
+arrears
}
class SupabaseBranchSettlementCalculationReader {
<<infrastructure adapter>>
+get_calculation_snapshot()
}
class SupabaseBranchSettlementOperatorBoardReader {
<<query adapter>>
+get_operator_board()
+get_operator_dashboard()
}
class SupabaseRow {
<<application platform helper>>
+required_text()
+optional_text()
+required_bool()
+required_non_negative_integer()
+required_date()
+required_datetime()
}
class SupabaseFinancialLedgerTables {
<<Supabase Postgres>>
+sanmopia_reservation_financial_lifecycles
+sanmopia_reservation_financial_ledger_lines
}
class SupabasePromotionalCouponCostSnapshots {
<<Supabase Postgres>>
+sanmopia_branch_promotional_coupon_cost_snapshots
}
OpenBranchSettlementBoardCommand ..> BranchSettlementCalculationQuery : builds read query
BranchSettlementCommandHandler ..> BranchSettlementCalculationSnapshot : freezes opening lines
BranchSettlementCalculationSnapshot "1" *-- "0..*" BranchSettlementCalculationEvidenceLine
BranchSettlementCalculationSnapshot ..> BranchSettlementBoard : creates evidence-linked lines
VoucherServiceCommissionCatalog ..> VoucherServiceCommission : selects effective rate
VoucherServiceCommission ..> BranchSettlementCalculationEvidenceLine : emits voucher line
BranchSettlementDeliveryFeeCatalog ..> BranchSettlementDeliveryFee : selects effective rate
BranchSettlementDeliveryFee ..> BranchSettlementCalculationEvidenceLine : emits delivery line
FrozenSettlementManualAdjustmentLine ..> BranchSettlementCalculationEvidenceLine : emits manual adjustment line
BranchSettlementOperatorDashboard "1" *-- "1" BranchSettlementStatusCounts
BranchSettlementOperatorDashboard ..> BranchSettlementBoard : counts domain statuses
SupabaseBranchSettlementOperatorBoardReader ..> BranchProfile : filters by settlement participation
SupabaseBranchSettlementOperatorBoardReader ..> BranchSettlementOperatorDashboard : builds query model
SupabaseBranchSettlementOperatorBoardReader ..> SupabaseRow : decodes Supabase rows
PromotionalCouponCost ..> BranchSettlementCalculationEvidenceLine : maps coupon cost evidence
SupabaseBranchSettlementCalculationReader ..> SupabaseFinancialLedgerTables : reads unsettled lifecycle lines
SupabaseBranchSettlementCalculationReader ..> SupabasePromotionalCouponCostSnapshots : reads PromotionalCouponCost snapshots
SupabasePromotionalCouponCostSnapshots ..> PromotionalCouponCost : rehydrates origin fact
SupabaseBranchSettlementCalculationReader ..> BranchSettlementCalculationSnapshot : maps read model
classDiagram
direction LR
class InterOfficeSettlement {
+inter_office_settlement_code
+reservation_id
+settlement_kind
+customer_relationship_branch_profile_id
+service_delivery_branch_profile_id
+frozen_charge_snapshot_id
+total_for(role)
+branch_settlement_line_items_for(branch_profile_id)
+total_allocated_amount_krw
}
class InterOfficeSettlementLookupKey {
+reservation_id
+customer_relationship_branch_profile_id
+service_delivery_branch_profile_id
+settlement_period_start
+settlement_period_end
+to_code()
}
class InterOfficeSettlementLine {
+line_kind
+beneficiary_role
+amount_krw
+policy_version_label
+payload
}
class InterOfficeSettlementFeeRule {
+fee_rate
+policy_version_label
+build_fee_line(charged_branch_profile_id)
}
class InterOfficeSettlementAcknowledgement {
+inter_office_settlement_code
+reservation_id
+acknowledgement_side
+acknowledging_branch_profile_id
+dataset_revision
+projected_settlement_line_keys
+metadata()
}
class BranchSettlementLineItem {
+kind
+direction
+amount_krw
+policy_version_label
}
class InterOfficeSettlementPayload {
+from_domain()
+to_domain()
}
class InterOfficeSettlementExport {
+columns
+rows
+total_row
+storage_bucket
}
class InterOfficeSettlementRepository {
<<application port>>
+get_by_code()
+get_by_lookup_key()
+save()
}
class SupabaseInterOfficeSettlementRepository {
<<infrastructure adapter>>
+get_by_code()
+get_by_lookup_key()
+save()
}
class SupabaseInterOfficeSettlementRpc {
<<PostgREST RPC>>
+sanmopia_save_inter_office_settlement()
}
class SupabaseInterOfficeSettlementTables {
<<Supabase Postgres>>
+sanmopia_inter_office_settlements
+sanmopia_inter_office_settlement_lines
}
InterOfficeSettlement "1" *-- "1" InterOfficeSettlementLookupKey
InterOfficeSettlement "1" *-- "1..*" InterOfficeSettlementLine
InterOfficeSettlementFeeRule ..> InterOfficeSettlementLine : builds fee line
InterOfficeSettlement ..> BranchSettlementLineItem : projects branch-facing share and fee
InterOfficeSettlementAcknowledgement ..> BranchSettlementLineItem : requires projected acknowledged lines
InterOfficeSettlementAcknowledgement ..> SettlementTransitionAudit : writes typed metadata
InterOfficeSettlementPayload ..> InterOfficeSettlement : maps contract
InterOfficeSettlementPayload ..> InterOfficeSettlementLookupKey : derives canonical code
InterOfficeSettlementExport ..> InterOfficeSettlementPayload : freezes reader output
SupabaseInterOfficeSettlementRepository ..|> InterOfficeSettlementRepository
SupabaseInterOfficeSettlementRepository ..> InterOfficeSettlement : rehydrates aggregate
SupabaseInterOfficeSettlementRepository ..> SupabaseInterOfficeSettlementRpc : writes aggregate
SupabaseInterOfficeSettlementRepository ..> SupabaseInterOfficeSettlementTables : reads canonical lookup
SupabaseInterOfficeSettlementRpc ..> SupabaseInterOfficeSettlementTables : upserts snapshot lines
classDiagram
direction LR
class SettlementDataRoomRequest {
+request_code
+collection scope
+status
+revision
+active_artifact()
+start_build()
+mark_ready()
+request_repair()
+issue_download_link()
}
class SettlementDataRoomScope {
+collection
+statement_kind
+settlement_period_start
+settlement_period_end
+branch_profile_id
+external_recipient_code
+origin_dataset_revision
}
class SettlementDataRoomArtifact {
+artifact_kind
+storage_bucket
+storage_object_key
+export_format
+content_sha256
+superseded_at
}
class SettlementDataRoomActionEntry {
+action_kind
+actor_kind
+idempotency_key
+expected_revision
+committed_revision
+artifact_id
}
class SettlementActorKind {
<<shared settlement vocabulary>>
+head_office_admin
+branch_director
+system_workflow
}
class SettlementDataRoomCommandHandler {
+open_export_request()
+start_build()
+mark_artifact_ready()
+request_repair()
+issue_download_link()
}
class SettlementDataRoomApi {
+open_export_request()
+get_request()
+start_build()
+mark_artifact_ready()
+request_repair()
+issue_download_handoff()
+require_actor_scope_permission()
}
class SettlementDataRoomDownloadHandoff {
+signed_url
+expires_at
+issued_action_id
+committed_revision
}
class SupabaseSettlementDataRoomRequestRepository {
+get_by_id()
+save()
}
class SupabaseTables {
+sanmopia_settlement_data_room_requests
+sanmopia_settlement_data_room_artifacts
+sanmopia_settlement_data_room_actions
}
SettlementDataRoomRequest "1" *-- "1" SettlementDataRoomScope
SettlementDataRoomRequest "1" *-- "0..*" SettlementDataRoomArtifact
SettlementDataRoomRequest "1" *-- "1..*" SettlementDataRoomActionEntry
SettlementDataRoomActionEntry ..> SettlementActorKind : records command actor
SettlementDataRoomDownloadHandoff ..> SettlementDataRoomArtifact : exposes signed URL only
SettlementDataRoomCommandHandler ..> SettlementDataRoomRequest : coordinates revisioned actions
SettlementDataRoomApi ..> SettlementDataRoomCommandHandler : actor scoped commands
SettlementDataRoomApi ..> SupabaseSpiceDB : branch settle permission
SettlementDataRoomApi ..> SupabaseStorage : signed URL handoff
SupabaseSettlementDataRoomRequestRepository ..> SupabaseTables : optimistic revision RPC
SettlementDataRoomCommandHandler ..> SupabaseSettlementDataRoomRequestRepository : persistence port
SettlementDataRoomArtifact ..> SupabaseStorage : business-report-exports
classDiagram
direction LR
class BranchOfficeProfileCommandHandler {
+handle_update_profile()
+handle_change_lifecycle()
+handle_replace_settlement_account()
+handle_snapshot_settlement_account_for_statement()
+handle_publish_membership_fee_policy()
+handle_rotate_operator_credential()
}
class BranchOfficeProfileApi {
+update_profile()
+change_lifecycle()
+replace_settlement_account()
+snapshot_settlement_account_for_statement()
}
class BranchOperationsContract {
+BRANCH_OFFICE_PROFILE_UPDATES_PATH
+branchOfficeProfileUpdatesPath()
+branchOfficeProfileUpdateRequestHeaders()
+BRANCH_OFFICE_LIFECYCLE_CHANGES_PATH
+branchOfficeLifecycleChangesPath()
+branchOfficeLifecycleChangeRequestHeaders()
+BRANCH_SETTLEMENT_ACCOUNT_REPLACEMENTS_PATH
+branchSettlementAccountReplacementsPath()
+branchSettlementAccountReplacementRequestHeaders()
+BRANCH_SETTLEMENT_ACCOUNT_STATEMENT_SNAPSHOTS_PATH
+branchSettlementAccountStatementSnapshotsPath()
+branchSettlementAccountStatementSnapshotRequestHeaders()
}
class BranchSettlementAccountSnapshotService {
+snapshot_for_statement()
}
class BranchOfficeProfileRepository {
<<port>>
+get_profile(branch_office_profile_id)
+save_profile(profile)
}
class BranchSettlementAccountSnapshotRepository {
<<port>>
+get_snapshot_by_idempotency_key(idempotency_key)
+save_snapshot(snapshot)
}
class SupabaseBranchOfficeProfileRepository {
+get_profile(branch_office_profile_id)
+save_profile(profile)
}
class SupabaseBranchSettlementAccountSnapshotRepository {
+get_snapshot_by_idempotency_key(idempotency_key)
+save_snapshot(snapshot)
}
class BranchOfficeProfileReadModel {
+current_revision
+lifecycle_state
+profile_revision
+settlement_accounts
+membership_fee_policies
+credential_rotations
}
class BranchSettlementAccountReadModel {
+purpose
+masked_account_reference
+verification_state
+effective_from
+revision_number
}
class BranchSettlementAccountSnapshotReadModel {
+settlement_statement_id
+settlement_account_revision
+snapshot_for_statement_at
+idempotency_key
}
class SupabaseBranchOfficeProfileTables {
<<Supabase Postgres>>
sanmopia_branch_office_profiles
sanmopia_branch_office_profile_revisions
sanmopia_branch_settlement_accounts
sanmopia_branch_membership_fee_policies
sanmopia_branch_operator_credential_rotations
}
class SupabaseSettlementRemittanceAccountSnapshots {
<<Supabase Postgres>>
sanmopia_settlement_remittance_account_snapshots
}
BranchOfficeProfileApi ..> BranchOfficeProfileCommandHandler : profile command
BranchOfficeProfileApi ..> BranchSettlementAccountSnapshotService : authenticated command
BranchOfficeProfileApi ..> SpiceDB : branch manage or settle permission
BranchOfficeProfileApi ..> BranchOperationsContract : OpenAPI and TS contract
BranchOfficeProfileCommandHandler ..> BranchOfficeProfileRepository : port
BranchSettlementAccountSnapshotService ..> BranchOfficeProfileCommandHandler : freezes account
BranchSettlementAccountSnapshotService ..> BranchSettlementAccountSnapshotRepository : idempotent persistence
SupabaseBranchOfficeProfileRepository ..|> BranchOfficeProfileRepository
SupabaseBranchOfficeProfileRepository ..> SupabaseBranchOfficeProfileTables : service-role Data API
SupabaseBranchSettlementAccountSnapshotRepository ..|> BranchSettlementAccountSnapshotRepository
SupabaseBranchSettlementAccountSnapshotRepository ..> SupabaseSettlementRemittanceAccountSnapshots : service-role Data API
BranchOfficeProfileCommandHandler ..> BranchOfficeProfileReadModel : commits revisions
BranchOfficeProfileReadModel "1" *-- "0..*" BranchSettlementAccountReadModel
BranchOfficeProfileCommandHandler ..> BranchSettlementAccountSnapshotReadModel : freezes verified account revision
classDiagram
direction LR
class ReservationServiceCalendarPolicyApi {
+decide_service_calendar_compatibility()
}
class ReservationServiceCalendarImpactApi {
+list_reservation_service_calendar_impact_facts()
}
class ServiceCalendarPolicy {
+plan_service_period()
+decide_historical_service_calendar_compatibility()
}
class ServiceCalendarCompatibilityDecision {
+decision_kind
+policy_fingerprint
+planned_service_end_on
+source_service_end_on
+reason_code
}
class ServiceCalendarContract {
+SERVICE_CALENDAR_COMPATIBILITY_DECISIONS_PATH
+RESERVATION_SERVICE_CALENDAR_IMPACTS_PATH
+serviceCalendarCompatibilityDecisionsPath()
+serviceCalendarCompatibilityDecisionRequestHeaders()
+reservationServiceCalendarImpactsPath()
+reservationServiceCalendarImpactRequestHeaders()
+findServiceCalendarCompatibilityDecisionRequestProblems()
+findReservationServiceCalendarImpactFactsProblems()
}
class SupabaseServiceCalendarImpactReader {
+list_reservation_service_calendar_impact_facts()
}
ReservationServiceCalendarPolicyApi ..> ServiceCalendarPolicy : branch-scoped decision
ReservationServiceCalendarPolicyApi ..> SpiceDB : branch view permission
ReservationServiceCalendarPolicyApi ..> ServiceCalendarContract : OpenAPI and TS contract
ReservationServiceCalendarImpactApi ..> SupabaseServiceCalendarImpactReader : persisted projection
ReservationServiceCalendarImpactApi ..> SpiceDB : reservation view permission
ReservationServiceCalendarImpactApi ..> ServiceCalendarContract : OpenAPI and TS contract
ServiceCalendarPolicy ..> ServiceCalendarCompatibilityDecision : names source drift
SupabaseServiceCalendarImpactReader ..> ServiceCalendarCompatibilityDecision : exposes stored decision
classDiagram
direction LR
class SettlementStatement {
+statement_code
+statement_kind
+branch_profile_id
+status
+revision
+message_to_branch
+head_office_private_memo
+line_acknowledgements
+acknowledge_branch_deposit()
+approve_head_office_settlement()
+request_arrears_deposit()
}
class SettlementRemittanceAccountSnapshot {
+bank_name
+account_holder
+account_number_display
+captured_at
+origin_reference_key
}
class SettlementTransitionAudit {
+command_kind
+actor_kind
+idempotency_key
+expected_revision
+committed_revision
+before_status
+after_status
}
class SettlementStatementLineAcknowledgement {
+settlement_line_key
+settlement_line_kind
+acknowledged_by_actor_profile_id
+acknowledged_at
}
class SettlementStatementCommandHandler {
+request_deposit()
+acknowledge_branch_deposit()
+approve_head_office_settlement()
+request_arrears_deposit()
}
SettlementStatement "1" *-- "1" SettlementRemittanceAccountSnapshot
SettlementStatement "1" *-- "1..*" SettlementTransitionAudit
SettlementStatement "1" *-- "0..*" SettlementStatementLineAcknowledgement
SettlementTransitionAudit ..> SettlementActorKind : records command actor
SettlementStatementCommandHandler ..> SettlementStatement : separates mixed board actions
SettlementStatement ..> BranchSettlementBoardStatus : reuses status vocabulary
SettlementStatementLineAcknowledgement ..> BranchSettlementLineItemKind : typed line kind
classDiagram
direction LR
class ReservationCollaborationCommand {
+reservation_id
+operation_command
+actor_kind
+expected_revision
+idempotency_key
+origin_workspace_reference
+mutation_kinds
+change_set
+navigation_intent
}
class ReservationCollaborationPolicy {
+decide(command, current_revision)
}
class ReservationCollaborationConflict {
+expected_revision
+current_revision
+conflicting_fields
+refresh_required
}
class ReservationCollaborationConflictLog {
+conflict_event_id
+workspace_id
+expected_revision
+current_revision
+conflicting_field_paths
+realtime_event_id
+resolution
}
class ReservationChangeJournalEntry {
+audit_event_id
+before_revision
+after_revision
+field_changes
+recorded_at
}
class ReservationRealtimeProjectionEvent {
+realtime_topic
+revision
+changed_field_paths
+audit_event_id
}
class ReservationWorkspaceCoordinationPolicy {
+realtime_event_name
+realtime_channel_mode
+stale_commit_policy
+dirty_navigation_policy
+audit_trail_mode
+presence_enabled
}
class ReservationWorkspaceDraftSession {
+workspace_id
+base_revision
+latest_known_revision
+status
+dirty_since
}
class ReservationWorkspaceEvent {
+event_kind
+workspace_id
+revision
+metadata
}
class ReservationCollaborationCommitPlan {
+next_revision
+audit_event
+realtime_event
}
class CommitReservationCollaborationHandler {
+commit(command)
}
class OpenReservationCollaborationWorkspaceHandler {
+open_workspace(query)
}
class ListReservationCollaborationJournalHandler {
+list_journal(query)
}
class RecordReservationWorkspaceEventHandler {
+record_event(command)
}
class ReservationCollaborationSnapshotReader {
<<application port>>
+get_current_snapshot()
}
class ReservationCollaborationJournalReader {
<<application port>>
+list_recent_entries()
}
class ReservationCollaborationCommitStore {
<<application port>>
+commit(plan)
}
class ReservationWorkspaceSessionStore {
<<application port>>
+record_session_event()
}
class ReservationCollaborationApi {
+POST /reservation-collaboration-workspaces/{reservationId}
+POST /reservation-collaboration-workspace-events/{reservationId}
+POST /reservation-collaboration-journal/{reservationId}
+POST /reservation-collaboration-commits/{reservationId}
}
class SupabaseReservationCollaborationSnapshotReader {
<<adapter>>
+get_current_snapshot()
}
class SupabaseReservationCollaborationCommitStore {
<<adapter>>
+commit(plan)
}
class SupabaseReservationCollaborationJournalReader {
<<adapter>>
+list_recent_entries()
}
class SupabaseReservationWorkspaceSessionStore {
<<adapter>>
+record_session_event()
}
class sanmopia_commit_reservation_collaboration {
<<Supabase RPC>>
+expected_revision
+idempotency_key
+branch_handoff.branch_profile_id
+service_schedule.start_on
+service_schedule.end_on
+service_schedule.extra_service_days
+caregiver_assignment.roster
+private Broadcast
}
class sanmopia_record_reservation_workspace_event {
<<Supabase RPC>>
+workspace_id
+session_status
+event_kind
+event_metadata
}
class sanmopia_reservation_bookings {
<<Supabase table>>
+reservation_id
+revision_number
+branch_profile_id
+service_start_at
+service_end_at
}
class sanmopia_reservation_extra_service_days {
<<Supabase table>>
+reservation_booking_id
+service_on
+day_kind
}
class sanmopia_reservation_caregiver_assignments {
<<Supabase table>>
+reservation_booking_id
+caregiver_role
+contract_assignment_key
+assigned_caregiver_user_id
+planned_service_days
}
class sanmopia_reservation_change_journal_entries {
<<Supabase table>>
+audit_event_id
+before_revision
+after_revision
}
class sanmopia_reservation_realtime_projection_events {
<<Supabase table>>
+realtime_topic
+broadcast_status
+realtime_payload
}
class sanmopia_reservation_workspace_sessions {
<<Supabase table>>
+workspace_id
+base_revision_number
+latest_known_revision_number
+session_status
+dirty_since
}
class sanmopia_reservation_workspace_events {
<<Supabase table>>
+event_kind
+workspace_id
+revision_number
+event_metadata
}
class realtime.messages {
<<Supabase Realtime>>
+broadcast
+presence
}
ReservationCollaborationPolicy ..> ReservationCollaborationCommand : validates
ReservationCollaborationPolicy ..> ReservationCollaborationConflict : returns stale write
ReservationCollaborationConflictLog ..> ReservationCollaborationConflict : records support evidence
ReservationCollaborationPolicy ..> ReservationCollaborationCommitPlan : returns accepted write
ReservationCollaborationCommitPlan *-- ReservationChangeJournalEntry
ReservationCollaborationCommitPlan *-- ReservationRealtimeProjectionEvent
ReservationRealtimeProjectionEvent ..> ReservationChangeJournalEntry : references audit_event_id
ReservationWorkspaceDraftSession *-- ReservationWorkspaceEvent : records UX events
OpenReservationCollaborationWorkspaceHandler ..> ReservationWorkspaceCoordinationPolicy : returns UX contract
OpenReservationCollaborationWorkspaceHandler ..> ReservationWorkspaceDraftSession : returns recoverable session
ReservationCollaborationApi ..> OpenReservationCollaborationWorkspaceHandler : opens current workspace
ReservationCollaborationApi ..> RecordReservationWorkspaceEventHandler : records browser UX event
ReservationCollaborationApi ..> ListReservationCollaborationJournalHandler : lists audit timeline
ReservationCollaborationApi ..> CommitReservationCollaborationHandler : dispatches command
CommitReservationCollaborationHandler ..> ReservationCollaborationSnapshotReader : reads current revision
CommitReservationCollaborationHandler ..> ReservationCollaborationPolicy : decides commit or conflict
CommitReservationCollaborationHandler ..> ReservationCollaborationCommitStore : stores accepted plan
OpenReservationCollaborationWorkspaceHandler ..> ReservationCollaborationSnapshotReader : reads current revision
OpenReservationCollaborationWorkspaceHandler ..> ReservationCollaborationJournalReader : reads latest audit event
OpenReservationCollaborationWorkspaceHandler ..> ReservationWorkspaceSessionStore : persists workspace_opened
ListReservationCollaborationJournalHandler ..> ReservationCollaborationJournalReader : reads recent audit entries
RecordReservationWorkspaceEventHandler ..> ReservationWorkspaceSessionStore : persists dirty/history events
ReservationCollaborationCommitStore ..> ReservationCollaborationCommitPlan : persists accepted write
SupabaseReservationCollaborationSnapshotReader ..|> ReservationCollaborationSnapshotReader
SupabaseReservationCollaborationCommitStore ..|> ReservationCollaborationCommitStore
SupabaseReservationCollaborationJournalReader ..|> ReservationCollaborationJournalReader
SupabaseReservationWorkspaceSessionStore ..|> ReservationWorkspaceSessionStore
SupabaseReservationCollaborationCommitStore ..> sanmopia_commit_reservation_collaboration : calls service-role RPC
SupabaseReservationCollaborationJournalReader ..> sanmopia_reservation_change_journal_entries : reads operator timeline
SupabaseReservationWorkspaceSessionStore ..> sanmopia_record_reservation_workspace_event : calls service-role RPC
sanmopia_commit_reservation_collaboration ..> sanmopia_reservation_bookings : bumps revision and applies branch handoff/service schedule
sanmopia_commit_reservation_collaboration ..> sanmopia_reservation_extra_service_days : replaces selected extra service days
sanmopia_commit_reservation_collaboration ..> sanmopia_reservation_caregiver_assignments : replaces caregiver roster
sanmopia_commit_reservation_collaboration ..> sanmopia_reservation_change_journal_entries : appends audit row
sanmopia_commit_reservation_collaboration ..> sanmopia_reservation_realtime_projection_events : stores Broadcast result
sanmopia_record_reservation_workspace_event ..> sanmopia_reservation_workspace_sessions : upserts recoverable session
sanmopia_record_reservation_workspace_event ..> sanmopia_reservation_workspace_events : appends UX event
realtime.messages ..> sanmopia_reservation_bookings : authorizes private reservation topics
Core Feature Flow
Section titled “Core Feature Flow”sequenceDiagram
autonumber
actor MotherFamilySponsor as Mother/FamilySponsor
actor FamilyPayer
actor CareManager
actor BranchOperator as BranchOperator/BranchOwner
actor HeadquartersOperator as HeadquartersOperator/HeadOfficeManager
participant Portal as Astro Portal
participant API as Backend API
participant Authz as SpiceDB + OPA
participant Supabase as Supabase Ledger
participant Queue as Supabase Queues / pgmq
participant Workflow as Restate
participant Payment as Kill Bill
participant Docs as Document Renderer
participant OTel as OpenTelemetry Collector
MotherFamilySponsor->>Portal: Submit reservation draft
Portal->>API: POST booking command
API->>Authz: Check stage capability and policy
API->>Supabase: Freeze booking context and accepted price quote
API->>Workflow: Start reservation booking workflow
Workflow->>API: Invoke booking handler
API->>Supabase: Write scheduled reservation, charge snapshot, waiting payment obligation
alt Delegated payment
MotherFamilySponsor->>API: Request FamilyPayer authority grant
API->>Supabase: Persist scoped grant, revision, interval, and amount ceiling
API->>Authz: Converge authorized payer relationship
end
MotherFamilySponsor->>Portal: Start payment
FamilyPayer->>Portal: Start delegated payment
Portal->>API: POST paymentId plus Idempotency-Key
API->>Supabase: Load backend-owned waiting obligation
API->>Authz: Resolve member, capability, and exact delegated grant use
API->>Payment: Pre-register payment amount
API->>Supabase: Atomically freeze fee and immutable payment actor snapshots
Payment-->>API: Webhook paid/cancelled/refund event
API->>Workflow: Start payment workflow with closeout kind and reservation status snapshot
Workflow->>API: Verify gateway state and finalize closeout
API->>Supabase: Write payment/refund ledger and settlement continuation facts
API->>CareManager: Publish assignment or report action through portal
CareManager->>Portal: Submit care report
Portal->>API: POST care report command
API->>Supabase: Store report submission and confirmation facts
API->>Docs: Render HTML/PDF document from template
Docs->>Supabase: Store private artifact and signed access facts
API->>Queue: Enqueue document, notification, export, or repair work with trace context
Queue->>API: Claim idempotent processor job
API->>OTel: Emit request, workflow, queue, and provider signals
API->>Workflow: Continue financial lifecycle workflow
Workflow->>API: Build payout, branch settlement, head office settlement
API->>Supabase: Freeze settlement statements and export read models
Payment-->>API: Partial refund result after settlement
API->>Supabase: Record provider refund result, paid-row transition, and reversal line
API->>Queue: Queue settlement, export, operator-board, and sales refresh targets
Queue->>API: Dispatch provider-refund reporting refresh
API->>Supabase: Refresh/validate read models and mark target outcome
HeadquartersOperator->>Portal: Request artifact repair after refund impact
Portal->>API: POST /settlement-data-room-workspaces/{code}/repair-requests
API->>Supabase: Supersede artifact, revoke active grants, record replacement request code
BranchOperator->>Portal: Edit reservation workspace
Portal->>API: POST reservation collaboration workspace open
API->>Authz: Check reservation view permission
API->>Supabase: Read current revision and latest journal entry
API-->>Portal: Return revision, realtime topic, coordination policy
Portal->>Supabase: Subscribe private reservation Broadcast topic
Portal->>Supabase: Track private reservation Presence
Portal->>API: POST reservation collaboration journal
API-->>Portal: Return operator-facing audit timeline
Portal->>API: POST reservation collaboration command
API->>Authz: Check command-stage permission
API->>Supabase: Compare expected revision and persist journal
alt Expected revision still current
API->>Supabase: Broadcast reservation projection invalidation
API-->>Portal: Return commit plan
else Revision changed after snapshot read
Supabase-->>API: RPC revision conflict
API->>Supabase: Re-read latest revision and fields
API-->>Portal: Return 409 conflict diff
end
HeadquartersOperator->>Portal: Request settlement deposit
Portal->>API: POST /settlement-deposit-requests
API->>Authz: Check settlement request capability
API->>Supabase: Save statement revision 1 and request audit
BranchOperator->>Portal: Acknowledge branch deposit lines
Portal->>API: POST /settlement-branch-deposit-acknowledgements
API->>Authz: Check branch settlement capability
API->>Supabase: Compare expected revision, save line acknowledgements, and revision 2
HeadquartersOperator->>Portal: Approve head office settlement
Portal->>API: POST /settlement-headquarters-settlement-approvals
API->>Authz: Check final settlement approval capability
API->>Supabase: Save approval audit, export workflow request, and settled or arrears status
API->>Workflow: Start or repair settlement export workflow
Workflow->>Queue: Publish delayed export/render work when needed
Zoom Map
Section titled “Zoom Map”| C4 level | Sanmopia documentation owner | Migration proof |
|---|---|---|
| Level 1 Context | architecture/c4-model | Actors and external systems named without historical screens. |
| Level 2 Container | architecture/c4-model, architecture/oss-service-stack, architecture/supabase-platform | Executable units and OSS boundaries use current package/runtime versions. |
| Level 3 Component | architecture/c4-model, architecture/bounded-context, architecture/feature-slice | Backend components match bounded contexts and Tach gates. |
| Level 4 Code | Feature docs and colocated tests | Aggregates, commands, queries, read models, ports, and contracts are verified by tests. |