Skip to content

Master Technical Architecture Documentation

Unified Architecture for Auth + Platform Core + Core App + Add-on Modules

Section titled “Unified Architecture for Auth + Platform Core + Core App + Add-on Modules”

NOTE: This version has been lightly reviewed and structured for clarity. No content has been removed.

Audience: frontend engineers, backend engineers, platform admins, DevOps, product/architecture leads
Status: working master specification
Scope: this document combines the current Auth documentation, Platform Core design, access model, platform admin model, frontend integration rules, backend integration rules, and module/backend responsibilities into one understandable reference.


See also: Architecture diagrams document at Architecture diagrams.

  • Master Architecture
  • Runtime Flow
  • Platform Admin Flow

  • Basic subscription: the commercial subscription that enables the Core App.
  • Core App: the tenant control center and basic UI experience.
  • Basic Backend: the backend serving Core/Basic business features.
  • Add-on module: a commercial module such as Finance, Market, Venue, AI, or Touring.
  • Company entitlement: the modules/subscriptions commercially active for a company.
  • Membership grant: the module access granted to a user inside a company.
  • Effective access: the intersection of company entitlements and membership grants.
  • Permission: a fine-grained action key inside a module.
  • Delegation: what a user is allowed to grant to another user.

ConcernSource of TruthCached WhereConsumed By
UsersAuth DBRedisAuth, backends
SessionsAuth DBRedisAuth, backends
MembershipsAuth DBRedisAuth
PermissionsAuth DBRedisAuth, backends
DelegationAuth DBRedisAuth
PackagesCore DBoptional RedisCore
Add-onsCore DBoptional RedisCore
Company entitlementsCore DBRedis via Auth aggregationAuth, frontend, backends
Business dataModule DBsmodule-specificmodule backends

Frontend -> Admin Backend -> Auth and/or Core

Frontend -> Auth (/auth/me, /auth/me/access)

Frontend -> Basic Backend -> Auth validation/access

Frontend -> Finance Backend -> Auth validation/access

Core App -> Auth

Admin Backend -> Core


  • All tenant-scoped backend requests must include x-org.
  • x-org identifies the active company context.
  • Backend resolves x-org to canonical company_id.
  • Auth access context must always be evaluated against this active company.
  • Frontend must update x-org when switching companies.

  1. Auth core: users, sessions, JWT, JWKS, /auth/me
  2. Platform Core: modules, packages, subscriptions, entitlements API
  3. Auth access aggregation: /auth/me/access
  4. Redis cache + invalidation
  5. Core App tenant management
  6. Business backend middleware enforcement
  7. Platform Admin commercial/product management

Kisum is being structured around three authority layers:

  1. Auth Backend

    • identity
    • sessions
    • JWT issuance and validation
    • company memberships
    • tenant roles
    • membership module grants
    • membership permission grants
    • delegation rules
  2. Platform Core Backend

    • package catalog
    • add-on catalog
    • module catalog
    • company subscriptions
    • company add-ons
    • company commercial entitlements
  3. Business Backends

    • Core/Basic business data
    • Finance data
    • Market/Touring data
    • Venue data
    • AI data

Effective access is always:

effective_access = company_entitlements ∩ membership_grants

Then inside each module:

effective_permissions = module_is_effective ∩ membership_permission_grants

A company does not need the Basic/Core subscription in order to have an add-on module.

That means:

  • a company may have only Finance
  • a company may have only Market
  • a company may have Basic + Finance + Market
  • a company may have Basic only
  • a company may have one or more modules without Basic

The Core App UI is enabled only when the company has an active Basic subscription.
The module UIs are enabled when that company has the relevant module and the user has access to it.


Service: auth.kisum.io
Database: PostgreSQL (auth_db)
Cache / hot path: Redis

Auth owns:

  • users
  • sessions
  • refresh token lifecycle
  • JWT signing / JWKS
  • company memberships
  • business unit memberships if used
  • tenant roles
  • platform roles
  • membership module grants
  • membership permission grants
  • delegation policies
  • account approval and activation state
  • access aggregation for frontend and backends

