Behind the build

Care Partners at Home

A multi-tenant operating platform for a home-care agency: operator, caregiver, and family, over one auditable workflow.

Pre-launch

Tailored product work, designed multi-tenant from the start.

  • Next.js
  • PostgreSQL · RLS
  • State machines
  • Append-only audit
  • SMS-first comms
  • AI workflows

Care Partners at Home presented a very different engineering problem from a typical business website.

A home-care agency does not simply need pages describing its services.

Behind those pages is an operating system of families asking for help, caregivers applying and working shifts, coordinators making matches, incidents being reported, consent being recorded, schedules changing, payroll moving, families asking questions, and sensitive decisions that may need to be reconstructed months later.

I built the system around that reality.

This is tailored product work for Care Partners at Home. The platform is currently in its final pre-launch stage and is projected to be online very soon.

Although the first deployment is tailored around the agency’s own operation, I designed the underlying system as multi-tenant software from the beginning so the architecture is not tied permanently to one agency.

Architecture at a Glance

                         Care Partners OS

                         Next.js Platform

          ┌────────────────────┼────────────────────┐
          │                    │                    │
          ▼                    ▼                    ▼
   Operator Console      Caregiver PWA        Family Portal
          │                    │                    │
          └────────────────────┼────────────────────┘

                         Service Layer

          ┌────────────────────┼────────────────────┐
          │                    │                    │
          ▼                    ▼                    ▼
     State Machines       Communications          AI
     + Audit Trail          + Consent          Workflows
          │                    │                    │
          └────────────────────┼────────────────────┘

                         PostgreSQL

                    Tenant-scoped RLS

The important part of this diagram is not Next.js.

It is that the operator, caregiver, and family are not treated as three views of the same screen.

They are three different participants in the same care operation, with different responsibilities, permissions, and expectations.


Case Study 1: One Business Process, Three Completely Different Users

The problem

Home care is collaborative, but it is not symmetrical.

An operator may need to review a care request, evaluate caregiver matches, resolve an incident, inspect an audit trail, or manage a schedule.

A caregiver needs something much simpler:

What am I doing today?

They may also need to report an incident, review a shift, request a pay adjustment, resign, submit a referral, or update something about themselves.

The family has another perspective entirely.

They care about schedules, care notes, invoices, concerns, caregiver teams, photos, authorized representatives, lifecycle changes, and what has happened over time.

Putting all of those users into one generic authenticated application would make the system easier to code initially.

It would make the product harder to use and harder to secure.

The decision

I separated the application around the people actually using it.

Operator

/dashboard
/care-requests
/matches
/schedule
/incidents
/moderation
/payroll
/audit
...

Caregiver

/c/today
/c/schedule
/c/incidents
/c/pay-raise
/c/resignation
/c/profile
...

Family

/f/dashboard
/f/schedule
/f/care-notes
/f/invoices
/f/concerns
/f/caregiver-team
/f/timeline
...

These are not separate products with duplicated business logic.

They meet at a shared service layer.

That allows the same event to appear differently depending on who is looking at it.

Consider an incident.

Caregiver reports concern


     Incident pipeline

     ┌────┴─────┐
     ▼          ▼
Operator      Family
queue         visibility


resolution


audit history

The workflow remains one business process.

The doors into it are different.

State, not buttons

I also avoided letting interface buttons define business rules.

Important workflows are represented as explicit state machines.

A transition is legal because the domain allows it, not because somebody happened to render a button that performs an update.

current state


allowed-transition check

     ├── allowed → update + audit

     └── denied  → no mutation

That matters for workflows such as caregiver screening, matching, care requests, incidents, resignations, family lifecycle changes, and other operations where jumping directly from one database status to another could bypass a real-world control.

The outcome

The product now supports three coherent experiences while preserving one underlying business model.

The operator gets an operational console.

The caregiver gets a mobile-first work surface.

The family gets a quieter portal focused on visibility and participation in care.

And all three remain connected to the same auditable workflow rather than becoming independent islands of application state.

That distinction is what turned the project from a website into an operating platform.


Case Study 2: Designing for Trust When the Data Represents Real People

The problem

Multi-tenancy is easy to describe:

Every agency sees only its own data.

The difficult part is proving that a forgotten WHERE tenant_id = ... cannot quietly violate that promise.

For a system containing caregiver information, family information, care records, incidents, schedules, communications, and operational histories, I did not want tenant isolation to depend entirely on every future developer remembering to write the correct query.

The decision

Tenant isolation is enforced at two levels.

Every business table carries a tenant identifier.

Every normal service operation runs inside an explicit tenant scope.

PostgreSQL Row Level Security independently enforces that same tenant boundary.

Authenticated user


Application permission


