Filed unassigned by the dev seat on #9058 (session session_011RB4waLuNbdruCo6X9oobm) while auditing every env-resolution call site for ADR-0076 OQ#9's D11 worklist item (4). Out of that card's scope — #9058 records an ADR outcome and deliberately carries no code — so recorded here. Searched open and closed issues by keyword first; the near neighbour is #4024 (closed, the issue that ADDED this probe), no open duplicate.
Measured against origin/main @ ba2e3c172
packages/rest/src/rest-server.ts has one shared entry point for "which environment does this request belong to": resolveRequestEnvironmentId (line 997). Its own doc-comment calls it
THE single entry point for every unscoped-route environment decision (protocol, i18n, exec-ctx, analytics, …) so they can never disagree about which kernel a request belongs to.
Eight call sites go through it — resolveEndpointMatchAuthority (869), resolveMetadataService (906), resolveProtocol (1054), resolveI18nService (1076), computeExecCtx (1550), resolveSecurityService (7337), the analytics service resolver (8114), the security-explain service resolver (8376).
probeMcpServeable (line 2842) is the ninth site that needs the request's environment, and the only one that does not. It re-derives:
letenvironmentId: string|undefined=req?.params?.environmentId;if((!environmentId||environmentId===':environmentId')&&this.defaultEnvironmentIdProvider){try{environmentId=this.defaultEnvironmentIdProvider()||undefined;}catch{/* ignore */}}So it consults neither the host's ADR-0006 kernel-resolver seam (which resolveRequestEnvironmentId consults first, wired by rest-api-plugin.ts:167-201) nor the legacy hostname / X-Environment-Id chain beneath it.
Why that is a defect rather than a quirk
The probe's own doc-comment claims parity with a sibling that does reach the entry point:
Same two probe paths as resolveRegisteredServices (ADR-0057 D10): the per-request kernel for multi-env hosts, else the single-env serviceExistsProvider.
resolveRegisteredServices gets its kernel as ctx.__kernel, set at line 1717 inside computeExecCtx — i.e. downstream of resolveRequestEnvironmentId (1550). probeMcpServeable gets no such kernel on the deployment shape that matters: on a hostname-routed multi-tenant host, an unscoped /discovery request carries no params.environmentId, and defaultEnvironmentIdProvider is registered by createSingleEnvironmentPlugin — not by a multi-tenant host. The probe then falls to serviceExistsProvider, which answers for the host kernel, not the request's environment.
Both error directions are reachable, and #4024 exists because of the first:
Neither is a crash, and on single-environment boots — where defaultEnvironmentIdProvider IS registered — the probe is correct. It is a multi-tenant-only inconsistency.
Suggested fix (not implemented here)
Replace the hand-rolled derivation with await this.resolveRequestEnvironmentId(req?.params?.environmentId, req), matching the eight siblings; the 'platform' guard and the serviceExistsProvider fallback below it stay as they are. Whoever takes it should confirm the discovery handler at line 2913 passes the same req the other resolvers receive.
Related: #4024 (added the probe) · #9058 / ADR-0076 OQ#9 item (4) (the audit that found this) · #2462 (the OQ#9 audit that set the worklist).
Filed unassigned by the dev seat on #9058 (session
session_011RB4waLuNbdruCo6X9oobm) while auditing every env-resolution call site for ADR-0076 OQ#9's D11 worklist item (4). Out of that card's scope — #9058 records an ADR outcome and deliberately carries no code — so recorded here. Searched open and closed issues by keyword first; the near neighbour is #4024 (closed, the issue that ADDED this probe), no open duplicate.Measured against
origin/main@ba2e3c172packages/rest/src/rest-server.tshas one shared entry point for "which environment does this request belong to":resolveRequestEnvironmentId(line 997). Its own doc-comment calls itEight call sites go through it —
resolveEndpointMatchAuthority(869),resolveMetadataService(906),resolveProtocol(1054),resolveI18nService(1076),computeExecCtx(1550),resolveSecurityService(7337), the analytics service resolver (8114), the security-explain service resolver (8376).probeMcpServeable(line 2842) is the ninth site that needs the request's environment, and the only one that does not. It re-derives:So it consults neither the host's ADR-0006
kernel-resolverseam (whichresolveRequestEnvironmentIdconsults first, wired byrest-api-plugin.ts:167-201) nor the legacy hostname /X-Environment-Idchain beneath it.Why that is a defect rather than a quirk
The probe's own doc-comment claims parity with a sibling that does reach the entry point:
resolveRegisteredServicesgets its kernel asctx.__kernel, set at line 1717 insidecomputeExecCtx— i.e. downstream ofresolveRequestEnvironmentId(1550).probeMcpServeablegets no such kernel on the deployment shape that matters: on a hostname-routed multi-tenant host, an unscoped/discoveryrequest carries noparams.environmentId, anddefaultEnvironmentIdProvideris registered bycreateSingleEnvironmentPlugin— not by a multi-tenant host. The probe then falls toserviceExistsProvider, which answers for the host kernel, not the request's environment.Both error directions are reachable, and #4024 exists because of the first:
mcp, the request's environment does not ⇒/discoveryadvertisesroutes.mcpfor an environment whose route 501s (thedeclared ≠ enforcedshape@objectstack/restadvertisesmcpin /discovery with no way to serve it — declared ≠ enforced, and the route-parity gate'smcp: falseseam is never exercised #4024 was filed to close);mcpServeable !== falsefails open only for anullprobe, not for a confidentfalsecomputed against the wrong kernel.)Neither is a crash, and on single-environment boots — where
defaultEnvironmentIdProviderIS registered — the probe is correct. It is a multi-tenant-only inconsistency.Suggested fix (not implemented here)
Replace the hand-rolled derivation with
await this.resolveRequestEnvironmentId(req?.params?.environmentId, req), matching the eight siblings; the'platform'guard and theserviceExistsProviderfallback below it stay as they are. Whoever takes it should confirm the discovery handler at line 2913 passes the samereqthe other resolvers receive.Related: #4024 (added the probe) · #9058 / ADR-0076 OQ#9 item (4) (the audit that found this) · #2462 (the OQ#9 audit that set the worklist).