Auth does not own:

  • commercial subscriptions
  • package catalog
  • add-on catalog
  • billing
  • company purchase state

Recommended service: core.kisum.io
Database: PostgreSQL (platform_core_db)

Platform Core owns:

  • packages
  • add-ons
  • modules
  • package-to-module mapping
  • add-on-to-module mapping
  • company subscriptions
  • company add-ons
  • entitlement versioning
  • future billing references (Stripe, trials, renewals, cancellations)

Platform Core does not own:

  • users
  • sessions
  • JWT
  • memberships
  • delegation rules
  • permission grants

Frontend: app.kisum.io
Backend: api-v2.kisum.dev
DB: current main business DB (MongoDB Main in the current architecture)

Owns the business logic for core/basic features.

Frontend path: app.kisum.io/finance
Backend: api-v2-finance.kisum.dev
DB: PostgreSQL Finance

Frontend path: app.kisum.io/market
Backend: api-v2-market.kisum.dev
DB: MongoDB Market/Touring (current plan)

Frontend path: app.kisum.io/touring
Backend: either dedicated Touring backend or shared with Market if that remains the chosen implementation
DB: MongoDB Market/Touring (current plan)

Frontend path: app.kisum.io/venue
Backend: api.kisum.dev/venue
DB: venue DB (TBC)

Frontend path: app.kisum.io/chat
Backend: api-v2-ai.kisum.dev
DB: AI DB (TBC)


Auth Backend
→ who the user is
→ what roles the user has
→ what modules the membership may access
→ what permissions the membership may execute
→ what the user may grant to others
Platform Core Backend
→ what the company bought
→ whether Basic is active
→ which add-on modules are active
→ package / add-on / module catalog
Business Backends
→ module data
→ CRUD and business rules
→ route-level authorization enforcement

Frontend is never the source of truth for access.

Frontend may:

  • read /auth/me
  • read /auth/me/access?companyId=...
  • cache the latest access context locally for UX

Frontend may not:

  • invent access
  • trust old browser state indefinitely
  • assume hidden UI equals secured backend

The current platform products are:

Includes the core operational features of the platform:

  • artist data and consultation
  • event creation tools and estimated cost / P&L
  • calendar
  • vendor directory
  • venue directory
  • news and updates
  • ticketing creation
  • workspace and task management
  • access to the core application experience
  1. Finance

    • expenses management
    • income management
    • ticketing management & reports
    • finance reports per event and company
  2. AI

    • market predictions
    • research
    • event/artist valuation support
  3. Touring (TBC)

    • routing access for logistics teams
    • promoter and artist approval / coordination
    • travel / accommodation / operational coordination
  4. Market

    • artist hiring
    • contract handling
    • escrow / blockchain related features (TBC)
    • funds & investment access
  5. Venue Availability

    • venue availability information
    • venue data and details

Rule A — Basic is not mandatory for modules

Section titled “Rule A — Basic is not mandatory for modules”

A company can have one or more add-ons without having Basic.

The Core App UI should only be shown if the company has an active Basic subscription.

A company can buy:

  • Finance only
  • Market only
  • Venue only
  • AI only
  • Touring only
  • any combination of those
  • Basic + any combination

Rule D — Company entitlement is the upper bound

Section titled “Rule D — Company entitlement is the upper bound”

If the company does not own a module, no user in that company can use it even if someone accidentally grants it.


These are global platform-admin roles, not tenant roles.

Examples:

  • PLATFORM_SUPERADMIN
  • PLATFORM_ADMIN
  • PLATFORM_MODERATOR

These are used for the Platform Admin system.


These are per-company roles.