withTenantScope(...)


tenant-scoped transaction


PostgreSQL RLS


business data

The database therefore participates in authorization rather than merely storing the result of authorization decisions made elsewhere.

A query that accidentally omits its tenant filter does not automatically become a cross-customer data leak.

Audit as business evidence

I treated audit history similarly.

Important business mutations write an audit entry.

For records where history matters, deletion is deliberately restricted.

A caregiver leaving the organization, a family ending service, a consent being withdrawn, or an incident reaching resolution should not make the prior state disappear.

The architecture therefore favors:

state transition
       +
append-only evidence

over destructive updates that erase the path the business took.

That audit history is useful beyond compliance.

The family timeline can reconstruct meaningful activity from the same evidence rather than requiring another parallel history system.

Consent documents receive another protection.

Published consent versions are immutable.

When someone accepts a consent document, the system records a cryptographic hash of the version they actually accepted.

Consent document


immutable version


SHA-256 body hash


acceptance ledger

If the wording later changes, that becomes a new version.

The old acceptance does not magically become consent to the new wording.

That sounds obvious when stated in English.

It is surprisingly easy to get wrong in software if a consent document is just another editable database row.

The outcome

Trust-sensitive rules are not scattered across page components.

Tenant isolation lives at the application and database layers.

State changes produce durable evidence.

Consent is versioned and tamper-anchored.

Permissions are role-based and rechecked server-side.

The system therefore has multiple independent controls protecting the same boundaries instead of assuming one perfect layer will never make a mistake.


Where AI Fits

Care Partners uses AI, but I drew a firm boundary around what AI is allowed to become.

There are workflows where a model is genuinely useful:

family intake
      → structured summary

caregiver SMS interview
      → conversational screening

caregiver pool
      → match ranking

incident text
      → classification / summary

submitted content
      → moderation

family concern
      → writing assistance

But the model is not the system of record.

Every AI invocation passes through one service boundary and is associated with a real business entity.

Token usage and invocation identity are recorded.

More importantly, failure behavior depends on the risk of the workflow.

For content moderation, an AI failure does not mean:

Probably fine. Publish it.

It means:

AI unavailable

hold for review

For a family writing-assistance feature, the opposite behavior is appropriate.

If the rewrite model fails, the family member’s original words survive and the submission continues.

AI rewrite unavailable

use author's original text

continue

Same technology.

Different risk.

Different failure policy.

That distinction matters much more to me than simply saying the platform “uses AI.”


Communications Are Part of the Domain

Home-care communication is another place where I avoided allowing individual pages to send messages however they wanted.

Outbound communication passes through one communications fabric.

Business event


communication service

      ├── verify consent
      ├── select template version
      ├── choose tenant/provider configuration
      ├── deliver SMS or email
      ├── record message
      └── write audit event

This means consent enforcement is not something every feature author has to remember independently.

The same boundary can eventually support different provider credentials for different agencies while preserving one application-level communication contract.

For Care Partners at Home specifically, the customer journey is intentionally SMS-first rather than pretending the agency operates a traditional phone-answering center.

That product decision is enforced throughout the application rather than appearing only in marketing copy.


Building Around People, Not Around the Database

A great deal of the design discipline in this project came from resisting technically convenient shortcuts.

The family site does not invent testimonials or staff.

The product does not pretend automated responses are human responses.

Accessibility is part of the design baseline.

The caregiver experience starts on a phone-sized viewport.

Operator actions are permission-checked again on the server even if the UI has already hidden an unavailable control.

Missing vendor integrations degrade explicitly rather than being disguised as complete functionality.

And sensitive workflows leave evidence behind.

Those are product decisions, but they become architecture once software has to guarantee them.


Current Stage

The platform is currently in its final pre-launch stage.

Core operator, caregiver, and family workflows have been built and exercised end-to-end, including a broader scenario harness covering the major operating journeys.

A small number of external-service dependencies still require production configuration, including areas such as communications verification, payment/payroll connectivity, object storage, and production observability.

I prefer to describe that boundary precisely rather than calling an alpha system fully live before those dependencies are actually complete.

Care Partners at Home is projected to be online very soon.


Why I Built It This Way

The hard part of Care Partners at Home was never creating another dashboard.

It was deciding what the software must remember, what it must never expose, who has authority to change something, which changes require history, where AI can assist safely, and how three very different groups of people participate in the same care relationship.

That led to an architecture built around explicit boundaries:

tenant isolation
role authority
state transitions
audit evidence
immutable consent
communications governance
AI failure policy

I could have built the public website first and treated the rest as later back-office work.

Instead, I built the operational system underneath it.

Because in home care, the promise on the website ultimately matters only if the operation behind it can keep that promise.