Finance Module Backend
Related documentation: Backend Modules · Finance API · Data ownership · Access Matrix · Error Contract
Overview
Section titled “Overview”Backend-Kisum-Finance is the Finance domain backend for Kisum.
It owns finance-domain workflows such as:
- bills / expenses
- income / revenue
- vendor portal flows
- Xero accounting integration
- finance-linked files, notifications, and exchange-rate helpers
- Kisum compatibility reads for event-linked finance data
It does not own:
- user identity
- sessions / JWT issuance
- company memberships
- business-unit memberships
- company master data
- business-unit master data
- package / add-on / entitlement truth
Those ownership boundaries now matter in runtime, not only in architecture diagrams.
Ownership Model
Section titled “Ownership Model”Auth owns
Section titled “Auth owns”- users
- sessions
- company memberships
- business-unit memberships
- permission / scope resolution for the acting user
Finance consumes Auth context. It is not allowed to become the source of truth for those relations again.
Core owns
Section titled “Core owns”- company master data
- business-unit master data
- packages
- add-ons
- company subscriptions
- entitlements
Finance now depends on Core for:
- company / business-unit master reads
- company commercial entitlement checks
- business-unit master writes
- Kisum company id as part of canonical company resolution
Finance owns (financial domain source of truth)
Section titled “Finance owns (financial domain source of truth)”Finance is the source of truth for financial workflow data stored in the Finance database: bills/invoices, income, vendor portal and vendor-finance links, Xero connection and sync state, finance-related files/notifications, and related audit rows. It is not the source of truth for company or business-unit master data (that is Core) or for users/memberships (that is Auth).
Concretely, Finance owns:
- bills / invoices in the finance sense
- income rows and income payments
- venue-deposit invoices once Venue submits them through the Finance income flow
- vendor finance workflows
- Xero sync state
- audit / notification behavior related to finance workflows
- scalar
companyId/businessUnitId(and other FKs) on finance tables that point at Core-owned ids — without re-defining company/BU master records in Finance
Current Runtime Rules
Section titled “Current Runtime Rules”Finance access requires both Auth and Core
Section titled “Finance access requires both Auth and Core”A company-scoped Finance request is allowed only when:
- the caller is authenticated
- Auth confirms the caller can act for the selected company
- Core confirms the selected company has the
financeadd-on / enabled module
If membership exists but the company is not entitled to Finance, Finance returns:
403- code:
finance_addon_required
x-org still selects the tenant
Section titled “x-org still selects the tenant”For company-scoped internal routes, the active tenant is selected through x-org.
Accepted forms:
- canonical
Company.idUUID kisumCompanyIdwhen the company is linked to Kisum
Finance resolves that value to the canonical Core company, then hydrates the local compatibility row if needed.
Current cross-service detail:
Backend-Kisum-Venuesnow reuses FinancePOST|PATCH /api/incomein machinesource=venue_depositmode for deposit invoices- Finance still runs the normal income/Xero flow and remains the source of truth for payment state
How company and business unit appear in Finance (no local org-master tables)
Section titled “How company and business unit appear in Finance (no local org-master tables)”The Finance Prisma schema does not include Company or BusinessUnit models. Finance tables store Core canonical UUIDs in scalar columns (e.g. companyId, businessUnitId on Invoice, Income, XeroConnection, vendor links, etc.).
Master truth for company and business unit name, code, status, and lifecycle remains in Core. Finance resolves display and validation by calling Core (and related helpers) and, where needed, enriches API responses in memory (enrichRowsWithCoreOrg, Core company maps, etc.) — not via Prisma relations to local org tables.
Practical rule: never treat Finance as the system of record for creating or editing tenant companies or BUs; use Core (or Admin’s Core proxies) for that. Use Finance for AP/AR, vendors, Xero, and other finance-domain persistence keyed by those Core ids.
What Finance No Longer Does
Section titled “What Finance No Longer Does”Finance company lifecycle is removed.
These company master write endpoints should not be used anymore:
POST /api/admin/companiesPUT /api/admin/companiesPATCH /api/admin/companiesDELETE /api/admin/companiesPOST /api/admin/companies/{id}/request-deletion
Current behavior:
- they return
405 - code:
company_master_write_removed
Business units are still finance-relevant, but BU master truth is now in Core.
Finance admin BU CRUD writes through Core, then syncs the local compatibility row.
Route Families
Section titled “Route Families”Main route groups in the current implementation:
admin/*bills/*income/*income-categories/*vendor/*xero/*kisum/*files/*upload/*notificationsexchange-rates/*dashboard/*auth/vendor/*
These are documented in more detail here:
Current Integration Boundaries
Section titled “Current Integration Boundaries”Finance relies on Auth for:
GET /auth/mestyle user context resolution- company and BU membership truth
- platform / company / BU access checks
Finance docs should never describe local Finance membership tables as the active runtime model.
Finance relies on Core for:
- company reads
- business-unit reads
- business-unit writes
- entitlements
- company lookup by canonical id and Kisum-linked id
kisum/* routes remain supported compatibility routes for event-linked finance reads.
Important current rule:
- remaining Kisum company resolution is now Core-first
- Finance local company rows are no longer the first resolver for those routes
Xero remains a first-class Finance integration area.
The Finance backend still owns:
- connect / callback
- sync
- account / tax / currency reads
- finance-domain Xero behavior
Environment / Runtime Dependencies
Section titled “Environment / Runtime Dependencies”Important Finance runtime dependencies now include:
- Auth internal/user context integration
- Core internal integration
- Redis where configured
- PostgreSQL / Prisma
- Kisum API
- Xero API
- S3-compatible file storage
For the Core integration, Finance must have working values for:
CORE_INTERNAL_BASE_URLCORE_INTERNAL_API_KEY
Without those, commercial entitlement verification and Core org-master synchronization will fail.
Migration Status
Section titled “Migration Status”What is already implemented:
- Finance entitlement enforcement through Core
- Auth as the source of truth for users and memberships
- Core as the source of truth for company / business-unit master data
- company master writes removed from Finance
- business-unit admin CRUD routed through Core (where applicable)
- remaining
kisum/*company resolution moved to Core-first behavior - removal of Finance-local
Company/BusinessUnitPrisma models; finance rows use scalar Core ids with runtime enrichment for responses
What still remains true:
- Finance remains the persistence and workflow owner for invoices, income, vendors, and Xero integration — keyed by Core
companyId/businessUnitIdwhere those columns exist - Any older docs or code comments referring to “local company rows” in Finance should be read as historical; the current model is FK scalars + Core enrichment, not Finance-owned org master tables
Practical Rule For Engineers
Section titled “Practical Rule For Engineers”When working in Backend-Kisum-Finance:
- do not add new company master ownership here
- do not add new business-unit master ownership here
- prefer Auth for user / membership truth
- prefer Core for company / BU / entitlement truth
- persist finance-domain data in Finance; store only Core ids for tenant scope — enrich names and org fields from Core at read/API boundaries, not from Finance-local org tables
- if code and older repo docs disagree, the implemented Auth / Core / Finance split above is the current platform rule