Recommended current model:

  • TENANT_SUPERADMIN
  • ADMIN
  • MANAGER
  • USER
  • highest authority inside a tenant/company
  • can manage company users
  • can buy/upgrade company subscriptions and add-ons
  • can grant modules and permissions
  • can define delegation boundaries for Admins / Managers
  • operational admin inside the company
  • can manage users and permissions within delegated scope
  • cannot exceed Superadmin delegation
  • whether ADMIN can buy subscriptions is product-policy dependent; current direction from your clarification is that tenant management for subscriptions happens in the Core App, so this should be controlled by permission/delegation rather than assumed by role name alone
  • lower than ADMIN
  • can grant only if delegation allows
  • can manage only lower-scope users or limited actions
  • no delegation by default
  • receives only assigned access

A tenant role does not automatically mean access to all modules.

Examples:

  • a USER may have only Finance
  • a MANAGER may have only Market + Venue
  • an ADMIN may have all active modules
  • a TENANT_SUPERADMIN may still be limited by what the company actually bought

So the rule is:

role = authority
module grants = module access
permissions = actions within module

Resolved by Platform Core.

Answers:

What modules and/or Basic subscription are active for this company right now?

Example:

{
"companyId": "cmp_001",
"hasBasic": false,
"enabledModules": ["finance", "market"]
}

Resolved by Auth.

Answers:

Which modules is this membership allowed to use inside this company?

Example:

{
"membershipId": "mem_001",
"grantedModules": ["finance"]
}

Resolved by Auth.

Answers:

Inside allowed modules, what can this membership do?

Example:

{
"permissions": [
"finance.expense.view",
"finance.expense.create",
"finance.report.view"
]
}

Resolved by Auth.

Answers:

What can this user grant to others?

Example:

{
"delegation": {
"canManageUsers": true,
"grantableModules": ["finance"],
"grantablePermissions": [
"finance.expense.view",
"finance.expense.create"
]
}
}

effective_modules = company_enabled_modules ∩ membership_granted_modules
effective_permissions =
all membership permissions whose module_key is inside effective_modules

Shown only if:

company has active Basic subscription
AND user has access to Basic/Core

Shown only if:

company has Finance
AND user has Finance grant

Shown only if:

company has Market
AND user has Market grant

Same rule for Venue, Touring, AI.


This section answers the practical developer question:

Which system owns the data and where do I fetch it from?


Owner: Auth Backend
Fetch from: Auth APIs / Auth DB

Examples:

  • user info
  • JWT validation
  • session revocation
  • token version
  • login state

Fetch from:

  • /auth/login
  • /auth/refresh
  • /auth/logout
  • /auth/logout-all
  • /auth/me
  • /.well-known/jwks.json

7.2 Membership / tenant role / delegation / module grant data

Section titled “7.2 Membership / tenant role / delegation / module grant data”

Owner: Auth Backend
Fetch from: Auth aggregation endpoint or internal Auth APIs / Auth DB

Examples:

  • tenant role
  • membership module grants
  • permissions
  • delegation
  • which modules the current user may access in a company

Fetch from:

  • /auth/me/access?companyId=... for frontend
  • internal access-context route or shared middleware path for backend
  • Auth DB directly only if service integration explicitly chooses DB reads instead of internal Auth calls

Owner: Platform Core
Fetch from: Platform Core internal APIs

Examples:

  • whether Basic subscription is active
  • which add-ons are active
  • company entitlement version

Fetch from:

  • /internal/companies/{companyId}/entitlements
  • /internal/companies/{companyId}/subscription-summary
  • catalog routes for packages/modules/add-ons

Owner: Basic Backend
Fetch from: api-v2.kisum.dev

Examples:

  • core events
  • artist records
  • core calendar logic
  • vendor directory logic
  • venue directory logic
  • ticketing inside the core/basic layer
  • workspace/task data

Important: exact CRUD route list for Core/Basic business endpoints is not fully specified in the uploaded docs, so this document defines the ownership and access pattern, but not a locked route-by-route contract for those business APIs.


Owner: Finance Backend
Fetch from: api-v2-finance.kisum.dev

Examples:

  • expenses
  • income
  • ticketing finance reports
  • financial reporting per event/company

Access rule: Finance backend must validate JWT and enforce Finance module + Finance permissions before serving business data.


Owner: Market Backend
Fetch from: api-v2-market.kisum.dev

