> 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-session02-hosted-configuration-and-client-exposure-boundaries/spec.md).

# Session Specification

**Session ID**: `phase07-session02-hosted-configuration-and-client-exposure-boundaries` **Phase**: 07 - Hosted Services and Analytics Guardrails **Status**: Not Started **Created**: 2026-05-30 **Package**: Cross-cutting (`apps/server`, `apps/web`, `packages/protocol`; docs and env examples) **Package Stack**: TypeScript, Express, React 18, Vite, Vitest, npm workspaces, Markdown docs

***

## 1. Session Overview

This session implements the Phase 07 hosted configuration boundary that Session 01 defined in planning artifacts. It turns the variable inventory and public-client/server-only/deploy-only/reserved categories into source-backed contracts, sanitized diagnostics, tests, and stable docs so later hosted identity, persistence, analytics, push, remote access, and validation sessions start from a clear configuration model.

The work is cross-package but deliberately narrow. `packages/protocol` owns the shared hosted config vocabulary, blocked exposure categories, diagnostic shapes, and helper contracts. `apps/server` reads process environment safely and exposes local diagnostics that report posture only, never raw values. `apps/web` validates browser-visible Vite config so only documented publishable values can become browser defaults, with local-only fallback when values are blank, malformed, or reserved.

The session must preserve the local-first posture. Core server, web, hooks, CLI, adapters, Worker fallback, public demo, local replay, export, archive, backup, and test workflows must keep working without Supabase, Umami, VAPID, Cloudflare credentials, Worker URL, tunnel tokens, provider keys, analytics, push, hosted storage, public replay hosting, or remote access. This session does not enable hosted auth, hosted database access, analytics capture, push delivery, public replay hosting, remote tunnels, hosted diagnostics upload, or account-backed behavior.

***

## 2. Objectives

1. Add shared hosted configuration categories, variable metadata, safe diagnostic shapes, and helper functions in `packages/protocol`.
2. Add server-side hosted config posture building and a local diagnostics route that reports only present/absent, enabled/disabled, valid/invalid, reserved, and blocked status labels.
3. Add browser-side public config validation helpers that accept only documented non-secret `VITE_` values and fall back to local-only behavior for blank, malformed, or unsafe values.
4. Update environment examples, hosted-service docs, deployment/privacy docs, API docs, and package README files so public-client, server-only secret, deploy-only, reserved, and blocked values are consistently documented.

***

## 3. Prerequisites

### Required Sessions

* [x] `phase07-session01-hosted-services-requirements-and-privacy-baseline` - provides hosted variable inventory, routing matrix, payload privacy blocklist, local-first fallback checks, and Phase 08 deferrals.
* [x] `phase06-session07-collaboration-isolation-and-mobile-validation-closeout` - provides current security posture, local browser evidence, hosted identity residual risk, trusted erasure deferral, and hosted validation deferral.
* [x] `phase05-session07-war-room-validation-and-documentation-closeout` - provides optional Worker boundary, Worker URL diagnostics, deployment docs, and room-local authority limits.
* [x] `phase03-session07-orchestration-validation-and-documentation-closeout` - provides diagnostics patterns, unsupported route family handling, and protocol-first shared contract lessons.

### Required Tools/Knowledge

* Node 20+, npm workspaces, TypeScript 5.9, Vitest, Express routers, Vite `import.meta.env`, React browser config boundaries, and Biome formatting/linting.
* Current source patterns in `packages/protocol/src/isolation.ts`, `apps/server/src/lib/isolationDiagnostics.ts`, `apps/server/src/routes/diagnostics.ts`, `apps/web/src/lib/warRoomDiagnostics.ts`, and their focused tests.
* Session 01 artifacts: `.spec_system/PRD/phase_07/hosted_services_requirements_privacy_baseline.md`, `.spec_system/PRD/phase_07/phase07_requirement_routing_matrix.md`, and `.spec_system/PRD/phase_07/hosted_payload_privacy_blocklist.md`.

### Environment Requirements

* Local checkout of the FactionOS monorepo with dependencies already installable through existing npm workspace scripts.
* No real hosted credentials are required. Do not read, copy, print, or commit raw values from `.env.local`.
* Use `.env.local.example`, `apps/server/.env.example`, docs, and source evidence for examples and tests.

***

## 4. Scope

### In Scope (MVP)

* Maintainers can consume one protocol-owned hosted config vocabulary - add categories for active local, public-client, server-only secret, deploy-only, reserved future, and blocked values with exhaustive helper coverage.
* Operators can inspect local hosted config posture safely - add server diagnostics that expose compact status and counts without raw secrets, account ids, zone ids, tunnel tokens, URLs with credentials, provider keys, local paths, replay/export/archive data, logs, or backups.
* Browser code can distinguish publishable config from unsafe config - validate `VITE_FACTIONOS_WARROOM_WORKER_URL`, reserved `VITE_SUPABASE_*` values, and future browser-visible hosted config through helper functions that preserve local-only fallback.
* Tests prove public and secret config separation - cover category classification, server diagnostics redaction, browser env parsing, unsafe `VITE_` mirror detection, blank/malformed fallback, and auth inheritance for the diagnostics route.
* Docs and env examples align with source behavior - update environment, hosted-service, deployment, privacy, API, release, and package README docs for current config boundaries.

### Out of Scope (Deferred)

* Implementing hosted account login, OAuth, SSO, organization membership, Supabase clients, PKCE, JWKS, RLS, or account UI - *Reason: Session 03 owns hosted identity and authorization guardrails.*
* Implementing hosted persistence, database migrations, storage buckets, public replay hosting, replay upload, retention workers, export-to-cloud, or takedown flows - *Reason: Session 04 owns persistence and public replay boundaries.*
* Enabling analytics capture, Umami event beacons, analytics dashboards, user tracking, consent UI, or analytics payload submission - *Reason: Session 05 owns analytics consent and payload controls.*
* Implementing push delivery, VAPID keypair generation, push subscription storage, remote tunnels, Cloudflare Tunnel workflows, remote access, or hosted operator diagnostics upload - *Reason: Session 06 owns push, remote access, and operator diagnostics guardrails.*
* Rotating real credentials, probing hosted accounts, committing service discovery output, or adding new required variables for local development - *Reason: this session is source-backed guardrails only.*
* Claiming trusted unified erasure, production-hosted validation, mobile certification, WCAG certification, release readiness, or legacy decommission completion - *Reason: Phase 08 owns those release gates.*

***

## 5. Technical Approach

### Architecture

Use `packages/protocol` as the shared contract owner. Add a hosted config module that exports category values, exposure values, blocked variable metadata, docs paths, diagnostic shapes, variable metadata, and pure helpers for classification and posture building. Keep the helpers deterministic and side-effect free so server and web packages can consume the same vocabulary without duplicating strings.

In `apps/server`, build a local hosted config posture from an environment record. The posture should report whether each known hosted-adjacent variable is absent, blank, present, enabled, disabled, malformed, reserved, or blocked from exposure. It should never return raw values. Mount the route under local diagnostics, behind the existing CORS, rate-limit, body-size, and optional bearer auth middleware.

In `apps/web`, add pure helpers for browser-visible config. These helpers should read a caller-provided `Record<string, string | undefined>` by defaulting to Vite env, normalize safe public values, reject unsafe or malformed values, and expose local-only fallback status for reserved or absent hosted config. UI integration is optional only if needed to preserve existing War Room URL behavior; do not add hosted account, analytics, push, or public replay UI.

### Design Patterns

* Protocol-first contracts: shared categories, statuses, docs paths, and diagnostic shapes live in `packages/protocol` before server or web consumption.
* Pure posture builders: config diagnostics accept explicit env records for deterministic tests and avoid ambient side effects where possible.
* Redacted diagnostics: diagnostics report status labels, counts, docs paths, category names, and booleans only.
* Disabled defaults: blank or absent hosted config always results in local-only, disabled, or reserved states rather than startup failure.
* Boundary-nearest authorization: the diagnostics route inherits server auth and should not bypass the existing local route middleware.
* Exhaustive enum handling: category and status helpers should be typed so unsupported categories are visible during implementation.

### Technology Stack

* TypeScript contracts and Vitest tests in `packages/protocol`.
* Express diagnostics routing, process env posture helpers, and Vitest route/unit tests in `apps/server`.
* Vite env helper logic and Vitest tests in `apps/web`.
* Markdown docs and env example comments under `.env.local.example`, `docs/`, and package README files.

***

## 6. Deliverables

### Files to Create

| File                                                | Purpose                                                                                                                   | Est. Lines |
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `packages/protocol/src/hostedConfig.ts`             | Shared hosted config variable categories, exposure rules, docs paths, diagnostic shapes, and pure classification helpers  | \~260      |
| `packages/protocol/tests/hostedConfig.test.ts`      | Protocol contract tests for categories, metadata, blocked exposure, helper behavior, and summary shapes                   | \~190      |
| `apps/server/src/lib/hostedConfig.ts`               | Server-side hosted config posture builder with redacted status-only diagnostics                                           | \~220      |
| `apps/server/tests/hostedConfig.test.ts`            | Server unit tests for env posture, blocked browser exposure, blank defaults, reserved variables, and no raw value leakage | \~170      |
| `apps/server/tests/hostedConfigDiagnostics.test.ts` | Server route tests for local diagnostics, auth inheritance, redacted output, and credential-free fallback                 | \~150      |
| `apps/web/src/lib/hostedConfig.ts`                  | Browser public config helper that validates documented `VITE_` values and preserves local-only fallback                   | \~180      |
| `apps/web/tests/hostedConfig.test.ts`               | Web helper tests for public config parsing, unsafe values, reserved hosted placeholders, and no secret leakage            | \~160      |

### Files to Modify

| File                                     | Changes                                                                                                            | Est. Lines |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ---------- |
| `packages/protocol/src/index.ts`         | Export hosted config contracts from the package barrel                                                             | \~2        |
| `apps/server/src/routes/diagnostics.ts`  | Add hosted config diagnostics route using existing diagnostics middleware path                                     | \~20       |
| `apps/server/src/server.ts`              | Pass hosted diagnostics dependencies if needed by the diagnostics router                                           | \~10       |
| `apps/web/src/lib/warRoomDiagnostics.ts` | Use shared browser config helper where it preserves existing Worker URL behavior                                   | \~20       |
| `.env.local.example`                     | Align comments for public-client, server-only, deploy-only, reserved, and blocked hosted values                    | \~25       |
| `apps/server/.env.example`               | Clarify server-side hosted config posture and no hosted-service requirement                                        | \~15       |
| `docs/environments.md`                   | Document source-backed hosted config categories, diagnostics route, browser config limits, and local-only fallback | \~40       |
| `docs/hosted-services.md`                | Document Session 02 config boundary, source-backed contracts, diagnostics, and remaining hosted deferrals          | \~35       |
| `docs/privacy-and-security.md`           | Add hosted config diagnostics privacy guarantees and blocked exposure rules                                        | \~30       |
| `docs/deployment.md`                     | Clarify deploy-only Cloudflare values and no local development requirement                                         | \~20       |
| `docs/release.md`                        | Add hosted config boundary checks to future Phase 07 release candidate notes                                       | \~20       |
| `docs/api/README_api.md`                 | Document local hosted config diagnostics and planned hosted route separation                                       | \~25       |
| `apps/server/README_server.md`           | Describe server hosted config posture, diagnostics, and raw-value exclusion                                        | \~25       |
| `apps/web/README_web.md`                 | Describe browser-visible config boundaries and local-only fallback                                                 | \~25       |
| `packages/protocol/README_protocol.md`   | Describe protocol ownership of hosted config vocabulary and diagnostics shapes                                     | \~25       |
| `apps/warroom/README_warroom.md`         | Clarify Worker URL/public config boundary and deploy-only credential separation                                    | \~15       |

***

## 7. Success Criteria

### Functional Requirements

* [ ] Shared hosted config contracts categorize known active local, public-client, server-only secret, deploy-only, reserved future, and blocked variables.
* [ ] Server hosted config diagnostics report bounded posture only: status labels, category names, counts, docs paths, and safe booleans.
* [ ] Server diagnostics never include raw credential values, account ids, zone ids, tunnel tokens, provider keys, webhook URLs, bearer values, local paths, replay/export/archive data, logs, backups, or request bodies.
* [ ] Browser config helpers accept only documented publishable `VITE_` values and reject credentials, embedded URL auth, malformed URLs, unsafe mirrors, and reserved values without breaking local-only mode.
* [ ] Core local server and web workflows still run when all hosted-service variables are absent or blank.
* [ ] Docs and env examples distinguish active local, public-client, server-only secret, deploy-only, reserved future, and blocked values.

### Testing Requirements

* [ ] Protocol hosted config tests written and passing.
* [ ] Server hosted config unit and diagnostics route tests written and passing.
* [ ] Web hosted config helper tests written and passing.
* [ ] Focused package typechecks run for changed TypeScript packages where feasible.
* [ ] Manual docs review completed for environment and hosted-service wording.

### Non-Functional Requirements

* [ ] Public browser config remains limited to documented publishable values and never includes service-role keys, API tokens, Cloudflare account ids, zone ids, tunnel tokens, provider secrets, OAuth secrets, webhook secrets, or raw authority tokens.
* [ ] Diagnostics are safe to view locally and remain credential-free even when the process environment contains secret-looking values.
* [ ] Hosted services remain optional and disabled by default; this session does not introduce required hosted variables for core local development.
* [ ] 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 env records.
* A variable being present in `.env.local.example` is not proof that runtime consumes it.
* Browser-safe values can still identify projects or origins, so docs should call them publishable and revocable rather than secret-safe.
* `VITE_FACTIONOS_AUTH_TOKEN` is an existing local development escape hatch and must not become a hosted secret pattern.
* Cloudflare account ids, zone ids, API tokens, and tunnel tokens are deploy-only or blocked from browser diagnostics.
* Supabase and Umami variables remain reserved unless later sessions add consent, authorization, payload, storage, and docs evidence.
* Keep diagnostics route local and status-only; do not add `/hosted/*` runtime routes that imply hosted services are active.

### Potential Challenges

* Over-broad diagnostics: mitigate by returning category and status only, with tests asserting sensitive substrings do not appear in serialized output.
* Duplicate variable vocabulary: mitigate by exporting shared protocol constants and consuming them from server and web where possible.
* Browser helper drift from War Room URL behavior: mitigate by preserving the existing `readBrowserSafeDefaultWarRoomWorkerUrl` tests while routing new behavior through shared helpers.
* Secret-looking placeholders in env examples: mitigate by using placeholders only in ignored private env files or clearly documented examples and by adding tests against synthetic values.
* Scope bleed into later hosted features: mitigate by documenting hosted auth, storage, analytics, push, remote access, public replay, hosted diagnostics upload, production validation, and trusted erasure as deferred.

### 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**: diagnostics, logs, browser config, replay, export, archive, adapter, backup, Worker, analytics, and hosted storage boundaries need separate minimization and redaction.
* \[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**: shared hosted config categories, diagnostics shapes, and blocked exposure vocabularies should start in `packages/protocol`.
* \[P06-apps/warroom+apps/web] **War Room federation is optional and redacted**: Worker URLs can be public-client config, but Worker authority and Cloudflare credentials must not become hosted identity or browser secrets.
* \[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-HOSTED-IDENTITY] **Hosted identity remains open**: configuration boundaries must not imply account lifecycle, consent, revocation, organization membership, or audit proof is shipped.
* \[P06-S07-ERASURE] **Trusted erasure remains open**: browser reset, local recovery, diagnostics, and Worker leave/reset are not trusted unified deletion.

### Behavioral Quality Focus

Checklist active: Yes Top behavioral risks for this session:

* Secret or deploy-only values accidentally appearing in browser config, diagnostics, logs, tests, or docs.
* Hosted config variables becoming required for local startup, hydration, diagnostics, tests, or public demo workflows.
* Diagnostics or helper errors exposing raw malformed values instead of compact safe messages.

***

## 9. Testing Strategy

### Unit Tests

* Test protocol variable metadata, category vocabulary, exposure helper behavior, blocked variable detection, summary shape, and exhaustive enum helpers.
* Test server posture building with absent, blank, valid public, reserved, server-only secret, deploy-only, and unsafe `VITE_` mirror values.
* Test web helper behavior for valid Worker URL, invalid URL, URL credentials, blank local-only mode, reserved Supabase placeholders, and unsafe secret-like browser values.

### Integration Tests

* Test `GET /diagnostics/hosted-config` returns status-only JSON, inherits local bearer auth, preserves local-only fallback when env is empty, and excludes synthetic raw secrets from serialized output.
* Test existing War Room diagnostics still accept `VITE_FACTIONOS_WARROOM_WORKER_URL` behavior after helper integration.

### Manual Testing

* Review `docs/environments.md`, `docs/hosted-services.md`, `docs/privacy-and-security.md`, `docs/deployment.md`, `docs/release.md`, package README files, and `.env.local.example` for consistent category names and no hosted feature overclaim.
* Run focused workspace commands first, then broader gates only if the implementation touches shared behavior broadly.

### Edge Cases

* Blank env values from `.env.local.example` should not enable hosted config.
* Exported env values should keep priority over file values where existing env loading behavior applies.
* URLs with usernames, passwords, tokens, query secrets, non-http schemes, or excessive length should be rejected or redacted.
* Secret names accidentally prefixed with `VITE_` should be flagged as blocked/unsafe, not accepted as browser config.
* Diagnostics should remain useful when every hosted-service variable is absent.

***

## 10. Dependencies

### External Libraries

* No new external runtime libraries are planned.
* Existing `dotenv`, Express, Vite, TypeScript, and Vitest are sufficient.

### Other Sessions

* **Depends on**: `phase07-session01-hosted-services-requirements-and-privacy-baseline`
* **Enables**: `phase07-session03-hosted-identity-and-authorization-guardrails`, `phase07-session04-hosted-persistence-and-public-replay-boundaries`, `phase07-session05-analytics-consent-and-payload-controls`, `phase07-session06-push-remote-access-and-operator-diagnostics-guardrails`, `phase07-session07-hosted-guardrails-validation-and-documentation-closeout`

***

## 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-session02-hosted-configuration-and-client-exposure-boundaries/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.
