Companies
Purpose
The tenancy boundary of the product. Every business-domain row (catalog, passes, wallet, payments) is scoped through one of three entities here:
- Company — the tenant.
- Company member — a platform user acting in a role inside the tenant (OWNER / ADMIN / MANAGER / COACH).
- Company customer — the join point between a platform user and per-company CRM data; the actor on bookings, wallet, and pass purchases.
Boundaries
- In: tenants, staff, customers, invitations, whitelabel apps.
- Out:
- SaaS subscription state of the tenant is in the Billing context (separate domain, separate lifecycle).
- Per-customer prepaid balance is in the Wallet context; the per-customer bonus-points balance (
bonusBalance) however lives here on Company customer (loyalty points are a CRM concept, not money).
Entities
| ID | Entity | Role in this context |
|---|---|---|
| ENT-016 | Company | The tenant — owns everything else |
| ENT-019 | Company member | Staff: OWNER / ADMIN / MANAGER / COACH |
| ENT-017 | Company customer | A person known to the company — online (linked user) or offline (name + phone/email) |
| ENT-018 | Company invitation | Pending invite to become a member |
| ENT-020 | Company whitelabel app | Per-tenant branding metadata exposed to client app |
Backend implementation
- Module:
libs/features/companies/ - Surface routing:
companies-client.module.ts,companies-admin.module.ts, plus invitation flows. - Drizzle schema:
libs/shared/data-access-db/src/lib/schema/companies.schema.ts(pgSchema('companies'))
Cross-context relationships
- This context owns
companies.{company, company_member, company_customer, company_invitation, company_whitelabel_app, company_subscription, subscription_payment}. The last two are physically here but logically belong to the Billing context. - This context is referenced by almost every other context — via
companyId(cross-schema, no FK, see ADR) and viacustomerId(FK in Booking, Customer pass, Wallet, etc.). - This context references Identity via
company_member.user_idandcompany_customer.user_id.
Open questions
- The OWNER uniqueness invariant is application-level only — see Company member.
- Some
companyIdcolumns in other contexts have no DB FK by design — see the ADR.