Examples:

  • market contacts
  • artist hiring
  • contracts
  • funding/investment related market flows

Owner: Touring backend or shared Market/Touring backend
Fetch from: touring service path chosen by implementation

Examples:

  • route logistics
  • travel coordination
  • accommodation coordination
  • promoter/artist coordination

Owner: Venue Backend
Fetch from: api.kisum.dev/venue

Examples:

  • venue availability
  • venue detail records

Owner: AI Backend
Fetch from: api-v2-ai.kisum.dev

Examples:

  • AI predictions
  • research outputs
  • event/artist value support

  • auth.kisum.io
  • PostgreSQL auth_db
  • Redis
  • Go + Chi + explicit SQL / pgx / sqlc (recommended direction)
  • core.kisum.io
  • PostgreSQL platform_core_db
  • api-v2-admin.kisum.dev
  • platform admin DB / config DB as needed
  • calls Auth and Core where appropriate
  • api-v2.kisum.dev
  • main business DB
  • Finance: api-v2-finance.kisum.dev
  • Market: api-v2-market.kisum.dev
  • Touring: dedicated service or Market/Touring shared service
  • Venue: api.kisum.dev/venue
  • AI: api-v2-ai.kisum.dev

Frontend should normally call:

  • Auth
  • Platform Admin Backend (for platform-admin UI)
  • Core/Basic Backend
  • module backends

Frontend should not call Platform Core directly for access resolution.


Used for access aggregation.

Used for package / company / subscription management.

Used for approval, membership, permission, and delegation management.

Used for token validation / access context fetch if not done by direct DB integration.


This section aligns with the current Auth API docs and OpenAPI.

Purpose:

  • authenticate user
  • create session
  • return access + refresh token
{
"email": "user@example.com",
"password": "string",
"accountType": "internal"
}
{
"success": true,
"data": {
"accessToken": "<jwt>",
"refreshToken": "<refresh-token>",
"tokenType": "Bearer",
"expiresIn": 900,
"user": {
"id": "uuid",
"email": "user@example.com",
"name": "User Name"
}
}
}

Purpose:

  • rotate / refresh tokens
{
"refreshToken": "<refresh-token>"
}

Same shape as login.


Purpose:

  • revoke one session using refresh token
{
"refreshToken": "<refresh-token>"
}
{
"success": true,
"data": {
"status": "ok"
}
}

Purpose:

  • revoke all current user sessions
Authorization: Bearer <access_token>
{
"success": true,
"data": {
"status": "ok"
}
}

Purpose:

  • return identity and membership summary
  • not the full access matrix
Section titled “Response (recommended normalized contract)”
{
"success": true,
"data": {
"user": {
"id": "uuid",
"email": "user@example.com",
"name": "User Name",
"globalRole": "PLATFORM_ADMIN",
"authType": "internal",
"isVendor": false
},
"session": {
"sessionId": "session-uuid",
"tokenVersion": 1
},
"companyMemberships": [
{
"companyId": "cmp_001",
"tenantRole": "TENANT_SUPERADMIN",
"isActive": true
}
],
"businessUnitMemberships": []
}
}

Purpose:

  • return resolved access for the current user in one company
  • this is the primary frontend access endpoint
  1. verify JWT
  2. resolve active membership for companyId
  3. load membership grants / permissions / delegation from Auth DB
  4. call Platform Core to get company entitlements
  5. compute effective access
  6. cache in Redis
  7. return final access object
{
"success": true,
"data": {
"user": {
"id": "uuid",
"email": "user@example.com",
"name": "User Name"
},
"company": {
"id": "cmp_001",
"tenantRole": "TENANT_SUPERADMIN"
},
"entitlements": {
"hasBasic": false,
"enabledModules": ["finance", "market"],
"basePackage": null,
"addons": ["finance", "market"]
},
"membership": {
"grantedModules": ["finance"],
"effectiveModules": ["finance"]
},
"permissions": [
"finance.expense.view",
"finance.expense.create"
],
"delegation": {
"canManageUsers": true,
"grantableModules": ["finance"],
"grantablePermissions": [
"finance.expense.view",
"finance.expense.create"
]
},
"meta": {
"accessVersion": 12,
"entitlementVersion": 7,
"cached": true,
"generatedAt": "2026-04-16T05:00:00Z"
}
}
}

