Skip to content
Closed
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
fdbbc14
docs: add v1 design documents directory
github-actions[bot] Jul 30, 2026
a16399f
docs: link design docs changelog entry to PR
NiveditJain Jul 30, 2026
bda251b
docs: draft failproofaid architecture
NiveditJain Jul 30, 2026
1c8a823
docs: design centralized policy management
NiveditJain Jul 30, 2026
eea0076
docs: split failproofaid design by concern
NiveditJain Jul 30, 2026
30ef934
docs: make policy evaluation location configurable
NiveditJain Jul 30, 2026
18aa936
docs: scope cloud evaluation beyond v1
NiveditJain Jul 30, 2026
95b8e58
docs: preserve standalone OSS policy workflows
NiveditJain Jul 30, 2026
6e94b39
docs: scope failproofaid v1 to linux and macos
NiveditJain Jul 30, 2026
bed7c98
docs: define login and OSS setup choice
NiveditJain Jul 30, 2026
66d938e
docs: harden setup delivery and update contracts
NiveditJain Jul 30, 2026
ef37b44
docs: narrow v1 distribution to npm
NiveditJain Jul 30, 2026
b947a96
docs: close setup and spool crash gaps
NiveditJain Jul 30, 2026
87127f7
docs: design user and system daemon scopes
NiveditJain Jul 30, 2026
e393e43
docs: prefer tamper-resistant enforcement scope
NiveditJain Jul 30, 2026
61ae486
docs: reconcile removed harness hooks
NiveditJain Jul 30, 2026
9a1c1c0
docs: replace binary updater with hook schemas
NiveditJain Jul 30, 2026
ec28e46
docs: make the enforcement boundary a service account, not root
NiveditJain Jul 30, 2026
4171a46
docs: close four holes in the service-account boundary
NiveditJain Jul 30, 2026
5cb4d84
docs: give the local dashboard an access model
NiveditJain Jul 30, 2026
bfb2b2c
docs: ship one service scope and split v1 into two phases
NiveditJain Jul 30, 2026
9799459
docs: move the whole collector into Phase 1
NiveditJain Jul 30, 2026
fe1cd14
docs: add the Phase 1 implementation plan
NiveditJain Jul 30, 2026
9de5c4f
feat: land Phase 1 Stage 0 and Stage 1 of failproofaid
NiveditJain Jul 30, 2026
da0fa55
fix: withdraw the corrupt bench baseline and gate the daemon's defaul…
NiveditJain Jul 30, 2026
47bcd33
fix: four defects an adversarial review found in the Stage 1 daemon
NiveditJain Jul 30, 2026
509e6e6
docs: record the four review fixes in the changelog
NiveditJain Jul 30, 2026
ca4c771
fix: make the bench harness's own integrity gate non-vacuous
NiveditJain Jul 30, 2026
2b3a61d
docs: record the bench-harness gate fix
NiveditJain Jul 30, 2026
a2cb9ee
fix: make two concurrent bench captures impossible
NiveditJain Jul 30, 2026
05ed3bb
docs: record the bench capture lock
NiveditJain Jul 30, 2026
912ff1b
fix(ci): run CI on every pull request, not only those targeting main
NiveditJain Jul 30, 2026
443c681
Revert "fix(ci): run CI on every pull request, not only those targeti…
NiveditJain Jul 30, 2026
9bf1311
fix: two failures CI caught that local runs never would have
NiveditJain Jul 30, 2026
4e00e93
docs: fold the Stage 0 amendments into the design set (in progress)
NiveditJain Jul 30, 2026
2c0f0a3
docs: finish folding the Stage 0 amendments, and record where each la…
NiveditJain Jul 30, 2026
35f890e
docs: record the amendment fold in the changelog
NiveditJain Jul 30, 2026
40a1d11
docs: name the sealed runtime accurately in the tier table
NiveditJain Jul 30, 2026
5dc478e
docs: cross-reference the per-user agent exception where the rule is …
NiveditJain Jul 30, 2026
4535acd
fix: make the remaining hooks-config mocks additive
NiveditJain Jul 30, 2026
d2a7b9e
perf: capture the cold-start latency baseline, cleanly this time
NiveditJain Jul 30, 2026
07f3998
refactor: run entirely in user scope for v1.0.0
NiveditJain Jul 30, 2026
11f211c
docs: record the user-scope simplification in the changelog
NiveditJain Jul 30, 2026
91298cb
docs: rewrite the user experience and harness integration for user sc…
NiveditJain Jul 30, 2026
3b6bed2
docs: state what hook reconciliation can and cannot do in user scope
NiveditJain Jul 30, 2026
e57f40b
refactor: finish the user-scope sweep across code and tests
NiveditJain Jul 30, 2026
d957171
docs: rewrite the daemon, service, collector and release docs for use…
NiveditJain Jul 30, 2026
122034f
refactor: make the client's path resolution pure, mirroring the Rust
NiveditJain Jul 30, 2026
8ce4e45
docs: rewrite the stages and verification layers for user scope
NiveditJain Jul 30, 2026
d67e6e8
docs: replace L3's boundary probes with assertions user scope can act…
NiveditJain Jul 30, 2026
3fe1c0b
fix: resolve the daemon socket after parsing arguments, not before
NiveditJain Jul 30, 2026
038b81d
docs: record which amendments the scope decision superseded
NiveditJain Jul 30, 2026
8209abf
docs: follow the scope decision into Phase 2's enrollment model
NiveditJain Jul 30, 2026
7d4dff9
test: drive the real binary in the path-agreement check
NiveditJain Jul 30, 2026
d71f806
docs: final consistency pass on the user-scope rewrite
NiveditJain Jul 30, 2026
c3f3f12
docs: state that the delivery key is readable by the user's agent
NiveditJain Jul 30, 2026
5f74c5b
fix: actually refuse a peer whose uid is not the daemon's
NiveditJain Jul 30, 2026
14b0b44
fix(ci): build dist/index.js before the unit suite
NiveditJain Jul 30, 2026
72967bb
fix: three defects an adversarial sweep found, all in code from this …
NiveditJain Jul 31, 2026
17192ff
docs: record the three adversarial-sweep fixes
NiveditJain Jul 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 0.0.16-beta.0 — 2026-07-30

