> 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/phase01-session04-server-routes-and-authorization-boundaries/spec.md).

# Session Specification

**Session ID**: `phase01-session04-server-routes-and-authorization-boundaries` **Phase**: 01 - Core Runtime Hardening **Status**: Completed **Created**: 2026-05-29 **Package**: Cross-package (`apps/server`, `packages/protocol`) **Package Stack**: TypeScript ESM, Express 4, ws, shared protocol types, Vitest node tests, Markdown docs

***

## 1. Session Overview

This session hardens the current local server route surface without pretending that the recovered historical route inventory is already fully shipped. The current server exposes a focused local-first REST API, a WebSocket fanout, and a clear 501 catch-all for historical routes that are not implemented. That is the right product posture for Phase 01, but the route layer still has uneven runtime validation, broad write paths, and documentation that marks some behaviors as hardening gaps.

The work centers on `apps/server` with a small protocol contract pass in `packages/protocol`. Server route handlers should reject malformed high-risk inputs consistently, keep auth-token enforcement optional but reliable, and return precise capability responses for unsupported historical routes. Protocol types should capture the REST/status vocabulary needed by server tests and docs, without promoting later-phase file, git, terminal, hosted auth, or War Room client integration work into this session.

This session enables Session 05 by making route-level authorization and unsupported-route decisions explicit before WebSocket hydration, archive, and export privacy are tightened. It also reduces release risk from security findings around unauthenticated local surfaces, prompt/path privacy, local retention, and raw external payloads by clarifying which current routes are safe local behavior and which routes remain planned or unsupported.

***

## 2. Objectives

1. Classify current local server routes against the recovered route inventory as shipped, tested-shipped, stubbed, planned, unsupported, or separate surface.
2. Add shared REST/status contracts and lightweight request validation helpers for high-risk current POST routes.
3. Harden notice, permission, plan approval, scroll collection, mission list, and unsupported-route responses with explicit validation and error mapping.
4. Add focused tests and stable docs for malformed payloads, auth-token boundaries, unsupported historical routes, and route capability responses.

***

## 3. Prerequisites

### Required Sessions

* [x] `phase01-session01-event-ingest-contract-reconciliation` - provides the current `/event` contract, ingest normalization, and source-backed API docs.
* [x] `phase01-session02-hook-runtime-safety` - provides hook payload limits and local-first error handling assumptions that influence route boundaries.
* [x] `phase01-session03-cli-lifecycle-parity` - provides current CLI launch, status, and auth-token usage context for local server access.

### Required Tools/Knowledge

* Node.js 20 or newer.
* npm workspaces and Vitest node projects.
* Express route handling in `apps/server/src/server.ts` and `apps/server/src/routes/*`.
* Shared protocol exports from `packages/protocol/src/index.ts`.
* Historical route evidence in `EXAMPLES/findings/api-routes.txt`, `EXAMPLES/findings/architecture.md`, `EXAMPLES/findings/BUILD_LINKS.md`, and `EXAMPLES/findings/websocket-events.txt`.

### Environment Requirements

* Work from the repository root.
* Keep core local workflows usable without Supabase, Umami, PostHog, Cloudflare credentials, Anthropic credentials, adapter tokens, or hosted storage.
* Do not implement later-phase file, git, terminal, branch-control, hosted auth, or War Room web-client routes in this session.
* Do not copy raw tokens, prompt bodies, long historical excerpts, or quarantined media from `EXAMPLES/` into source or docs.

***

## 4. Scope

### In Scope (MVP)

* Maintainer can compare the current local server route map against `EXAMPLES/findings/api-routes.txt` - classify shipped, stubbed, unsupported, planned, and separate-surface route families in code tests and docs.
* Developer receives deterministic 501 responses for unsupported historical local-server routes - include method, path, route family, status, and a docs pointer without exposing sensitive request data.
* Server accepts high-risk current POST routes only with schema-validated input and explicit error mapping - cover notice, permission response, plan approval, scroll collect, and route body parsing boundaries.
* Server keeps mission list reads bounded - validate pagination input and keep deterministic ordering from the existing mission manager contract.
* Server keeps auth-token behavior optional but reliable - prove that read, write, and unsupported routes are all guarded when `FACTIONOS_AUTH_TOKEN` is configured.
* Server keeps `/warroom` documented as a local compatibility stub and the real Worker API as a separate surface - avoid implying local route parity.
* Stable docs describe route status, validation expectations, auth-token boundaries, and unsupported route behavior without sending users to `EXAMPLES/` as product documentation.

### Out of Scope (Deferred)

* File, git, terminal, branch, worktree, IDE-open, and command-control routes - *Reason: these are later orchestration and developer-operation surfaces.*
* Supabase-backed auth, hosted accounts, hosted persistence, or OAuth flows - *Reason: Phase 01 keeps local auth-token boundaries only.*
* War Room web-to-Worker client integration - *Reason: the Worker backend is a separate surface and full client integration belongs to Phase 05.*
* Export redaction and archive retention policy - *Reason: Session 05 owns archive, export, replay, and retention privacy.*
* LLM scan/provider-transfer hardening - *Reason: Session 06 owns LLM fallback and scan privacy.*

