Skip to content

soa-api-util: shared CORS origin allowlist + Datadog RUM header constant#114

Merged
SethPaul merged 2 commits into
mainfrom
feat/soa-api-util-cors-origins
Jun 2, 2026
Merged

soa-api-util: shared CORS origin allowlist + Datadog RUM header constant#114
SethPaul merged 2 commits into
mainfrom
feat/soa-api-util-cors-origins

Conversation

@SethPaul
Copy link
Copy Markdown
Contributor

@SethPaul SethPaul commented Jun 2, 2026

Why

Four Saga backends (iam-api, programs-api, scheduling-api, connectv3-api) each re-implement the same two CORS bits, with subtle drift:

  • the 7-header Datadog RUM tracing list in allowedHeaders, and
  • an environment-isolated origin allowlist (prod=*.saga.org, dev=*.wootdev.com).

Extracting them into @saga-ed/soa-api-util gives one source of truth — one place to update if Datadog changes its header set, and consistent dev/prod isolation. (Part of the RUM/backend-CORS rollout, hipponot/iac#358.)

What (new exports)

  • DATADOG_RUM_TRACING_HEADERS — readonly tuple of the 7 headers; spread into a service's allowedHeaders.
  • buildSagaOriginAllowlist({ env?, devOrigins? }) — env-isolated allowlist: prod (NODE_ENV==='production') → explicit CORS_ORIGIN + https://*.saga.org; dev → CORS_ORIGIN + devOrigins (localhost, non-prod only) + https://*.wootdev.com. Wildcards are anchored + https-only (suffix-attack safe — adopts iam-api's stricter form).
  • originAllowed(list, origin) — matcher for the cors middleware origin callback and/or an Origin/Referer CSRF gate (keeps them in lockstep).

Primitives only — each service keeps its own cors() wiring (header sets differ slightly per service). No change to soa-api-core's existing express-server CORS.

Verification

pnpm --filter @saga-ed/soa-api-util build ✓ (tsup ESM + dts typecheck) · test ✓ (10 tests).

Minor bump 1.1.1 → 1.2.0.

Follow-up (after merge + publish)

Publish 1.2.0 to CodeArtifact (single-package workflow), then adopt in iam-api / programs-api / scheduling-api (wildcard model) and connectv3-api (header constant). Those service PRs replace the inline copies (superseding the interim inline-fix PRs: rostering#377, janus#40, program-hub#135, qboard#127).

…onstant

Backends were each re-implementing the same two things: the 7-header Datadog
RUM tracing list (allowedHeaders) and an env-isolated origin allowlist
(prod=*.saga.org, dev=*.wootdev.com). Extract both into soa-api-util:

- DATADOG_RUM_TRACING_HEADERS — the 7-header constant.
- buildSagaOriginAllowlist({ env, devOrigins }) — env-isolated (NODE_ENV)
  allowlist + CORS_ORIGIN; anchored https-only wildcards (suffix-attack safe);
  localhost devOrigins added in non-prod only.
- originAllowed(list, origin) — matcher for cors origin + Origin/Referer CSRF.

iam-api/programs-api/scheduling-api/connectv3-api will adopt these, replacing
their inline copies. Minor bump 1.1.1 -> 1.2.0. Re hipponot/iac#358.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

❌ Test Results

Status Suites Tests
✅ Passed 158 397
❌ Failed 0 9
⏭️ Skipped 0 0
Total 158 406

Package Results

Package Tests Passed Failed
✅ @saga-ed/soa-core 23 23 0
✅ @saga-ed/soa-node 288 288 0
✅ @saga-ed/soa-web 17 17 0

Commits

  • Branch: ac4398b (feat/soa-api-util-cors-origins)
  • Merge: eb09a3c

Links


Updated: 2026-06-02T17:55:30.891Z

@SethPaul SethPaul merged commit 80012cb into main Jun 2, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant