Backend Base Architecture
Version: 1.0.0
Audience: junior backend developers, frontend developers, QA, DevOps, tech leads
Status: architecture and enforcement reference
1. Purpose of this document
Section titled “1. Purpose of this document”This document explains how the Base Backend is supposed to work in the new architecture.
It does not try to be the full endpoint catalog.
Its job is to explain:
- what the Base Backend owns
- what the Base Backend does not own
- how Auth and Platform Core fit into runtime access control
- how
Authorizationandx-orgmust be handled - how effective access is resolved
- how request enforcement must work
- what must fail closed
- what old logic is deprecated and must be removed
This document is intentionally detailed so junior developers can understand the architecture without guessing.
2. High-level architecture
Section titled “2. High-level architecture”The platform is split into multiple backends with different responsibilities.
Base Backend
Section titled “Base Backend”Owns:
- business features
- business CRUD
- business workflows
- artists
- events
- vendors
- venues
- tasks
- offers
- dashboard-related business data
- other non-auth, non-commercial business domains
Does not own:
- login
- JWT issuance
- password flows
- company membership
- effective access
- packages
- add-ons
- subscriptions
- commercial entitlements
Auth Backend
Section titled “Auth Backend”Owns:
- identity
- users
- login
- JWT issuance
- JWT refresh
- memberships
- tenant roles
- permissions
- invitations
- effective access resolution
Platform Core Backend
Section titled “Platform Core Backend”Owns:
- packages
- add-ons
- subscriptions
- module catalog
- package/add-on catalog
- company commercial entitlements
Financial Backend
Section titled “Financial Backend”Owns:
- financial records
- accounting truth
- settlements
- final expense/income authority where applicable
3. Final responsibility split
Section titled “3. Final responsibility split”Base Backend= business execution
Auth Backend= identity + membership + permissions + effective access
Platform Core Backend= commercial ownership + entitlements
Financial Backend= final finance/accounting truthThis split is not optional.
This is the architecture the Base Backend must follow.
4. What the Base Backend must do
Section titled “4. What the Base Backend must do”The Base Backend must:
- receive a bearer token from the client
- receive
x-orgfrom the client - validate the JWT
- treat
x-orgas the active company context - obtain effective access from Auth
- verify the
basicmodule is enabled - verify the route-specific
basic.*permission exists - allow or deny the request
- execute business logic only after access checks pass
5. What the Base Backend must never do
Section titled “5. What the Base Backend must never do”The Base Backend must never:
- log users in
- issue tokens
- refresh tokens
- reset passwords
- create invitations
- decide membership locally
- decide whether the company owns Basic
- decide module access locally from old package tables
- decide permission access locally from old permission tables
- read Platform Core directly for runtime user authorization
- allow access because the frontend hid or showed a button
- allow access when Auth resolution fails
- guess a default company if
x-orgis missing
6. Identity model
Section titled “6. Identity model”6.1 Source of truth
Section titled “6.1 Source of truth”The source of truth for who the user is is the Auth Backend.
The Base Backend must trust Auth for:
- user identity
- token issuer
- membership
- effective access
6.2 Required request headers
Section titled “6.2 Required request headers”All protected Base Backend requests must include:
Authorization: Bearer <JWT_FROM_AUTH_SERVICE>x-org: <COMPANY_ID>6.3 Meaning of Authorization
Section titled “6.3 Meaning of Authorization”This token is:
- issued by Auth
- consumed by Base
- never created by Base
6.4 Meaning of x-org
Section titled “6.4 Meaning of x-org”This is the active company context for the request.
The Base Backend must:
- read it
- validate it
- use it consistently
- reject the request if it is missing or malformed
7. JWT validation model
Section titled “7. JWT validation model”The Base Backend must validate JWTs issued by the external Auth service.
7.1 Minimum required checks
Section titled “7.1 Minimum required checks”For every protected request, validate:
- token presence
- token structure
- signature
- expiration
- issuer
- audience
- token format
- session validity if the chosen middleware supports that check
7.2 What JWT validation is not
Section titled “7.2 What JWT validation is not”JWT validation in Base is not:
- local login
- local credential validation
- token generation
- token refresh
7.3 Migration rule
Section titled “7.3 Migration rule”Any old local JWT/auth code in Base is deprecated and must be removed:
/auth/*handlers- local login services
- token issuing helpers
- refresh flows
- password reset flows
- auth DB logic in Base
Only JWT consumption/validation middleware is allowed.
8. Company context model
Section titled “8. Company context model”8.1 Active company context
Section titled “8.1 Active company context”The active company is provided through:
x-org: <COMPANY_ID>8.2 Required company-context behavior
Section titled “8.2 Required company-context behavior”For all tenant-scoped routes, Base must:
- read
x-org - require it
- validate it
- treat it as the active company for the request
- use it for all downstream access decisions
8.3 Forbidden behaviors
Section titled “8.3 Forbidden behaviors”Base must not:
- invent a default company silently
- resolve company from local session state
- use a company chosen in Base as the access authority
- decide membership locally
- decide commercial entitlement locally
8.4 Company membership authority
Section titled “8.4 Company membership authority”Whether the user belongs to the company in x-org is decided by Auth, not Base.
9. Effective access model
Section titled “9. Effective access model”9.1 Source of truth
Section titled “9.1 Source of truth”The source of truth for effective access is Auth Backend.
9.2 How effective access is formed
Section titled “9.2 How effective access is formed”Auth resolves effective access by combining:
- company entitlements from Platform Core
- user grants / roles / permissions from Auth
Conceptually:
effectiveAccess = entitlements ∩ userGrants9.3 Important membership rule
Section titled “9.3 Important membership rule”Effective access must not be computed unless the user already has a valid membership in the company.
Membership is created through:
- invitations in Auth
- admin actions in Auth
9.4 What Base receives conceptually
Section titled “9.4 What Base receives conceptually”Base should enforce against an effective access model that answers questions like:
- does this user have access to company X?
- is
basicenabled? - does the user have
basic.artist.view? - does the user have
basic.event.create?
9.5 What Base must not do
Section titled “9.5 What Base must not do”Base must not:
- derive effective access from JWT alone
- infer access from old local package logic
- use local permission tables as truth
- call Platform Core directly for runtime per-request authorization
10. Base module enforcement
Section titled “10. Base module enforcement”The Base Backend is the backend for the Basic/Core business application.
That means every protected business route in this service must require:
- the
basicmodule - the appropriate
basic.*permission
10.1 Example permissions
Section titled “10.1 Example permissions”Examples include:
basic.dashboard.viewbasic.artist.viewbasic.artist.createbasic.artist.editbasic.artist.deletebasic.event.viewbasic.event.createbasic.event.editbasic.event.deletebasic.calendar.viewbasic.calendar.editbasic.vendor.viewbasic.vendor.createbasic.vendor.editbasic.vendor.deletebasic.venue.viewbasic.ticketing.viewbasic.ticketing.createbasic.workspace.viewbasic.workspace.createbasic.workspace.editbasic.workspace.delete
10.2 Rule
Section titled “10.2 Rule”No basic module → no Base app access.
No route permission → deny the route.
11. Runtime enforcement flow
Section titled “11. Runtime enforcement flow”For every protected Base Backend request:
- Receive request
- Read
Authorization - Read
x-org - Validate JWT
- Validate
x-org - Resolve effective access from Auth
- Confirm membership exists for
x-org - Confirm
basicis present in effective modules - Confirm required
basic.*permission exists - Execute business logic
- Return response
11.1 Fail order matters
Section titled “11.1 Fail order matters”You should fail early and clearly:
- missing JWT →
401 - invalid JWT →
401 - missing
x-org→400 - malformed
x-org→400 - no membership →
403 - no
basicmodule →403 - no permission →
403 - Auth access resolution unavailable →
503
12. Mandatory fail-closed policy
Section titled “12. Mandatory fail-closed policy”The Base Backend must operate under a strict fail-closed model.
If Base cannot verify any of the following:
- JWT validity
- company context
- membership
- effective access
- permissions
Then the request must be denied.
12.1 Never do this
Section titled “12.1 Never do this”Never:
- allow temporarily
- guess access
- infer permission from UI visibility
- fallback to old package logic
- fallback to local role tables
- fallback to stale assumptions without an explicit approved design
12.2 Why this matters
Section titled “12.2 Why this matters”A fail-open design becomes a security bug very quickly.
If Auth or access resolution is unavailable, access must stop.
13. Required HTTP outcomes
Section titled “13. Required HTTP outcomes”13.1 400 Bad Request
Section titled “13.1 400 Bad Request”Use when:
x-orgis missingx-orgis malformed- request shape is invalid
13.2 401 Unauthorized
Section titled “13.2 401 Unauthorized”Use when:
- JWT missing
- JWT invalid
- JWT expired
- JWT rejected by validation middleware
13.3 403 Forbidden
Section titled “13.3 403 Forbidden”Use when:
- user is authenticated but not allowed for this company
basicmodule missing- permission missing
13.4 503 Service Unavailable
Section titled “13.4 503 Service Unavailable”Use when:
- effective access cannot be resolved from Auth
- Auth service unavailable
- network failure or timeout blocks access resolution
When returning 503, Base must fail closed.
14. Deprecated legacy domains
Section titled “14. Deprecated legacy domains”The following domains are deprecated in Base and must not be used as live authorities:
- Auth
- Company Users
- Company User Invitations
- Company Teams
- Packages
- Permissions
- Role
- Subscription
- Users
14.1 What this means
Section titled “14.1 What this means”These domains may still exist in old code, old Swagger groupings, or old files.
That does not mean they are valid.
14.2 Required migration action
Section titled “14.2 Required migration action”All logic related to those domains must be removed from Base:
- routes
- controllers
- services
- repositories
- tables used as source of truth
- access checks based on those local domains
14.3 New ownership
Section titled “14.3 New ownership”- Auth / Users / Invitations / Membership / Teams / Roles / Permissions → Auth Backend
- Packages / Add-ons / Subscriptions / Entitlements → Platform Core Backend
15. How Base should think about other services
Section titled “15. How Base should think about other services”15.1 Base and Auth
Section titled “15.1 Base and Auth”Base depends on Auth for:
- identity
- access control
- company membership
- effective access
15.2 Base and Platform Core
Section titled “15.2 Base and Platform Core”Base depends on Core only indirectly through Auth for runtime authorization.
That means:
- Auth talks to Core
- Base talks to Auth
- Base does not call Core directly for user access checks
15.3 Base and Financial Backend
Section titled “15.3 Base and Financial Backend”Base may coexist with financial-related read/write domains, but it is not the final accounting authority where the Financial Backend is the source of truth.
16. Junior developer checklist
Section titled “16. Junior developer checklist”Before adding any new Base endpoint, ask:
- Is this business-domain logic or auth/commercial logic?
- Does this route require
basicmodule? - What is the exact
basic.*permission for the route? - Does the request require
x-org? - Does the route fail closed if Auth cannot resolve access?
- Am I accidentally using old local tables for access?
- Am I duplicating something that belongs in Auth or Core?
If any answer is unclear, stop and resolve it before coding.
17. Example route-to-permission mapping
Section titled “17. Example route-to-permission mapping”These are examples only, but they show the expected pattern.
| Route area | Module required | Permission |
|---|---|---|
| Dashboard read | basic | basic.dashboard.view |
| Artist list | basic | basic.artist.view |
| Artist create | basic | basic.artist.create |
| Artist update | basic | basic.artist.edit |
| Artist delete | basic | basic.artist.delete |
| Event list | basic | basic.event.view |
| Event create | basic | basic.event.create |
| Event update | basic | basic.event.edit |
| Event delete | basic | basic.event.delete |
| Vendor list | basic | basic.vendor.view |
| Vendor create | basic | basic.vendor.create |
| Venue list | basic | basic.venue.view |
| Workspace/task read | basic | basic.workspace.view |
18. Pseudocode for middleware
Section titled “18. Pseudocode for middleware”handleRequest(request): token = readAuthorizationHeader(request) if token missing: return 401
companyId = readXOrgHeader(request) if companyId missing or malformed: return 400
jwtResult = validateJWT(token) if jwtResult invalid: return 401
accessResult = resolveEffectiveAccessFromAuth(token, companyId) if accessResult unavailable: return 503
if accessResult.membership != valid: return 403
if "basic" not in accessResult.modules: return 403
requiredPermission = mapRouteToPermission(request.route) if requiredPermission not in accessResult.permissions: return 403
return executeBusinessLogic(request)19. Final architecture statement
Section titled “19. Final architecture statement”The Base Backend is a business backend, not an identity backend and not a commercial entitlement backend.
Its job is:
- validate incoming Auth-issued JWTs
- require explicit company context
- enforce effective access returned by Auth
- execute business logic only after access is approved
That boundary must remain strict.