Skip to content

feat: add headless CDN API client - #140

Closed
ethanpschoen wants to merge 3 commits into
ethanpschoen/feat/rule-triggersfrom
ethanpschoen/feat/headless-api-client
Closed

feat: add headless CDN API client#140
ethanpschoen wants to merge 3 commits into
ethanpschoen/feat/rule-triggersfrom
ethanpschoen/feat/headless-api-client

Conversation

@ethanpschoen

@ethanpschoen ethanpschoen commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Description of this change

Adds a standalone client for the config/consent/rights/subscriptions CDN endpoints, independent of the WebView-hosted tag.

Part 4/5 of the split of #126. Full stack: #137#138#139#140#141.

Review finding inherited from #126, fixed here:

  • Environment dropped without language (flagged on feat: add headless CDN API client and provider methods #126 at headlessApiClient.ts:94): the long config path (which carries environment) was only used when environment, jurisdiction, and language were all present; a caller who set environment and jurisdiction but not language silently fell to a path that carries no environment at all. Fixed by synthesizing language from the device locale whenever environment and jurisdiction are both set, so the long path is always taken in that case. Not adding ?environment= to the short path — nothing in ketch-tag, the canonical web client, suggests the CDN reads it.

Also fixed, found independently while verifying the above (not one of #126's tracked findings): a vendors-only consent response left purposes as undefined instead of {}, inconsistent with the empty-consent shape used elsewhere in this client. A caller doing Object.keys(consent.purposes) on such a response would throw. Normalized to {}.

This PR does not build standalone, for the same reason as the PR below it in the stack — the missing KetchService.trigger default lives in #141.

Why is this change being made?

  • Chore (non-functional changes)
  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

How was this tested? How can the reviewer verify your testing?

npm run lint passes standalone. npm run typecheck fails standalone for the single inherited reason described above (not from this PR's own content). This PR's own test suite (headlessApiClient.test.ts, 31/31 passing, including 2 new tests covering both fixes above) passes standalone.

The full 5-PR stack was verified as a faithful, complete split of #126 before publishing: git diff --exit-code <top-of-stack> origin/ethanpschoen/feat/headless-api is empty (exit 0), and the top of the stack passes the full local gate (lint, typecheck, build, npm test).

Related issues

Refs #126.

Checklist

  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • I have evaluated the security impact of this change, and OWASP Secure Coding Practices have been observed.
  • I have informed stakeholders of my changes.

Adds a standalone client for the config/consent/rights/subscriptions CDN endpoints, independent of the WebView-hosted tag.

Part 4/5 of the split of #126.
…onfig requests

The long config path (which carries environment) was only taken when environment, jurisdiction, and language were all present. A caller who set environment and jurisdiction but not language fell to the short path, which carries no environment at all, so a staging-configured app with a jurisdiction set silently received the default environment's config.

Synthesize language from the device locale whenever environment and jurisdiction are both set, so the long path is always used in that case. Not adding ?environment= to the short path — nothing in ketch-tag suggests the CDN reads it.

Refs #126.
parseConsent() left purposes undefined whenever a server response omitted it, while emptyConsent() returns { purposes: {} }. A vendors-only or protocols-only response therefore returned an inconsistent shape, and a caller doing Object.keys(consent.purposes) on it would throw.

Refs #126.
@ethanpschoen
ethanpschoen force-pushed the ethanpschoen/feat/rule-triggers branch from 590fde6 to 738c2b1 Compare August 6, 2026 21:22
@ethanpschoen
ethanpschoen force-pushed the ethanpschoen/feat/headless-api-client branch from bc61706 to b54c0ab Compare August 6, 2026 21:22
@ethanpschoen ethanpschoen reopened this Aug 7, 2026
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