### Docs
- Add a versioned home for the failproofai v1.0.0 design documents. (#625)
- Draft the Linux/macOS Rust `failproofaid` design, preserving standalone OSS while adding an optional Login tier, AgentEye collection, rollback-safe updates, and signed distribution; define Login/OSS setup in the existing branded CLI and defer Windows. (#625)

## 0.0.15-beta.1 — 2026-07-29

### Features
Expand Down
7 changes: 7 additions & 0 deletions desgin-docs/v1.0.0/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# failproofai v1.0.0 design documents

This directory contains checked-in design documents for the next major version of failproofai.

## Documents

- [`failproofaid` design](./failproofaid/) — user experience, harness integration, daemon architecture, cloud policy management, collector convergence, updates, and delivery plan.
274 changes: 274 additions & 0 deletions desgin-docs/v1.0.0/failproofaid/01-user-experience.md

Large diffs are not rendered by default.

212 changes: 212 additions & 0 deletions desgin-docs/v1.0.0/failproofaid/02-harness-integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
# Agent harness integration

## Definition

An agent harness is an agent CLI, IDE integration, gateway, or runtime whose lifecycle and tool-execution events can be observed or controlled. Examples include Claude Code, Codex, Cursor, Copilot CLI, OpenCode, Pi, Hermes, OpenClaw, Factory, Devin, Antigravity, and Goose.

Harnesses do not implement FailproofAI policies. They expose native events; a thin FailproofAI adapter converts those events into the stable local daemon protocol and converts the daemon's canonical result back into the harness's native allow/deny/instruction contract.

## Integration boundary

```text
harness native event
|
v
harness registration/configuration
|
v
native `failproofai hook` client
|
| versioned local IPC
v
`failproofaid` canonicalization + policy evaluation
|
v
canonical allow / deny / instruct response
|
v
harness-specific stdout, exit code, callback, or plugin response
```

The harness-facing client must stay small and bounded. It reads one event, makes one local request, writes one response, and exits or returns control. It does not load policies, scan transcripts, contact the cloud, upload events, check for updates, or start the dashboard.

## Harness adapter contract

Each harness adapter declares a versioned capability descriptor:

- harness ID and detected harness version;
- native event name to canonical event mapping;
- native tool name/input to canonical tool mapping;
- fields that provide session, agent, project, working-directory, transcript, permission-mode, and parent-session identity;
- events on which the harness can block, observe only, or add context;
- response encoding: stdout schema, callback object, exit code, or gateway result;
- maximum safe response time and timeout semantics;
- behavior of stop-class nonzero responses, including whether they retry;
- configuration scopes and files used to register the adapter.

Capability descriptors are code and test data, not prose-only documentation. `failproofaid` records the descriptor version used for every decision so AgentEye can distinguish a policy allow from a harness that could not enforce the result.

## Registration strategies

Harnesses expose different extension surfaces. v1 supports three adapter shapes:

### Command hook

The harness invokes a command for an event and passes JSON or another documented payload on stdin. Setup writes the harness's supported configuration to call:

```sh
failproofai hook --harness <name> --event <native-event>
```

The native client reads stdin and returns the required stdout and exit status. This is preferred where the harness has a real blocking hook contract.

### In-process plugin shim

Some harnesses expose JavaScript/TypeScript, Python, or another plugin API rather than a command hook. A minimal versioned shim invokes the same native client or local IPC protocol and returns the harness callback result.

The shim contains only vendor adaptation. Policy evaluation and cloud logic remain in the daemon. A shim failure is visible and follows the integration's configured failure behavior.

### Gateway or wrapper adapter

Some runtimes expose events only inside a gateway process or require a wrapper around invocation. The adapter runs at that boundary and forwards events to the daemon. Setup must clearly disclose when enforcement depends on using the configured gateway/wrapper rather than every possible way of launching the agent.

## Request envelope

The client sends a length-prefixed request over a Unix domain socket. A conceptual request is:

```json
{
"protocol_version": 1,
"operation": "evaluate_hook",
"request_id": "018f...",
"deadline_monotonic_ms": 8421931,
"client": {
"version": "1.0.0",
"harness": "codex",
"harness_version": "...",
"adapter_version": 3
},
"event": {
"native_name": "...",
"payload": {}
}
}
```

The payload remains native at the wire boundary so adapter fixes can be made centrally in the daemon without requiring every hook registration to change. The client still enforces a fixed input-size limit before allocating or sending data.

The client supplies an absolute monotonic deadline. The daemon never invents a longer one. Time reserved for response translation and process exit is excluded before the request is sent. This deadline covers local queueing and policy evaluation.

## Canonical event model

The daemon canonicalizes the request into a common event containing:

- canonical lifecycle event;
- harness and native event identity;
- machine, agent, project, session, and parent-session identity with provenance;
- canonical tool name and normalized input where applicable;
- working directory, transcript reference, and permission mode when exposed;
- raw payload retained only for policy fields that require it and within size limits;
- enforcement capability for this event/harness version.

Canonicalization must preserve evidence about absent or uncertain fields. An inferred session ID is not represented as vendor-provided. A session-targeted cloud assignment never broadens when session identity is unavailable.

## Session lifecycle

Harness adapters should report explicit session start, resume, compact, subagent start, and end events where available. The daemon uses them to maintain a local session registry that maps native IDs to the stable targeting identity used by cloud assignments and AgentEye.

When explicit lifecycle events do not exist, the daemon derives a session boundary from documented identifiers and activity. The adapter descriptor records this identity quality. Session-scoped enforcement is enabled only when the identity is strong enough to avoid applying a policy to the wrong run.

Agent and session identity must align with collector output. An enforcement decision and captured session from the same harness run must join on stable identifiers without heuristic cloud-side matching.

## Response model

The daemon returns a canonical response:

```json
{
"request_id": "018f...",
"generation": 184,
"decision": "deny",
"message": "Policy explanation safe to show to the agent",
"context": null,
"decision_id": "018f...",
"deadline_status": "within_budget"
}
```

The harness adapter translates it according to declared capability:

| Canonical result | Blocking event | Observe-only event | Context-capable event |
|---|---|---|---|
| `allow` | allow | continue | continue |
| `deny` | block using native contract | continue and record unenforced deny | block if supported, otherwise observe |
| `instruct` | allow with native message where supported | record only | add context/instruction |

The daemon records both the policy result and effective harness action. Reporting a deny as enforced when the harness ignores that event is forbidden.

## Deadlines and unavailable daemon

Every adapter has a tested total time budget. Connection, daemon admission, policy evaluation, and response translation each consume that one budget.

During the v1 migration, the native client may invoke a packaged compatibility evaluator when the daemon endpoint is absent or protocol-incompatible. This is a bounded migration mechanism, not a permanent second architecture.

After fallback deprecation, unavailable-daemon behavior is explicit per integration and policy class:

- fail open and record degradation;
- fail closed using the native blocking contract;
- use a locally cached emergency decision for narrowly defined mandatory policies.

Stop-class hooks require an adapter-specific response because some harnesses interpret a nonzero exit as “retry” and can loop forever. No generic failure exit is applied across harnesses.

## Configuration ownership

`failproofai setup` owns only marked FailproofAI entries in harness configuration. It must:

- merge without deleting unrelated user hooks or plugins;
- detect and upgrade older FailproofAI commands in place;
- avoid registering the same event twice;
- preserve the original file format and permissions where practical;
- use atomic writes and retain a rollback copy until verification succeeds;
- remove only owned entries during disable or uninstall.

Project-scoped integrations remain possible, but they still connect to the user's daemon. Setup displays whether an integration is user-, project-, or local-scoped and which projects it covers.

## Version negotiation

The client and daemon negotiate a protocol version before evaluation or use a cached compatible version after a recent successful handshake. Releases declare:

- supported IPC protocol range;
- harness adapter descriptor revisions;
- policy runtime/API range;
- minimum compatible client and daemon versions.

Rolling updates must tolerate the old client talking to the new daemon and the new client talking briefly to the old daemon. Incompatible versions fail with an actionable diagnostic and use the documented migration fallback where available.

## Adding a harness

A new harness integration is complete only when it provides:

1. detection and version probing;
2. an adapter capability descriptor;
3. install, upgrade, disable, and uninstall configuration transforms;
4. fixture-backed canonicalization tests for every supported native event;
5. response-contract tests proving allow, deny, instruct, timeout, and daemon-unavailable behavior;
6. session/agent identity tests aligned with its collector source;
7. enforcement-capability evidence traced to the harness call site or vendor contract;
8. an end-to-end test against the real harness or a version-pinned conformance probe;
9. health and diagnostics output;
10. user documentation stating what is enforceable and what is observation-only.

## Harness acceptance criteria

- The thin client makes no cloud request and performs no policy-loading work.
- Golden fixtures preserve current canonical decisions and native response contracts.
- Every event is labeled block, observe, or context-capable from verified evidence.
- A harness upgrade that changes payload or response behavior fails conformance visibly rather than silently allowing.
- Hook installation is idempotent and uninstall preserves unrelated configuration.
- Enforcement and collector records for one session share stable identity.
- Missing session identity never broadens a session-targeted assignment.
- Timeout and daemon-unavailable behavior is tested separately for every harness, especially stop-class events.

The envelope and framing remain transport-neutral so a later Windows implementation can add a named-pipe transport without changing harness semantics.
130 changes: 130 additions & 0 deletions desgin-docs/v1.0.0/failproofaid/03-daemon-architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Daemon architecture

## Responsibilities

`failproofaid` is the Rust local enforcement plane. It owns:

- local IPC and request admission;
- event canonicalization and policy evaluation coordination;
- immutable local policy generations and optional connected-tier cloud assignment generations;
- collector source workers, checkpoints, spooling, and delivery;
- optional cloud desired-state reconciliation;
- health, diagnostics, logs, and resource limits;
- update discovery and staging, but not activation.

The user-facing `failproofai` CLI is a client of the daemon and service manager. Agent harnesses use the smaller hook client described in [Agent harness integration](./02-harness-integration.md).

## Execution lanes

The daemon separates work into independently bounded lanes:

1. **Enforcement** — reserved workers, strict deadlines, and no network dependency.
2. **Collection** — source watching, transcript parsing, checkpointing, and backfill.
3. **Delivery** — batching, upload, retry, and quarantine.
4. **Management** — when connected, cloud authentication, desired-state reconciliation, verification, and acknowledgement; otherwise dormant.
5. **Maintenance** — configuration reload, health snapshots, cleanup, and update discovery.

Each lane has its own queue, concurrency, memory, and time limits. Background work cannot consume enforcement's reserved capacity. Overload is reported per lane rather than causing unbounded queue growth.

## Local IPC

- Linux and macOS use an owner-only Unix domain socket under the user's runtime directory.
- The daemon does not expose its control protocol over TCP, including loopback.
- Messages are length-prefixed and versioned rather than newline-delimited.
- Peer identity is verified where supported.
- Hook and administrative operations are distinct protocol operations.

Windows transport and service integration are deferred beyond v1.0.0. The framed protocol remains transport-independent so a later named-pipe implementation does not change request semantics.

Initial operations are `Ping`, `EvaluateHook`, `Status`, `Reload`, and `Flush`. Administrative calls can gain stronger authorization later without changing the hook request.

## Policy generations

The daemon evaluates each request against an immutable generation. A generation contains resolved configuration, policy artifacts, assignment metadata, runtime compatibility, and content identity.

A local reload or optional cloud reconciliation constructs a candidate away from the active generation:

1. resolve inputs and immutable artifacts;
2. verify schema, signature, digest, compatibility, and target binding;
3. load and initialize policies within bounds;
4. reject duplicates and invalid registrations;
5. atomically publish the complete generation.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

In-flight requests finish on the generation with which they started. A failed candidate never partially replaces active state. The last known-good generation is persisted and loaded before accepting hook traffic after restart.

## Policy runtime boundary

Rust is the authoritative implementation language for the daemon and new core subsystems.

Existing local custom policies are JavaScript or TypeScript and may use transitive local and package imports. v1 cannot silently narrow that contract. A supervised, long-lived policy worker behind an internal runtime interface is the migration design. It is shipped, versioned, monitored, and terminated with the daemon; users do not manage it as a separate service.

Standalone OSS policy is a first-class source, not a fallback for a missing cloud connection. Builtins, explicit custom files, project/user convention directories, and existing configuration scopes produce the active local generation without authentication or enrollment.

Cloud-created policy requires a deterministic, capability-limited representation or sandbox. The existence of a legacy JavaScript worker does not authorize the cloud to send arbitrary JavaScript with the user's filesystem, environment, process, or network authority.

Each evaluation has a deadline and resource budget. Repeated timeout, crash, or memory failure trips a circuit breaker for the offending generation or artifact and records structured diagnostics.

## Evaluation path

For an accepted hook request, the daemon:

1. validates the envelope and remaining deadline;
2. canonicalizes the native harness event;
3. resolves machine, agent, project, session, event, and tool targeting context;
4. selects an immutable active generation;
5. finds all matching policies and assignment effects;
6. evaluates matching policy locally within the remaining deadline;
7. combines results deterministically (`deny` over `instruct` over `allow`, absent an authorized suppression);
8. writes decision evidence asynchronously to the durable activity spool;
9. returns a canonical result and decision ID.

The response never waits for cloud acknowledgement, event upload, transcript processing, or update work.

### Future cloud evaluation compatibility

Cloud evaluation is not implemented or user-configurable in v1.0.0. A later version is expected to move some or all policy evaluation into the FailproofAI cloud.

To keep that migration possible, the harness contract terminates at `failproofaid`, policy decisions use a location-independent canonical request/result model, deadlines are end-to-end, and decision evidence carries stable request, policy, assignment, and session identity. No v1.0.0 configuration, cloud-decision client, fallback mode, or user interface is added for the future design.

## Configuration and state

The canonical user root is `~/.failproofai/`, overridable for tests and managed deployments:

```text
~/.failproofai/
config.json
credentials.json
policies/
state/
policy-generations/
checkpoints/
activity/
spool/
failed/
health.json
updates/
logs/
```

Credentials use the operating-system credential store where practical; an owner-only file is the portability fallback. Secrets never appear in service definitions or routine process arguments.

Configuration is schema-versioned and written transactionally. File notifications prompt reload, while periodic reconciliation is the correctness backstop. Project policy caches are bounded by memory and entry count and invalidated by resolved input changes.

## Failure isolation

| Failure | Required behavior |
|---|---|
| Policy worker crashes | Restart it, retain verified generation data, apply configured event failure behavior, keep collection running. |
| Policy hangs | Enforce deadline, trip its circuit breaker after repeated failures, keep IPC responsive. |
| Cloud management unavailable | Continue last known-good policy assignments; report staleness. |
| Backend unavailable | Continue enforcement; spool delivery data and retry. |
| One source parser fails | Degrade that source without stopping other sources or enforcement. |
| Invalid configuration | Reject candidate and retain active generation. |
| Spool reaches quota | Report degradation and apply explicit queue policy; never wait on network in enforcement. |
| Daemon crashes | Service manager restarts it; persisted generations, checkpoints, and spool recover work. |

## Health

Health is a structured, versioned snapshot covering IPC readiness, enforcement latency and queue depth, local policy generation and reload state, optional cloud freshness, source progress, spool age and size, delivery acknowledgements, quarantined data, resource pressure, and update state. Cloud health is `not_configured` for standalone OSS installs.

Logs are structured, correlated by request/batch/update ID, rotated, and size-bounded. Sensitive hook payloads and transcript contents are excluded by default.
Loading