Platform Provider Credential Management — Current Source — 2026-08-08¶
- Status:
CURRENT SOURCE CONTRACT / ENVIRONMENT AND ROLE EVIDENCE REQUIRED - Current review ref:
qa@2163051c30380585f07b9541ccd15cbc28d7e7fe - Owning source change:
feat: allow admin provider credential reveal - Integration refresh:
PLATFORM_INTEGRATION_PROVIDER_CURRENT_SOURCE_REFRESH_2026-08-08.md - Read-only evidence package:
RBR-CREDENTIAL-001-READONLY-CURRENT-STATE-PREFLIGHT.md - Current Admin Runbook:
PLATFORM_TENANT_CONFIGURATION_ADMIN_SUPPORT_RUNBOOK.md - Phase implementation:
USER HOLD
1. Purpose¶
This document records the current source contract for Provider Settings credential reveal and replacement.
It separates:
credential definition
credential storage
credential availability metadata
credential reveal
credential replacement
provider authentication
provider effect authorization
provider effect result
These are not interchangeable.
2. Current Actors¶
Super administrator¶
Can select a tenant in Admin Console and invoke the managed credential routes for that explicit tenant.
Tenant administrator¶
Current server access requires Admin Console access and restricts a non-super-admin actor to:
requested clientId == effective getClientId()
The current Admin Console access helper accepts super-admin or effective numeric role 1.
Other roles¶
No current managed credential access is intended through these routes. The source rechecks the Admin Console predicate server-side.
Important distinction¶
Tenant administrator may reveal/update an allowlisted tenant credential
!= tenant administrator may call every provider operation
Module, capability, action, record and provider-effect authorization remain separate.
3. Credential Allowlist¶
A key is manageable only when:
tenant_provider_config_definitions()[KEY] exists
AND valueType == secret
Current families represented in the allowlist include:
- Gemini and legacy image-provider credentials;
- Telegram bot/webhook/cron secrets;
- Gmail credential and operation secrets;
- QuickBooks Time OAuth/client/setup secrets;
- QuickBooks Online OAuth/client secrets;
- APMT consumer/authorization keys;
- Twilio auth and AI Voice secrets.
Non-secret provider settings such as model, URL, timeout, mailbox name or enabled flag are not revealable through this credential endpoint.
Arbitrary config keys and environment-variable names are rejected.
4. Storage Authority¶
4.1 Preferred row¶
T_TENANT_CONFIG.CONFIG_KEY = SECRET.<ORIGINAL_KEY>
4.2 Envelope¶
enc:v1:<base64(nonce + GCM tag + ciphertext)>
Encryption key source:
CTC_TENANT_SECRET_KEY
Required key shape:
base64-encoded 32-byte key
4.3 Legacy compatibility¶
Read supports either:
SECRET.<KEY>
OR
<KEY>
and prefers the encrypted companion row.
This means a legacy plaintext row may still be readable until a managed replacement retires it.
4.4 Replacement migration¶
Managed replacement:
- reads current source/revision;
- encrypts the replacement;
- updates or inserts
SECRET.<KEY>; - records
VALUE_TYPE='secret'when schema supports it; - associates module metadata when schema supports it;
- wipes and soft-deletes the active legacy plaintext
<KEY>row; - rereads the stored credential metadata.
4.5 Schema compatibility¶
Current helper adapts to presence/absence of:
VALUE_TYPE
UPDATED_AT
MODULE_ID
Therefore source support does not prove which metadata is installed in the current environment.
5. Safe List/Status Read¶
The ordinary tenant-config/provider-list query:
- removes
SECRET.*rows from the response; - returns the public original key;
- reports whether an encrypted row has a value;
- reports last-updated metadata when available;
- keeps
CONFIG_VALUEempty for secret fields.
Safe status output may include:
credential key
provider
label
module key
configured / not configured
updatedAt
It must not include the credential value.
6. Reveal Command¶
Current route:
POST /platform/admin/tenants/{clientId}/credentials/{credentialKey}/reveal
Preconditions¶
- authenticated session;
- Admin Console access;
- same-tenant restriction for non-super-admin;
- allowlisted secret key;
- readable/decryptable stored value.
Result¶
credentialKey
configured
value
updatedAt
The current result intentionally contains the decrypted credential value.
Response controls¶
Cache-Control: no-store, private
Pragma: no-cache
UI controls¶
The current page:
- requests one credential only;
- uses password input by default;
- toggles Show/Hide;
- clears the displayed value when another credential is revealed;
- clears credential fields on page exit;
- provides accessible show/hide labels.
Non-implications¶
Reveal succeeded
!= credential is valid at provider
!= module/capability enabled
!= provider effect authorized
!= provider connection healthy
7. Replacement Command¶
Current route:
POST /platform/admin/tenants/{clientId}/credentials/{credentialKey}
Body semantics:
VALUE
EXPECTED_UPDATED_AT optional
Current behavior¶
- empty
VALUEis rejected; - key must remain allowlisted;
- tenant/admin checks are repeated;
- revision conflict is returned when expected metadata differs;
- encrypted row is written;
- legacy plaintext row is retired;
- response returns updated metadata, not plaintext.
Concurrency¶
When UPDATED_AT metadata is installed and supplied, the update uses a conditional revision check.
When the environment does not support UPDATED_AT, the same optimistic concurrency protection is not available in the inspected helper.
Removal¶
Current helper text says removal is a separate explicit action. No managed credential removal helper or route was located in the inspected source.
Current classification:
REVEAL: PRESENT
REPLACE: PRESENT
REMOVE: NOT ESTABLISHED
Do not describe blank Save, Cancel or Hide as credential removal.
8. Logging And Evidence¶
Current routes declare:
redactRequestBody = true
Current API logging:
- replaces the request body with an empty structure in route log context;
- masks names matching credential/config/token/secret patterns in ordinary masking;
- does not use the credential response as normal request-log content.
Current static test asserts these boundaries.
No credential-domain immutable event was located for:
REVEAL
REPLACE
FAILED REVEAL
FAILED REPLACE
Current request diagnostics may establish actor, route, time, request ID and result metadata, but request diagnostics are not a business/security approval ledger.
Required future evidence should distinguish:
request observed
credential row changed
provider later consumed the credential
provider operation succeeded
9. Dedicated Deployment Boundary¶
Current Admin Console page presents tenant management as read-only in a dedicated deployment.
The inspected credential route/helper does not contain an explicit dedicated-deployment guard.
Current classification:
UI read-only intent: PRESENT
Direct credential route deployment guard: NOT LOCATED
Current deployed behavior: NOT VERIFIED
Do not infer server denial from disabled/hidden UI controls.
10. Cache And Consumer Boundary¶
Current tenant-config readers use process-local static caches.
Managed replacement invalidates the shared menu cache, but the inspected helper does not expose a general reset for every already-loaded tenant-config static cache in the same long-lived process.
Typical request-scoped PHP execution may naturally discard static state at request end, but that is an environment/runtime fact, not a portable contract.
Evidence must establish:
- PHP execution model;
- long-running CLI or worker consumers;
- next-request readback;
- provider adapter effective source;
- whether service restart/reload is needed for any non-PHP consumer.
11. Provider Definition And Module Boundary¶
Every allowlisted provider definition carries a module key, but current credential access is registered with:
moduleKey = null
The Admin route relies on Admin Console authorization and tenant/key allowlist rather than provider module enablement at route dispatch.
Therefore:
Provider module disabled
!= credential reveal/update route necessarily unavailable
The Admin Runbook says a credential does not authorize or enable provider use. Current environment evidence must determine whether disabled-module credential management is intended for setup/recovery or should be limited by a separate accepted policy.
No policy change is authorized by this document.
12. Current Error/Conflict Classes¶
Source-observed classes include:
FORBIDDEN
actor lacks Admin Console access or targets another tenant
NOT_FOUND
key is not an allowlisted provider secret
INVALID
missing/empty replacement value
CONFLICT
expected updatedAt differs
UNAVAILABLE
encryption key absent, envelope invalid or decrypt/store failed
User-visible errors should not include the credential value or cryptographic material.
13. Read-Only Evidence Requirements¶
RBR-CREDENTIAL-001 must establish without revealing values:
- current
T_TENANT_CONFIGschema and indexes; - configured provider-secret keys by tenant;
- encrypted companion versus legacy plaintext row counts;
enc:v1:envelope classification using safe prefix/length expressions only;- duplicate active rows;
- metadata/revision availability;
- allowlist/provider/module mapping;
- Admin role/account/menu/page source;
- request-log redaction configuration;
- dedicated deployment behavior;
- current caller effective source after replacement;
- no plaintext copied into evidence.
14. Target Reconstruction Inputs¶
Future architecture should preserve:
credential definition registry
credential owner tenant
credential storage reference/version
availability metadata
separate privileged reveal
separate replacement/rotation
explicit removal/retirement
actor/subject/request correlation
provider consumer read
provider effect authorization
It should not require copying plaintext credential values into:
- React state beyond the explicit reveal field;
- ordinary Next.js server logs;
- business tables;
- provider attempt payloads;
- Wiki, Task or incident documents;
- generic analytics.
A future external secret store may replace encrypted DB storage, but the application contract should continue to return safe availability/reference metadata by default and plaintext only through a separately authorized reveal operation when the product requires it.
15. Current Disposition¶
Allowlisted secret definition:
SOURCE PRESENT
Encrypted tenant storage:
SOURCE PRESENT
Legacy plaintext compatibility read:
SOURCE PRESENT
Reveal route/UI:
SOURCE PRESENT
Replacement route/UI:
SOURCE PRESENT
Request-body redaction:
SOURCE PRESENT
Credential-specific immutable audit:
NOT LOCATED
Managed removal route:
NOT LOCATED
Dedicated direct-route enforcement:
NOT LOCATED
Current DB rows/metadata:
NOT READ
Current role/account behavior:
NOT RUN
Current credential values:
NOT READ
Provider validity after replacement:
NOT VERIFIED
M3:
NO
M4:
NO
---¶
Source:
docs/reconstruction/PLATFORM_PROVIDER_CREDENTIAL_MANAGEMENT_CURRENT_SOURCE_2026-08-08.md— ctc repository · This page is an English translation of the source document. Identifiers, file paths and code symbols are unchanged.