Possible error responses for GET /auth/me/access

Section titled “Possible error responses for GET /auth/me/access”

401 unauthorized

  • invalid token
  • expired token
  • revoked session

403 forbidden

  • user inactive
  • membership inactive
  • company access not allowed

404 not_found

  • company not found
  • membership not found for company

503 service_unavailable

  • core entitlement service unavailable
  • cache/database dependency failure
  • hasBasic may be false while modules are still enabled
  • basePackage can be null if the company has no active Basic subscription
  • addons can still list one or more active modules
  • this endpoint should be the frontend’s main access source

JWT remains small and identity-only.

Example:

{
"id": "d7b61435-d9cc-4162-9346-d5300e13b553",
"email": "mrios@primuse.net",
"name": "Marco Rios",
"sessionId": "3e3c9232-2800-474c-b477-b6a9fd3b63b1",
"authType": "internal",
"globalRole": "PLATFORM_SUPERADMIN",
"roles": "Admin",
"isVendor": false,
"vendorId": null,
"tokenVersion": 1,
"iss": "auth.kisum.io",
"sub": "d7b61435-d9cc-4162-9346-d5300e13b553",
"aud": ["kisum-apps2026-prod-apps"],
"exp": 1776335662,
"iat": 1776249262
}

Do not add:

  • packages
  • add-ons
  • modules
  • permissions
  • delegation
  • company access matrix

These are internal-service APIs.

11.1 GET /internal/companies/{companyId}/entitlements

Section titled “11.1 GET /internal/companies/{companyId}/entitlements”

Purpose:

  • return commercial access state for one company
{
"companyId": "cmp_001",
"hasBasic": false,
"basePackage": null,
"addons": [
{
"key": "finance",
"status": "active"
},
{
"key": "market",
"status": "active"
}
],
"enabledModules": ["finance", "market"],
"entitlementVersion": 7,
"updatedAt": "2026-04-16T05:00:00Z"
}

Purpose:

  • return module catalog
{
"modules": [
{ "key": "basic", "name": "Core App", "type": "base" },
{ "key": "finance", "name": "Finance", "type": "addon" },
{ "key": "ai", "name": "AI", "type": "addon" },
{ "key": "touring", "name": "Touring", "type": "addon" },
{ "key": "market", "name": "Market", "type": "addon" },
{ "key": "venue", "name": "Venue", "type": "addon" }
]
}

11.3 GET /internal/companies/{companyId}/subscription-summary

Section titled “11.3 GET /internal/companies/{companyId}/subscription-summary”

Purpose:

  • admin/business summary for a company’s commercial state
{
"companyId": "cmp_001",
"hasBasic": true,
"basePackage": "basic",
"addons": ["finance", "market"],
"status": "active",
"entitlementVersion": 7
}

11.4 POST /internal/companies/{companyId}/basic

Section titled “11.4 POST /internal/companies/{companyId}/basic”

Purpose:

  • activate/deactivate Basic subscription
{
"status": "active",
"startsAt": "2026-04-16T00:00:00Z",
"endsAt": "2026-05-16T00:00:00Z",
"source": "platform_admin"
}
{
"companyId": "cmp_001",
"hasBasic": true,
"basePackage": "basic",
"entitlementVersion": 8
}

11.5 POST /internal/companies/{companyId}/addons

Section titled “11.5 POST /internal/companies/{companyId}/addons”

Purpose:

  • activate or update an add-on
{
"addonKey": "finance",
"status": "active",
"startsAt": "2026-04-16T00:00:00Z",
"endsAt": "2026-05-16T00:00:00Z",
"source": "platform_admin"
}
{
"companyId": "cmp_001",
"addonKey": "finance",
"status": "active",
"entitlementVersion": 9
}