***

## 5. Technical Approach

### Architecture

Add a small shared REST contract module in `packages/protocol` for route status vocabulary, route capability envelopes, and current request/response helper types that tests and docs can reference. Keep it framework-independent and free of Express imports.

In `apps/server`, add lightweight validation utilities instead of introducing a new runtime dependency. Route handlers should validate at the boundary closest to the resource, return compact JSON error envelopes, and avoid logging or echoing sensitive request fields. A dedicated unsupported-route helper should classify known historical route families and produce deterministic 501 payloads from the existing catch-all.

Tests should boot real ephemeral servers where auth and catch-all behavior matter, and use isolated route helpers where pure validation is easier to test. Documentation updates should summarize current support and hardening decisions without duplicating the full historical inventory.

### Design Patterns

* Protocol-led contracts: define route status and capability envelopes in `packages/protocol` before server docs depend on them.
* Boundary validation: validate request bodies and query values inside route handlers or shared route helpers before manager calls.
* Explicit unsupported behavior: keep 501 responses useful and stable rather than allowing historical route paths to look like accidental 404s.
* Local-first auth boundary: preserve optional bearer-token auth and test that it covers read, write, and unsupported routes uniformly.
* Fixture-backed docs: update docs only for behavior covered by current source and tests.

### Technology Stack

* TypeScript ESM in `apps/server` and `packages/protocol`.
* Express 4 route handlers and middleware.
* Existing `ws` server upgrade authorization behavior.
* Vitest node tests through the root test projects.
* Biome formatting and linting.
* No new runtime dependency expected.

***

## 6. Deliverables

### Files to Create

| File                                          | Purpose                                                                                                | Est. Lines |
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ---------- |
| `packages/protocol/src/rest.ts`               | Shared REST route status, capability, request, and error-envelope contracts                            | \~120      |
| `packages/protocol/tests/rest.test.ts`        | Protocol tests for route status vocabulary and REST contract exports                                   | \~90       |
| `apps/server/src/lib/requestValidation.ts`    | Server request validation helpers for non-empty strings, booleans, arrays, pagination, and JSON errors | \~160      |
| `apps/server/src/lib/unsupportedRoutes.ts`    | Historical route-family classifier and deterministic 501 response builder                              | \~140      |
| `apps/server/tests/authBoundaries.test.ts`    | Auth-token tests across read, write, and unsupported route families                                    | \~140      |
| `apps/server/tests/unsupportedRoutes.test.ts` | Tests for historical route-family 501 payloads and War Room separation                                 | \~170      |

### Files to Modify

| File                                   | Changes                                                                                                           | Est. Lines |
| -------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ---------- |
| `packages/protocol/src/index.ts`       | Export REST contracts                                                                                             | \~5        |
| `apps/server/src/server.ts`            | Wire unsupported-route helper into the catch-all and preserve auth/rate-limit ordering                            | \~35       |
| `apps/server/src/routes/heroes.ts`     | Validate mission list limits, notice bodies, severity, targets, scroll collect bodies, and War Room stub metadata | \~120      |
| `apps/server/src/routes/permission.ts` | Validate IDs and optional booleans for permission and plan approval responses                                     | \~80       |
| `apps/server/src/routes/event.ts`      | Align `/event` invalid-body responses with shared route error conventions where practical                         | \~30       |
| `apps/server/tests/routes.test.ts`     | Extend route coverage for notice validation, pagination bounds, scroll collect bodies, and stub metadata          | \~120      |
| `apps/server/tests/permission.test.ts` | Extend permission and plan approval coverage for malformed IDs, invalid booleans, and duplicate-safe responses    | \~100      |
| `docs/api/README_api.md`               | Update concise route status, auth, validation, and unsupported-route behavior                                     | \~90       |
| `docs/api/event-api-hook-contracts.md` | Update detailed route classification, source traceability, and Phase 01 hardening notes                           | \~140      |
| `apps/server/README_server.md`         | Align server README route notes with new validation/auth/capability behavior                                      | \~60       |

***

## 7. Success Criteria

### Functional Requirements

* [ ] Current local server route families are classified as shipped, tested-shipped, stubbed, planned, unsupported, or separate-surface.
* [ ] Unsupported historical routes return deterministic 501 JSON with method, path, route family, status, and docs pointer.
* [ ] High-risk current POST routes reject malformed bodies with compact, explicit JSON errors before manager state changes.
* [ ] `/missions` list limits are bounded and invalid limits do not produce unbounded or nondeterministic results.
* [ ] Permission and plan approval responses validate request identifiers and optional booleans while remaining duplicate-safe.
* [ ] Bearer-token auth covers read routes, write routes, and unsupported catch-all routes when configured.
* [ ] `/warroom` remains explicitly documented as a local stub, with the Cloudflare Worker routes documented as a separate surface.

### Testing Requirements

* [ ] Protocol REST contract tests pass.
* [ ] Server route validation tests pass.
* [ ] Auth-boundary tests pass for read, write, and unsupported route families.
* [ ] Unsupported historical route tests pass for representative file, git, terminal, local War Room, and unknown route paths.
* [ ] Focused Vitest command passes for protocol and server tests touched by this session.

### Non-Functional Requirements

* [ ] No route error response echoes prompts, command previews, tokens, request bodies, or private file contents.
* [ ] No hosted service, remote relay, or non-loopback exposure becomes required for local runtime use.
* [ ] Route docs describe current behavior without overstating historical parity.

### Quality Gates

* [ ] All files ASCII-encoded.
* [ ] Unix LF line endings.
* [ ] Code follows project conventions.
* [ ] Biome format/lint succeeds for touched files.
* [ ] TypeScript typecheck succeeds for touched packages.

***

## 8. Implementation Notes

### Key Considerations

* `apps/server/src/server.ts` currently applies CORS, rate limiting, optional auth, and JSON parsing before route registration. Keep auth before all routes and the catch-all so unsupported route probes are still protected when a local token is configured.
* `apps/server/src/routes/heroes.ts` owns several unrelated read/write routes. Keep changes scoped and avoid large route reorganization unless tests show it is needed.
* `packages/protocol` must remain framework-independent. Do not import Express or server managers into protocol contracts.
* `EXAMPLES/` remains traceability input only. Route names can be referenced, but raw historical implementation snippets, tokens, or long inventories should not be copied.

### Potential Challenges

* Historical route inventory is much larger than the current server surface: classify representative route families instead of duplicating all 207 paths in code.
* Validation could break existing clients that rely on loose defaults: preserve documented defaults where they are intentional, but reject malformed types when they create ambiguous state changes.
* Permission and plan pending maps are not yet populated by every producer: keep response routes duplicate-safe and do not require pending entries until a later approval orchestration session defines that contract.
* Export and LLM routes are high-risk, but their privacy scope is owned by Sessions 05 and 06: document retained gaps instead of broadening this session beyond route authorization and validation.

### Relevant Considerations

* \[P00] **Historical artifacts quarantined**: Use `EXAMPLES/` as route evidence only, not as runtime source or user documentation.
* \[P00] **Prompt and path privacy**: Route errors and unsupported responses must not echo sensitive request bodies, prompts, command previews, tokens, or full paths.
* \[P00-apps/server+packages/protocol] **Typed surface exceeds implementation**: Preserve clear unsupported behavior and prioritize current workflow value over historical route parity.
* \[P00] **Local-first boundary**: Keep optional services optional and avoid adding remote or hosted prerequisites.
* \[P00-packages/protocol] **Protocol leads cross-package work**: Add shared route contracts before server/docs rely on them.

### Behavioral Quality Focus

Checklist active: Yes

Top behavioral risks for this session:

* Malformed external input mutates server state before validation.
* Optional local auth is bypassed on unsupported or stubbed route families.
* Unsupported historical route responses imply support, leak request details, or make later route ownership ambiguous.

***

## 9. Testing Strategy

### Unit Tests

* Add protocol tests for REST route status vocabulary and exported contract shapes in `packages/protocol/tests/rest.test.ts`.
* Add pure validation helper tests where validators have edge cases for empty strings, whitespace IDs, invalid booleans, non-array targets, and pagination bounds.

### Integration Tests

* Boot ephemeral `createFactionOsServer({ port: 0, mock: false })` instances for auth boundary, unsupported route, and high-risk POST route tests.
* Cover read, write, and unsupported routes with `FACTIONOS_AUTH_TOKEN` or explicit `authToken` options.
* Cover representative unsupported historical route families, including file, git, terminal, local War Room, and unknown route paths.

### Manual Testing

* Start the local server with no auth token and verify current routes still work.
* Start the local server with `FACTIONOS_AUTH_TOKEN` and verify an unauthenticated read, write, and unsupported route each returns 401 while authenticated requests proceed.
* Hit a known unsupported historical path and verify the response is a stable 501 with docs pointer and no echoed request body.

### Edge Cases

* Empty JSON body, array body, malformed JSON content type, and whitespace-only IDs.
* `approved` values supplied as strings, numbers, null, or omitted.
* `targets` supplied as non-arrays, arrays with non-strings, duplicate strings, or over the allowed count.
* `limit` supplied as zero, negative, decimal, non-numeric, and larger than the documented cap.
* Unsupported route request with sensitive-looking body or token headers.

***

## 10. Dependencies

### External Libraries

* None expected.

### Other Sessions

* **Depends on**: `phase01-session01-event-ingest-contract-reconciliation`, `phase01-session02-hook-runtime-safety`, `phase01-session03-cli-lifecycle-parity`.
* **Depended by**: `phase01-session05-websocket-hydration-and-archive-export-privacy`, `phase01-session07-runtime-contract-documentation`.

***

## 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/phase01-session04-server-routes-and-authorization-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.
