Skip to content

Platform Authorization And Access — Capability Rebuild Packet


1. Required Platform Outcome

For every protected query or command, the system returns one explicit, explainable decision.

Authenticated Actor/Subject
+ Strict Tenant Context
+ Product/Module Availability
+ Named Capability
+ Page/API/Action Policy
+ Record Ownership/Relation
+ Record-State Eligibility
+ Config/Credential Prerequisite
= Access Decision

1.1 Decision values

ALLOW
DENY
UNAVAILABLE
UNKNOWN
  • ALLOW: all required checks are satisfied.
  • DENY: actor/subject is not permitted.
  • UNAVAILABLE: owning product/module/capability/config/provider is not available.
  • UNKNOWN: authority cannot determine a safe result.

Consequential writes treat UNKNOWN as not authorized. Existing live compatibility is migrated caller-by-caller rather than changed globally by this packet.

1.2 Administrator/support result

An authorized support user can inspect a redacted decision trace:

  • physical actor and effective subject type;
  • tenant provenance;
  • page/API/action key;
  • module/capability/config availability;
  • role/action decision;
  • record predicate category;
  • record-state predicate category;
  • result and stable reason;
  • current source/release version;
  • compatibility fallback used;
  • owner for correction.

The trace never returns secret values or unauthorized record content.

1.3 Non-goals

Do not create:

  • one monolithic isAllowed() business engine;
  • page/menu visibility as final authorization;
  • generalized workflow state inside access policy;
  • a new permission table without accepted data model;
  • a customer-specific role fork;
  • universal fail-closed rollout under this documentation wave;
  • frontend-only access control;
  • automatic super-admin bypass of every business command;
  • a second tenant/module/capability authority.

2. Access Decision Contract

interface AccessDecision {
  decision: 'ALLOW' | 'DENY' | 'UNAVAILABLE' | 'UNKNOWN'
  reasonCode: string
  requestId: string
  policyVersion: string
  sourceRevision?: string
  actor: { type: string; id: string }
  subject?: { type: 'USER'; id: string } | null
  tenant: {
    localTenantId: number
    globalTenantId?: string
    provenance: string
  }
  resource: {
    pageKey?: string
    apiRouteKey?: string
    actionKey: string
    recordType?: string
    recordId?: string
  }
  checks: {
    authentication: CheckResult
    tenant: CheckResult
    module?: CheckResult
    capability?: CheckResult
    menuPage?: CheckResult
    roleAction?: CheckResult
    record?: CheckResult
    recordState?: CheckResult
    config?: CheckResult
    credential?: CheckResult
  }
  compatibilityFallbacks: string[]
  safeUserMessage: string
  correctionOwner?: string
}

interface CheckResult {
  state: 'PASS' | 'FAIL' | 'NOT_APPLICABLE' | 'UNKNOWN'
  reasonCode: string
  source?: string
}

The client receives a safe subset. Protected support tooling may receive the redacted full trace.


3. Target Evaluation Order

1. Authenticate physical actor
2. Resolve effective subject and strict tenant
3. Resolve owning product/module/capability
4. Resolve page/API adapter availability
5. Resolve semantic action permission
6. Load record through tenant-scoped repository predicate
7. Validate parent/child relation
8. Validate record-state eligibility in owning application command
9. Validate required config/credential
10. Return decision and execute query/command only on ALLOW

3.1 Why record state stays with the application owner

Authorization may ask whether the state check passed, but the owning command defines the rule.

Examples:

May user invoke Reverse Allocation?
= access policy

Is this Allocation reversible after downstream Scale/Delivery?
= Allocation application/domain policy

Do not duplicate state-transition rules in a generic access registry.


4. Semantic Queries

4.1 EvaluatePageAccess

Input:

  • actor/subject/tenant context;
  • page key and query variant;
  • requested mode.

Returns module/capability/menu/role availability and safe route result.

4.2 EvaluateApiAccess

Input:

  • request method/route key;
  • actor/subject/tenant;
  • owning module/capability/action.

Does not load or reveal protected record content.

4.3 EvaluateActionAccess

Evaluates semantic action permission independent of UI placement.

mk.allocation.apply
mk.scale.reverse
ctc.final-review.confirm
platform.impersonation.start

