Raxx · internal docs

internal · gated ↑ index

ADR-0045 — Support Portal Topology: CF Pages + Raptor Proxy (Option A)

Status: Accepted Date: 2026-05-03 UTC Deciders: software-architect Scope: Hosting topology for support.raxx.app — which of three architectural options best meets the privacy, brand, and infra constraints Design doc: docs/architecture/support-raxx-app.md Refs: Epic #651 · ADR-0028 (status page hosting) · ADR-0002 (no stored credentials)


Context

Three topology options exist for the customer-facing support portal:

Option A: New CF Pages project (raxx-support), static React SPA, calls Raptor API endpoints that proxy FreeScout. No direct customer → FreeScout traffic.

Option B: Public Antlers route inside the existing raxx.app app (e.g., raxx.app/support) that uses the same backend and auth.

Option C: FreeScout's own customer-facing portal UI, re-skinned via the Customization & Rebranding module.

The constraints to evaluate against: 1. No FreeScout/Tagras name ever visible to customers. 2. Privacy boundary enforced server-side (not in the browser). 3. No new Heroku app — Raptor endpoints on existing raxx-api-prod. 4. Confidence Engine visual identity (full design control). 5. Passkey-only authentication (platform invariant). 6. support.raxx.app subdomain (specified in epic #651). 7. CF Access gate absent — this is a public-access surface.


Decision

Option A: New CF Pages project raxx-support, calling Raptor API proxy endpoints.

This mirrors the proven status.raxx.app pattern (ADR-0028) and satisfies all six constraints above. The CF Pages project is a new deployment (raxx-support) distinct from raxx-status and raxx-app. Raptor endpoints are added to the existing raxx-api-prod dyno — no new Heroku app.


Consequences

Positive

Negative / Risks

Neutral


Alternatives Considered

Option B: Public Antlers route at raxx.app/support

Rejected for this design run, not permanently. Option B would share the Antlers codebase and avoid the cross-domain auth complexity. However, it conflicts with the support.raxx.app subdomain requirement in epic #651. It also couples the support portal release cycle to the main Antlers app — a support portal regression could require an Antlers hotfix. Option B remains a valid long-term consolidation path if the team wants to reduce surface count post-launch.

Option C: FreeScout native customer portal, re-skinned

Rejected. FreeScout's customer portal has a fixed URL structure under tickets.raxx.app (the same host as the operator UI, which is CF Access gated). Making it customer-accessible without CF Access would expose the operator UI host to the public network. Routing customers to a different subdomain (support.raxx.app) would require reverse-proxy rewriting of FreeScout's HTML — fragile and version-sensitive. The Customization & Rebranding module allows CSS and logo overrides but not full design control; the result would be FreeScout's layout with Raxx colors, not Confidence Engine. Passkey authentication cannot be integrated into FreeScout's auth flow without a custom FreeScout plugin (PHP, non-trivial). Option C fails constraints 1, 4, and 5 without significant custom FreeScout development that would need to be maintained across FreeScout upgrades.