This section reflects your clarification:

Platform Admin is only global/platform-side. Company-side management happens in the Core App.

Platform Admin manages:

  • package catalog
  • add-on catalog
  • module catalog
  • permission type catalog
  • organization approval / customer onboarding
  • company approval / activation
  • company subscription state
  • company add-on state
  • platform-level moderation and approval flows

12.2 What Platform Admin does not manage directly as tenant UI

Section titled “12.2 What Platform Admin does not manage directly as tenant UI”

Tenant/company-specific daily user management belongs in the Core App and Auth-backed company management flows.


  • create package records
  • create add-on records
  • create module definitions
  • map modules to package/add-ons
  • approve pending registrations or companies
  • activate companies
  • assign initial subscription state
  • activate Basic
  • activate/deactivate add-ons
  • upgrade/downgrade company subscription state
  • create permission keys
  • assign permission keys to modules
  • control permission catalog

This section reflects your clarification:

company admin (tenant) will use the Core App for modules, permissions, upgrade subscription, etc.

13.1 Core App is the tenant control center

Section titled “13.1 Core App is the tenant control center”

When Basic is active, the Core App is where tenant-side users manage:

  • tenant users
  • company memberships
  • user module grants
  • user permission grants
  • delegation rules
  • tenant-level purchase/upgrade flows
  • current company subscription visibility
  • current company add-on visibility

The company can still use standalone modules they own, but the full Core App is not shown.

That means the system must support:

  • direct module entry
  • direct module APIs
  • no dependency on Core App for module runtime

Every business backend must:

  1. validate JWT using Auth/JWKS
  2. resolve current company from x-org
  3. resolve access context from Auth cache/Auth internal context path
  4. verify module access
  5. verify permission access
  6. execute business logic only if allowed
  • Do not trust frontend-hidden UI as authorization.
  • Do not store final permission truth inside JWT.
  • Do not let module backends invent their own entitlement rules.
  • Do not let Platform Core become an authorization engine.
  • Do not bypass Auth when checking membership grants.
  • Do not duplicate company entitlement state into module DBs as source of truth.

Frontend → Finance Backend /expenses
  1. verify JWT
  2. resolve company
  3. fetch access context
  4. ensure finance is inside effectiveModules
  5. ensure permission such as finance.expense.view exists
  6. execute finance query
  7. return data
{
"success": true,
"data": {
"items": [
{
"id": "exp_001",
"title": "Artist hotel",
"amount": 2000,
"currency": "USD"
}
]
}
}
{
"success": false,
"error": {
"code": "forbidden",
"message": "Module or permission not allowed"
}
}

Flow is the same, but enforce:

  • market module
  • relevant market.* permission

Flow is the same, but enforce:

  • venue module
  • relevant venue.* permission

Flow is the same, but enforce:

  • ai module
  • relevant ai.* permission

Flow is the same, but enforce:

  • basic module access (which requires active Basic subscription)
  • relevant basic.* permission

id uuid primary key
email text unique not null
password_hash text not null
full_name text
is_active boolean not null
approval_status text not null
global_role text not null
token_version integer not null
created_at timestamptz not null
updated_at timestamptz not null
id uuid primary key
user_id uuid not null
refresh_token_hash text not null
is_revoked boolean not null
expires_at timestamptz not null
created_at timestamptz not null
updated_at timestamptz not null
id uuid primary key
user_id uuid not null
company_id uuid not null
tenant_role text not null
is_active boolean not null
access_version integer not null
created_at timestamptz not null
updated_at timestamptz not null
id uuid primary key
company_membership_id uuid not null
module_key text not null
granted boolean not null
granted_by_membership_id uuid
created_at timestamptz not null
updated_at timestamptz not null
id uuid primary key
key text unique not null
module_key text not null
category text
description text
is_active boolean not null
created_at timestamptz not null
updated_at timestamptz not null
id uuid primary key
company_membership_id uuid not null
permission_id uuid not null
granted boolean not null
granted_by_membership_id uuid
created_at timestamptz not null
updated_at timestamptz not null
id uuid primary key
company_membership_id uuid not null
target_role text not null
module_key text not null
can_grant_module_access boolean not null
can_grant_permissions boolean not null
created_at timestamptz not null
updated_at timestamptz not null

