> 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/phase03-session04-guarded-local-action-runtime/spec.md).

# Session Specification

**Session ID**: `phase03-session04-guarded-local-action-runtime` **Phase**: 03 - Agent Orchestration **Status**: Not Started **Created**: 2026-05-29 **Package**: Cross-cutting (`packages/protocol`, `apps/server`, `apps/cli`) **Package Stack**: TypeScript protocol contracts, Express routes, in-memory server managers, WebSocket events, JavaScript CLI helpers, Vitest, Node test runners

***

## 1. Session Overview

This session defines and implements the guarded local action runtime that Phase 03 needs before the web cockpit can expose orchestration decisions or the CLI can diagnose guarded-action state. It starts in `packages/protocol` with shared proposal, decision, expiration, execution-result, unavailable, and failure contracts, then wires the approved local runtime subset through `apps/server`.

The runtime goal is explicit state, not hidden command execution. File, git, terminal, spawn, resume, stop, fork, and handoff requests must become bounded guarded proposals or deterministic unavailable responses. Approval and rejection paths must guard duplicate decisions, recheck expiration, emit compact WebSocket updates, and avoid echoing raw prompts, command bodies, terminal output, file contents, tokens, transcript paths, or broad absolute paths.

This work is next because `phase03-session01-orchestration-requirements-and-safety-baseline` approved the guarded-action safety model, `phase03-session02-task-queue-and-agent-template-contracts` shipped local queue/template contracts, and `phase03-session03-subagent-lineage-and-mission-graph-runtime` shipped typed lineage state. Sessions 05 and 06 depend on guarded-action contracts before web controls or CLI diagnostics can present those states honestly.

***

## 2. Objectives

1. Define protocol-owned guarded-action contracts with explicit action families, proposal state, decision state, execution results, unavailable reasons, and compact WebSocket frames.
2. Implement local server proposal, list, detail, approve, reject, expire, and unavailable result handling with validation and duplicate-decision guards.
3. Preserve deterministic fail-closed behavior for unsupported file, git, terminal, remote-access, and container route families.
4. Add CLI helper support for safe local guarded-action HTTP calls without adding broad remote execution or user-facing orchestration commands.

***

## 3. Prerequisites

### Required Sessions

* [x] `phase03-session01-orchestration-requirements-and-safety-baseline` - provides the Phase 03 matrix, guarded-action owner rows, and safety boundaries.
* [x] `phase03-session02-task-queue-and-agent-template-contracts` - provides queue/template references, route discipline, validation patterns, and WebSocket update conventions.
* [x] `phase03-session03-subagent-lineage-and-mission-graph-runtime` - provides lineage references for subagent-related guarded actions.
* [x] `phase01-session07-runtime-contract-documentation` - provides current local server, WebSocket, auth, route-family, and privacy baselines.

### Required Tools/Knowledge

* Node 20+, npm workspaces, TypeScript, JavaScript CLI helpers, Express 4, `ws`, Biome, and Vitest.
* Existing protocol files in `packages/protocol/src/`, especially `events.ts`, `rest.ts`, `taskQueue.ts`, `lineage.ts`, and `index.ts`.
* Existing server patterns in `apps/server/src/lib/orchestrationValidation.ts`, `apps/server/src/routes/orchestration.ts`, `apps/server/src/ws/handlers.ts`, `apps/server/src/ws/clientMessageValidation.ts`, and `apps/server/src/lib/unsupportedRoutes.ts`.
* Existing CLI helper patterns in `apps/cli/src/lib/lifecycle.js`, `apps/cli/src/lib/localFiles.js`, `apps/cli/src/commands/status.js`, and `apps/cli/src/commands/doctor.js`.

### Environment Requirements

* No hosted service credentials are required.
* Local server auth, CORS, Origin, rate-limit, body-size, and loopback defaults must remain unchanged.
* Historical `EXAMPLES/` files remain evidence only and must not be copied into runtime code, docs, fixtures, proposal previews, or CLI output.

***

## 4. Scope

### In Scope (MVP)

* Maintainers can share guarded-action state through protocol types - define proposals, decisions, expiration, execution results, unavailable states, request/response envelopes, and WebSocket frames.
* Local clients can create, inspect, approve, and reject guarded proposals through schema-validated server routes - keep proposal payloads bounded, local, and explicit about unsupported or unavailable execution.
* Browser or future clients can receive guarded-action WebSocket updates and submit guarded-action decisions through the typed local WebSocket contract.
* Approved action families can fail closed with explicit unavailable, expired, rejected, failed, or no-execution result states when the local dependency or safety policy does not allow execution.
* CLI helpers can call guarded-action routes with local auth, timeouts, compact parsing, and sanitized error output for later Session 06 diagnostics.
* Implementers can verify duplicate approvals, expired actions, auth inheritance, non-loopback guardrails, command redaction, and unavailable dependencies with focused tests.

