@openape/nest 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # @openape/nest
2
+
3
+ Local control-plane daemon. Manages OpenApe agents on a single machine — provisions macOS users, hands the bridge lifecycle off to launchd, exposes a localhost HTTP API gated by DDISA grant tokens.
4
+
5
+ ## What it does
6
+
7
+ - Runs as a long-lived launchd-managed daemon under your user account (`~/Library/LaunchAgents/ai.openape.nest.plist`)
8
+ - Accepts API calls on `127.0.0.1:9091` for agent lifecycle ops (`spawn`, `destroy`, `list`, `status`)
9
+ - Every API call requires a DDISA-signed grant token in the `Authorization: Bearer …` header
10
+ - Bridge processes (`openape-chat-bridge` per agent) are NOT supervised in-daemon — they run as system-domain LaunchDaemons (one plist per agent in `/Library/LaunchDaemons/eco.hofmann.apes.bridge.<agent>.plist`) installed by `apes agents spawn --bridge`. launchd is the right OS-level supervisor on macOS; trying to duplicate that in the daemon crashloops without adding value.
11
+
12
+ ## Setup (one-time)
13
+
14
+ ```bash
15
+ apes nest install # install + load the launchd plist
16
+ apes nest enroll # daemon gets its own DDISA agent identity
17
+ apes nest authorize # set the YOLO policy — covers the inner
18
+ # `apes agents spawn` calls the daemon makes
19
+ ```
20
+
21
+ After that, day-to-day lifecycle goes through `apes nest`:
22
+
23
+ ```bash
24
+ apes nest spawn igor18 # provision a new agent
25
+ apes nest list # show agents this nest knows about
26
+ apes nest status # health-check
27
+ apes nest destroy igor18 # tear down
28
+ apes nest uninstall # remove the launchd plist
29
+ ```
30
+
31
+ ## Why every API call needs a grant token
32
+
33
+ Without auth the API is gated only by "process running as the logged-in human can reach localhost:9091" — a compromised local process inherits everything. The grant-token requirement closes that gap and gives every call an audit record at the IdP. The flow:
34
+
35
+ 1. `apes nest <op>` looks for an existing approved `'always'`/`'timed'` grant matching the operation.
36
+ 2. If none, requests a fresh grant from the IdP. **First-time** grants for human callers wait for human approval (one approval covers the lifetime of the grant — `'always'` is the default for nest-CLI calls).
37
+ 3. Token (RFC-7519 JWT signed by the IdP) is fetched and presented as `Authorization: Bearer …`.
38
+ 4. The Nest verifies signature against the IdP's JWKS, checks `aud=nest`, `iss=<IdP URL>`, `target_host=<local hostname>`, and exact-matches the embedded `command` claim against the route. Fails: `401` (auth) or `403` (command mismatch).
39
+
40
+ ### Grant-scope conventions
41
+
42
+ | CLI | Grant `command` | Reuse semantics |
43
+ |---|---|---|
44
+ | `apes nest list` | `["nest","list"]` | One approval, reused forever. |
45
+ | `apes nest status` | `["nest","status"]` | One approval, reused forever. |
46
+ | `apes nest spawn <name>` | `["nest","spawn"]` (no name baked in) | One approval, any future spawn. Trade-off: a compromised local process running as the human can spawn arbitrary agents under that grant. Acceptable because spawn is reversible and audited. |
47
+ | `apes nest destroy <name>` | `["nest","destroy","<name>"]` | Per-name. Destroying each agent is its own approval. Destructive ops keep tighter scoping by design. |
48
+
49
+ Direct `curl` to the API is supported but you must fetch a grant token yourself. See `tests/auth-negative.sh` for an example token-fetch.
50
+
51
+ ## Negative-test smoke
52
+
53
+ ```bash
54
+ bash apps/openape-nest/tests/auth-negative.sh
55
+ ```
56
+
57
+ Verifies: no-bearer → 401, garbage-bearer → 401, wrong-audience → 401, command-mismatch → 403.
58
+
59
+ ## Why no in-daemon bridge supervisor
60
+
61
+ Earlier versions ran a per-agent process supervisor inside the Nest daemon to keep `openape-chat-bridge` instances alive. It was removed because:
62
+
63
+ - `apes agents spawn --bridge` already installs a system-domain `LaunchDaemon` per agent. launchd KeepAlive's it as the agent UID with the right PATH (the bridge binary is at `/Users/<agent>/.bun/bin/openape-chat-bridge`).
64
+ - The supervisor's children inherited the daemon's PATH (the human user's PATH, which doesn't include any agent's `~/.bun/bin`), so they crashlooped on `Command not found: openape-chat-bridge` while the launchd-domain bridge ran fine.
65
+ - Each crashloop produced an auto-approved YOLO grant — pushing one notification per cycle.
66
+
67
+ Single-source-of-truth on launchd. The Nest is now an API surface in front of `apes agents spawn|destroy`, nothing more.