Skip to content

Platform Tenant / Config / Credential — Current Source Refresh — 2026-08-10

  • Status: CURRENT SOURCE-RECONCILED DOCUMENTATION / NO IMPLEMENTATION ACTIVATION
  • Task: CTC-CDOC-005
  • Source baseline actually reviewed: qa@8981a02f7b2a2fa256a7365d6921f3d7636f1fe2, then master@f82a91f596e6d3ed636c102b458b3dd07d8475be
  • Source-owner baseline: 8981a02f7b2a2fa256a7365d6921f3d7636f1fe2; f82a91f... adds only CTC-CDOC-006 documentation and does not change the owner source reviewed here
  • Packet baseline: qa@4f6165bc4c53a7d98b0c246392dd9ed5bd75c21c
  • Provider credential packet baseline: qa@2163051c30380585f07b9541ccd15cbc28d7e7fe
  • Phase implementation: USER HOLD
  • Effects: repository documentation only; no Runtime, DB, config, credential, role, menu, provider, Wiki, service or deployment effects

1. Authority And Concern Separation

Current source controls current implementation facts. Target reconstruction packets remain future design inputs only where explicitly labeled target.

Tenant identity
!= Operating Profile
!= Module enablement
!= Named process capability
!= Typed config value
!= Credential availability
!= Credential reveal/update authority
!= Menu/Page/API/Action/Record authorization
!= Provider effect authorization

No positive result in one concern grants another.


2. Baseline Drift And Current Owners

The platform packet baseline 4f6165... is an ancestor of the current source and is stale as a current owner baseline.

Owner Current finding
app/platform/tenant/config_helper.php changed after packet baseline; now owns encrypted tenant-secret support, provider definitions, capability metadata and mixed cache behavior
app/platform/tenant/capability_resolver.php current blob is unchanged from the packet baseline; typed decision semantics remain stable
app/platform/tenant/CapabilityDefinitionRegistry.php current source present; absent from the old packet baseline
app/platform/tenant/effective_capability_diagnostics.php current source present; returns safe effective-state diagnostics
app/platform/tenant/module_guard.php current source has strict typed module resolution alongside legacy module/page/config decisions
app/platform/tenant/api_strict_principal.php strict tenant context bridge into API scalar compatibility context
app/platform/api_routes.php current managed credential and effective-capability API owner
app/shared/api/logging.php current request-body redaction and sensitive-field masking owner
frontend/pages/platform/admin-console/tenants.php current Admin Console consumer for tenant/config/credential/effective diagnostics

The credential packet baseline 2163051... is also historical. Its managed reveal/replace/encrypted-storage contract remains represented in current source, with later capability-definition/diagnostics integration layered on top.


3. Plain Config, Secret Config And Managed Credential

Ordinary plain config

tenant_config_get() reads active T_TENANT_CONFIG by effective CLIENT_ID and CONFIG_KEY. Missing, stored-empty or source-error cases collapse to the caller default at the scalar boundary. Typed wrappers normalize bool/int values but still lose provenance and validity.

scalar config value
!= explicit configured policy
!= module/capability authorization

Secret-classified runtime config read

For a key classified secret, the helper considers both <KEY> and SECRET.<KEY> and prefers the managed SECRET.<KEY> row. Managed envelopes are decrypted for trusted Runtime consumers. Legacy plaintext <KEY> remains compatibility-read behavior.

This internal Runtime read is not credential reveal.

Managed credential storage

Preferred managed storage is:

T_TENANT_CONFIG.CONFIG_KEY = SECRET.<ORIGINAL_KEY>

Current source uses an enc:v1: AES-256-GCM envelope with key material derived from CTC_TENANT_SECRET_KEY, which must decode to 32 bytes.

No plaintext, ciphertext or key material was read in this task.


4. Credential Lifecycle

Managed credential operations are allowlisted by tenant_provider_config_definitions() entries with valueType = secret.

Reveal

Current source provides the explicit privileged reveal route documented as:

POST /platform/admin/tenants/{clientId}/credentials/{credentialKey}/reveal

It is separate from ordinary config/status reads and may return the decrypted credential only through that privileged response path. Source-level response controls include no-cache/no-store semantics.

Replace / rotate

Current source provides:

POST /platform/admin/tenants/{clientId}/credentials/{credentialKey}

The managed replacement contract:

  1. validates tenant/admin/key scope;
  2. rejects empty replacement values;
  3. checks EXPECTED_UPDATED_AT when compatible revision metadata exists;
  4. encrypts the replacement into SECRET.<KEY>;
  5. writes available value-type/module/update metadata;
  6. wipes and soft-deletes the active legacy plaintext <KEY> row;
  7. rereads/returns metadata rather than the credential value.

Revision conflict

Optimistic conflict protection depends on installed revision metadata. Source support does not prove UPDATED_AT exists in the target environment. If it is absent, equivalent optimistic concurrency is not established by the inspected source.

Removal

No managed remove/clear/revoke helper or route was located in the reviewed source set.

REVEAL: SOURCE PRESENT
REPLACE / ROTATE: SOURCE PRESENT
LEGACY PLAINTEXT RETIREMENT ON REPLACE: SOURCE PRESENT
REMOVE / CLEAR: NOT ESTABLISHED

Hide, Cancel, blank Save, provider disconnect, or plaintext retirement during replacement must not be mislabeled as credential removal.


5. Module / Profile / Capability Applicability

Current effective diagnostics explicitly keep the unresolved authorities unresolved:

Operating Profile: UNBOUND
Entitlement: UNKNOWN
Module: RESOLVED PER MODULE
Named capability: REGISTERED SUBSET
Role/Menu: EXTERNAL AUTHORITY
Provider effect authority: UNKNOWN

Legacy module behavior remains compatibility-oriented: explicit disable denies, while missing/source-error cases can allow under existing defaults.

Selected strict API paths instead use:

strict TenantExecutionContext
-> current row observation
-> CapabilityDefinitionRegistry
-> CapabilityResolver
-> safe typed resolution

The registered process-capability subset includes compatibility definitions such as MK_DOCUMENT_WORKFLOW_ENABLED and EXPORT_BROKERAGE_WORKFLOW_ENABLED. A compatibility default is not accepted Product entitlement or explicit tenant policy.


6. Strict Resolver Versus Legacy PHP/Scalar Callers

Current architecture is hybrid.

Strict selected API flow:

TenantExecutionContextAdapter
-> strict TenantExecutionContext
-> scalar bridge + safe serialized context
-> typed module/capability/config resolution where opted in

Legacy/current compatibility flow still exists through:

getClientId()
moduleGuardModuleDecision()
moduleGuardPageDecision()
moduleGuardConfigDecision()
isModuleEnabled()
tenant_config_get*()

Therefore:

typed foundation present
!= repository-wide typed execution
!= repository-wide profile/capability cutover

Caller-by-caller parity is still required before retirement of legacy behavior.


7. Current Cache Behavior

Helper Static cache partition
tenant_config_get() DB object identity + tenant + config key
tenant_config_get_many() tenant + config key; no DB object identity
tenant_module_enabled() DB host/database + tenant + module key
tenant_config_supports_metadata() one process-static capability result

tenant_config_upsert() invalidates the shared menu cache, but no universal reset for all already-populated config static caches was located.

Evidence implications:

  • same-process read-after-write freshness is not established;
  • multi-read must not be assumed DB-object isolated;
  • heterogeneous-schema multi-DB processes can make the metadata-support static result material;
  • short-lived PHP requests may naturally discard static state, but that is Runtime evidence, not a source guarantee.

No Production incident is inferred.


8. Secret-Safe Diagnostics And Logging

tenant_effective_capability_diagnostics() internally reads configured rows but replaces secret content with a configured-presence marker before safe resolver serialization. Safe output may expose hasValue, source, validity, module/provider labels, fallback and reason; it is not secret reveal or provider validation.

Source inspection of app/shared/api/logging.php confirms:

  1. routes with redactRequestBody = true store an empty request body in API log context;
  2. apiLogMask() masks password/token/authorization/API-key/config-value/credential-value-like fields;
  3. audit input summaries exclude sensitive categories.

No Runtime log was read and no credential route was executed.


9. Stale / Historical Findings

Original Tenant/Profile/Capability packet

The 4f6165... source baseline remains historical evidence but is no longer current for this owner set.

2026-08-09 dual-ref authority

PLATFORM_TENANT_CAPABILITY_DUAL_REF_CURRENT_AUTHORITY_2026-08-09.md accurately described a prior state where effective diagnostics were QA-only and absent from release master.

At this task's current reviewed refs, the diagnostics/registry source is present in both qa@8981a02... and master@f82a91f.... The prior QA-only/master-absent statement is therefore historical branch-status evidence, not current navigation.

master@f82a91f... differs from qa@8981a02... only because a parallel CTC-CDOC-006 documentation commit landed during this session; it does not change the Tenant/Config source-owner facts above.

Neither Git ref proves deployed Runtime identity.


10. Open Policy Questions

  1. What explicit lifecycle owns credential remove/revoke/clear?
  2. Should credential reveal require privileged-action reauthentication beyond current Admin Console/session authorization?
  3. Is credential administration allowed while the provider module is disabled for setup/recovery, or should a separate management capability gate it?
  4. What is the accepted tenant-to-operating-profile composition model?
  5. Which callers may retain missing/error compatibility fallback and which must become strict?
  6. What cache invalidation/version contract is required for same-process, long-running and multi-DB consumers?
  7. Does package/tier ever become entitlement authority?

No policy answer is invented here.


11. Runtime / Environment Evidence Still Required

Still NOT RUN:

  • deployed source/config/schema identity;
  • installed T_TENANT_CONFIG columns/indexes and active-row metadata;
  • managed-secret versus legacy-row coexistence counts without values;
  • Admin/super-admin/same-tenant/cross-tenant behavior;
  • dedicated-deployment direct-route behavior;
  • safe effective-diagnostics API/browser readback;
  • runtime log-redaction observation with synthetic values;
  • same-request/next-request/long-running cache freshness;
  • multi-DB cache partition behavior;
  • credential replacement provider consumption/validity;
  • current Wiki content;
  • complete strict-versus-legacy caller inventory.

Use RBR-TENANT-CONFIG-002-READONLY-PREFLIGHT.md only after separate environment-read authorization.


12. Disposition

Current source reconciliation: COMPLETE FOR CTC-CDOC-005
Plain config contract: SOURCE PRESENT
Managed encrypted credential storage: SOURCE PRESENT
Managed reveal: SOURCE PRESENT
Managed replace/rotate: SOURCE PRESENT
Legacy plaintext retirement on replace: SOURCE PRESENT
Managed removal: NOT ESTABLISHED
Request-body redaction: SOURCE PRESENT
Safe effective diagnostics: SOURCE PRESENT
Canonical profile binding: NOT ESTABLISHED
Repository-wide strict adoption: NOT ESTABLISHED
Runtime/environment evidence: NOT RUN
Phase impact: NONE
M3: NO
M4: NO
External effects: NONE

---

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