feat(self-host): make vendor telemetry, endpoints, and support staff configurable - #1
Open
kopertop wants to merge 1 commit into
Open
feat(self-host): make vendor telemetry, endpoints, and support staff configurable#1kopertop wants to merge 1 commit into
kopertop wants to merge 1 commit into
Conversation
…configurable A self-hosted build currently ships Macro's own marketing stack and points itself at macro.com. None of it is gated on anything an operator can set. - analytics: move the GA4 / GTM / Google Ads / Meta Pixel ids out of the source and into VITE_* build env (new apps/web/src/lib/analytics/config.ts). Absent => the script is never injected, matching how PostHog is already gated. The only prior guard was `import.meta.env.DEV`, which is false in every real build — including the repo's own headless stack — so the sanctioned self-host bundle sent page views and user emails to Macro's GA property and Meta pixel. Macro's deploys inject the ids in CI. - servers: honor an explicit backend origin (VITE_BACKEND_ORIGIN, or the existing VITE_LOCAL_BACKEND_ORIGIN) in any build mode, not just MODE=development, and add VITE_AUTH_LOGOUT_URL. A production-mode bundle was otherwise hardwired to *.macro.com with no override path. - support channels: replace the hardcoded jacob@/julia@/teo@macro.com constants with SUPPORT_CHANNEL_HOST / SUPPORT_CHANNEL_MEMBERS. Unset => no support channel. User ids are email-derived, so a fork seeding those addresses grants whoever registers them membership in every user's private support channel. - macro_env: warn once when ENVIRONMENT is unset and new_or_prod() falls back to Production, which silently resolves every service URL to *.macro.com. Behavior for Macro's own dev/prod deploys is unchanged: the CI build passes the same ids, and the welcome-message test asserts byte-identical copy from the equivalent SUPPORT_CHANNEL_* config.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A self-hosted build of this repo currently ships Macro's own marketing stack and points itself at
macro.com, and none of it is gated on anything an operator can set. The defaults fail toward the vendor rather than toward the deployment.The concrete leak:
apps/web/src/lib/analytics/providers.tsinjected Macro's GA4, GTM, Google Ads, and Meta Pixel ids with the only guard beingimport.meta.env.DEV === true(analytics.ts:167).DEVis true only under the Vite dev server — this repo's own headless stack builds withbun run build+NODE_ENV=production(tooling/xtask/.../frontend.rs:56-63), soDEVis false and all four trackers were live.identify()then sent each user's email address to Google in cleartext and to Meta viafbq('init', …, {em}), landing in Macro's analytics property and pixel.What changed
Third-party analytics ids → build env (new
apps/web/src/lib/analytics/config.ts)VITE_GA_MEASUREMENT_ID,VITE_GTM_CONTAINER_ID,VITE_GOOGLE_ADS_ID,VITE_META_PIXEL_ID. Absent means the script is never injected and no request reaches the vendor — the same shape PostHog already had viaVITE_POSTHOG_API_KEY. Everygtag/fbqcall site is guarded, so no console noise when the globals don't exist. Macro's own builds get the ids from CI (deploy_web_app.yml, regenerated from its xtask source).Backend origin honored in any build mode (
servers.ts)SERVER_HOSTSpreviously ignored the proxy origin unlessMODE === 'development', so a plainvite buildproduced a client pinned to*.macro.comwith no override. NowVITE_BACKEND_ORIGIN(or the existingVITE_LOCAL_BACKEND_ORIGIN) applies in any mode, sync-service included, plusVITE_AUTH_LOGOUT_URLfor a self-hosted FusionAuth tenant. Unset →serverHostRemote, unchanged.Support team → config (
SUPPORT_CHANNEL_HOST/SUPPORT_CHANNEL_MEMBERS)create_user_webhook.rshardcodedjacob@,julia@,teo@macro.cominto every new user's support channel. Macro user ids are email-derived (macro|<email>), so on a self-hosted instance with open signup, whoever registers one of those addresses lands on an identity that already holds membership in every user's private support channel. Now resolved from config at startup (bad value fails startup, not every signup); unset → no support channel is created, and starter-doc seeding still runs.Entry format is
email[:label], where the label is the parenthetical in the welcome copy. Macro's own configuration isSUPPORT_CHANNEL_HOST=julia@macro.com:julia,SUPPORT_CHANNEL_MEMBERS=jacob@macro.com:ceo,teo@macro.com:cto— needs adding to Doppler before this deploys, or new users silently stop getting support channels.Loud
ENVIRONMENTfallback (macro_env)new_or_prod()returningProductionfor unset config makes everymacro_service_urlslookup resolve to*.macro.com. Still does, but now warns once with the fix. No call-site churn.Verification
MODE=development NODE_ENV=production, the xtask stack's flags): zero occurrences ofG-52HPEL3FTV,GTM-M58X7PJ8,AW-11035820781,639142540393286, and nogoogletagmanager.com/connect.facebook.netin the emitted JS (sourcemap only).bun run type-checkclean;biome checkclean.cargo check/clippy -p macro_env -p authentication_service --testsclean;cargo test -p authentication_service --lib support_→ 9 passed, including the pre-existingposts_the_welcome_messagetest that asserts the exact welcome string — so the deployed copy is byte-identical under the config above.cargo x workflows --check→ "all generated workflows are up to date".Deliberately out of scope
Flagging rather than changing: the analytics proxy renames
posthog-recorder.js→runtime.jsspecifically to evade tracker blockers (services/analytics-proxy/src/index.ts:23-26) — inert when self-hosting since there's no key, but the intent is deliberate and worth a separate decision. Tauri's CSP isnull.proxyServers()still falls back tolocalhostforpdf-service/scheduled-action, which have no local container.