These names are semantic inputs; registry implementation remains a later decision.

4.4 EvaluateRecordAccess

Loads a minimal tenant/ownership/relation projection through the owning repository.

Returns either:

  • allowed record reference;
  • denied/not-found according to disclosure policy;
  • relation/state owner for next check.

4.5 GetVisibleActions

Returns UI action hints derived from the same accepted policy inputs. It never replaces backend checks.

4.6 GetAccessDecisionTrace

Read-only administrator/support query. Requires a privileged diagnostic capability and returns redacted reasons, not protected record data.

4.7 GetAccessMatrixForTenantRole

Produces a review matrix for one tenant/profile/role and selected page/API/action set. Used for P2-style acceptance, not request-time authorization.


5. Semantic Commands

5.1 AuthorizeCommand

Application adapter invokes this with:

  • strict actor/subject/tenant context;
  • action key;
  • record reference if any;
  • expected record state/version;
  • request/correlation ID.

ALLOW is required before the owning command executes.

5.2 GrantTemporaryAdminDiagnosticAccess

Optional future command for a narrow diagnostic page/action, not general business mutation.

Required:

  • physical super-admin;
  • target tenant;
  • exact diagnostic resource;
  • reason/authorization reference;
  • short expiry;
  • audit;
  • no secret exposure.

5.3 RevokeTemporaryAdminDiagnosticAccess

Ends the diagnostic grant and records the result.

5.4 PublishRoleActionPolicy

Target control-plane command only if a versioned role/action policy model is accepted. Current T_MENU/role state must not be silently rewritten by documentation.


6. Stable Error Contract

ACCESS_UNAUTHENTICATED
ACCESS_SESSION_INVALID
ACCESS_TENANT_CONTEXT_REQUIRED
ACCESS_TENANT_FORBIDDEN
ACCESS_MODULE_DISABLED
ACCESS_MODULE_UNKNOWN
ACCESS_CAPABILITY_DISABLED
ACCESS_CAPABILITY_UNAVAILABLE
ACCESS_CONFIG_UNAVAILABLE
ACCESS_CREDENTIAL_UNAVAILABLE
ACCESS_MENU_REQUIRED
ACCESS_PAGE_FORBIDDEN
ACCESS_API_FORBIDDEN
ACCESS_ROLE_DENIED
ACCESS_ACTION_DENIED
ACCESS_RECORD_NOT_FOUND_OR_DENIED
ACCESS_RECORD_RELATION_DENIED
ACCESS_RECORD_STATE_DENIED
ACCESS_OVERRIDE_FORBIDDEN
ACCESS_IMPERSONATION_RESTRICTED
ACCESS_POLICY_STALE
ACCESS_POLICY_SOURCE_ERROR
ACCESS_UNKNOWN
ACCESS_UNEXPECTED_ERROR

Disclosure policy decides when a missing/foreign record uses one combined not-found/denied response.


7. Role And Capability Model

7.1 Current compatibility

Current roles are numeric IDs and can be stored as comma-separated values.

Representative compatibility labels:

1 Administrator
2 Office Manager
3 Dispatch Manager
4 Forklift Operator
5 Truck Operator
6 Yard Truck Driver

Current special policies and onboarding seeds use these IDs directly.

7.2 Target semantic capability

Target action permission uses stable semantic keys, for example:

platform.users.manage
platform.impersonation.start
ctc.inbound.assign-loader
ctc.loader.complete
ctc.final-review.confirm
mk.commercial.update
mk.booking.update
mk.allocation.apply
mk.scale.reverse

A role is a named bundle of capabilities for one profile/tenant. The bundle does not become record ownership or state eligibility.

7.3 Migration rule

numeric role decision
-> read-shadow semantic capability decision
-> compare expected allow/deny
-> selected route/action cutover
-> rollback
-> numeric-role caller-zero for that action

Do not rename numeric roles and call the migration complete.


8. Record Authorization Contract

Every consequential record query/command defines:

record type
primary ID / UUID
owning tenant field
parent/child tenant relationship
soft-delete predicate
profile applicability
actor/subject ownership if applicable
required related record
current state/version
safe denial response

8.1 Required repository pattern

