Skip to content

feat(legal): allow partners to customise Terms of Use and Privacy Policy#232

Open
wilfredeveloper wants to merge 2 commits into
mainfrom
feat/partner-customizable-legal-docs
Open

feat(legal): allow partners to customise Terms of Use and Privacy Policy#232
wilfredeveloper wants to merge 2 commits into
mainfrom
feat/partner-customizable-legal-docs

Conversation

@wilfredeveloper

@wilfredeveloper wilfredeveloper commented May 26, 2026

Copy link
Copy Markdown
Collaborator

JIRA

Summary

  • Replaces the bundled, build-time !!raw-loader imports of the Terms of Use and Privacy Policy markdown with a runtime fetch driven by a new partner-customisable env var FRONTEND_LEGAL_DOCUMENTS (mirrors the existing logo / asset customisation model).
  • Partners can either replace frontend-new/public/legal/{terms-of-use,privacy-policy}.md in their fork (Path A) or point each variant at an absolute URL (Path B). Schema is forward-compatible to Record<Locale, string> for future per-locale documents.
  • Renames the LegalDocumentVariant union from "privacy" | "terms" to "privacyPolicy" | "termsOfUse" for consistency with the JSON config. Drops the unused {{appName}} placeholder substitution (zero usages in the bundled docs).

What changed

  • Config: new legal.documents namespace in config/default.json; wired through config/inject-config.py (env map + JSON-stringify field).
  • IaC: added env-var whitelist entry (iac/templates/env.template), reader (iac/frontend/prepare_frontend.py), and no_cache_paths entries (iac/frontend/deploy_frontend.py).
  • Frontend:
    • New legalDocumentsConfig.ts parser (modelled on branding/seoConfig.ts).
    • Rewrote legalDocumentLoader.ts to fetch from the configured URL with a per-variant default title fallback.
    • LegalDocumentPage now async-loads with <Backdrop> while loading and <ErrorPage showRefreshButton /> on failure (mirrors KnowledgeHubDocument).
    • New legal.documentUnavailable translation key added to all 7 locales.
    • Default markdown files moved from src/legal/documents/ to public/legal/.
  • Docs: new "Legal Documents Configuration" section in config/CUSTOMIZATION.md (Path A/B, frontmatter contract, non-goal callout for re-consent, forward-compat callout for per-locale).
  • Tests: 13 unit tests across legalDocumentsConfig.test.ts, legalDocumentLoader.test.ts, and LegalDocumentPage.test.tsx covering success, loading, fetch failure, missing config, malformed JSON, and frontmatter fallback.

Non-goals

  • No backend changes; accepted_tc: datetime semantics preserved. Updates affect only future consents.
  • No per-locale legal docs in v1 (schema is additive-extensible).
  • No admin-frontend upload UI; the ticket's "upload" requirement is satisfied by the partner-config-at-deploy-time model, consistent with how logos already work.

Test plan

  • yarn compile clean
  • yarn lint clean
  • yarn format:check clean
  • yarn test --testPathPattern='src/legal/' — 13/13 pass (full suite not run locally due to OOM risk; CI will cover)
  • python3 inject-config.py --config default.json runs clean and writes the expected FRONTEND_LEGAL_DOCUMENTS: btoa(JSON.stringify({...})) into env.js
  • Manual QA: visit /terms-of-use and /privacy-policy, confirm rendering with defaults
  • Manual QA: edit public/legal/terms-of-use.md, hard-refresh, confirm the change is visible
  • Manual QA: temporarily rename the public file to confirm <ErrorPage> shows with refresh button

Replaces the bundled-at-build-time legal markdown imports with a runtime fetch
driven by a new FRONTEND_LEGAL_DOCUMENTS env var. Partners can either replace
the default markdown files in public/legal/ or point each variant at an
absolute URL, matching the existing logo-asset customisation model.

export const getLegalDocument = async (variant: LegalDocumentVariant): Promise<LegalDocument> => {
const url = getLegalDocumentsConfig()[variant];
if (!url) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If thre is no URL, I think it might be a good idea to return the default values instead of throwing an error.

for backward config compatibility.

"documents": {
      "termsOfUse": "/legal/terms-of-use.md",
      "privacyPolicy": "/legal/privacy-policy.md"
    }

What do you think?

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.

2 participants