### Out of Scope (Deferred)

* Hidden or automatic terminal, git, filesystem, remote, Docker, or container execution - *Reason: guarded actions must be explicit proposals with reviewed execution policy and audit behavior.*
* Web cockpit decision controls beyond protocol and server contract support - *Reason: Session 05 owns visible controls, accessibility, loading, error, and duplicate-click UI behavior.*
* Broad CLI recovery commands or status/doctor guarded-action summaries - *Reason: Session 06 owns diagnostics and recovery after state exists.*
* Inbound chat or webhook commands - *Reason: adapters remain outbound-only until a separate permission and audit model exists.*
* War Room federation, hosted queues, shared queues, public sharing, analytics, Docker isolation, remote access tunnels, or remote device control - *Reason: later phases require separate trust, consent, authorization, and validation models.*

***

## 5. Technical Approach

### Architecture

Protocol leads the change. Add guarded-action domain types under `packages/protocol/src/`, export them from the package root, and reference them from REST and WebSocket contracts before server or CLI code consumes them.

The server should own a small in-memory guarded-action manager. The manager keeps proposals bounded, assigns revisions, tracks idempotency keys, expires old proposals on read or decision paths, rejects duplicate decisions, records compact execution results, and emits WebSocket updates after state changes. Approved-but-unavailable action families should produce explicit unavailable or failed results rather than attempting hidden local side effects.

Routes should follow existing high-risk route patterns: route-level body validation, bounded strings and arrays, compact validation envelopes, deterministic ordering, no raw payload echo in errors, and no changes to auth, CORS, Origin, rate-limit, or body-size middleware. WebSocket decision handling should mirror the current permission and plan duplicate-response lessons without overloading existing permission or plan contracts.

CLI work should stay helper-level. Add a dependency-light HTTP helper for proposal and decision calls that reads the local auth token, applies bounded timeouts, parses compact error envelopes, and returns sanitized diagnostics. Do not add user-facing commands that imply terminal control or remote execution in this session.

### Design Patterns

* Protocol-first contracts: guarded-action shapes live in `packages/protocol` before server, web, or CLI packages consume them.
* Bounded local manager: guarded-action state is in-memory, deterministic, capped, and easy to include in later reset or erasure work.
* Fail-closed execution policy: unsupported or unsafe action kinds produce explicit unavailable, expired, rejected, or failed states.
* Compact validation envelopes: invalid requests identify fields and reasons without echoing sensitive developer data.
* Duplicate-decision guards: approvals, rejections, and WebSocket decisions are idempotent by request ID and revision.

### Technology Stack

* TypeScript 5.9 in `packages/protocol` and `apps/server`.
* JavaScript ESM helpers in `apps/cli`.
* Express 4 route handling and existing server middleware.
* WebSocket broadcasting through `apps/server/src/ws/broadcaster.ts`.
* Vitest and Node-based package tests.

***

## 6. Deliverables

### Files to Create

| File                                             | Purpose                                                                                                | Est. Lines |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------ | ---------- |
| `packages/protocol/src/guardedActions.ts`        | Guarded action proposal, decision, result, unavailable, state, request, response, and event contracts  | \~220      |
| `apps/server/src/lib/guardedActionValidation.ts` | Server-side validators for guarded-action proposal and decision routes                                 | \~180      |
| `apps/server/src/managers/guardedActions.ts`     | Bounded in-memory guarded-action manager with idempotency, expiration, and duplicate-decision handling | \~260      |
| `apps/server/src/routes/guardedActions.ts`       | Guarded-action REST routes and WebSocket update emission                                               | \~220      |
| `apps/cli/src/lib/guardedActions.js`             | Local HTTP helper for guarded-action proposal and decision calls                                       | \~160      |
| `packages/protocol/tests/guardedActions.test.ts` | Protocol contract tests for guarded-action states, REST shapes, and WebSocket discriminants            | \~150      |
| `apps/server/tests/guardedActions.test.ts`       | Server route, manager, validation, expiration, duplicate-decision, and redaction tests                 | \~260      |
| `apps/cli/tests/guardedActions.test.js`          | CLI helper tests for auth headers, timeouts, compact errors, and sanitized output                      | \~140      |

