Platform, Tenant, Role And Access — Source-Reconciled Current Contract¶
- Status:
SOURCE_RECONCILED / TARGET ROLLOUT NOT APPROVED - Task:
NS0-003 - Current-source revision:
98b3a59d76ce66c3e69788c93aac7e3e08e6edff - Scope: Platform/Tenant/Role/Access/Config/Audit/File dependencies consumed by CTC and MK
- Evidence level: repository source, schema-plan, migration and test review
- Runtime/DB/browser/operator verification:
NOT_RUN
1. Authority Decision¶
Current Platform behavior is not one gate.
Authentication
-> effective Tenant Context
-> module/config availability
-> menu/page/API availability
-> numeric-role compatibility
-> command-specific authorization
-> record tenant/relation predicate
-> record-state eligibility
-> provider/config/credential prerequisites
The following implications are invalid:
authenticated
!= authorized for every tenant
module enabled
!= menu visible
!= process capability enabled
!= action allowed
menu visible
!= page/API/record authorized
role assigned
!= every action allowed
super-admin actor
!= impersonated subject has every permission
2. Current Tenant Context¶
2.1 Legacy scalar resolution¶
The common PHP compatibility path resolves the effective local tenant in this order:
impersonation target CLIENT_ID
-> session CLIENT_ID
-> deployment Config::CLIENT_ID fallback
Actor and subject helpers also prefer impersonation target data where present.
Current implications:
- normal authenticated Web/API requests generally carry one numeric local tenant;
- impersonation separates the physical super-admin actor from the effective tenant/user;
- selected super-admin API routes can use an allowlisted tenant override;
- legacy CLI/direct callers can receive deployment tenant
1unless they bind an explicit context; - numeric
CLIENT_IDis deployment-local compatibility identity, not the target portable identity.
2.2 Typed context foundation¶
TenantExecutionContext already models:
localTenantId
optional globalTenantId
identityState: MAPPED | LEGACY_LOCAL_ONLY
tenantProvenance
entrypoint
sourceName / requestId
accessMode
actor
optional subject
optional credentialOwnerRef
policyState: STRICT | COMPATIBILITY_ONLY
A strict typed context rejects all-tenant request scope and can reject a new write when the context is compatibility-only.
2.3 Current rollout boundary¶
Typed context is active only for selected callers and opt-in routes.
strictTenantPrincipal = true
-> create strict TenantExecutionContext
-> expose compatibility scalar context to the handler
Non-opted routes still consume apiContext() and legacy scalar helpers.
Therefore:
typed foundation exists
!= repository-wide strict tenant execution
3. Current Authentication And Session Validation¶
Current API authentication:
session start
-> login_username present
-> active session user reread
-> role/tenant consistency check
-> 401 on failure
Session validation can invalidate a session when the current active user, tenant or role assignment no longer matches the session. Impersonated sessions additionally validate the original administrator and the target subject.
This proves active-session reread behavior. It does not prove SSO, token rotation, distributed session ownership or a target Next.js session bridge.
4. Current Module, Config And Capability Resolution¶
4.1 Concerns remain separate¶
Current and target questions are distinct:
| Concern | Current source owner |
|---|---|
| Tenant identity | session/impersonation helpers and selected TenantExecutionContext adapters |
| Module availability | T_MODULE, T_MODULE_PAGE, T_TENANT_MODULE, config/modules.php, module guard |
| Config value | T_TENANT_CONFIG, current config helper and caller fallback |
| Named process capability | mixed direct config/module/route logic; typed resolver foundation exists |
| Menu visibility | T_MENU, role lists and menu helpers |
| Action/record authorization | route metadata plus handler-specific predicates |
| Secret ownership | config/provider helper plus optional typed credential-owner reference |
4.2 Current compatibility behavior¶
Current page/module compatibility includes:
explicit disabled tenant-module row
-> deny
missing tenant-module row
-> compatibility allow
module source error
-> compatibility allow
inactive or failed page-registry lookup
-> deny
unmapped page
-> allowed / unknown
required config missing/false/error
-> deny for that mapped config gate
A boolean allow from the current module helper does not preserve whether the module was explicitly enabled or merely unconfigured.
4.3 Typed resolver foundation¶
The typed resolver distinguishes:
PLATFORM_CORE
MODULE_ENABLEMENT
PROCESS_CAPABILITY
CONFIG_VALUE
SECRET
and returns decision, source, validity, compatibility fallback and stable reason. It requires a strict tenant context. Broad first-party caller adoption is not proven.
Target new-system code should consume one resolved effective contract and must not reproduce raw config reads or numeric tenant branches across pages.
5. Current Menu, Page, API And Role Model¶
5.1 Storage¶
T_USER.ROLE_ID
= comma-separated numeric role IDs
T_ROLE
= tenant role records and DEFAULT_MENU_ID
T_MENU.MENU_ROLE_LIST
= comma-separated numeric role visibility/access compatibility
T_MODULE_PAGE
= global page registry/module binding
The menu tree is tenant scoped and excludes soft-deleted and permission-only rows. It can join a menu to a page by registry ID or legacy URL.
5.2 API route decision order¶
Current API v2 route handling can enforce:
authentication
-> optional strict tenant principal
-> moduleKey
-> requiredMenuRoutes
-> requiredRoleIds
-> handler
The handler still owns record predicates and state eligibility.
5.3 Current role limitations¶
- role IDs are implementation identifiers, not semantic action capabilities;
- route role lists are incomplete as a Product authorization model;
- super-admin bypasses several numeric-role checks;
- impersonation keeps the physical super-admin actor while changing the effective subject;
- UI hiding is not backend authorization.
A complete target action matrix cannot be inferred from the current menu alone.
6. Booking Dependency Readback¶
Booking currently depends on this Platform chain:
session tenant
-> page route
-> module/page compatibility
-> menu/role access
-> Booking API module tms.booking
-> handler tenant predicates
Current ownership conflict:
CTC booking-list page
= oms.inbound-order module binding
MK mk-booking-list page
= tms.booking module binding
shared Booking API
= tms.booking
The Legacy routes must remain available during coexistence. The target semantic owner remains Transportation/Ocean Booking, subject to target approval.
7. Audit And Correlation¶
Current audit/evidence is fragmented across:
- page usage/reporting;
- super-admin operations;
- Control Tower/admin audit helpers;
- operation events;
- table lifecycle timestamps;
- request IDs and application logs;
- process-specific evidence tables and fields.
No single current source proves a universal business-command audit envelope for Booking, Commercial Order or every Platform write.
Target requirement:
command request
-> actor/subject/tenant/correlation
-> owning transaction/effect
-> authoritative readback
-> immutable audit/event evidence
This is a target foundation requirement, not a claim that current Runtime already provides it.
8. File And Object Storage¶
Current file authority is split:
T_FILE
= tenant-scoped polymorphic metadata and record attachment
FileStorage
= EFS or S3 object adapter
record-specific helpers
= upload, preview, cleanup and relation validation
The object key includes tenant, related table and file UUID. Storage supports EFS and S3. Database soft-delete/cleanup and physical object deletion are separate effects.
Important current boundary:
T_FILE mutation committed
!= remote/local object deletion succeeded
Commercial Order delete explicitly prepares file object cleanup before soft-deleting attached file rows. Other modules require their own evidence.
9. Current Gaps¶
| ID | Gap | Consequence |
|---|---|---|
PLAT-GAP-010 |
strict typed tenant context is not universal | caller-by-caller migration required |
PLAT-GAP-020 |
missing module rows/errors can allow | current boolean cannot prove explicit enablement |
PLAT-GAP-030 |
menu/page/API/action/record gates are distributed | one route test does not prove authorization |
PLAT-GAP-040 |
numeric role IDs act as coarse capabilities | role changes can unintentionally broaden actions |
PLAT-GAP-050 |
first-class Operating Profile binding is not universally consumed | profile cannot be inferred from current tenant ID |
PLAT-GAP-060 |
config provenance/validity often collapses to a fallback value | diagnostics and strict rollout are incomplete |
PLAT-GAP-070 |
audit/effect evidence is fragmented | no universal command completion proof |
PLAT-GAP-080 |
file metadata and object effects are separate | cleanup/retry/reconciliation need explicit ownership |
PLAT-GAP-090 |
CTC/MK Booking pages have different current module bindings | target owner and compatibility routes must be separated |
10. Target Contract Direction¶
The new system should use:
strict TenantExecutionContext
-> Operating Profile binding
-> module resolution
-> named capability resolution
-> typed policy/config resolution
-> role/action/record access
-> owning command/query
-> repository transaction
-> audit/outbox/effect
-> authoritative readback
Rules:
- no new
if (clientId === 2)or customer-name branch; - no module allow interpreted as action permission;
- no profile interpreted as authorization;
- no request-time Control Tower database dependency;
- no all-tenant business write context;
- no record access without tenant and relation predicates;
- no secret value in safe serialized diagnostics.
11. Lifecycle Result¶
Platform/Tenant/Role source map
= SOURCE_RECONCILED
strict typed Runtime adoption
= PARTIAL / CALLER-SPECIFIC
target profile binding
= OPEN_DECISION
target role/action matrix
= OPEN_DECISION
live role/menu/config proof
= NOT_RUN
12. Evidence Sources¶
Primary current sources:
config/config.php
config/modules.php
config/page_routes.php
app/shared/api/runtime.php
app/platform/tenant/TenantExecutionContext.php
app/platform/tenant/tenant_execution_context_adapter.php
app/platform/tenant/module_guard.php
app/platform/tenant/config_helper.php
app/platform/tenant/CapabilityDefinitionRegistry.php
app/platform/tenant/capability_resolver.php
app/platform/menu/menu_query_helper.php
app/platform/master-data/api_helper.php
app/shared/storage/file_storage.php
app/platform/audit/**
Secondary dated evidence:
docs/reconstruction/PLATFORM_TENANT_PROFILE_CAPABILITY_CONFIGURATION_SOURCE_AUTHORITY.md
docs/reconstruction/PLATFORM_AUTHORIZATION_ACCESS_SOURCE_AUTHORITY.md
scripts/migrations/2026-08-01_p2_003_client2_office_access.php
Secondary documents provide historical reconciliation only; current source remains the current-behavior authority.
---¶
Source:
new-system/docs/reconstruction/PLATFORM_TENANT_ROLE_SOURCE_RECONCILED.md— ctc repository · This page is an English translation of the source document. Identifiers, file paths and code symbols are unchanged.