id uuid primary key
key text unique not null
name text not null
type text not null
is_active boolean not null
created_at timestamptz not null
updated_at timestamptz not null
id uuid primary key
key text unique not null
name text not null
is_active boolean not null
created_at timestamptz not null
updated_at timestamptz not null
id uuid primary key
key text unique not null
name text not null
is_active boolean not null
created_at timestamptz not null
updated_at timestamptz not null
package_id uuid not null
module_id uuid not null
primary key (package_id, module_id)
addon_id uuid not null
module_id uuid not null
primary key (addon_id, module_id)
id uuid primary key
company_id uuid not null
package_id uuid not null
status text not null
starts_at timestamptz
ends_at timestamptz
entitlement_version integer not null
created_at timestamptz not null
updated_at timestamptz not null
id uuid primary key
company_id uuid not null
addon_id uuid not null
status text not null
starts_at timestamptz
ends_at timestamptz
created_at timestamptz not null
updated_at timestamptz not null
id uuid primary key
company_id uuid not null
change_type text not null
payload_json jsonb not null
changed_by text
created_at timestamptz not null

Redis can be used for every hot-path optimization needed for near-perfect performance.

  • access-context cache
  • revocation markers
  • session hot cache
  • login rate limiting
  • refresh throttling
  • password reset throttling
  • company resolution cache
  • internal access snapshot cache
access:{companyId}:{membershipId}:{accessVersion}:{entitlementVersion}
session:{sessionId}
revoked:session:{sessionId}
ratelimit:login:ip:{ip}
ratelimit:login:email:{email}
company-map:{raw-x-org}
{
"tenantRole": "ADMIN",
"effectiveModules": ["finance"],
"permissions": ["finance.expense.view", "finance.expense.create"],
"delegation": {
"canManageUsers": true,
"grantableModules": ["finance"]
}
}

Invalidate access cache when:

  • company subscription changes
  • company add-on changes
  • membership grant changes
  • membership permission changes
  • delegation changes
  • membership deactivation
  • logout-all or token-sensitive user state changes if needed

  1. call /auth/login
  2. store tokens
  3. call /auth/me
  4. choose company if needed
  5. call /auth/me/access?companyId=...
  6. render UI from access response
  • token
  • user identity
  • current company selection
  • latest access object
  • optional session storage/local storage copy for convenience
  • treat cached access as permanent truth
  • build authorization rules in place of backend
  • assume module visibility means server permission

18.4 When frontend must refetch /auth/me/access

Section titled “18.4 When frontend must refetch /auth/me/access”
  • login
  • hard reload
  • company switch
  • refresh-token session restore
  • after admin changes permissions/modules
  • after buying/upgrading subscription
  • after 403 that indicates access changed

Frontend → Auth /auth/login → JWT + Refresh Token
Frontend → Auth /auth/me/access?companyId=...
Auth → Auth DB
Auth → Platform Core
Auth → merge + cache
Auth → return access context
Frontend checks access
if hasBasic and membership has basic:
show Core App
else:
hide Core App

19.4 Opening standalone module without Basic

Section titled “19.4 Opening standalone module without Basic”
Frontend checks access
if company owns module and membership has module:
show module UI
else:
deny
Core App / company management UI → Auth
Auth verifies actor role + delegation
Auth verifies company owns module
Auth writes grant
Auth invalidates target access cache
Core App or Platform Admin → Platform Core
Core updates company subscription / add-on
Core bumps entitlement version
Auth invalidates related access cache
Frontend refetches /auth/me/access

20. Platform Admin vs tenant/company management

Section titled “20. Platform Admin vs tenant/company management”

Handles:

  • create/update packages
  • create/update modules
  • create/update add-ons
  • create/update permission types
  • approve customers / organizations
  • activate/deactivate company subscriptions
  • activate/deactivate company add-ons

