Skip to content

feat(registry): serve CORS headers for configured browser origins - #173

Merged
lmcorbalan merged 18 commits into
mainfrom
feat/registry-cors
Sep 7, 2026
Merged

feat(registry): serve CORS headers for configured browser origins#173
lmcorbalan merged 18 commits into
mainfrom
feat/registry-cors

Conversation

@lmcorbalan

@lmcorbalan lmcorbalan commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

Closes #172

The registry mounted no CORS middleware, so a browser dApp on another origin could send a request but never read the response. It now serves CORS headers for origins named in CORS_ORIGINS, defaulting to http://localhost:3012.

Changes

  • cors mounted ahead of the body parser and the OpenAPI validators, so their own 400s stay readable cross-origin rather than reaching the page as a network error.
  • CORS_ORIGINS, comma-separated, * for any origin; an entry no browser could send is refused at boot, whether a near miss, a non-http(s) scheme or a wildcard pattern, and the accepted list is on the startup line.
  • Preflight advertises only what the service serves (GET,HEAD,POST,OPTIONS, Content-Type) and is cacheable for 600s, so a factory call is one round trip.

Acceptance criteria

  • All five from the issue are met. Criterion 2 is met by mounting order rather than by the preflight: probed both ways, the preflight answers 204 identically, because the validators pass OPTIONS through untouched. The order is pinned by the two tests asserting a rejection carries the header.

Test plan

Automated tests

246 registry unit tests in 11 files (was 205 in 10); 80 Daml scenarios; 18 e2e against a live participant on Canton 3.5.12. Lint, both typechecks, check:deps and smoke:registry all clean.

Manual verification

Mutation batteries in a throwaway clone red every new assertion: the mount order (below the validators reds two tests, below express.json() one, below the routers eight), each boot guard on its own, the absence of credentials, and the log line's omission of the origin. Against the compiled registry/dist: an allowed origin is reflected, a disallowed one gets Vary: Origin and no header, the preflight returns 204 with the exact method list and Max-Age: 600, and CORS_ORIGINS=http://localhost:3012/ refuses the boot naming the form to use.

Breaking changes

No documented route changes its request or response schema. Three operational notes: every response now carries Vary: Origin; OPTIONS on a path the service does not route answers 204 where it used to 404; and an unset or empty CORS_ORIGINS means the default, so there is no value that allows no origin at all.

Checklist

  • Self-reviewed my own diff
  • Tests added or updated
  • Docs updated (if applicable)
  • No unrelated changes bundled in

Screenshots

None.

@lmcorbalan
lmcorbalan merged commit ff967b8 into main Sep 7, 2026
3 checks passed
@lmcorbalan
lmcorbalan deleted the feat/registry-cors branch September 7, 2026 16:20
@github-project-automation github-project-automation Bot moved this from Backlog to Done in Canton - dAppBooster (#390) Sep 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Registry serves no CORS headers, so a browser dApp on another origin cannot read its responses

2 participants