2026-09-23·by Sijie Wang#software#project#flexmesh

compliance-from-zero

Compliance, from zero — down to the mechanism

Privacy compliance here is not a banner; it is a code path, and the code path has teeth:

Consent gating (app, analytics_service.dart):

  • Default is off. _consentGranted = prefs.getBool('analytics_consent_granted') ?? false — absent consent means no collection, then setAnalyticsCollectionEnabled(_consentGranted) pushes the gate into Firebase itself, stopping even native auto-events (first_open, session_start, screen_view), not just custom ones.
  • grantConsent is called only after the user accepts the terms on the consent screen — and the grant is awaited in the E2E suite (2026-04-18 commit fixed exactly that), so consent is a tested path, not decoration.
  • A build-flag hard-kill for test/dev builds goes further: setAnalyticsCollectionEnabled(false) plus resetAnalyticsData() — dropping the cached app-instance id "so test simulators don't masquerade as returning users." Data hygiene enforced at the source; the analytics CLI excludes simulators at the query end — the same discipline at both ends of the pipe (measurement-stack).
  • Fire-and-forget with try/catch throughout — analytics is never allowed to crash the product it measures; failures log instead of silently vanishing (a bare-debugPrint swallow was later indicted as "GA4 全瞎" in the camera investigation — camera-bug-looked-like-user-behavior).

Web (same law, same day): GA4 Consent Mode v2 cookie banner, scoped to PIPEDA (Canada's federal privacy law — the Personal Information Protection and Electronic Documents Act), landed 2026-03-27 — the same day as the app's consent gating commit. One law, two surfaces, one changeset boundary.

Session replay behind the same wall (2026-07-24): Clarity screen recording on mobile starts only from one combination — release build, not build-disabled, consent granted — and the gate is a pure shouldStart() whose full decision table is tested: the one allowed combination starts, all fifteen others refuse. Recording a driver's screen without consent is a privacy violation; a dead gate ships a silently useless instrument. Dashboard masking is strict, so recipient names and addresses on waybill screens never appear in a recording.

Store-mandated surfaces: privacy policy, terms, delete-account page (the App Store requirement indie apps most often fail) — shipped on the site.

Policy as lint: ESLint-enforced i18n (2025-12-24, "fix all hardcoded strings") converts "everything must be localizable" from a review nag into a build failure — the owner's constraints mechanized, not socialized applied to compliance.

Claims held to the same bar: hardcoded fake aggregate-rating schema deleted (2026-03-29); unguaranteeable on-device-data claims stripped from the landing About (2026-07-09). Compliance extended to what the marketing says, not just what the code does.

Interview archetype: "how do you handle privacy/compliance?" — consent defaults off and is pushed into the SDK, the grant path is E2E-tested, dev builds can't pollute cohorts, the policy is a lint rule, and marketing claims I can't guarantee get deleted.

cited by
about this entry

One of sijie's wiki entries. The AI on this site is grounded in the same corpus and answers in sijie's voice, with citations back to entries like this one — answering costs sijie money, so it waits behind a code: enter an access code →