> For the complete documentation index, see [llms.txt](https://faction-os.gitbook.io/faction-os-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://faction-os.gitbook.io/faction-os-docs/.spec_system/archive/sessions/phase07-session05-analytics-consent-and-payload-controls/spec.md).

# Session Specification

**Session ID**: `phase07-session05-analytics-consent-and-payload-controls` **Phase**: 07 - Hosted Services and Analytics Guardrails **Status**: Not Started **Created**: 2026-05-30 **Package**: Cross-package (`apps/web`, `packages/protocol`; docs and env examples) **Package Stack**: TypeScript, React 18, Vite, Vitest, npm workspaces, Markdown docs

***

## 1. Session Overview

This session defines the analytics consent and payload controls that must exist before FactionOS can describe optional Umami analytics as active. It turns the Phase 07 hosted-services baseline, payload privacy blocklist, hosted config boundaries, hosted identity guardrails, and hosted persistence guardrails into a source-backed analytics posture: analytics remains disabled by default, provider configuration is replaceable, consent is required before capture, and approved payloads are minimal and testable.

The work is intentionally scoped to `packages/protocol` and `apps/web` plus stable documentation. `packages/protocol` should own analytics provider, status, consent, event taxonomy, payload field, blocked payload, docs path, and summary vocabulary. `apps/web` should provide pure helpers that evaluate browser-visible analytics readiness, disabled or unavailable copy, local-only fallback, consent and opt-out state, and payload scrubbing without sending analytics events. The web UI may surface honest disabled-state settings copy, but this session must not add a tracking beacon, hosted dashboard, recorder, heatmap, replay inspection, or server-side ingestion.

This session prepares Session 06 and Session 07 by giving the hosted guardrail closeout a concrete analytics contract and focused tests. It must preserve core local workflows without Umami, hosted auth, hosted storage, analytics, Cloudflare credentials, public replay hosting, push, remote tunnels, provider credentials, or production-hosted validation.

***

## 2. Objectives

1. Define analytics provider, enabled-state, consent, opt-out, self-hosting, replaceability, event taxonomy, payload minimization, and local-only fallback requirements.
2. Add protocol-owned analytics guardrail contracts that classify approved events, allowed payload fields, blocked sensitive categories, unsupported claims, and compact summary counts.
3. Add web-owned analytics readiness and payload helpers that keep analytics disabled unless configuration and consent requirements are both satisfied.
4. Update hosted-service, privacy, environment, release, UX, and package README docs so analytics remains planned, disabled by default, scrubbed, replaceable, and covered by tests before activation.

***

## 3. Prerequisites

### Required Sessions

* [x] `phase07-session01-hosted-services-requirements-and-privacy-baseline` - provides analytics routing, optional-hosted posture, payload blocklist, and local-first fallback checks.
* [x] `phase07-session02-hosted-configuration-and-client-exposure-boundaries` - provides hosted config categories, reserved analytics variables, browser exposure rules, and disabled-default tests.
* [x] `phase07-session03-hosted-identity-and-authorization-guardrails` - provides hosted identity non-overclaim, consent separation, and analytics-consent deferral wording.
* [x] `phase07-session04-hosted-persistence-and-public-replay-boundaries` - provides local replay/export/archive/storage boundaries and hosted-payload negative claims.
* [x] `phase02-session06-settings-replay-notifications-and-scan-ux` - provides current settings, local replay, notification, export, and scan UX boundaries.
* [x] `phase06-session07-collaboration-isolation-and-mobile-validation-closeout` - provides current security posture, local browser evidence, and Phase 08 erasure/hosted-validation deferrals.

### Required Tools/Knowledge

* Node 20+, npm workspaces, TypeScript 5.9, React 18, Vite env handling, localStorage settings patterns, Vitest, Testing Library, and Biome.
* Existing hosted config, identity, and persistence patterns in `packages/protocol/src/hostedConfig.ts`, `packages/protocol/src/hostedIdentity.ts`, `packages/protocol/src/hostedPersistence.ts`, `apps/web/src/lib/hostedConfig.ts`, and `apps/web/src/lib/hostedPersistence.ts`.
* Current settings drawer and persisted settings behavior in `apps/web/src/components/SettingsDrawer.tsx` and `apps/web/src/store/useSettingsStore.ts`.
* ADR 0003 for Umami as the selected optional default analytics provider.

### Environment Requirements

* Local checkout of the FactionOS monorepo with dependencies available through existing npm workspace scripts.
* No Umami instance, hosted account, analytics API key, production host, or real credential is required.
* Do not read, copy, print, or commit raw values from `.env.local`, hosted consoles, analytics dashboards, replay buffers, exports, archives, logs, backups, or local filesystem paths. Use synthetic test records and documented examples only.

***

## 4. Scope

### In Scope (MVP)

* Maintainers can reference an analytics consent and payload control spec - add provider, disabled-default, operator config, user consent, opt-out, self-hosting, replaceability, approved event, payload minimization, forbidden payload, and Phase 08 handoff requirements.
* Protocol consumers can share one analytics guardrail contract - add planned, disabled, unavailable, consent-required, opt-out, provider, taxonomy, payload field, blocked payload, docs path, unsupported claim, and bounded summary vocabulary in `packages/protocol`.
* Browser code can evaluate analytics readiness safely - add web helpers that require explicit enabled config and consent, reject malformed provider config, preserve local-only fallback, and produce no network side effects.
* Tests can prevent analytics payload drift - assert blocked categories never appear in analytics payloads and that configuration alone, consent alone, malformed URLs, disabled flags, or missing website IDs cannot activate analytics.
* Settings UX can be honest without enabling tracking - expose disabled or unavailable analytics copy where useful, with accessibility labels and revalidation on drawer entry, while avoiding a working send-event control.
* Stable docs and package README files align with current source behavior and keep analytics dashboards, replay capture, heatmaps, console-log capture, server-side ingestion, production-hosted validation, and trusted erasure outside shipped claims.

### Out of Scope (Deferred)

* Sending analytics events, installing a browser tracking script, creating a server analytics adapter, importing `@umami/node` in runtime code, or shipping a dashboard - *Reason: this session defines guardrails and disabled readiness only.*
* Enabling recorder, session replay, heatmap, console-log capture, site apps, broad user tracking, marketing funnel analytics, or event payloads outside the approved taxonomy - *Reason: ADR 0003 and the hosted payload blocklist keep those surfaces off by default.*
* Uploading prompts, file contents, command bodies, terminal output, transcripts, tokens, broad paths, exports, replay buffers, scan payloads, media drafts, diagnostics, logs, backups, account ids, or quarantined historical content - *Reason: blocked by the Phase 07 hosted payload privacy blocklist.*
* Making analytics required for local development, public demo use, War Room collaboration, hosted identity, hosted storage, push, or remote access - *Reason: analytics remains optional and local-first fallback is required.*
* Closing trusted unified erasure, production-hosted validation, release hardening, mobile certification, WCAG certification, or legacy decommission - *Reason: Phase 08 owns those release gates.*

***

## 5. Technical Approach

### Architecture

Use `packages/protocol` as the shared contract owner for hosted analytics guardrails. Add a focused `hostedAnalytics` module that exports provider values, status values, consent states, consent requirements, approved event names, allowed payload fields, blocked payload labels, unsupported claim labels, docs paths, diagnostic shapes, and pure helpers for building a compact guardrail summary. The helpers should be deterministic and side-effect free so web and future server or diagnostics packages can consume them without duplicating strings.

In `apps/web`, add pure helper functions that evaluate browser analytics readiness from a caller-provided environment record and consent state. The helper should return disabled, unavailable, or ready-with-consent states without loading a tracking script or sending a beacon. It should normalize the Umami host URL using existing public URL rules, require a non-empty website id only when analytics is explicitly enabled, treat all absent or malformed config as local-only fallback, and expose safe settings copy for disabled or consent-required states.

Analytics payload construction should be allowlist based. Approved events should carry only bounded product posture fields such as event id, surface, status label, feature label, and coarse counts where explicitly allowed. Payload helpers must reject or drop blocked keys for prompts, transcripts, file/code content, command bodies, terminal output, secrets, URLs with credentials, broad paths, exports, replay buffers, scan payloads, media drafts, diagnostics, logs, backups, account identifiers, zone identifiers, tunnel tokens, and historical intake. Tests should serialize synthetic payloads and assert the sensitive substrings do not appear.

Documentation updates should make the lifecycle explicit: Umami is the selected future default provider, but analytics remains disabled unless both operator configuration and user or operator consent requirements are met. PostHog remains historical context only. Server-side ingestion, dashboards, production-hosted validation, and trusted erasure stay deferred unless a later approved session moves that scope.

### Design Patterns

* Protocol-first contracts: shared analytics provider, event, payload, and unsupported-state vocabulary starts in `packages/protocol`.
* Planned-state scaffolding: source can expose disabled or consent-required posture without creating half-wired analytics capture.
* Disabled defaults: blank, absent, malformed, reserved, or explicitly false analytics config results in local-only behavior.
* Consent separation: configuration, operator intent, user consent, and opt-out are distinct states; credentials or website ids are not consent.
* Allowlisted payload builder: analytics payload helpers accept declared fields only and reject or drop blocked categories deterministically.
* Negative claim tests: tests assert helpers do not imply dashboards, recorder, heatmaps, session replay, server-side ingestion, public replay analytics, production validation, or trusted erasure.

### Technology Stack

* TypeScript contracts and Vitest tests in `packages/protocol`.
* Vite/browser helper logic, React settings copy, Testing Library, and Vitest tests in `apps/web`.
* Markdown docs under `.spec_system/PRD/phase_07/`, `docs/`, and package README files.

***

## 6. Deliverables

### Files to Create

| File                                                              | Purpose                                                                                                                                         | Est. Lines |
| ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `.spec_system/PRD/phase_07/analytics_consent_payload_controls.md` | Source-backed analytics provider, consent, opt-out, taxonomy, payload minimization, blocklist, local fallback, and Phase 08 handoff baseline    | \~240      |
| `packages/protocol/src/hostedAnalytics.ts`                        | Shared analytics status, provider, consent, taxonomy, payload field, blocked payload, docs path, unsupported claim, and pure summary helpers    | \~260      |
| `packages/protocol/tests/hostedAnalytics.test.ts`                 | Protocol tests for provider/status vocabulary, consent requirements, event taxonomy, payload allowlists, blocked labels, and negative claims    | \~190      |
| `apps/web/src/lib/hostedAnalytics.ts`                             | Browser helper for disabled analytics readiness, consent and opt-out evaluation, local-only fallback, safe settings copy, and payload scrubbing | \~220      |
| `apps/web/tests/hostedAnalytics.test.ts`                          | Web helper tests for disabled default, config plus consent gating, malformed config, opt-out, payload scrubbing, and no network side effects    | \~180      |
| `apps/web/tests/SettingsHostedAnalytics.test.tsx`                 | Settings drawer tests for disabled/unavailable analytics copy, accessible status, and revalidation on drawer entry                              | \~120      |

### Files to Modify

| File                                           | Changes                                                                                                                                          | Est. Lines |
| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
| `packages/protocol/src/index.ts`               | Export hosted analytics contracts from the package barrel                                                                                        | \~2        |
| `packages/protocol/src/hostedConfig.ts`        | Refine reserved analytics variable metadata to point to Session 05 disabled-default and consent ownership                                        | \~12       |
| `packages/protocol/tests/hostedConfig.test.ts` | Assert analytics variables remain reserved, disabled by default, and blocked from browser-secret mirrors                                         | \~35       |
| `apps/web/src/components/SettingsDrawer.tsx`   | Surface disabled or unavailable analytics status copy without adding a tracking control, with revalidation on drawer entry and accessible labels | \~45       |
| `.env.local.example`                           | Align analytics comments with Session 05 consent, opt-out, payload tests, and disabled-default source behavior                                   | \~20       |
| `docs/hosted-services.md`                      | Add Session 05 analytics boundary, Umami/self-hosting posture, consent, opt-out, payload minimization, and disabled-default behavior             | \~45       |
| `docs/privacy-and-security.md`                 | Add analytics data inventory notes, blocked payload categories, consent boundaries, and no raw-value analytics guarantees                        | \~45       |
| `docs/environments.md`                         | Clarify analytics variables remain optional, disabled by default, and insufficient without consent and payload controls                          | \~35       |
| `docs/release.md`                              | Add analytics release guardrails, negative-claim checks, and Phase 08 production-hosted validation deferrals                                     | \~35       |
| `.spec_system/PRD/PRD.md`                      | Update Phase 07 status map and analytics guardrail wording after implementation                                                                  | \~15       |
| `.spec_system/PRD/PRD_UX.md`                   | Update UX requirements for disabled analytics status copy, consent, opt-out, and no dashboard claim                                              | \~20       |
| `.spec_system/PRD/phase_07/PRD_phase_07.md`    | Add Session 05 outputs and progress wording after implementation                                                                                 | \~30       |
| `packages/protocol/README_protocol.md`         | Document protocol ownership of analytics guardrail contracts and future consumer rules                                                           | \~30       |
| `apps/web/README_web.md`                       | Document browser analytics readiness helpers, disabled settings copy, local-only fallback, and no tracking runtime                               | \~35       |

***

## 7. Success Criteria

### Functional Requirements

* [ ] Analytics requirements define provider selection, disabled default, enabled-state, operator configuration, user or operator consent, opt-out, self-hosting, replaceability, event taxonomy, payload minimization, and local-only fallback.
* [ ] Protocol analytics contracts expose planned/disabled/unavailable/ready states, provider metadata, consent requirements, approved events, allowed payload fields, blocked payload labels, docs paths, unsupported claims, and bounded summary helpers.
* [ ] Web analytics helpers return local-only disabled behavior when analytics config is absent, blank, malformed, explicitly false, missing a website id, or lacking consent.
* [ ] Configuration alone, credentials alone, a website id alone, or consent alone cannot activate analytics.
* [ ] Payload helpers never serialize prompts, provider prompts, file contents, code bodies, command bodies, terminal output, transcripts, tokens, broad paths, exports, replay buffers, scan payloads, media drafts, diagnostics, logs, backups, account ids, zone ids, tunnel tokens, or quarantined historical content.
* [ ] Settings copy presents analytics as disabled, unavailable, or consent-required without implying a shipped dashboard or active capture.
* [ ] No source, UI, docs, diagnostics, or tests imply analytics dashboards, recorder, heatmaps, session replay, server-side ingestion, production-hosted validation, or trusted erasure is shipped.

### Testing Requirements

* [ ] Protocol hosted analytics tests written and passing.
* [ ] Web hosted analytics helper tests written and passing.
* [ ] Settings drawer disabled analytics status tests written and passing.
* [ ] Hosted config regression tests updated for analytics reserved variables and blocked browser mirrors.
* [ ] Focused package typechecks run for changed TypeScript packages where feasible.
* [ ] Manual docs review completed for analytics, consent, opt-out, payload, disabled-default, and Phase 08 deferral wording.

### Non-Functional Requirements

* [ ] Core local workflows remain usable without Umami, analytics keys, hosted accounts, hosted storage, Cloudflare credentials, push, remote access, tunnels, public replay hosting, or production hosts.
* [ ] Browser code does not load remote analytics scripts, send beacons, write account-backed consent records, store hosted identifiers, or expose raw analytics secrets.
* [ ] Analytics payload processing is bounded, deterministic, side-effect free, and safe to test with synthetic sensitive strings.
* [ ] Phase 08 trusted erasure and production-hosted validation remain explicitly deferred.

### Quality Gates

* [ ] All files ASCII-encoded.
* [ ] Unix LF line endings.
* [ ] Code follows project conventions.
* [ ] `git diff --check` passes.

***

## 8. Implementation Notes

### Key Considerations

* Do not read or copy `.env.local`; tests should use synthetic environment records and synthetic sensitive strings.
* `FACTIONOS_ANALYTICS_ENABLED=true`, `UMAMI_WEBSITE_ID`, or `UMAMI_API_KEY` is not consent and must not activate capture by itself.
* `@umami/node` is installed as an optional server dependency but this session should not import it or add server-side analytics ingestion.
* Umami is the selected optional default provider; PostHog remains historical service-discovery context only.
* Browser-visible config can identify an origin or site, so docs should call it publishable and revocable rather than secret-safe.
* Local settings, replay links, exports, archives, diagnostics, logs, backups, and War Room payloads remain local or redacted; analytics helpers must not treat them as share-safe.

### Potential Challenges

* Scope bleed into event capture: mitigate by shipping pure readiness and payload helpers only, with no beacon, script injection, SDK import, or route wiring.
* Payload leakage through broad event maps: mitigate by allowlisting event names and payload keys, then testing serialized output against blocked synthetic values.
* Consent drift: mitigate by making config, consent, and opt-out separate typed states and testing every combination.
* Settings overclaim: mitigate by using disabled or unavailable status copy and avoiding controls that suggest an active analytics dashboard.
* Documentation drift: mitigate by updating stable docs and package READMEs in the same session as source helpers and tests.

### Relevant Considerations

* \[P00] **Hosted services are optional**: Supabase, Umami analytics, hosted storage, public replay hosting, and hosted validation remain planned or optional; core local workflows must work without hosted accounts or public client tokens.
* \[P05] **Redaction is boundary-specific**: analytics payloads need their own minimization and redaction instead of inheriting replay, export, archive, adapter, diagnostics, backup, log, or Worker boundaries by assumption.
* \[P03] **Local-first boundary is architectural**: server, web, hooks, CLI, adapters, LLM, analytics, backups, logs, and Worker integrations should degrade cleanly when API keys, hosted services, and remote relays are absent.
* \[P03-packages/protocol] **Protocol leads cross-package work**: analytics provider, taxonomy, consent, payload, and blocked-label vocabulary should start in `packages/protocol`.
* \[P01] **Credentials are not consent**: provider configuration and user or operator transfer permission must be separate controls when developer data could leave the browser or local runtime.
* \[P06] **Phase complete is not release complete**: this session does not close production-hosted validation, trusted erasure, mobile certification, WCAG certification, or release decommission gates.
* \[P06-S07-ERASURE] **Trusted erasure remains open**: local opt-out, settings reset, or disabled analytics state is not trusted unified deletion.

### Behavioral Quality Focus

Checklist active: Yes Top behavioral risks for this session:

* Analytics becomes enabled by configuration alone, consent alone, or a future reserved variable without explicit combined readiness checks.
* Analytics payload helpers accidentally accept prompt, path, command, export, replay, diagnostic, log, backup, token, account, or historical-intake data.
* Settings copy or docs imply an active analytics dashboard, recorder, heatmap, hosted validation, or trusted erasure before those surfaces exist.

***

## 9. Testing Strategy

### Unit Tests

* Test protocol provider, status, consent, event taxonomy, payload field, blocked payload, unsupported claim, docs path, and summary helper behavior.
* Test web readiness helpers for absent config, blank config, explicit false, malformed Umami host URL, missing website id, consent missing, consent denied, opt-out, and ready-with-consent states.
* Test payload helper output against synthetic prompts, paths, commands, tokens, replay buffers, exports, diagnostics, logs, backups, account ids, zone ids, tunnel tokens, and historical content.

### Integration Tests

* Test `SettingsDrawer` renders disabled or unavailable analytics status copy with accessible labeling and refreshes state when the drawer opens.
* Test hosted config regression coverage for reserved analytics variables and blocked browser mirrors.

### Manual Testing

* Open the settings drawer with analytics env absent and verify the UI reports analytics as disabled or unavailable without a send-event control.
* Review hosted-service, privacy, environment, release, UX, and README docs for consistent shipped versus planned wording.

### Edge Cases

* `FACTIONOS_ANALYTICS_ENABLED=true` with no consent.
* Consent present with analytics explicitly disabled.
* Umami host URL with credentials, query string, fragment, unsupported protocol, or excessive length.
* Empty or whitespace-only website id.
* Payloads containing blocked keys under nested objects or unknown event names.
* Storage-unavailable browser context where local settings cannot be read.

***

## 10. Dependencies

### External Libraries

* React 18.3.1: existing settings drawer UI.
* Vite 6.4.2: browser environment handling.
* Vitest 4.1.7 and Testing Library: focused unit and component tests.
* `@umami/node` 0.4.0: optional installed server dependency, explicitly not imported or activated by this session.

### Internal Modules

* `packages/protocol/src/hostedConfig.ts`: existing hosted config categories and public URL normalization behavior.
* `packages/protocol/src/hostedIdentity.ts`: identity consent and non-overclaim vocabulary.
* `packages/protocol/src/hostedPersistence.ts`: storage, replay, and blocked payload vocabulary.
* `apps/web/src/lib/hostedConfig.ts`: browser-visible hosted config helpers.
* `apps/web/src/components/SettingsDrawer.tsx`: settings status surface.
* `apps/web/src/store/useSettingsStore.ts`: persisted local settings patterns.

### Other Sessions

* **Depends on**: Phase 07 Sessions 01-04, Phase 02 Session 06, Phase 06 Session 07.
* **Depended by**: Phase 07 Session 06, Phase 07 Session 07, Phase 08 release hardening and legacy decommission.

***

## Next Steps

Run the implement workflow step to begin AI-led implementation.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://faction-os.gitbook.io/faction-os-docs/.spec_system/archive/sessions/phase07-session05-analytics-consent-and-payload-controls/spec.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