Handles:

  • company user administration
  • grant/revoke module access
  • grant/revoke permissions
  • delegation boundaries
  • TENANT_SUPERADMIN can buy/upgrade only if self-service billing is enabled for that tenant.

This section is intentionally honest about what is fully specified vs what is still TBC.

What it does

  • serves core/basic business features
  • relies on active Basic subscription + basic module access

How to grab the data

  • frontend calls Core App UI
  • Core App calls Basic Backend endpoints
  • Basic Backend validates JWT, resolves access, then reads current main DB data

What is fully defined

  • ownership
  • access rules
  • service boundary

What is not fully locked in uploaded docs

  • complete business endpoint list for all basic features

What it does

  • expenses
  • income
  • finance reports
  • ticketing finance reports
  • event/company financial reporting

What it reads from other systems:

  • Auth: JWT validation + access context
  • x-org / company context
  • maybe Core indirectly through Auth only

How to grab the data

  • frontend module calls Finance backend endpoints
  • Finance backend verifies JWT + checks access context
  • Finance backend reads from PostgreSQL Finance

Access required

  • company must own Finance
  • membership must have Finance
  • membership effectiveModules includes Finance
  • route permission must match, e.g. finance.expense.view
  • route permission matches finance.*

What it does

  • contacts
  • artist hiring
  • contracts
  • funding/investment related market flows

How to grab the data

  • frontend module calls Market backend
  • Market backend enforces Market module + Market permission
  • reads Market DB / shared Market-Touring DB

What it does

  • route logistics
  • travel coordination
  • accommodation coordination
  • promoter/artist coordination

How to grab the data

  • frontend module calls Touring backend
  • Touring backend enforces Touring module + Touring permissions
  • reads touring data source (currently planned shared DB if Market/Touring stays combined)

What it does

  • venue availability
  • venue details

How to grab the data

  • frontend module calls Venue backend
  • Venue backend enforces Venue module + Venue permissions
  • reads venue DB

What it does

  • market predictions
  • research
  • event/artist value support

How to grab the data

  • frontend module calls AI backend
  • AI backend enforces AI module + AI permissions
  • reads AI service / AI DB

  • JWT must remain small
  • JWT must be RS256-verified through JWKS
  • services should validate iss, aud, exp, and required custom claims
  • business backends must not accept access based only on frontend claims
  • Platform Core should not serve as a public user-facing authorization checker
  • internal service-to-service auth should use internal API key, service token, allowlist, or stronger internal auth mechanism
  • refresh tokens should be rotated and stored hashed
  • session revocation must be supported
  • tokenVersion should be used to invalidate outdated tokens where relevant

These items are not fully defined by the uploaded docs and should be finalized by the backend team:

  1. exact Core/Basic business API route list
  2. whether Touring remains a separate backend or a shared Market/Touring backend
  3. exact tenant-side self-service billing flows inside Core App
  4. whether company purchases can be done by TENANT_SUPERADMIN only or a wider delegated policy
  5. final service-to-service auth mechanism between Auth and Core
  6. whether module business backends query Auth internal route vs Auth DB directly vs shared auth library cache

  • login / refresh / logout / logout-all
  • /auth/me
  • /auth/me/access
  • JWKS
  • session revocation
  • access aggregation
  • Redis access cache
  • package catalog
  • add-on catalog
  • module catalog
  • company subscriptions
  • company add-ons
  • entitlement versioning
  • internal entitlement APIs
  • package management
  • module management
  • permission-type management
  • company approval
  • subscription management
  • tenant user management
  • module grants UI
  • permission grants UI
  • delegation UI
  • tenant purchase / upgrade UI (if enabled)
  • JWT validation
  • x-org resolve
  • access fetch / cache
  • module enforcement
  • permission enforcement

Auth decides who the user is and what that membership may do.
Platform Core decides what the company commercially owns.
Business backends only execute requests that pass both checks.
Core App is the tenant control center when Basic is active.
Standalone modules may operate even when Basic is not active.