### Files to Modify

| File                                                                                        | Changes                                                                                                                        | Est. Lines |
| ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ---------- |
| `packages/protocol/src/index.ts`                                                            | Export guarded-action contracts                                                                                                | \~2        |
| `packages/protocol/src/rest.ts`                                                             | Add guarded-action REST request and response contracts plus route-family vocabulary where needed                               | \~70       |
| `packages/protocol/src/events.ts`                                                           | Add guarded-action update events and guarded-action decision client messages                                                   | \~90       |
| `apps/server/src/server.ts`                                                                 | Instantiate the guarded-action manager and register guarded-action routes and WebSocket deps                                   | \~25       |
| `apps/server/src/ws/clientMessageValidation.ts`                                             | Validate guarded-action WebSocket decisions with bounded IDs, booleans, revisions, and reasons                                 | \~80       |
| `apps/server/src/ws/handlers.ts`                                                            | Process guarded-action WebSocket decisions with duplicate-trigger prevention and update emission                               | \~80       |
| `apps/server/src/lib/unsupportedRoutes.ts`                                                  | Preserve deferred file/git/terminal/remote/container route classification and remove only implemented guarded-action endpoints | \~40       |
| `apps/server/tests/websocket.test.ts`                                                       | Cover guarded-action update frames and duplicate decision handling                                                             | \~120      |
| `apps/server/tests/authBoundaries.test.ts`                                                  | Confirm guarded-action HTTP routes inherit bearer auth before validation or mutation                                           | \~60       |
| `apps/server/tests/unsupportedRoutes.test.ts`                                               | Confirm unapproved file/git/terminal/remote/container paths remain deterministic 501 responses                                 | \~50       |
| `docs/api/README_api.md`                                                                    | Document guarded-action route and WebSocket runtime boundaries                                                                 | \~45       |
| `docs/api/event-api-hook-contracts.md`                                                      | Record guarded-action route-family, WebSocket, and safety contract status                                                      | \~70       |
| `.spec_system/specs/phase03-session04-guarded-local-action-runtime/implementation-notes.md` | Implementation log, commands run, and validation notes                                                                         | \~100      |
| `.spec_system/specs/phase03-session04-guarded-local-action-runtime/security-compliance.md`  | Session privacy, security, and GDPR posture                                                                                    | \~90       |

***

## 7. Success Criteria

### Functional Requirements

* [ ] Guarded-action protocol types are exported and covered by focused contract tests.
* [ ] Local guarded-action proposals can be created, listed, inspected, approved, and rejected through validated server routes.
* [ ] Expired, duplicate, unsafe, unsupported, failed, and unavailable action paths produce explicit compact states.
* [ ] Guarded-action route and WebSocket responses do not expose raw prompts, command bodies, terminal output, file contents, tokens, transcript paths, or broad absolute paths.
* [ ] Unapproved file, git, terminal, remote-access, and container route families continue returning deterministic capability responses.
* [ ] CLI helpers can call local guarded-action endpoints with auth, timeout, compact error parsing, and sanitized output.

### Testing Requirements

* [ ] `npm --workspace packages/protocol run typecheck` passes.
* [ ] `npm --workspace apps/server run typecheck` passes.
* [ ] Focused protocol, server, WebSocket, auth-boundary, unsupported-route, and CLI helper tests pass.
* [ ] Manual validation confirms no guarded-action output leaks sensitive prompts, command previews, tokens, terminal output, file contents, or broad absolute paths.

### Non-Functional Requirements

* [ ] Guarded-action state remains local, in-memory, bounded, and non-executing unless an action has an explicit approved local policy.
* [ ] Existing auth, CORS, Origin, rate-limit, body-size, and loopback defaults are unchanged.
* [ ] List responses use bounded pagination, validated filters, and deterministic ordering.
* [ ] Error responses remain compact and do not echo request bodies, query strings, command bodies, file contents, tokens, or private path fragments.

### Quality Gates

* [ ] All files ASCII-encoded.
* [ ] Unix LF line endings.
* [ ] Code follows project conventions.

***

## 8. Implementation Notes

### Key Considerations

* Session 04 is the first guarded-action runtime session, not a remote-control session.
* Approval is a state transition. Execution remains explicit, policy-bound, and unavailable for action families that do not have a safe local executor.
* Proposal previews should be redacted summaries, not raw commands, raw file contents, full terminal output, transcript paths, or broad absolute paths.
* Current permission and plan approvals remain separate contracts. Guarded action decisions should reuse the duplicate-response lessons without overloading those route or event types.

