Context
This is a narrow B3 cleanup child under #12461 / #12456 for the shared MCP TransportService auth proxy selector.
Current verified source on origin/dev:
if (!baseAuth && aiConfig.auth?.trustProxyIdentity) {V-B-A before filing:
git grep on origin/dev shows the TransportService site at ai/mcp/server/shared/services/TransportService.mjs:57.
ai/config.template.mjs defines auth.trustProxyIdentity: leaf(false, 'NEO_AUTH_TRUST_PROXY_IDENTITY', 'boolean').
gh issue list --state open --search "TransportService trustProxyIdentity AiConfig B3" returned no open issue.
gh pr list --state open --search "TransportService trustProxyIdentity AiConfig B3" returned no open PR.
- PR #12532 was checked for overlap and does not touch TransportService; it is memory-sharing scoped.
ask_knowledge_base(query='TransportService trustProxyIdentity AiConfig auth B3 defensive read') confirmed the trust-proxy behavior: when enabled, proxy identity headers become the auth source; without the header, the request is rejected.
Problem
TransportService.resolveAuthContext() reads aiConfig.auth?.trustProxyIdentity defensively. Under ADR 0019, resolved AiConfig leaves are the use-site source of truth and B3 defensive reads should fail loudly instead of silently treating a missing config subtree as disabled.
For this auth selector, silent disablement is particularly misleading: if the auth subtree were absent, the current ?. would bypass the proxy-identity branch rather than surfacing that the server config is malformed.
Architectural Reality
TransportService is a shared MCP transport service. It consumes the resolved server config passed by Memory Core / Knowledge Base startup code. It is not the owner of auth defaults and should not defend against the top-level auth subtree.
The top-level AiConfig auth subtree owns trustProxyIdentity through leaf(false, 'NEO_AUTH_TRUST_PROXY_IDENTITY', 'boolean'). The transport layer should read the leaf directly and keep the existing behavior:
false leaves proxy headers ignored.
true accepts the configured proxy identity header as the auth source when no bearer-auth context exists.
- Missing
auth config fails loudly at the read site.
Fix
Replace the defensive read in ai/mcp/server/shared/services/TransportService.mjs with a direct resolved-leaf read:
if (!baseAuth && aiConfig.auth.trustProxyIdentity) {Do not add a local fallback, alias, or default.
Contract Ledger
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs / Commentary |
Evidence |
TransportService.resolveAuthContext() proxy trust gate |
aiConfig.auth.trustProxyIdentity |
Reads the resolved auth leaf directly |
None |
Existing method JSDoc remains accurate |
Focused TransportService unit coverage |
AiConfig.auth.trustProxyIdentity |
ai/config.template.mjs auth subtree |
Owns the false default and env override |
leaf(false, 'NEO_AUTH_TRUST_PROXY_IDENTITY', 'boolean') |
Template JSDoc already documents the selector |
Source grep + config template line |
| Proxy-identity request behavior |
TransportService auth context resolution |
Preserves accept/reject semantics when the leaf is present |
Missing auth subtree fails loudly |
No public API change |
Existing proxy identity tests stay green |
Decision Record Impact
Aligned with ADR 0019: the reactive Provider-backed AiConfig singleton remains the SSOT. This ticket removes a consumer-side defensive read and does not create new config ownership.
Acceptance Criteria
Out of Scope
- Memory-sharing policy work in PR #12532.
- Other #12461 B3 clusters in Orchestrator, BaseServer, Logger, SessionService, MemoryService, SummaryService, or CollectionProxy.
- Auth policy or header-name changes.
Related
- Parent: #12461
- Epic: #12456
- ADR:
learn/agentos/decisions/0019-aiconfig-reactive-provider-ssot.md
Origin Session ID
dcdaac0b-9ae0-45b5-b4da-da39541af497
Retrieval Hint
TransportService trustProxyIdentity AiConfig B3 ADR 0019
Context
This is a narrow B3 cleanup child under #12461 / #12456 for the shared MCP
TransportServiceauth proxy selector.Current verified source on
origin/dev:if (!baseAuth && aiConfig.auth?.trustProxyIdentity) {V-B-A before filing:
git greponorigin/devshows the TransportService site atai/mcp/server/shared/services/TransportService.mjs:57.ai/config.template.mjsdefinesauth.trustProxyIdentity: leaf(false, 'NEO_AUTH_TRUST_PROXY_IDENTITY', 'boolean').gh issue list --state open --search "TransportService trustProxyIdentity AiConfig B3"returned no open issue.gh pr list --state open --search "TransportService trustProxyIdentity AiConfig B3"returned no open PR.ask_knowledge_base(query='TransportService trustProxyIdentity AiConfig auth B3 defensive read')confirmed the trust-proxy behavior: when enabled, proxy identity headers become the auth source; without the header, the request is rejected.Problem
TransportService.resolveAuthContext()readsaiConfig.auth?.trustProxyIdentitydefensively. Under ADR 0019, resolved AiConfig leaves are the use-site source of truth and B3 defensive reads should fail loudly instead of silently treating a missing config subtree as disabled.For this auth selector, silent disablement is particularly misleading: if the
authsubtree were absent, the current?.would bypass the proxy-identity branch rather than surfacing that the server config is malformed.Architectural Reality
TransportServiceis a shared MCP transport service. It consumes the resolved server config passed by Memory Core / Knowledge Base startup code. It is not the owner of auth defaults and should not defend against the top-level auth subtree.The top-level
AiConfigauth subtree ownstrustProxyIdentitythroughleaf(false, 'NEO_AUTH_TRUST_PROXY_IDENTITY', 'boolean'). The transport layer should read the leaf directly and keep the existing behavior:falseleaves proxy headers ignored.trueaccepts the configured proxy identity header as the auth source when no bearer-auth context exists.authconfig fails loudly at the read site.Fix
Replace the defensive read in
ai/mcp/server/shared/services/TransportService.mjswith a direct resolved-leaf read:if (!baseAuth && aiConfig.auth.trustProxyIdentity) {Do not add a local fallback, alias, or default.
Contract Ledger
TransportService.resolveAuthContext()proxy trust gateaiConfig.auth.trustProxyIdentityAiConfig.auth.trustProxyIdentityai/config.template.mjsauth subtreeleaf(false, 'NEO_AUTH_TRUST_PROXY_IDENTITY', 'boolean')Decision Record Impact
Aligned with ADR 0019: the reactive Provider-backed AiConfig singleton remains the SSOT. This ticket removes a consumer-side defensive read and does not create new config ownership.
Acceptance Criteria
TransportService.resolveAuthContext()no longer usesaiConfig.auth?.trustProxyIdentity.Out of Scope
Related
learn/agentos/decisions/0019-aiconfig-reactive-provider-ssot.mdOrigin Session ID
dcdaac0b-9ae0-45b5-b4da-da39541af497Retrieval Hint
TransportService trustProxyIdentity AiConfig B3 ADR 0019