Platform Authorization And Access — Source Authority¶
- Status:
CURRENT SOURCE-AUTHORITY MAP / DOCUMENTATION ONLY - Current source baseline:
qa/master@3c084671c034f8f5136b02dce990ecff6c66d107 - Identity input:
PLATFORM_IDENTITY_SESSION_IMPERSONATION_SOURCE_AUTHORITY.md - Tenant/config input:
PLATFORM_TENANT_PROFILE_CAPABILITY_CONFIGURATION_SOURCE_AUTHORITY.md - Phase implementation:
USER HOLD - Effects: no Runtime, role, menu, account, module, config, DB, Wiki DB or deployment mutation
1. Authority Decision¶
Authorization is not one boolean and is not owned by menu visibility.
Authentication
-> Tenant context
-> Product/module/capability availability
-> Menu/page/API availability
-> Action permission
-> Record ownership/relation
-> Record-state eligibility
-> Required config/credential validity
-> Allow or deny one query/command
Every step can independently deny or return unavailable/unknown.
1.1 Required invariants¶
Menu visible != Page authorized
Page authorized != API authorized
API authorized != Command authorized
Command authorized != Record authorized
Record authorized != State transition allowed
UI hidden != Backend denied
Module enabled != User authorized
Role assigned != Every action allowed
Super-admin actor != Every impersonated action allowed
1.2 Current owner categories¶
| Question | Current source owner |
|---|---|
| Is the user authenticated? | PHP session helpers / API or endpoint bootstrap |
| Which tenant/user/role is effective? | config compatibility helpers and selected typed context |
| Is a module/config available? | module guard and tenant config helper |
| Is a menu route visible/owned by role? | T_MENU, virtual menu rules and menu helpers |
| May a page load? | index.php, page helper/guard and page-local guard |
| May an API route execute? | API v2 route metadata or legacy TYPE/ACTION endpoint owner |
| May one action execute? | route role checks plus handler-specific logic |
| May one record be read/mutated? | module/helper-specific SQL predicates and relation guards |
| Is the record state eligible? | application helper/process logic |
| Which override is allowed? | super-admin, impersonation and allowlisted admin route logic |
No single current source fully owns the entire chain.
2. Current Access Layers¶
2.1 Authentication layer¶
Current request families use several helpers:
- application shell redirects to login when
login_usernameis absent; - API v2 returns
401 UNAUTHENTICATED; - legacy JSON endpoint returns its legacy error envelope;
- direct page/download helpers return redirect, HTML or plain-text errors;
- CLI paths may bypass browser authentication and require separate explicit identity.
Authentication is necessary but not sufficient.
2.2 Tenant context layer¶
Current paths may use:
- session tenant;
- impersonation target tenant;
- allowlisted super-admin API tenant override;
- strict typed tenant principal;
- legacy deployment default;
- handler-supplied/scalar client ID.
Record SQL remains responsible for scoping by effective tenant unless a shared typed relation guard is used.
2.3 Module/config availability layer¶
Current module guard can use:
T_MODULE;T_MODULE_PAGE;T_TENANT_MODULE;config/modules.php;- prerequisite config keys.
Current compatibility includes:
- missing tenant-module row can allow;
- module source error can allow through
isModuleEnabled(); - unmapped page can allow/unknown;
- page registry error or inactive page denies;
- config prerequisite missing/false/error denies in the mapped config guard.
2.4 Menu and role layer¶
Current menu authority uses:
T_MENU.MENU_URL
T_MENU.MENU_ROLE_LIST
T_ROLE.DEFAULT_MENU_ID
virtual menu rows
special field-role policies
Role values are numeric and can be comma-separated.
Current special policies include Forklift Operator page/menu behavior and virtual menu construction. These are compatibility behavior, not accepted universal semantic capability definitions.
2.5 Page layer¶
The application shell:
- normalizes the requested page;
- checks file existence;
- evaluates role/menu access;
- evaluates module/config availability;
- renders access denied, module unavailable or the page;
- some direct pages also call
requirePageRoleAccess().
Current page compatibility:
- menu DB error may return unknown/allowed;
- client ID <= 0 may return unknown/allowed;
- menu-unregistered page can be allowed to role 1;
- print-page aliases can inherit an owner page;
- unmapped module page can remain available/unknown;
- super-admin generally needs an impersonation target for tenant application pages.
2.6 API v2 route layer¶
Route metadata can define:
public
strictTenantPrincipal
moduleKey
requiredMenuRoutes
requiredRoleIds
sessionMode
Dispatch order is effectively:
authentication
-> optional strict tenant context
-> module
-> menu
-> numeric role
-> handler
The handler still owns command-level and record-level predicates.
2.7 Legacy TYPE/ACTION endpoint layer¶
Legacy post/query endpoints use a separate model:
authenticated endpoint
-> TYPE/ACTION to module mapping
-> optional menu assertion
-> effective scalar context
-> selected handler
Some handlers use advancedOperations = super-admin or role 1; others have additional internal role/state checks.
2.8 Record and state layer¶
Record-level access remains distributed across:
- tenant predicates in SQL;
- parent-child relation queries;
- helper-specific ownership checks;
- target-user/role comparisons;
- process status checks;
- provider/credential owner checks;
- current action state.
The shared router cannot prove record authorization merely because a route passed its metadata checks.
3. Current Page And Menu Decision Semantics¶
3.1 getMenuRouteAccessDecision¶
Current behavior includes:
- non-impersonating super-admin bypass;
- exact normalized route and query matching;
- role intersection with
MENU_ROLE_LIST; - field-role special denies/allows;
- caller-selectable
failOpenon missing tenant/DB error; - route not found returns unknown/denied.
Different callers can request different fail-open behavior.
3.2 getPageRoleAccessDecision¶
Current behavior includes:
- current query-specific menu route check;
- role intersection across menu rows sharing a page base;
- operations-manual special rule;
- print-page aliases;
- DB/menu errors can allow unknown;
- unregistered pages can allow role 1 only;
- result contains only
knownandallowed, so detailed reason/provenance is often lost.
3.3 Module filtering versus actual authorization¶
Sidebar/menu filtering can remove a menu for a disabled module. A direct route or API still requires its own guard.
Menu filtered out
!= direct URL rejected
!= API rejected
4. Current Super-Admin And Override Semantics¶
4.1 Physical super-admin¶
Physical super-admin is detected from original session client/role values.
Current bypasses include:
- role check bypass in API v2;
- module bypass when current client is 0 and not impersonating;
- menu route bypass when not impersonating;
- admin console access and selected cross-tenant routes.
4.2 Impersonated super-admin¶
When impersonating a tenant/user:
- original super-admin status remains true;
- effective tenant/user/roles can come from target context;
- application page access generally delegates to target page-role decisions;
- individual handlers may still use
isSuperAdmin()and therefore permit behavior beyond the subject's normal role unless separately constrained.
This is a key reason actor and subject must remain explicit in target authorization.
4.3 Direct-access hub¶
Admin direct-access UI displays page/module availability and may show:
Available
Default Allow
Unknown Module
Disabled
No Module Guard
It is a diagnostic/navigation surface. Opening a page does not itself authorize every API/action/record behind that page.
4.4 Admin tenant override¶
Selected platform APIs accept X-Admin-Client-Id only on an allowlist and only for physical super-admin. Typed strict override additionally requires an authorization reference.
This is not the same as session impersonation.
5. UI Visibility And Backend Parity¶
Current UI can expose or hide actions using:
- menu rows;
- role IDs;
- module/config flags;
- page state;
- JavaScript flags such as administrator/super-admin;
- record status;
- virtual menu policy.
UI decisions are hints only.
For every consequential action the target must prove:
UI visible -> backend command allows expected actor/record
UI hidden -> backend command still denies direct request
UI partial/unavailable -> user sees exact reason and recovery owner
P2-007 remains the live-tenant role/page/API acceptance owner; this document does not activate it.
6. Current Fail-Open, Fail-Closed And Unknown Inventory¶
| Surface | Current behavior | Classification |
|---|---|---|
missing T_TENANT_MODULE row |
module allowed | compatibility fail-open |
| module DB error | module allowed | availability fail-open |
| page registry error | page denied | fail-closed |
| inactive page registry row | page denied | fail-closed |
| unmapped page in module map | allowed/unknown | compatibility |
| page menu DB error | page allowed/unknown | access fail-open |
| menu route DB error | caller-selected fail-open/fail-closed | heterogeneous |
| unregistered page | role 1 may enter | admin compatibility |
| API missing authentication | 401 | fail-closed |
| API role mismatch | 403 | fail-closed |
| strict tenant context mismatch | typed 4xx | fail-closed |
| record predicate absent or incomplete | handler-dependent | unknown/risk |
| browser button hidden | no backend guarantee | presentation only |
A broad conversion is prohibited while Phase implementation is held and live callers remain uncharacterized.
7. Current Source Gap Register¶
| ID | Gap | Consequence |
|---|---|---|
ACC-GAP-010 |
one page decision loses detailed reasons | support cannot explain the complete chain |
ACC-GAP-020 |
module/menu/page fail-open behavior differs | rollout risk and inconsistent direct/API behavior |
ACC-GAP-030 |
API v2 and legacy endpoints use different guard models | one role test does not prove all callers |
ACC-GAP-040 |
record predicates are handler-specific | route metadata cannot prove tenant/record safety |
ACC-GAP-050 |
numeric roles serve as action capabilities | role additions/remaps can broaden actions unintentionally |
ACC-GAP-060 |
physical super-admin remains true during impersonation | actor bypass can conflict with subject expectations |
ACC-GAP-070 |
UI action visibility is separate | hidden controls can still have callable endpoints |
ACC-GAP-080 |
direct/unregistered pages have compatibility access | page inventory is required before strict rollout |
ACC-GAP-090 |
special field-role policies live in shared config helpers | target semantic capability ownership is unclear |
ACC-GAP-100 |
virtual menu rows synthesize role policy | DB menu alone is not full authority |
ACC-GAP-110 |
admin direct-access availability is not command authorization | support may misread “available” as fully permitted |
ACC-GAP-120 |
no universal decision/correlation record | denied/allowed behavior is hard to reconcile across layers |
ACC-GAP-130 |
record-denial disclosure policy varies | 403/404/data leakage semantics are inconsistent |
ACC-GAP-140 |
config/credential prerequisites are not universally part of action decision | provider/action availability can diverge |
ACC-GAP-150 |
current Role/API matrix is incomplete across live users | broad guard changes can cause Client 1 outage |
8. Target Authority Map¶
| Concern | Target owner |
|---|---|
| Authentication and actor/subject | identity/session authority |
| Tenant context | typed tenant execution context |
| Profile/module/capability/config/credential | platform policy/resolution contracts |
| Page/API availability | route/application adapter policy |
| Action permission | semantic capability/action policy |
| Record ownership/relation | repository/application record predicate |
| Record-state eligibility | owning domain/application command |
| Override | explicit privileged delegation policy |
| Access decision diagnostics | read-only support decision trace |
| Business mutation | owning application command, not access helper |
Authorization evaluates existing authority. It does not become a generic workflow or business-state engine.
9. Caller Inventory Required Before Migration¶
For each selected page/API/action:
page route and direct URL
menu route and roles
module/config prerequisites
API v2 routes
legacy TYPE/ACTION routes
JavaScript callers
server-side internal callers
record tables and parent/child predicates
state blockers
super-admin/impersonation behavior
provider/file/device effects
current denial response
A capability cannot move to strict target authorization while an unlisted legacy caller can still mutate the same record.
10. Access Evidence Required¶
Per action/record:
- allowed role/tenant direct path;
- denied role;
- foreign tenant;
- missing record;
- wrong parent/child relation;
- wrong record state;
- module disabled;
- capability/config unavailable;
- direct URL;
- API direct call with hidden UI;
- super-admin direct mode;
- user impersonation;
- tenant-only impersonation;
- duplicate/unknown request where applicable;
- exact response and no information leakage;
- Client 1 non-regression;
- Client 2 expected behavior.
11. Evidence Boundary¶
This source authority does not prove:
- current Production
T_MENU,T_ROLE, module/config rows; - every direct URL;
- every legacy endpoint;
- every JavaScript caller;
- every record-level predicate;
- actual field-role behavior;
- current Client 1/Client 2 role matrix;
- provider/credential access;
- current denied-page UX;
- current Wiki access instructions;
- Next.js authorization behavior.
These require separately authorized source inventory, DB read, role/browser/API tests and field acceptance.
---¶
Source:
docs/reconstruction/PLATFORM_AUTHORIZATION_ACCESS_SOURCE_AUTHORITY.md— ctc repository · This page is an English translation of the source document. Identifiers, file paths and code symbols are unchanged.