### Potential Challenges

* Scope creep: file, git, terminal, remote, and container route inventories can tempt broad parity. Mitigation: implement only guarded-action endpoints and keep unapproved route families deterministic 501 responses.
* Execution ambiguity: "approved" could be mistaken for "executed." Mitigation: model accepted, rejected, expired, failed, unavailable, and execution-result states separately.
* Privacy drift: proposal previews could leak sensitive commands or paths. Mitigation: bound and redact previews, keep tests asserting non-echo, and avoid raw historical fixtures.
* Contract drift: server or CLI code could invent local-only shapes. Mitigation: import protocol-owned contracts and discriminants.

### Relevant Considerations

* \[P01] **Redaction is boundary-specific**: guarded actions, exports, replay, adapters, diagnostics, and future external-transfer paths need boundary-appropriate redaction before data leaves local state.
* \[P01-apps/server] **Local server boundary must stay conservative**: new routes and frames inherit loopback, auth, CORS, Origin, rate-limit, body-size, validation, and explicit failure defaults.
* \[P01-packages/protocol] **Protocol leads cross-package work**: guarded-action contracts must be protocol-owned before server, web, CLI, or hook packages consume them.
* \[P01-apps/server+packages/protocol] **Unsupported historical routes are explicit 501s**: preserve deterministic unsupported-route envelopes for unapproved file, git, terminal, remote, and container paths.
* \[P00-apps/adapters] **Chat adapters are outbound only**: guarded-action work must not introduce inbound chat, webhook, or adapter commands.
* \[P01] **Unified erasure still missing**: new local guarded-action state should remain bounded and easy to include in later trusted reset and erasure workflows.

### Behavioral Quality Focus

Checklist active: Yes Top behavioral risks for this session:

* Duplicate approvals or WebSocket decisions could mutate a guarded action more than once.
* Expired, unavailable, or failed action states could be confused with executed work.
* Proposal previews, validation errors, or CLI helper output could expose raw commands, file contents, tokens, terminal output, transcript paths, or broad absolute paths.

***

## 9. Testing Strategy

### Unit Tests

* Protocol tests for guarded-action family, kind, state, decision, expiration, unavailable, execution result, REST request, REST response, event, and client message discriminants.
* Server manager tests for create, list, detail, approve, reject, expire, idempotent create, duplicate decision, stale revision, unavailable result, capacity, and deterministic ordering.
* CLI helper tests for auth headers, timeout handling, compact JSON parsing, server-unavailable results, and sanitized error summaries.

### Integration Tests

* Server route tests for proposal create/list/detail, approve/reject decisions, expired proposals, duplicate decisions, compact validation errors, auth inheritance, and sensitive-field non-echo.
* WebSocket tests for guarded-action update frames, guarded-action decision client messages, duplicate suppression, malformed decision rejection, and compact frame payloads.
* Unsupported-route tests confirming unapproved file, git, terminal, remote-access, and container paths remain deterministic 501 responses.

### Manual Testing

* Start the local server, create a guarded-action proposal, approve or reject it, and confirm route responses and WebSocket frames show pending, accepted, rejected, expired, unavailable, or failed states without raw sensitive data.
* Run CLI helper tests against fixture servers to confirm sanitized output when the server is unreachable, unauthorized, timed out, or returning compact validation errors.

### Edge Cases

* Duplicate idempotency keys, repeated approval, repeated rejection, and mixed approve-then-reject attempts.
* Expired proposals approved after deadline and proposals that expire during list/detail reads.
* Malformed action kind, unsupported family, overlong requester/rationale/ preview fields, stale revision, missing references, and invalid WebSocket decision bodies.
* Requests containing raw prompts, command bodies, terminal output, tokens, file contents, transcript-like values, and broad absolute paths.

***

## 10. Dependencies

### External Libraries

* No new runtime dependencies are expected.
* Existing `nanoid` in `apps/server` can be used for local proposal IDs.
* Existing Node `http` and timer APIs can be used by CLI helper tests.

### Other Sessions

* **Depends on**: `phase03-session01-orchestration-requirements-and-safety-baseline`, `phase03-session02-task-queue-and-agent-template-contracts`, `phase03-session03-subagent-lineage-and-mission-graph-runtime`.
* **Depended by**: `phase03-session05-web-orchestration-cockpit-controls`, `phase03-session06-cli-diagnostics-and-recovery-controls`, `phase03-session07-orchestration-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/phase03-session04-guarded-local-action-runtime/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.