FindAuthorizedRecordForAction(
  tenant,
  recordId,
  action,
  expectedVersion
)

The repository returns only the minimal projection needed for authorization/application validation.

8.2 Prohibited patterns

  • load by ID without tenant and check later in UI;
  • accept CLIENT_ID from body as authority;
  • infer record access from parent page visibility;
  • return foreign record metadata in a denial;
  • treat super-admin actor as automatic owner while impersonating;
  • duplicate record-state logic in menu/page policy.

9. Page/API/UI Parity Matrix

For every selected action:

Dimension Required evidence
Menu expected visibility for each role/profile
Page direct URL allow/deny
Initial query page can/cannot load data
Action UI button/control visible or hidden
API direct request allow/deny independent of UI
Record own tenant, foreign tenant, missing and wrong relation
State valid and invalid current state
Impersonation direct actor, user subject and tenant-only support mode
Module/config enabled, disabled, missing and source-error compatibility
Result stable error and no data leak

P2-007 or its future accepted successor owns live role acceptance. This packet supplies the matrix structure only.


10. Policy Decision Matrix

ID Decision Current evidence Recommended target Status
ACC-POL-010 Unknown write decision current fail-open exists in some layers deny selected consequential writes REQUIRED FOR TARGET
ACC-POL-020 Unknown read decision compatibility varies caller-specific explicit policy OPEN
ACC-POL-030 Missing module assignment current allow seed parity before strict cutover RECOMMENDED
ACC-POL-040 Module source error current allow in core helper expose unavailable/compatibility reason; migrate by caller OPEN
ACC-POL-050 Unmapped page current allow/unknown inventory and explicit ownership before strict REQUIRED BEFORE CUTOVER
ACC-POL-060 Unregistered page admin entry role 1 compatibility explicit diagnostic/owner route or retire OPEN
ACC-POL-070 Super-admin bypass broad in some layers action-specific privileged capability OPEN
ACC-POL-080 Impersonation permission actor and subject semantics mixed in callers explicit actor/subject policy REQUIRED
ACC-POL-090 Tenant-only impersonation current support mode diagnostics/support only unless action explicitly allowed RECOMMENDED
ACC-POL-100 Record denial response handler-specific stable 403/404 disclosure policy OPEN
ACC-POL-110 Menu as API prerequisite current API supports required menu routes keep as compatibility input, not sole target action authority RECOMMENDED
ACC-POL-120 Numeric roles current primary access input semantic capability migration by action REQUIRED FOR TARGET
ACC-POL-130 Virtual menu roles current compatibility move accepted behavior to profile/capability owner OPEN
ACC-POL-140 UI visibility source multiple JS/PHP hints derive from same policy inputs; backend always rechecks REQUIRED
ACC-POL-150 Direct page aliases selected print-page aliases explicit owner/action mapping OPEN
ACC-POL-160 Legacy TYPE/ACTION routes separate guard architecture adapter or retirement after caller-zero REQUIRED FOR P12
ACC-POL-170 Access diagnostic trace not universal redacted support query RECOMMENDED
ACC-POL-180 Client 1 broad guard rollout prior outage risk no global conversion without full caller/role evidence FIXED SAFETY RULE

11. Target Component Architecture

flowchart TB
    React[React Pages and Action Hints]
    Next[Next.js Page/API Adapters]
    PHP[Legacy PHP Adapters]
    Identity[Actor + Tenant Context]
    Platform[Module / Capability / Config]
    Access[TypeScript Access Policy]
    App[Owning Application Command / Query]
    Repo[Tenant-scoped Repository]
    DB[(MySQL)]
    Audit[Decision / Transition Evidence]

    React --> Next
    Next --> Identity
    PHP --> Identity
    Identity --> Platform
    Platform --> Access
    Access --> App
    App --> Repo
    Repo --> DB
    Access --> Audit
    App --> Audit

The access policy does not execute business SQL or provider calls.


12. Migration Waves

