Skip to main content

Agency Manager Domain Model

Purpose

This is the planning-level domain model for the product.

It is not a final schema. It is the model that pages, capabilities, and backend boundaries should align to.

Core Entities

Agency

Represents the operating business using the product.

Owns:

  • agency identity and profile
  • billing configuration for the agency's own subscription to the SaaS later
  • staff membership context
  • default operating rules

Surface:

  • org
  • later platform

Agency User

Represents a staff user of the agency.

Owns:

  • org membership
  • base role
  • client access scope
  • optional user-specific capability overrides
  • profile and notification preferences

Surface:

  • org

Client Access Assignment

Represents the agency-side visibility relationship between an agency user and a client account.

Owns:

  • agency user reference
  • client account reference
  • assignment state
  • who granted access
  • timestamps

Surface:

  • org

Truth note:

The first model should stay simple:

  • the agency owner defaults to full business oversight across all client accounts
  • some agency users may have access to all clients
  • others may be assigned to specific clients only

Recommended persistence note:

  • base role should live with membership state
  • selected-client access should be modeled separately from role policy

Agency Role Policy

Represents the agency-owned permission policy for non-owner staff roles.

Owns:

  • default role templates used by the agency
  • capability toggles per role
  • delegation rules for staff invites, portal invites, billing visibility, and similar operational actions
  • update history

Surface:

  • org

Truth note:

The first practical model should be template-first, not blank-slate enterprise RBAC:

  • start from common roles
  • let the owner adjust what those roles can do
  • allow user-specific overrides only when needed

Recommended persistence note:

  • one organization-level policy record is the right first shape
  • owner is not just another editable role inside that policy

Agency Permission Override

Represents a sparse exception applied to one agency user's default role policy.

Owns:

  • agency user reference
  • explicitly allowed capabilities
  • explicitly denied capabilities
  • who changed the override
  • timestamps

Surface:

  • org

Truth note:

  • overrides should be exceptional, not the main permission model
  • if many users need overrides, the base role policy is wrong

Client Account

Represents a customer relationship managed by one agency.

Owns:

  • company or client identity
  • service relationship metadata
  • account status
  • primary contacts
  • billing identity and defaults used to provision/sync the Stripe customer
  • internal billing mapping link
  • project portfolio link

Surface:

  • org
  • summarized into portal

Portal User

Represents an org-scoped portal identity for one external person inside one agency tenant.

Owns:

  • login/access to the client portal realm for that agency organization
  • the durable external identity bound to the auth account

Does not directly own:

  • company-specific role
  • company-specific permission scope

Those belong to company access grants.

Portal Access Grant

Represents one company-specific access grant linking a portal identity to one client account and one client-local person record.

Owns:

  • company-specific role
  • company-specific status
  • company-specific permission scope
  • the link between portalUser, clientAccount, and clientContact

Surface:

  • portal

Engagement

Represents the commercial relationship or service package between agency and client.

Examples:

  • monthly retainer
  • website redesign engagement
  • SEO engagement
  • support plan

Owns:

  • commercial model
  • service start and end dates
  • budget or retainer context
  • linked projects
  • optional context for subscriptions or recurring service relationships

Surface:

  • org
  • summarized into portal

Project

Represents a tracked delivery unit under a client account or engagement.

Owns:

  • title and scope
  • status
  • owners
  • dates
  • milestone and deliverable relationships
  • client-visible summary

Surface:

  • org
  • summarized into portal

Project Update

Represents a client-visible progress update, not internal scratch capture.

Owns:

  • message or summary
  • visibility flag
  • timestamps
  • optional links to deliverables

Surface:

  • authored in org
  • consumed in portal

Note

Represents internal working memory that may be personal or linked to a client or project.

Owns:

  • internal capture
  • author-private visibility in the first slice
  • optional client-account link
  • optional project link
  • pin and archive state

Surface:

  • authored in org
  • not projected into portal

Time Entry

Represents work logged by agency staff.

Owns:

  • staff owner
  • client account reference
  • optional project reference
  • duration
  • date
  • billable state
  • notes

Surface:

  • org

Billing Profile

Represents the internal app-owned Stripe mapping for a client account.

Owns:

  • Stripe customer linkage
  • sync/health context around that linkage
  • account-level billing anchor for invoices and subscriptions

Surface:

  • internal backend layer
  • summarized into org and portal through the client account and billing surfaces

Truth note:

This is not the finance ledger, and it is not meant to be a primary user-facing route. It is the internal app context around Stripe truth.

Invoice Record

Represents mirrored invoice state needed for app workflows.

Owns:

  • invoice identifiers
  • amount summary
  • status summary
  • due date
  • payment outcome summary
  • optional engagement or project context when relevant, without requiring it

Surface:

  • org
  • portal

Truth note:

Invoice records should mirror Stripe state instead of competing with it.

Subscription Record

Represents mirrored recurring billing state needed for app workflows.

Owns:

  • subscription identifiers
  • status summary
  • billing period summary
  • service label or retainer label
  • optional engagement or project context when relevant, without requiring it

Surface:

  • org
  • portal

Truth note:

Subscription records should be anchored to the client account first. Project or engagement linkage is optional context, not a required billing dependency.

Document

Represents a shared file or managed artifact.

Owns:

  • storage reference
  • display metadata
  • client account or project relationship
  • visibility scope
  • uploader
  • source side (agency or client)
  • timestamps

Surface:

  • authored in org
  • consumed in portal

File Request

Represents a lightweight request from the agency asking the client for a specific file or material.

Owns:

  • client account reference
  • optional project reference
  • request title or instruction
  • requested by
  • requested from
  • status
  • due date when relevant
  • submitted file linkage when fulfilled

Surface:

  • authored in org
  • fulfilled and viewed in portal

Truth note:

File requests should structure collaboration, not replace the shared drive. Normal uploads should still be possible without creating a formal request every time.

Notification

Represents app-visible or email-visible notices relevant to users.

Owns:

  • audience
  • kind
  • severity
  • call to action
  • delivery state

Surface:

  • org
  • portal
  • later platform

Activity Event

Represents a timeline event for significant account, project, billing, or document actions.

Owns:

  • actor
  • timestamp
  • event kind
  • related entity reference
  • summary

Surface:

  • primarily org
  • selectively exposed to portal

Relationship Direction

  • one Agency has many Agency Users
  • one Agency has many Client Accounts
  • one Client Account has many Client Users
  • one Client Account has one or more Engagements
  • one Client Account has one or more Projects
  • one Project can belong to one Engagement
  • one Project has many Project Updates
  • one Agency User can create many Time Entries
  • one Client Account has one internal Billing Profile
  • one Client Account has many Invoice Records
  • one Client Account has many Subscription Records
  • one Client Account has many Documents
  • one Client Account has many File Requests
  • one Project can have many Documents
  • one Project can have many File Requests
  • many entities can emit Notifications and Activity Events

Boundary Rules

Keep client identity separate from agency identity

Portal users are not just weaker org users.

Keep billing truth separate from project truth

Do not drive invoice state from project status fields.

Keep high-churn records separate from account profiles

Time entries, notifications, and activity events should stay in their own records rather than bloating client or project documents.

Keep client-visible summaries separate from internal-only notes

The same underlying relationship can have both internal and client-visible views, but those should not be the same field or the same document responsibility.

Later Optional Entities

These can exist later if the product proves the need:

  • Approval
  • Task
  • SupportThread
  • Proposal
  • AutomationRule
  • Template

Do not start with them unless a real workflow forces the need.