api-core: configurable ExpressServer CORS allowedHeaders + Datadog RUM by default#118
Merged
Merged
Conversation
…og-aware by default ExpressServer hardcoded `allowedHeaders: ['Content-Type', 'Authorization']`, so any service relying on its built-in CORS (rather than a hand-rolled cors() override before init()) silently failed the browser preflight for Datadog RUM's cross-origin tracing headers (traceparent, tracestate, x-datadog-*). coach-api and saga-sm inherit this default. - Default allowedHeaders is now ['Content-Type', 'Authorization', ...DATADOG_RUM_TRACING_HEADERS] (the canonical set from @saga-ed/soa-api-util), so RUM-instrumented frontends work fleet-wide with no per-service config. - Add an optional `allowedHeaders` field to ExpressServerConfig; when set it replaces the default (services overriding should spread DATADOG_RUM_TRACING_HEADERS to keep RUM working). This lets services that hand-roll a cors() override before init() retire that boilerplate and the "TODO: remove when ExpressServer supports configurable allowedHeaders" comment. - Add @saga-ed/soa-api-util as a dependency for the shared constant. - Integration tests: default preflight admits the baseline + every Datadog header; an explicit allowedHeaders list replaces the default. Backward-compatible — the default only ADDS allowed request headers. Bump api-core 1.1.4 -> 1.2.0.
✅ Test Results
Package Results
Commits
LinksUpdated: 2026-06-03T18:52:24.985Z |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
@saga-ed/soa-api-core'sExpressServerhardcodedallowedHeaders: ['Content-Type', 'Authorization']with no way to override it. Any service that relies on the built-in CORS (instead of a hand-rolledapp.use(cors(...))beforeinit()) therefore can't clear the browser preflight for Datadog browser-RUM's cross-origin tracing headers (traceparent,tracestate,x-datadog-*). Confirmed inheritors of the default: coach-api, saga-sm (+ the saga-soa examples).This closes that gap fleet-wide and makes the list configurable.
Changes
allowedHeadersis now['Content-Type', 'Authorization', ...DATADOG_RUM_TRACING_HEADERS]— the canonical set from@saga-ed/soa-api-util. Inheriting services get Datadog RUM support automatically, no config needed.allowedHeadersfield onExpressServerConfig. When set, it replaces the default (standardcorssemantics). This lets the services that currently hand-roll acors()override beforeinit()retire that boilerplate and the// TODO: remove when SOA ExpressServer supports configurable allowedHeaderscomment (thrive iam-api, etc.).@saga-ed/soa-api-util(workspace:*) as an api-core dependency for the shared constant.api-core1.1.4 → 1.2.0 (additive, backward-compatible).Design note (wants a 👍)
A caller-supplied
allowedHeadersreplaces the default rather than merging the Datadog headers in. That's the predictablecorssemantic and matches the existing per-service override lists (which already spread the constant), but it means an overriding service that forgets to spreadDATADOG_RUM_TRACING_HEADERSloses RUM support. If we'd prefer Datadog headers always-on (merge), it's a one-line change — flagging for a decision.Verification
turbo run build --filter=@saga-ed/soa-api-coregreen (tsup DTS type-check passes).pnpm --filter @saga-ed/soa-api-core test→ 33/33, including 2 new integration tests inexpress-server.int.test.ts:Access-Control-Allow-Headersadmits the baseline + every Datadog header;allowedHeadersconfig replaces the default (Datadog not auto-merged).Rollout
Backward-compatible — the default only adds allowed request headers (strictly more permissive, no security change). Consumers pick it up when they bump
@saga-ed/soa-api-core. No required follow-up; services that hand-roll CORS overrides can now drop them.Context: this came out of adding Datadog RUM header allows across the APIs (rtsm was the trigger — rtsm itself hand-rolls CORS and doesn't use ExpressServer, so it's handled separately). See hipponot/iac#358.