ACC-W0  Full selected page/API/action/record caller inventory
ACC-W1  Redacted read-only access decision trace
ACC-W2  Semantic action definition for one low-risk query
ACC-W3  UI/backend parity for one read-only page
ACC-W4  One strict API read cohort
ACC-W5  One bounded write action read-shadow
ACC-W6  One authoritative semantic action cutover
ACC-W7  Record/state denial parity and rollback
ACC-W8  Impersonation/super-admin decision parity
ACC-W9  Legacy TYPE/ACTION adapter or retirement
ACC-W10 Target-role and Client 1/2 stabilization
ACC-W11 Current Wiki/admin diagnostics publication
ACC-W12 Numeric role/menu-only caller-zero for selected scope
ACC-W13 Shared/Dedicated parity
ACC-W14 PostgreSQL later

No wave is activated by this document.


13. Rollback

Rollback restores the previous accepted decision owner for the selected route/action. It preserves:

  • current role/menu/module rows;
  • record data;
  • audit/decision evidence;
  • current URL/API compatibility;
  • actor/subject/tenant lineage;
  • explicit denial fixes already accepted.

Rollback does not:

  • dual-authorize old and new decisions indefinitely;
  • convert an unknown result into allow;
  • expose previously denied record data;
  • remove audit/history;
  • revert business records changed by an already-committed command;
  • broadly reopen a disabled module.

14. Stable Acceptance Scenarios

Page and menu

ACC-SCN-010 expected menu and page allow
ACC-SCN-020 hidden menu / direct page denied
ACC-SCN-030 query-specific menu route
ACC-SCN-040 unregistered page compatibility
ACC-SCN-050 page registry inactive/error
ACC-SCN-060 module disabled/missing/error
ACC-SCN-070 config prerequisite disabled/error

API and action

ACC-SCN-110 authenticated API allow
ACC-SCN-120 unauthenticated API
ACC-SCN-130 menu prerequisite denied
ACC-SCN-140 numeric role denied
ACC-SCN-150 UI hidden / direct API denied
ACC-SCN-160 legacy TYPE/ACTION parity
ACC-SCN-170 unknown decision on write

Record and state

ACC-SCN-210 own-tenant record allow
ACC-SCN-220 foreign-tenant record denied without leak
ACC-SCN-230 missing record
ACC-SCN-240 wrong parent/child relation
ACC-SCN-250 invalid record state
ACC-SCN-260 stale version
ACC-SCN-270 provider/config prerequisite unavailable

Privileged and migration

ACC-SCN-310 non-impersonating super-admin diagnostic
ACC-SCN-320 user impersonation subject decision
ACC-SCN-330 tenant-only support decision
ACC-SCN-340 admin override allowlisted/unauthorized
ACC-MIG-SCN-010 old/new read parity
ACC-MIG-SCN-020 semantic action one-decision cutover
ACC-MIG-SCN-030 rollback without access widening
ACC-MIG-SCN-040 Client 1 non-regression
ACC-MIG-SCN-050 Client 2 expected behavior
ACC-MIG-SCN-060 legacy caller-zero
ACC-MIG-SCN-070 Shared/Dedicated parity
ACC-MIG-SCN-080 PostgreSQL parity

15. Definition Of Ready For Implementation Review

  • selected pages/APIs/actions/records and callers are fully inventoried;
  • current role/menu/module/config rows are read for the target environment;
  • actor/subject/tenant semantics are accepted;
  • semantic action and record predicate are explicit;
  • record-state owner is identified;
  • unknown/fail-open compatibility is documented for the selected cohort;
  • UI/API direct-call parity scenarios exist;
  • Client 1 non-regression and rollback are explicit;
  • no unrelated broad guard conversion is required;
  • remaining unknowns cannot change live access for the selected wave.

16. Definition Of Complete

A selected authorization migration wave is complete only after:

  • current and target decisions match accepted policy;
  • target-role browser and direct API tests pass;
  • foreign record and wrong-state negatives pass;
  • UI visibility and backend authorization agree;
  • impersonation and super-admin cases are verified;
  • one authoritative decision is active for the cohort;
  • rollback is rehearsed;
  • current support/Wiki guidance is published and read back;
  • old route/role/menu-only decision callers reach zero for the selected scope;
  • observation/stabilization passes.

Documentation alone does not satisfy these criteria.

---

Source: docs/reconstruction/PLATFORM_AUTHORIZATION_ACCESS_REBUILD_PACKET.md — ctc repository · This page is an English translation of the source document. Identifiers, file paths and code symbols are unchanged.