@forgezero/agent 0.1.40 → 0.1.42

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.
Files changed (64) hide show
  1. package/README.md +573 -424
  2. package/dist/agent-heartbeat.js +6 -3
  3. package/dist/agent-update-helper.js +5 -2
  4. package/dist/agent-update.js +5 -2
  5. package/dist/bootstrap.d.ts +17 -8
  6. package/dist/bootstrap.js +1504 -512
  7. package/dist/cli/agent-install.d.ts +6 -5
  8. package/dist/cli/cloudflare-bootstrap.d.ts +12 -1
  9. package/dist/cli/maintenance.d.ts +23 -0
  10. package/dist/cli/run.d.ts +3 -1
  11. package/dist/cli/session-store.d.ts +5 -0
  12. package/dist/cloudflare-bootstrap.d.ts +73 -35
  13. package/dist/cloudflare-bootstrap.js +587 -90
  14. package/dist/cloudflare-edge.d.ts +64 -12
  15. package/dist/cloudflare-edge.js +103 -8
  16. package/dist/community-rehearsal-host.d.ts +51 -0
  17. package/dist/community-rehearsal-host.js +272 -0
  18. package/dist/credential-schema.d.ts +54 -0
  19. package/dist/credential-schema.js +47 -0
  20. package/dist/definition.d.ts +31 -5
  21. package/dist/definition.js +271 -44
  22. package/dist/deploy-file.js +294 -68
  23. package/dist/deployment-runner.js +18 -5
  24. package/dist/deployment.d.ts +13 -1
  25. package/dist/fz-agent.js +9162 -7564
  26. package/dist/fz-git-ssh.js +122 -0
  27. package/dist/fz.js +5679 -5077
  28. package/dist/git-ssh.d.ts +5 -0
  29. package/dist/guest-enrolment.d.ts +2 -0
  30. package/dist/guest-enrolment.js +1 -0
  31. package/dist/host-maintenance.d.ts +39 -0
  32. package/dist/host-maintenance.js +135 -0
  33. package/dist/index.d.ts +4 -2
  34. package/dist/mesh-connector.d.ts +16 -0
  35. package/dist/mesh-connector.js +46 -0
  36. package/dist/metal-bootstrap.js +145 -7
  37. package/dist/metal-helper-socket.js +61 -31
  38. package/dist/metal-provision.d.ts +2 -2
  39. package/dist/metal-provision.js +62 -32
  40. package/dist/operator-bootstrap.d.ts +90 -0
  41. package/dist/operator-bootstrap.js +5704 -0
  42. package/dist/otel-collector.d.ts +18 -0
  43. package/dist/pipeline.d.ts +3 -2
  44. package/dist/pipeline.js +1 -1
  45. package/dist/platform-bootstrap-runtime.d.ts +39 -21
  46. package/dist/platform-bootstrap-runtime.js +182 -59
  47. package/dist/platform-fleet-verification.d.ts +19 -0
  48. package/dist/platform-fleet-verification.js +3873 -0
  49. package/dist/platform-genesis-config.d.ts +7 -0
  50. package/dist/platform-genesis.d.ts +17 -0
  51. package/dist/provision.d.ts +76 -3
  52. package/dist/provision.js +1061 -229
  53. package/dist/recovery-host.d.ts +7 -0
  54. package/dist/recovery-host.js +124 -0
  55. package/dist/service-supervisor.d.ts +42 -0
  56. package/dist/software-helper.d.ts +4 -0
  57. package/dist/software-helper.js +865 -63
  58. package/dist/software.d.ts +14 -3
  59. package/dist/software.js +163 -37
  60. package/dist/ssh-bootstrap.d.ts +97 -0
  61. package/dist/supervised-app.d.ts +2 -0
  62. package/dist/version.d.ts +1 -1
  63. package/package.json +175 -164
  64. package/schema/{deploy-v2.json → deploy-v3.json} +53 -6
package/README.md CHANGED
@@ -1,472 +1,621 @@
1
+ <!--
2
+ GENERATED FILE — do not edit.
3
+
4
+ Change tools/generate-guides.ts or its typed sources, run `bun run guides`,
5
+ and commit the generator and rendered files together.
6
+ -->
7
+
1
8
  # @forgezero/agent
2
9
 
3
- **`fz` controls the machine; `fz-agent` runs its managed work.**
10
+ The node agent deploys on a compute; tenant mode also holds one complete project across environments in RAM and serves it over a group-scoped unix socket, while platform mode never duplicates the API vault.
4
11
 
5
- The agent keeps a project-scoped copy of your vault in RAM and answers over a
6
- unix socket. `@forgezero/vault` prefers that socket over an API key whenever it
7
- exists, so an application on a machine running the agent reads its secrets
8
- because of *where it is*, not because it holds something that could be stolen
9
- from it.
12
+ ## Package overview
10
13
 
11
- ```bash
12
- bun add -g @forgezero/agent # or let `fz agent install` do it
14
+ Every managed compute. It owns node identity, attestation and repository pipelines. Tenant mode additionally holds one whole project across its environments in RAM and answers over a unix socket; platform mode never replicates the API vault beside the process that already holds every unlocked realm seed. Supported runtimes: bun, node. Package root: @forgezero/agent. The sections below show the actual named imports emitted by each declaration entry point; wildcard imports are intentionally not used in the documentation.
15
+
16
+ ```text
17
+ bun add -g @forgezero/agent
18
+ ```
19
+
20
+ ## ForgeZero package family
21
+
22
+ The five packages are installation boundaries. Choose a package by who installs it; choose a subpath by the capability used in that file.
23
+
24
+ | package | short description | runtimes | documentation |
25
+ |---|---|---|---|
26
+ | @forgezero/vault | Scoped secret access with Agent, API-key and systemd-credential sources. | bun, node, workers, deno | [Open](https://www.forgezero.net/docs/vault-package) |
27
+ | @forgezero/access | Typed route, principal, factor, RBAC and request-pipeline contracts. | bun, node, workers, deno | [Open](https://www.forgezero.net/docs/access) |
28
+ | @forgezero/providers | Typed external providers with priority, health and classified fallback. | bun, node, workers, deno | [Open](https://www.forgezero.net/docs/providers) |
29
+ | @forgezero/runtime | Portable runtime primitives for queries, jobs, events, schemas and finance. | bun, node | [Open](https://www.forgezero.net/docs/runtime) |
30
+ | @forgezero/agent | Operator CLI and managed-node agent for bootstrap, deploy and lifecycle. | bun, node | [Open](https://www.forgezero.net/docs/agent) |
31
+
32
+ ## @forgezero/agent public imports and commands
33
+
34
+ Every row links to the detailed explanation and named-import/example area below. This table and those details are generated from the package inventory and emitted declarations.
35
+
36
+ | public entry | short description | runtime | details |
37
+ |---|---|---|---|
38
+ | fz | The operator command: keys, status, genesis, unlock, run, and agent install. | Bun/Node host | [Details + example](#fz) |
39
+ | fz run | The fallback for software that cannot read the local socket: start a process with scoped vault values in its environment. | Bun/Node host | [Details + example](#fz-run) |
40
+ | fz agent install | Provision the same hardened agent service locally that the platform provisions remotely. | Bun/Node host | [Details + example](#fz-agent-install) |
41
+ | fz-agent | The service entry point. Identity and private Git material arrive only as systemd credentials. A platform bootstrap may use a statically configured local control socket; an enrolled tenant guest instead builds each deployment manager from the signed server claim and reads all commands from the checked-out .fz definition. Tenant cache scope and live attestation still need to be constructed from enrolment. | Bun/Node host | [Details + example](#fz-agent) |
42
+ | fz-agent (socket) | identity, sign, attest, get, sync and held — the whole interface an application sees. | Bun/Node host | [Details + example](#fz-agent-socket) |
43
+ | @forgezero/agent/migration-pull | PQ-authenticated outbound lifecycle claims with fenced renewal, awaited async execution, idempotent acknowledgement and bounded shutdown drain. The executor reports local facts only. | Bun/Node host | [Details + example](#forgezero-agent-migration-pull) |
44
+ | @forgezero/agent/lifecycle-helper | The root-owned fixed-operation boundary for migration work. Signed controller claims can request only private reachability probes, local health checks, or stops of units named in a root-owned profile; they cannot carry commands. | Bun/Node host | [Details + example](#forgezero-agent-lifecycle-helper) |
45
+ | @forgezero/agent/provision | The install plan as data, with no transport — so `fz` running locally and the platform running over SSH provision an identical machine. | Bun/Node host | [Details + example](#forgezero-agent-provision) |
46
+ | @forgezero/agent/subscribe | Realtime scope sync over a WebSocket, with the poll kept underneath it: the poll is what establishes freshness, and a change it finds that the socket never sent is proof the socket is lying. | Bun/Node host | [Details + example](#forgezero-agent-subscribe) |
47
+ | @forgezero/agent/ssh-listen | The socket SSH_AUTH_SOCK points at. The protocol handler had nowhere to speak — an agent protocol with no socket is a parser. The containing directory is 0700 before anything binds, because the socket’s own mode is only corrected after it already exists. | Bun/Node host | [Details + example](#forgezero-agent-ssh-listen) |
48
+ | @forgezero/agent/ssh-server | Serve the SSH agent protocol so SSH_AUTH_SOCK points at the vault — two operations implemented, and ADD_IDENTITY refused so no process can inject a key ssh would offer to every host. | Bun/Node host | [Details + example](#forgezero-agent-ssh-server) |
49
+ | @forgezero/agent/pipeline | CI/CD on the compute: secrets reach the step that named them and nothing else, attestation gates the run, and a required attestation that fails is a refusal rather than a downgrade. | Bun/Node host | [Details + example](#forgezero-agent-pipeline) |
50
+ | @forgezero/agent/agent-heartbeat | Signed node health publication with bounded renewal and shutdown withdrawal. | Bun/Node host | [Details + example](#forgezero-agent-agent-heartbeat) |
51
+ | @forgezero/agent/agent-update | Verified Agent update planning against the platform release coordinate. | Bun/Node host | [Details + example](#forgezero-agent-agent-update) |
52
+ | @forgezero/agent/agent-update-helper | Root-owned fixed update operations with registry origin and integrity validation. | Bun/Node host | [Details + example](#forgezero-agent-agent-update-helper) |
53
+ | @forgezero/agent/bootstrap | Typed one-time platform bootstrap and internal API-driven enrolled-compute activation contracts. | Bun/Node host | [Details + example](#forgezero-agent-bootstrap) |
54
+ | @forgezero/agent/operator-bootstrap | Pinned-host operator transport that stages owner-only handoffs and invokes the same typed platform bootstrap through the caller-approved SSH agent. | Bun/Node host | [Details + example](#forgezero-agent-operator-bootstrap) |
55
+ | @forgezero/agent/host-maintenance | Closed host maintenance plans for staging transaction rehearsal and fleet-fenced schema consolidation through fixed transient systemd units. | Bun/Node host | [Details + example](#forgezero-agent-host-maintenance) |
56
+ | @forgezero/agent/capacity-calibration | One-time target-local safe-concurrency calibration with private evidence. | Bun/Node host | [Details + example](#forgezero-agent-capacity-calibration) |
57
+ | @forgezero/agent/cloudflare-bootstrap | Attended two-token Cloudflare Tunnel/DNS reconciliation and per-node connector/KV runtime handoff for existing KV resources. | Bun/Node host | [Details + example](#forgezero-agent-cloudflare-bootstrap) |
58
+ | @forgezero/agent/cloudflare-edge | Strict Cloudflare REST operations used by the attended bootstrap controller. | Bun/Node host | [Details + example](#forgezero-agent-cloudflare-edge) |
59
+ | @forgezero/agent/mesh-connector | Fixed Cloudflare Mesh/WARP connector enrollment using only the unit-loaded connector credential. | Bun/Node host | [Details + example](#forgezero-agent-mesh-connector) |
60
+ | @forgezero/agent/compute | Compute claim, renewal, execution and completion client contracts. | Bun/Node host | [Details + example](#forgezero-agent-compute) |
61
+ | @forgezero/agent/credential-schema | Canonical systemd credential names and validation shared by bootstrap and services. | Bun/Node host | [Details + example](#forgezero-agent-credential-schema) |
62
+ | @forgezero/agent/definition | Validated project deployment definition and workload profiles. | Bun/Node host | [Details + example](#forgezero-agent-definition) |
63
+ | @forgezero/agent/deploy-file | Read and validate a checked-out .fz deployment file without executing project input. | Bun/Node host | [Details + example](#forgezero-agent-deploy-file) |
64
+ | @forgezero/agent/metal-bootstrap | Physical-metal bootstrap planning, application and status evidence. | Bun/Node host | [Details + example](#forgezero-agent-metal-bootstrap) |
65
+ | @forgezero/agent/metal-provision | Validated confidential guest provisioning profiles and cloud-init rendering. | Bun/Node host | [Details + example](#forgezero-agent-metal-provision) |
66
+ | @forgezero/agent/platform-bootstrap-runtime | Pure platform bootstrap validation, render and resumable phase-state contracts. | Bun/Node host | [Details + example](#forgezero-agent-platform-bootstrap-runtime) |
67
+ | @forgezero/agent/project-context | Project identity and repository context validation for operator and managed runs. | Bun/Node host | [Details + example](#forgezero-agent-project-context) |
68
+ | @forgezero/agent/provisioning-pull | Signed provisioning work claim, renewal, execution and acknowledgement. | Bun/Node host | [Details + example](#forgezero-agent-provisioning-pull) |
69
+ | @forgezero/agent/schema/deploy-v3.json | Published JSON Schema for deployment definition version 3 with exact argv execution. | Bun/Node host | [Details + example](#forgezero-agent-schema-deploy-v3-json) |
70
+ | @forgezero/agent/software | Exact managed-software inventory, requirement and evidence contracts. | Bun/Node host | [Details + example](#forgezero-agent-software) |
71
+ | @forgezero/agent/software-helper | Root-owned fixed installation/update boundary for declared software. | Bun/Node host | [Details + example](#forgezero-agent-software-helper) |
72
+ | @forgezero/agent/ubuntu | Ubuntu host validation and deterministic systemd/unit rendering helpers. | Bun/Node host | [Details + example](#forgezero-agent-ubuntu) |
73
+ | fz-agent (replica) | The project-scoped vault replica: resident in RAM, never on disk, invalidated by cursor rather than by timer, and refusing a read it can no longer vouch for. | Bun/Node host | [Details + example](#fz-agent-replica) |
74
+
75
+ ## Commands
76
+
77
+ bun add -g @forgezero/agent — Install the version-matched fz operator CLI and fz-agent daemon.
78
+ fz bootstrap platform remote prepare --bootstrap-config /secure/forgezero/development/dev-fz-n1-remote.json — Dry-plan one pinned operator-to-guest bootstrap; add --apply only after review.
79
+ fz bootstrap platform --help — Inspect attended platform bootstrap inputs before applying them.
80
+ fz bootstrap metal --help — Inspect the identity-only physical provisioner bootstrap.
81
+ fz host transactions|schema-plan|schema-apply — Plan fixed supervised database maintenance; add --apply only after reviewing the exact argv and credential names.
82
+ fz status — Read installed service and bootstrap evidence.
83
+
84
+ ```text
85
+ bun add -g @forgezero/agent
86
+ fz bootstrap platform remote prepare --bootstrap-config /secure/forgezero/development/dev-fz-n1-remote.json
87
+ fz bootstrap platform --help
88
+ fz bootstrap metal --help
89
+ fz host transactions|schema-plan|schema-apply
90
+ fz status
91
+ ```
92
+
93
+ <a id="fz"></a>
94
+ ## fz
95
+
96
+ The operator command: keys, status, genesis, unlock, run, and agent install. This entry requires a Bun/Node host runtime. Run the command with `--help` before applying it.
97
+
98
+ ```text
13
99
  fz --help
14
100
  ```
15
101
 
16
- The one public package installs both commands. Keeping bootstrap and the daemon
17
- in one version prevents a newly installed `fz` from provisioning a different
18
- agent protocol. Both executable artifacts bundle their ForgeZero runtime
19
- dependencies, so the constrained SSH bootstrap can transfer the reviewed pair
20
- to a new host without relying on a checkout, `node_modules`, or a second remote
21
- package-resolution step. Library subpath exports remain modular packages.
102
+ ## fz Keep project truth synchronized
22
103
 
23
- The operator command starts browser-first platform genesis, inspects status,
24
- wraps processes, and installs the daemon. Genesis opens the one-use founder
25
- invitation, waits for the new passkey account to approve this CLI through device
26
- authorization, then continues custody in the browser. Passkey PRF output and
27
- both recovery phrases never enter the terminal:
104
+ One versioned ForgeZero manifest generates thin AI-tool adapters and CI rejects drift.
28
105
 
29
- ```bash
30
- fz status
31
- fz genesis --mode 2-of-3 --api https://api.example --app https://console.example
32
- fz unlock --phrase-file /secure/offline-phrase.txt # run once per participating custodian
33
- ```
34
-
35
- Install the service explicitly:
36
-
37
- ```bash
38
- fz agent install --apply # writes a hardened systemd unit
39
- ```
40
-
41
- ## Host bootstrap
42
-
43
- The package is also the host installer. There is no separate shell setup
44
- script and no second implementation for tenant or platform machines:
45
-
46
- ```bash
47
- fz bootstrap platform # interactive plan, no mutation
48
- sudo fz bootstrap platform prepare --bootstrap-config ./platform.json --apply
49
- # Register the printed read-only deploy key. For genesis, run --apply on all
50
- # three Agency members concurrently; later agency:none joiners run alone.
51
- sudo fz bootstrap platform --bootstrap-config ./platform.json --apply
52
- sudo fz bootstrap tenant --bootstrap-config ./tenant.json --apply
53
- sudo fz bootstrap metal --bootstrap-config ./metal.json --apply
54
- sudo fz bootstrap status
55
- sudo fz bootstrap repair --bootstrap-config ./original.json --apply
56
- ```
57
-
58
- Interactive bootstrap prompts only for missing typed inputs and validates every
59
- answer before it changes the host. It must then render a secret-free plan, apply
60
- idempotently, and verify the external and local result. Initial platform bring-up
61
- has exactly three attended owner gates:
62
-
63
- 1. SMTP host, port, sender, optional user, and an owner-only password file; the
64
- resulting provider must pass its configured health/send acceptance.
65
- 2. The separate Cloudflare phase consumes owner-only management and KV-runtime
66
- token files, reconciles Tunnel/hostname state, and emits the node handoff; the
67
- normal API/Agent never receives the management token.
68
- 3. `prepare` prints that machine's read-only Git deploy public key. The owner adds
69
- it to the repository and confirms completion; bootstrap then proves repository
70
- access before the first deployment.
71
-
72
- Browser authentication is deliberately not automated away. If npm or another
73
- provider prints an authentication URL, leave the command attached to its TTY,
74
- open the URL, complete the passkey flow, and let the same command continue.
75
-
76
- Platform database participation is explicit in the private JSON configuration.
77
- The three genesis nodes use `database.agency: "member"`; later DB+API joiners
78
- normally use `database.agency: "none"`, which starts a Coordinator and DBServer
79
- without adding a fourth Agency member. Enrolment is likewise explicit:
80
- `enrolment.source: "genesis-derived"` only for the offline genesis fleet, or
81
- `"api-token"` with `tokenFile` for every API-authorized later node. No behavior
82
- is inferred from a hostname or numeric suffix.
83
-
84
- Repair is not a second installation path: the CLI detects the installed
85
- platform/tenant or metal state and dispatches to that profile's validator. It
86
- fails closed if both state formats are present or neither is present. A private
87
- intent journal binds an interrupted first apply, and later repair refuses a
88
- config whose immutable host identity differs from the installed profile. Status checks the persisted
89
- identity record, both Agent sockets, profile-owned systemd units and, for a
90
- platform host, the active API health endpoint, nginx configuration and live
91
- Coordinator-mode evidence.
92
-
93
- Platform bootstrap supports an elastic Community ArangoDB 3.11.14 fleet. The
94
- first three database-capable computes establish the writable cluster; later
95
- database joiners and API-only computes use the same command with their typed
96
- profile and an API-issued one-time enrolment file. Nothing treats three as a
97
- maximum.
98
-
99
- After genesis, a tenant can designate an enrolled compute as a bootstrap
100
- runner. The API creates a project-bound, expiring job containing only public
101
- SSH coordinates and a pinned Ed25519 host-key fingerprint. The runner claims it
102
- with its hybrid node identity, reads its SSH key only from a local systemd
103
- credential, pins one vetted DNS answer, transfers this packaged CLI, and runs
104
- the same `fz bootstrap tenant` flow on the target. Claim renewal, completion,
105
- retry and cancellation are fenced in the compute aggregate; the API never
106
- stores the SSH private key or a plaintext enrolment token.
107
-
108
- The attended Cloudflare resource phase is part of the same published command,
109
- but remains separate from the root host install so its management token never
110
- enters the API or Agent service environment:
111
-
112
- ```bash
113
- chmod 600 cloudflare-bootstrap.json cloudflare-management.token cloudflare-runtime-kv.token
114
- fz bootstrap platform cloudflare --bootstrap-config ./cloudflare-bootstrap.json
115
- fz bootstrap platform cloudflare --bootstrap-config ./cloudflare-bootstrap.json --apply
116
- # After every host is bootstrapped and publishing healthy KV state:
117
- fz bootstrap platform cloudflare verify --bootstrap-config ./cloudflare-handoff.json
118
- ```
119
-
120
- Tenant-owned public origins use the identical reviewed request and handoff with
121
- `fz bootstrap tenant cloudflare ...`; `fz bootstrap tenant` consumes only that
122
- tenant node's handoff. Both host kinds seal the connector and supplied KV token
123
- and can repair after the plaintext handoff has been removed.
124
-
125
- The reviewed JSON has `format: 1`, kind
126
- `forgezero-cloudflare-bootstrap-request`, a `checkpointPath`, the typed
127
- `coordinates`, and token **file paths only**. The recommended token split is:
128
-
129
- ```json
130
- {
131
- "format": 1,
132
- "kind": "forgezero-cloudflare-bootstrap-request",
133
- "checkpointPath": "./cloudflare-handoff.json",
134
- "coordinates": {
135
- "accountId": "0123456789abcdef0123456789abcdef",
136
- "zoneId": "0123456789abcdef0123456789abcdef",
137
- "hostname": "dev-api-n1.example.com",
138
- "service": "http://127.0.0.1:3000",
139
- "tunnelName": "dev-api-n1",
140
- "kvNamespaceId": "0123456789abcdef0123456789abcdef",
141
- "nodes": [
142
- {
143
- "nodeName": "dev-api-n1",
144
- "hostname": "dev-api-n1.example.com",
145
- "service": "http://127.0.0.1:3000",
146
- "tunnelName": "dev-api-n1"
147
- }
148
- ]
149
- },
150
- "tokenFiles": {
151
- "managementApiTokenFile": "./cloudflare-management.token",
152
- "runtimeApiTokenFile": "./cloudflare-runtime-kv.token"
153
- }
154
- }
155
- ```
156
-
157
- The management token has exact-account **Cloudflare Tunnel Write** and
158
- exact-zone **DNS Write**. The runtime token has exact-account **Workers KV
159
- Storage Write**. Apply creates or adopts one remotely managed Tunnel per node,
160
- checkpoints its connector token, configures the public-hostname ingress, and
161
- reconciles the exact proxied CNAME. DNS reconciliation lists the hostname
162
- without a type filter: it updates one existing CNAME, creates only when absent,
163
- and refuses ambiguity or an incompatible A/AAAA/other owner before changing
164
- Tunnel ingress. It does not create a Worker, KV namespace, Access application,
165
- Access service token, or Cloudflare API token.
166
-
167
- The Worker and its KV/DO bindings are deployed separately through Cloudflare's
168
- Git integration. Durable Objects are reached through the Worker's binding, not
169
- with a Cloudflare REST token. The complete 0600 checkpoint stays on the
170
- operator machine; `<checkpoint>.hosts/<node>.json` contains only that node's
171
- connector plus the supplied KV runtime token. Host bootstrap seals them as the
172
- `cloudflared-token` and `cloudflare-kv-token` systemd credentials and removes
173
- the plaintext node handoff. The API resolves `cloudflare.kvApiToken` from the
174
- platform Vault first and falls back to the same systemd credential while the
175
- Vault is locked or unavailable. Management credentials are never persisted or
176
- loaded into the API/Agent service.
177
-
178
- Platform and tenant bootstrap configs may declare a bounded
179
- `deploymentCredentials` map from the exact pipeline secret name to its
180
- encrypted `.cred` source, for example
181
- `{"SMTP_PASSWORD":"/etc/forgezero/creds/SMTP_PASSWORD.cred"}`. The supervised
182
- Agent loads only those named credentials. A deployment asks for the same name;
183
- the Agent reads its project-scoped in-memory Vault replica first and uses the
184
- same-name systemd credential only until the replica can supply it. There is no
185
- directory scan, cross-project lookup, or differently named fallback.
186
-
187
- This is a versioned runtime schema, not a naming convention. The enrolled
188
- binding supplies the exact project and environment; `credential-schema.ts`
189
- maps a requested name to that environment's Vault cache coordinate. Platform
190
- and tenant computes use this Vault-first policy. Physical metal has no project
191
- Vault and loads only its fixed `metal-agent-seed` systemd credential. Attended
192
- operator Cloudflare/bootstrap tokens are owner-only input files and are never a
193
- runtime fallback. The schema is exported as `@forgezero/agent/credential-schema`.
106
+ ```text
107
+ fz project init
108
+ fz project sync
109
+ fz project check
110
+ ```
194
111
 
195
- ## What changes for an application
112
+ <a id="fz-run"></a>
113
+ ## fz run
196
114
 
197
- Nothing.
115
+ The fallback for software that cannot read the local socket: start a process with scoped vault values in its environment. This entry requires a Bun/Node host runtime. Run the command with `--help` before applying it.
198
116
 
199
- ```ts
200
- import { ForgeZero } from '@forgezero/vault';
201
- const fz = new ForgeZero({ project: 'altpilot', environment: 'production' });
202
- await fz.get('STRIPE_KEY');
117
+ ```text
118
+ fz run --help
203
119
  ```
204
120
 
205
- With no agent, that needs `FORGEZERO_API_KEY` in the environment. With the
206
- agent, it does not — and the key that would have been in the environment does
207
- not exist on the box.
121
+ <a id="fz-agent-install"></a>
122
+ ## fz agent install
208
123
 
209
- ## A local copy, not a cache
124
+ Provision the same hardened agent service locally that the platform provisions remotely. This entry requires a Bun/Node host runtime. Run the command with `--help` before applying it.
210
125
 
211
- The agent holds the **whole assigned project across every environment**, not
212
- just what has already been read. Each application still selects one environment
213
- and cannot cross the enrolled project boundary. That is the difference between surviving an outage and not: a
214
- cache only has what you fetched, so a secret you have never read is exactly the
215
- one you cannot get when the platform is unreachable.
126
+ ```text
127
+ fz agent install --help
128
+ ```
216
129
 
217
- The cost, stated rather than buried: a compromised guest exposes everything in
218
- scope rather than only what was read. It is bounded by the scope the compute is
219
- assigned to, and by SEV-SNP keeping the host out of guest memory.
130
+ <a id="fz-agent"></a>
131
+ ## fz-agent
220
132
 
221
- **Never on disk.** A cache file would hand an attacker with filesystem access
222
- every secret this guest has ever held — the exact artefact the design exists to
223
- remove. A restart re-fetches.
133
+ The service entry point. Identity and private Git material arrive only as systemd credentials. A platform bootstrap may use a statically configured local control socket; an enrolled tenant guest instead builds each deployment manager from the signed server claim and reads all commands from the checked-out .fz definition. Tenant cache scope and live attestation still need to be constructed from enrolment. This entry requires a Bun/Node host runtime. Run the command with `--help` before applying it.
224
134
 
225
- **Invalidated by cursor, not by a timer.** A TTL alone means a rotated secret
226
- keeps working for the length of the TTL, which is the window rotation exists to
227
- close. The agent polls a change cursor and drops what moved.
135
+ ```text
136
+ fz-agent --help
137
+ ```
228
138
 
229
- **A stale read is refused, not served.** If sync has not succeeded within the
230
- staleness bound, `get` fails rather than returning a value it can no longer
231
- vouch for. An application that receives a revoked credential and succeeds with
232
- it is worse off than one that receives an error — the error is visible.
139
+ <a id="fz-agent-socket"></a>
140
+ ## fz-agent (socket)
233
141
 
234
- ## Two postures, decided by the hardware
142
+ identity, sign, attest, get, sync and held — the whole interface an application sees. This entry requires a Bun/Node host runtime. Run the command with `--help` before applying it.
235
143
 
236
- | | |
237
- |---|---|
238
- | `attested` | SEV-SNP guest. The credential is a hardware report, and the platform can refuse a node whose measurement is wrong. |
239
- | `enrolled` | No SNP. The credential is the enrolment token plus a hybrid Ed25519 + ML-DSA-65 signature. |
144
+ ```text
145
+ fz-agent (socket) --help
146
+ ```
240
147
 
241
- Both are real. `enrolled` is still strictly better than an API key in the
242
- application: the key never leaves the agent, rotation reaches every process, and
243
- the socket is filesystem-scoped. The socket is mode `0660` under the dedicated
244
- `forgezero-vault` group; add only the intended application service account to
245
- that group. The credential-free deployment runner is not a member.
148
+ ## fz-agent (socket) Outbound control boundary
246
149
 
247
- The attested posture is the intended production upgrade, not current live
248
- evidence: report acquisition and AMD-rooted measurement verification still have
249
- to cross the production fleet. Until then the node is honestly `enrolled`; the
250
- Agent never manufactures an attestation-shaped fallback.
150
+ The Metal Agent initiates outbound signed HTTPS for orchestration. Applications use the project-scoped local Unix socket; the platform never opens an inbound shell control plane.
251
151
 
252
- Every Agent request uses the same hybrid signature codec as an external API key
253
- and signs its one-use hybrid ML-KEM-768 + X25519 response key. Vault replication,
254
- deployment claims, attestation and metal provisioning responses are AES-256-GCM
255
- sealed to that request before crossing the edge; there is no Ed25519-only or
256
- successful plaintext-response downgrade.
152
+ ```text
153
+ metal/compute Agent -> outbound signed HTTPS -> platform API
154
+ application -> local Unix socket -> project-scoped Vault replica
155
+ ```
257
156
 
258
- The first guest enrolment uses the same contract before the identity exists in
259
- the database: the guest signs the exact token and public-key body with both keys
260
- it is asking the API to admit, and it accepts only an ML-KEM-sealed
261
- acknowledgement. The short-lived token is therefore not an unsigned Agent path.
157
+ <a id="forgezero-agent-migration-pull"></a>
158
+ ## @forgezero/agent/migration-pull
262
159
 
263
- ## The socket interface
160
+ PQ-authenticated outbound lifecycle claims with fenced renewal, awaited async execution, idempotent acknowledgement and bounded shutdown drain. The executor reports local facts only. Named value imports: pullMigrationOnce, startMigrationPull. Named type imports: MigrationAction, MigrationEvidence, MigrationEvidenceProfile, MigrationNetwork, MigrationPullOptions, MigrationPullResult, RemoteMigrationClaim. Import only the names used by this file.
264
161
 
162
+ ```text
163
+ import { pullMigrationOnce, startMigrationPull } from '@forgezero/agent/migration-pull';
164
+ import type { MigrationAction, MigrationEvidence, MigrationEvidenceProfile, MigrationNetwork, MigrationPullOptions, MigrationPullResult } from '@forgezero/agent/migration-pull';
165
+ import type { RemoteMigrationClaim } from '@forgezero/agent/migration-pull';
265
166
  ```
266
- get one secret
267
- sync what changed since a cursor
268
- held what this guest is holding, by name only
167
+
168
+ <a id="forgezero-agent-lifecycle-helper"></a>
169
+ ## @forgezero/agent/lifecycle-helper
170
+
171
+ The root-owned fixed-operation boundary for migration work. Signed controller claims can request only private reachability probes, local health checks, or stops of units named in a root-owned profile; they cannot carry commands. Named value imports: DEFAULT_LIFECYCLE_HELPER_SOCKET, executeLifecycleAction, loadLifecycleProfile, requestLifecycleAction, spawnLifecycleCommand, startLifecycleHelper, validateLifecycleProfile. Named type imports: LifecycleCommandResult, LifecycleExec, LifecycleProfile. Import only the names used by this file.
172
+
173
+ ```text
174
+ import { DEFAULT_LIFECYCLE_HELPER_SOCKET, executeLifecycleAction, loadLifecycleProfile, requestLifecycleAction, spawnLifecycleCommand, startLifecycleHelper } from '@forgezero/agent/lifecycle-helper';
175
+ import { validateLifecycleProfile } from '@forgezero/agent/lifecycle-helper';
176
+ import type { LifecycleCommandResult, LifecycleExec, LifecycleProfile } from '@forgezero/agent/lifecycle-helper';
269
177
  ```
270
178
 
271
- The application Vault socket never accepts identity, signing, attestation,
272
- commands or deployment definitions. The Agent signs and attests only inside its
273
- own outbound clients. Otherwise a compromised application could ask for a valid
274
- node signature over a deployment or whole-project sync request and impersonate
275
- the Agent without ever extracting its key. Deployment enters through the
276
- root-only control socket or signed outbound claim path, then the deployment
277
- manager validates the checked-in definition and submits it to the common keyed
278
- queue.
179
+ <a id="forgezero-agent-provision"></a>
180
+ ## @forgezero/agent/provision
279
181
 
280
- ## Project context for any repository
182
+ The install plan as data, with no transport — so `fz` running locally and the platform running over SSH provision an identical machine. Named value imports: AGENT_EGRESS_UNIT_PATH, AGENT_SOCKET_PROXY_UNIT_PATH, AGENT_SOCKET_UNIT_PATH, APPLICATION_RUNTIME_USER, CAPABILITY_CHECKS, DEFAULT_RUNNER_PUBLIC_TCP_PORTS, DEPLOYMENT_GROUP, DEPLOYMENT_RUNNER_SOCKET, DEPLOYMENT_RUNNER_UNIT_PATH, DEPLOYMENT_RUNNER_USER, ENROLMENT_UNIT_PATH, LIFECYCLE_GROUP, LIFECYCLE_HELPER_SOCKET, LIFECYCLE_HELPER_UNIT_PATH, UNIT_PATH, VAULT_GROUP, WARP_CONFIG_UNIT_PATH, WARP_SERVICE_DROP_IN_PATH, agentBackendSocketPath, agentEgressUnit, agentEnrolmentUnit, agentSocketProxyUnit, agentSocketUnit, agentUnit, agentUpdateHelperUnit, atLeast, deploymentRunnerUnit, lifecycleHelperUnit, modeFor, planProvision, reasonFor, softwareHelperUnit, warpConfigUnit, warpServiceDropIn. Named type imports: AgentMode, Capabilities, CapabilityId, CapabilityOperation, Check, DirectorySpec, FixedHostCommand, ProvisionOperation, ProvisionPlan, Step, UnitOptions. Import only the names used by this file.
281
183
 
282
- Conversation memory is not a project database. Initialize one vendor-neutral,
283
- Git-owned context and generate the small files each AI product discovers:
184
+ ```text
185
+ import { AGENT_EGRESS_UNIT_PATH, AGENT_SOCKET_PROXY_UNIT_PATH, AGENT_SOCKET_UNIT_PATH, APPLICATION_RUNTIME_USER, CAPABILITY_CHECKS, DEFAULT_RUNNER_PUBLIC_TCP_PORTS } from '@forgezero/agent/provision';
186
+ import { DEPLOYMENT_GROUP, DEPLOYMENT_RUNNER_SOCKET, DEPLOYMENT_RUNNER_UNIT_PATH, DEPLOYMENT_RUNNER_USER, ENROLMENT_UNIT_PATH, LIFECYCLE_GROUP } from '@forgezero/agent/provision';
187
+ import { LIFECYCLE_HELPER_SOCKET, LIFECYCLE_HELPER_UNIT_PATH, UNIT_PATH, VAULT_GROUP, WARP_CONFIG_UNIT_PATH, WARP_SERVICE_DROP_IN_PATH } from '@forgezero/agent/provision';
188
+ import { agentBackendSocketPath, agentEgressUnit, agentEnrolmentUnit, agentSocketProxyUnit, agentSocketUnit, agentUnit } from '@forgezero/agent/provision';
189
+ import { agentUpdateHelperUnit, atLeast, deploymentRunnerUnit, lifecycleHelperUnit, modeFor, planProvision } from '@forgezero/agent/provision';
190
+ import { reasonFor, softwareHelperUnit, warpConfigUnit, warpServiceDropIn } from '@forgezero/agent/provision';
191
+ import type { AgentMode, Capabilities, CapabilityId, CapabilityOperation, Check, DirectorySpec } from '@forgezero/agent/provision';
192
+ import type { FixedHostCommand, ProvisionOperation, ProvisionPlan, Step, UnitOptions } from '@forgezero/agent/provision';
193
+ ```
284
194
 
285
- ```bash
286
- fz project init
287
- # edit .forgezero/project.json and create its named truth sources
288
- fz project sync
289
- fz project check
195
+ <a id="forgezero-agent-subscribe"></a>
196
+ ## @forgezero/agent/subscribe
197
+
198
+ Realtime scope sync over a WebSocket, with the poll kept underneath it: the poll is what establishes freshness, and a change it finds that the socket never sent is proof the socket is lying. Named value imports: backoffMs, subscribe. Named type imports: ChangeFrame, SocketLike, SubscribeOptions, Subscriber. Import only the names used by this file.
199
+
200
+ ```text
201
+ import { backoffMs, subscribe } from '@forgezero/agent/subscribe';
202
+ import type { ChangeFrame, SocketLike, SubscribeOptions, Subscriber } from '@forgezero/agent/subscribe';
290
203
  ```
291
204
 
292
- `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, Copilot instructions and the Cursor rule
293
- are generated adapters. They contain no independent architecture or progress.
294
- `fz project check` fails when a truth source is missing or an adapter was edited
295
- by hand. Tools and skills remain optional execution aids; accepted decisions and
296
- status live in the repository and therefore survive switching AI agents.
205
+ <a id="forgezero-agent-ssh-listen"></a>
206
+ ## @forgezero/agent/ssh-listen
297
207
 
298
- ## Browser-authorized project control
208
+ The socket SSH_AUTH_SOCK points at. The protocol handler had nowhere to speak — an agent protocol with no socket is a parser. The containing directory is 0700 before anything binds, because the socket’s own mode is only corrected after it already exists. Named value imports: MAX_MESSAGE_BYTES, startSshAgent. Named type imports: SshListenOptions. Import only the names used by this file.
299
209
 
300
- Sign in from any checkout with the public CLI. The terminal displays a device
301
- code and the browser approves it in the selected tenant realm:
210
+ ```text
211
+ import { MAX_MESSAGE_BYTES, startSshAgent } from '@forgezero/agent/ssh-listen';
212
+ import type { SshListenOptions } from '@forgezero/agent/ssh-listen';
213
+ ```
302
214
 
303
- ```bash
304
- fz login --api https://api.forgezero.net --realm acme
305
- fz whoami
306
- fz ui routes --json
215
+ <a id="forgezero-agent-ssh-server"></a>
216
+ ## @forgezero/agent/ssh-server
217
+
218
+ Serve the SSH agent protocol so SSH_AUTH_SOCK points at the vault — two operations implemented, and ADD_IDENTITY refused so no process can inject a key ssh would offer to every host. Named value imports: MAX_MESSAGE_BYTES, SSH_AGENT_FAILURE, SSH_AGENT_IDENTITIES_ANSWER, SSH_AGENT_SIGN_RESPONSE, SSH_AGENT_SUCCESS, SshAgentError, describeIdentities, frame, handleMessage, readMessage. Named type imports: AgentBackend, AgentIdentity. Import only the names used by this file.
219
+
220
+ ```text
221
+ import { MAX_MESSAGE_BYTES, SSH_AGENT_FAILURE, SSH_AGENT_IDENTITIES_ANSWER, SSH_AGENT_SIGN_RESPONSE, SSH_AGENT_SUCCESS, SshAgentError } from '@forgezero/agent/ssh-server';
222
+ import { describeIdentities, frame, handleMessage, readMessage } from '@forgezero/agent/ssh-server';
223
+ import type { AgentBackend, AgentIdentity } from '@forgezero/agent/ssh-server';
224
+ ```
225
+
226
+ <a id="forgezero-agent-pipeline"></a>
227
+ ## @forgezero/agent/pipeline
228
+
229
+ CI/CD on the compute: secrets reach the step that named them and nothing else, attestation gates the run, and a required attestation that fails is a refusal rather than a downgrade. Named value imports: PipelineError, redact, runPipeline. Named type imports: Pipeline, PipelineStep, RunOptions, RunResult, StepOutcome, StepResult. Import only the names used by this file.
230
+
231
+ ```text
232
+ import { PipelineError, redact, runPipeline } from '@forgezero/agent/pipeline';
233
+ import type { Pipeline, PipelineStep, RunOptions, RunResult, StepOutcome, StepResult } from '@forgezero/agent/pipeline';
234
+ ```
235
+
236
+ <a id="forgezero-agent-agent-heartbeat"></a>
237
+ ## @forgezero/agent/agent-heartbeat
238
+
239
+ Signed node health publication with bounded renewal and shutdown withdrawal. Named value imports: heartbeatAgentOnce, observeAgentHost, startAgentHeartbeat. Named type imports: AgentHeartbeatOptions, AgentHeartbeatResponse, AgentObservation. Import only the names used by this file.
240
+
241
+ ```text
242
+ import { heartbeatAgentOnce, observeAgentHost, startAgentHeartbeat } from '@forgezero/agent/agent-heartbeat';
243
+ import type { AgentHeartbeatOptions, AgentHeartbeatResponse, AgentObservation } from '@forgezero/agent/agent-heartbeat';
244
+ ```
245
+
246
+ <a id="forgezero-agent-agent-update"></a>
247
+ ## @forgezero/agent/agent-update
248
+
249
+ Verified Agent update planning against the platform release coordinate. Named value imports: DEFAULT_AGENT_RELEASE_ROOT, DEFAULT_AGENT_UPDATE_SOCKET, MAX_AGENT_TARBALL_BYTES, compareVersions, restoreAgentRelease, selectAgentRelease, stageAgentRelease, validateAgentRelease. Named type imports: AgentRelease, StagedAgentRelease, UpdateCommand, UpdateCommandResult. Import only the names used by this file.
250
+
251
+ ```text
252
+ import { DEFAULT_AGENT_RELEASE_ROOT, DEFAULT_AGENT_UPDATE_SOCKET, MAX_AGENT_TARBALL_BYTES, compareVersions, restoreAgentRelease, selectAgentRelease } from '@forgezero/agent/agent-update';
253
+ import { stageAgentRelease, validateAgentRelease } from '@forgezero/agent/agent-update';
254
+ import type { AgentRelease, StagedAgentRelease, UpdateCommand, UpdateCommandResult } from '@forgezero/agent/agent-update';
255
+ ```
256
+
257
+ <a id="forgezero-agent-agent-update-helper"></a>
258
+ ## @forgezero/agent/agent-update-helper
259
+
260
+ Root-owned fixed update operations with registry origin and integrity validation. Named value imports: AGENT_UPDATE_GROUP, AGENT_UPDATE_HELPER_UNIT_PATH, AGENT_UPDATE_JOURNAL, AGENT_UPDATE_RECEIPT, activateAgentRelease, probeAgentSocket, readAgentUpdateReceipt, recoverInterruptedAgentUpdate, requestAgentUpdate, startAgentUpdateHelper. Named type imports: AgentUpdateOutcome, AgentUpdateReceipt, AgentUpdateRequest, AgentUpdateResponse. Import only the names used by this file.
261
+
262
+ ```text
263
+ import { AGENT_UPDATE_GROUP, AGENT_UPDATE_HELPER_UNIT_PATH, AGENT_UPDATE_JOURNAL, AGENT_UPDATE_RECEIPT, activateAgentRelease, probeAgentSocket } from '@forgezero/agent/agent-update-helper';
264
+ import { readAgentUpdateReceipt, recoverInterruptedAgentUpdate, requestAgentUpdate, startAgentUpdateHelper } from '@forgezero/agent/agent-update-helper';
265
+ import type { AgentUpdateOutcome, AgentUpdateReceipt, AgentUpdateRequest, AgentUpdateResponse } from '@forgezero/agent/agent-update-helper';
266
+ ```
267
+
268
+ <a id="forgezero-agent-bootstrap"></a>
269
+ ## @forgezero/agent/bootstrap
270
+
271
+ Typed one-time platform bootstrap and internal API-driven enrolled-compute activation contracts. Named value imports: BOOTSTRAP_STATE_PATH, PLATFORM_BOOTSTRAP_PROFILES, applyBootstrap, bootstrapIdentityDigest, bootstrapStatus, localBootstrapHost, planBootstrap, preparePlatformBootstrap, readBootstrapConfig, resolveInstalledBootstrapKind, validateBootstrapConfig. Named type imports: BootstrapConfig, BootstrapEnvironment, BootstrapHost, BootstrapPlan, BootstrapResult, BootstrapStatus, BootstrapStep, DatabaseAgencyParticipation, DatabaseBootstrapRole, EnrolledComputeActivationConfig, InstalledBootstrapKind, PlatformBootstrapConfig, PlatformBootstrapPreparation, PlatformBootstrapProfile, PlatformEnrolmentSource. Import only the names used by this file.
272
+
273
+ ```text
274
+ import { BOOTSTRAP_STATE_PATH, PLATFORM_BOOTSTRAP_PROFILES, applyBootstrap, bootstrapIdentityDigest, bootstrapStatus, localBootstrapHost } from '@forgezero/agent/bootstrap';
275
+ import { planBootstrap, preparePlatformBootstrap, readBootstrapConfig, resolveInstalledBootstrapKind, validateBootstrapConfig } from '@forgezero/agent/bootstrap';
276
+ import type { BootstrapConfig, BootstrapEnvironment, BootstrapHost, BootstrapPlan, BootstrapResult, BootstrapStatus } from '@forgezero/agent/bootstrap';
277
+ import type { BootstrapStep, DatabaseAgencyParticipation, DatabaseBootstrapRole, EnrolledComputeActivationConfig, InstalledBootstrapKind, PlatformBootstrapConfig } from '@forgezero/agent/bootstrap';
278
+ import type { PlatformBootstrapPreparation, PlatformBootstrapProfile, PlatformEnrolmentSource } from '@forgezero/agent/bootstrap';
279
+ ```
280
+
281
+ <a id="forgezero-agent-operator-bootstrap"></a>
282
+ ## @forgezero/agent/operator-bootstrap
283
+
284
+ Pinned-host operator transport that stages owner-only handoffs and invokes the same typed platform bootstrap through the caller-approved SSH agent. Named value imports: applyOperatorMetalBootstrap, applyOperatorPlatformBootstrap, planOperatorMetalBootstrap, planOperatorPlatformBootstrap, readOperatorMetalBootstrapRequest, readOperatorPlatformBootstrapRequest. Named type imports: OperatorCommand, OperatorCommandResult, OperatorMetalBootstrapMode, OperatorMetalBootstrapPlan, OperatorMetalBootstrapRequest, OperatorPlatformBootstrapMode, OperatorPlatformBootstrapOptions, OperatorPlatformBootstrapPlan, OperatorPlatformBootstrapRequest, OperatorSshHop. Import only the names used by this file.
285
+
286
+ ```text
287
+ import { applyOperatorMetalBootstrap, applyOperatorPlatformBootstrap, planOperatorMetalBootstrap, planOperatorPlatformBootstrap, readOperatorMetalBootstrapRequest, readOperatorPlatformBootstrapRequest } from '@forgezero/agent/operator-bootstrap';
288
+ import type { OperatorCommand, OperatorCommandResult, OperatorMetalBootstrapMode, OperatorMetalBootstrapPlan, OperatorMetalBootstrapRequest, OperatorPlatformBootstrapMode } from '@forgezero/agent/operator-bootstrap';
289
+ import type { OperatorPlatformBootstrapOptions, OperatorPlatformBootstrapPlan, OperatorPlatformBootstrapRequest, OperatorSshHop } from '@forgezero/agent/operator-bootstrap';
307
290
  ```
308
291
 
309
- The short session is stored by API origin and realm in an owner-only local file.
310
- It is never committed to `.fz/config.json`. A protected mutation opens a browser
311
- page for passkey or TOTP proof and then replays the exact request once; the CLI
312
- has no privileged server mode.
292
+ ## @forgezero/agent/operator-bootstrap Run the same typed platform bootstrap from an operator laptop
293
+
294
+ The request contains only an explicit target IP, pinned host public key/fingerprint, the caller public-key file, SSH-agent socket and a path to the reviewed platform config. Credential values stay in owner-only files, the private SSH key stays in the operator agent, and the default command is a non-contacting plan.
295
+
296
+ ```text
297
+ fz bootstrap platform remote prepare \
298
+ --bootstrap-config /secure/forgezero/development/dev-fz-n1-remote.json
299
+ # Review, then allow the SSH-agent approval prompt:
300
+ fz bootstrap platform remote prepare \
301
+ --bootstrap-config /secure/forgezero/development/dev-fz-n1-remote.json --apply
302
+ ```
303
+
304
+ <a id="forgezero-agent-host-maintenance"></a>
305
+ ## @forgezero/agent/host-maintenance
306
+
307
+ Closed host maintenance plans for staging transaction rehearsal and fleet-fenced schema consolidation through fixed transient systemd units. Named value imports: applyHostMaintenance, planHostMaintenance. Named type imports: HostMaintenanceOperation, HostMaintenancePlan, HostMaintenanceRequest, HostMaintenanceResult, HostMaintenanceRuntime. Import only the names used by this file.
308
+
309
+ ```text
310
+ import { applyHostMaintenance, planHostMaintenance } from '@forgezero/agent/host-maintenance';
311
+ import type { HostMaintenanceOperation, HostMaintenancePlan, HostMaintenanceRequest, HostMaintenanceResult, HostMaintenanceRuntime } from '@forgezero/agent/host-maintenance';
312
+ ```
313
+
314
+ ## @forgezero/agent/host-maintenance — Plan a fixed supervised host operation
315
+
316
+ The library discovers only a trusted blue/green slot, attaches fixed credential names and returns exact argv as reviewable data. The public fz host commands use the same operation and require root only for apply.
317
+
318
+ ```text
319
+ import { planHostMaintenance } from '@forgezero/agent/host-maintenance';
320
+
321
+ const plan = planHostMaintenance({ operation: 'schema-plan' });
322
+ console.log(plan.argv);
323
+ ```
324
+
325
+ <a id="forgezero-agent-capacity-calibration"></a>
326
+ ## @forgezero/agent/capacity-calibration
327
+
328
+ One-time target-local safe-concurrency calibration with private evidence. Named value imports: calibrateHttpConcurrency, localCalibrationEndpoint, validateCapacityCalibrationOptions. Named type imports: CapacityCalibration, CapacityCalibrationOptions, CapacityStage, ValidatedCapacityCalibrationOptions. Import only the names used by this file.
329
+
330
+ ```text
331
+ import { calibrateHttpConcurrency, localCalibrationEndpoint, validateCapacityCalibrationOptions } from '@forgezero/agent/capacity-calibration';
332
+ import type { CapacityCalibration, CapacityCalibrationOptions, CapacityStage, ValidatedCapacityCalibrationOptions } from '@forgezero/agent/capacity-calibration';
333
+ ```
334
+
335
+ <a id="forgezero-agent-cloudflare-bootstrap"></a>
336
+ ## @forgezero/agent/cloudflare-bootstrap
337
+
338
+ Attended two-token Cloudflare Tunnel/DNS reconciliation and per-node connector/KV runtime handoff for existing KV resources. Named value imports: applyCloudflareBootstrap, cloudflareHostHandoffPath, finalizeCloudflareBootstrapAcceptance, planCloudflareBootstrap, readCloudflareBootstrapAcceptanceEvidence, readCloudflareBootstrapTokens, readCloudflareConnectorHandoff, readCloudflareHostHandoff, readOwnerApiToken, runAttendedCloudflareBootstrap, validateCloudflareBootstrapCoordinates, verifyCloudflareBootstrapAcceptance, writeOwnerBootstrapOutput. Named type imports: AttendedCloudflareBootstrapRequest, CloudflareBootstrapAcceptanceEvidence, CloudflareBootstrapAcceptedNode, CloudflareBootstrapCoordinates, CloudflareBootstrapDependencies, CloudflareBootstrapEvidence, CloudflareBootstrapFinalizeRequest, CloudflareBootstrapNodeCoordinates, CloudflareBootstrapOutput, CloudflareBootstrapPhaseRunner, CloudflareBootstrapPlan, CloudflareBootstrapTokenFiles, CloudflareBootstrapTokens, CloudflareConnectorHandoff, CloudflareHostHandoff, CloudflareMeshCoordinates, CloudflareRealtimeCoordinates. Import only the names used by this file.
339
+
340
+ ```text
341
+ import { applyCloudflareBootstrap, cloudflareHostHandoffPath, finalizeCloudflareBootstrapAcceptance, planCloudflareBootstrap, readCloudflareBootstrapAcceptanceEvidence, readCloudflareBootstrapTokens } from '@forgezero/agent/cloudflare-bootstrap';
342
+ import { readCloudflareConnectorHandoff, readCloudflareHostHandoff, readOwnerApiToken, runAttendedCloudflareBootstrap, validateCloudflareBootstrapCoordinates, verifyCloudflareBootstrapAcceptance } from '@forgezero/agent/cloudflare-bootstrap';
343
+ import { writeOwnerBootstrapOutput } from '@forgezero/agent/cloudflare-bootstrap';
344
+ import type { AttendedCloudflareBootstrapRequest, CloudflareBootstrapAcceptanceEvidence, CloudflareBootstrapAcceptedNode, CloudflareBootstrapCoordinates, CloudflareBootstrapDependencies, CloudflareBootstrapEvidence } from '@forgezero/agent/cloudflare-bootstrap';
345
+ import type { CloudflareBootstrapFinalizeRequest, CloudflareBootstrapNodeCoordinates, CloudflareBootstrapOutput, CloudflareBootstrapPhaseRunner, CloudflareBootstrapPlan, CloudflareBootstrapTokenFiles } from '@forgezero/agent/cloudflare-bootstrap';
346
+ import type { CloudflareBootstrapTokens, CloudflareConnectorHandoff, CloudflareHostHandoff, CloudflareMeshCoordinates, CloudflareRealtimeCoordinates } from '@forgezero/agent/cloudflare-bootstrap';
347
+ ```
348
+
349
+ <a id="forgezero-agent-cloudflare-edge"></a>
350
+ ## @forgezero/agent/cloudflare-edge
351
+
352
+ Strict Cloudflare REST operations used by the attended bootstrap controller. Named value imports: configureCloudflareEdge, configureCloudflareRealtimeSecrets, ensureCloudflareMeshConnector, ensureCloudflarePrivateDatabaseRoute, ensureCloudflarePrivateRoute, ensureCloudflareTunnel, ensureCloudflareWarpDatabaseInclude, ensureCloudflareWarpNetworkIncludes, removeCloudflarePrivateDatabaseRoute, removeCloudflarePrivateRoute, removeCloudflareWarpDatabaseInclude, verifyCloudflareWorkerDurableObjects. Named type imports: CloudflareDurableObjectNamespace, CloudflareEdgeConfig, CloudflareMeshConnector, CloudflarePrivateRoute, CloudflarePrivateRouteConfig, CloudflareTunnel, CloudflareWarpIncludeConfig. Import only the names used by this file.
353
+
354
+ ```text
355
+ import { configureCloudflareEdge, configureCloudflareRealtimeSecrets, ensureCloudflareMeshConnector, ensureCloudflarePrivateDatabaseRoute, ensureCloudflarePrivateRoute, ensureCloudflareTunnel } from '@forgezero/agent/cloudflare-edge';
356
+ import { ensureCloudflareWarpDatabaseInclude, ensureCloudflareWarpNetworkIncludes, removeCloudflarePrivateDatabaseRoute, removeCloudflarePrivateRoute, removeCloudflareWarpDatabaseInclude, verifyCloudflareWorkerDurableObjects } from '@forgezero/agent/cloudflare-edge';
357
+ import type { CloudflareDurableObjectNamespace, CloudflareEdgeConfig, CloudflareMeshConnector, CloudflarePrivateRoute, CloudflarePrivateRouteConfig, CloudflareTunnel } from '@forgezero/agent/cloudflare-edge';
358
+ import type { CloudflareWarpIncludeConfig } from '@forgezero/agent/cloudflare-edge';
359
+ ```
360
+
361
+ <a id="forgezero-agent-mesh-connector"></a>
362
+ ## @forgezero/agent/mesh-connector
363
+
364
+ Fixed Cloudflare Mesh/WARP connector enrollment using only the unit-loaded connector credential. Named value imports: configureMeshConnector, readMeshConnectorCredential. Named type imports: MeshConnectorCommandResult, MeshConnectorExec. Import only the names used by this file.
365
+
366
+ ```text
367
+ import { configureMeshConnector, readMeshConnectorCredential } from '@forgezero/agent/mesh-connector';
368
+ import type { MeshConnectorCommandResult, MeshConnectorExec } from '@forgezero/agent/mesh-connector';
369
+ ```
370
+
371
+ <a id="forgezero-agent-compute"></a>
372
+ ## @forgezero/agent/compute
373
+
374
+ Compute claim, renewal, execution and completion client contracts. Named value imports: ComputeError, deviceInUse, guestUnit, parseCensus, qemuArgv, shapeEgressCommands, shapeEgressUnitDirectives, tapFor, unitName. Named type imports: GuestSpec, RunningGuest. Import only the names used by this file.
375
+
376
+ ```text
377
+ import { ComputeError, deviceInUse, guestUnit, parseCensus, qemuArgv, shapeEgressCommands } from '@forgezero/agent/compute';
378
+ import { shapeEgressUnitDirectives, tapFor, unitName } from '@forgezero/agent/compute';
379
+ import type { GuestSpec, RunningGuest } from '@forgezero/agent/compute';
380
+ ```
381
+
382
+ <a id="forgezero-agent-credential-schema"></a>
383
+ ## @forgezero/agent/credential-schema
384
+
385
+ Canonical systemd credential names and validation shared by bootstrap and services. Named value imports: AGENT_CREDENTIAL_LOCATIONS, AGENT_CREDENTIAL_POLICY, CLOUDFLARE_CREDENTIAL_NAMES, CLOUDFLARE_CREDENTIAL_SCHEMA, METAL_SYSTEMD_CREDENTIALS, credentialBinding, deploymentCredentialSchema. Named type imports: AgentCredentialLocation, DeploymentCredentialBinding, DeploymentCredentialSchema. Import only the names used by this file.
386
+
387
+ ```text
388
+ import { AGENT_CREDENTIAL_LOCATIONS, AGENT_CREDENTIAL_POLICY, CLOUDFLARE_CREDENTIAL_NAMES, CLOUDFLARE_CREDENTIAL_SCHEMA, METAL_SYSTEMD_CREDENTIALS, credentialBinding } from '@forgezero/agent/credential-schema';
389
+ import { deploymentCredentialSchema } from '@forgezero/agent/credential-schema';
390
+ import type { AgentCredentialLocation, DeploymentCredentialBinding, DeploymentCredentialSchema } from '@forgezero/agent/credential-schema';
391
+ ```
313
392
 
314
- Any ordinary website operation is available to developers and AI agents through
315
- the same API and access matrix:
393
+ <a id="forgezero-agent-definition"></a>
394
+ ## @forgezero/agent/definition
316
395
 
317
- ```bash
396
+ Validated project deployment definition and workload profiles. Named value imports: DEPLOY_SCHEMA_URL, DefinitionError, PIPELINE_VERSION, parseDeployDefinition, phasePipeline, validateDeploymentService. Named type imports: DeployDefinition, DeployStep, DeploymentPortAllocation, DeploymentService, PipelineProfile. Import only the names used by this file.
397
+
398
+ ```text
399
+ import { DEPLOY_SCHEMA_URL, DefinitionError, PIPELINE_VERSION, parseDeployDefinition, phasePipeline, validateDeploymentService } from '@forgezero/agent/definition';
400
+ import type { DeployDefinition, DeployStep, DeploymentPortAllocation, DeploymentService, PipelineProfile } from '@forgezero/agent/definition';
401
+ ```
402
+
403
+ <a id="forgezero-agent-deploy-file"></a>
404
+ ## @forgezero/agent/deploy-file
405
+
406
+ Read and validate a checked-out .fz deployment file without executing project input. Named value imports: DEPLOY_FILE, DEPLOY_SCHEMA_URL, DEPLOY_TODO_PREFIX, defaultDeployFile, deployDefinitionDigest, initializeDeployFile, inspectDeployFile. Named type imports: DeployFileSummary, InitializedDeployFile. Import only the names used by this file.
407
+
408
+ ```text
409
+ import { DEPLOY_FILE, DEPLOY_SCHEMA_URL, DEPLOY_TODO_PREFIX, defaultDeployFile, deployDefinitionDigest, initializeDeployFile } from '@forgezero/agent/deploy-file';
410
+ import { inspectDeployFile } from '@forgezero/agent/deploy-file';
411
+ import type { DeployFileSummary, InitializedDeployFile } from '@forgezero/agent/deploy-file';
412
+ ```
413
+
414
+ <a id="forgezero-agent-metal-bootstrap"></a>
415
+ ## @forgezero/agent/metal-bootstrap
416
+
417
+ Physical-metal bootstrap planning, application and status evidence. Named value imports: METAL_BOOTSTRAP_STATE_PATH, MetalBootstrapError, applyMetalBootstrap, metalBootstrapStatus, planMetalBootstrap, readMetalBootstrapConfig, renderMetalUnits, validateMetalBootstrapConfig, validateOwnerOnlyPath. Named type imports: MetalBootstrapApplyOptions, MetalBootstrapConfig, MetalBootstrapExec, MetalBootstrapPlan, MetalBootstrapResult, MetalBootstrapStatus. Import only the names used by this file.
418
+
419
+ ```text
420
+ import { METAL_BOOTSTRAP_STATE_PATH, MetalBootstrapError, applyMetalBootstrap, metalBootstrapStatus, planMetalBootstrap, readMetalBootstrapConfig } from '@forgezero/agent/metal-bootstrap';
421
+ import { renderMetalUnits, validateMetalBootstrapConfig, validateOwnerOnlyPath } from '@forgezero/agent/metal-bootstrap';
422
+ import type { MetalBootstrapApplyOptions, MetalBootstrapConfig, MetalBootstrapExec, MetalBootstrapPlan, MetalBootstrapResult, MetalBootstrapStatus } from '@forgezero/agent/metal-bootstrap';
423
+ ```
424
+
425
+ <a id="forgezero-agent-metal-provision"></a>
426
+ ## @forgezero/agent/metal-provision
427
+
428
+ Validated confidential guest provisioning profiles and cloud-init rendering. Named value imports: MetalProvisionError, allocateAddress, allocateCpuPool, cloudInit, guestBootstrapOperations, guestNameFor, macForAddress, provisionMetalGuest, removeMetalGuest, tapNameFor, validateMetalProfile. Named type imports: GuestManifest, MetalCommandResult, MetalCpuPool, MetalExec, MetalImage, MetalProvisionProfile. Import only the names used by this file.
429
+
430
+ ```text
431
+ import { MetalProvisionError, allocateAddress, allocateCpuPool, cloudInit, guestBootstrapOperations, guestNameFor } from '@forgezero/agent/metal-provision';
432
+ import { macForAddress, provisionMetalGuest, removeMetalGuest, tapNameFor, validateMetalProfile } from '@forgezero/agent/metal-provision';
433
+ import type { GuestManifest, MetalCommandResult, MetalCpuPool, MetalExec, MetalImage, MetalProvisionProfile } from '@forgezero/agent/metal-provision';
434
+ ```
435
+
436
+ <a id="forgezero-agent-platform-bootstrap-runtime"></a>
437
+ ## @forgezero/agent/platform-bootstrap-runtime
438
+
439
+ Pure platform bootstrap validation, render and resumable phase-state contracts. Named value imports: activatePlatformRelease, planLocalOtlpProof, planPlatformActivation, platformApiCredentialSpecs, renderPlatformActivationFiles, renderPlatformApiUnits, renderPlatformNginx, renderPlatformSharedEnvironment, validatePlatformSharedEnvironment. Named type imports: ActivationBoundary, ApiRuntimeRenderOptions, ApiSlot, LocalOtlpProofPlan, PlatformActivationCommandResult, PlatformActivationConfig, PlatformActivationExec, PlatformBootstrapEmail, PlatformDatabaseRole, PlatformSharedEnvironment, PlatformSoftwareProfile, SystemdCredentialSpec. Import only the names used by this file.
440
+
441
+ ```text
442
+ import { activatePlatformRelease, planLocalOtlpProof, planPlatformActivation, platformApiCredentialSpecs, renderPlatformActivationFiles, renderPlatformApiUnits } from '@forgezero/agent/platform-bootstrap-runtime';
443
+ import { renderPlatformNginx, renderPlatformSharedEnvironment, validatePlatformSharedEnvironment } from '@forgezero/agent/platform-bootstrap-runtime';
444
+ import type { ActivationBoundary, ApiRuntimeRenderOptions, ApiSlot, LocalOtlpProofPlan, PlatformActivationCommandResult, PlatformActivationConfig } from '@forgezero/agent/platform-bootstrap-runtime';
445
+ import type { PlatformActivationExec, PlatformBootstrapEmail, PlatformDatabaseRole, PlatformSharedEnvironment, PlatformSoftwareProfile, SystemdCredentialSpec } from '@forgezero/agent/platform-bootstrap-runtime';
446
+ ```
447
+
448
+ <a id="forgezero-agent-project-context"></a>
449
+ ## @forgezero/agent/project-context
450
+
451
+ Project identity and repository context validation for operator and managed runs. Named value imports: PROJECT_CONTEXT_VERSION, ProjectContextError, checkProjectContext, defaultProjectContext, initializeProjectContext, parseProjectContext, projectContextFiles, renderProjectContext, syncProjectContext. Named type imports: ContextCheck, ContextFile, ProjectContextManifest, ProjectTruthSource. Import only the names used by this file.
452
+
453
+ ```text
454
+ import { PROJECT_CONTEXT_VERSION, ProjectContextError, checkProjectContext, defaultProjectContext, initializeProjectContext, parseProjectContext } from '@forgezero/agent/project-context';
455
+ import { projectContextFiles, renderProjectContext, syncProjectContext } from '@forgezero/agent/project-context';
456
+ import type { ContextCheck, ContextFile, ProjectContextManifest, ProjectTruthSource } from '@forgezero/agent/project-context';
457
+ ```
458
+
459
+ <a id="forgezero-agent-provisioning-pull"></a>
460
+ ## @forgezero/agent/provisioning-pull
461
+
462
+ Signed provisioning work claim, renewal, execution and acknowledgement. Named value imports: pullProvisioningOnce, startProvisioningPull. Named type imports: CreateRemoteProvisionClaim, GuestAccess, ProvisionPullResult, ProvisionResult, ProvisionRunner, ProvisioningPullOptions, RemoteProvisionClaim. Import only the names used by this file.
463
+
464
+ ```text
465
+ import { pullProvisioningOnce, startProvisioningPull } from '@forgezero/agent/provisioning-pull';
466
+ import type { CreateRemoteProvisionClaim, GuestAccess, ProvisionPullResult, ProvisionResult, ProvisionRunner, ProvisioningPullOptions } from '@forgezero/agent/provisioning-pull';
467
+ import type { RemoteProvisionClaim } from '@forgezero/agent/provisioning-pull';
468
+ ```
469
+
470
+ <a id="forgezero-agent-schema-deploy-v3-json"></a>
471
+ ## @forgezero/agent/schema/deploy-v3.json
472
+
473
+ Published JSON Schema for deployment definition version 3 with exact argv execution. This entry is JSON data rather than a JavaScript namespace.
474
+
475
+ ```text
476
+ import schema from '@forgezero/agent/schema/deploy-v3.json' with { type: 'json' };
477
+ ```
478
+
479
+ ## @forgezero/agent/schema/deploy-v3.json — Validate a deployment definition against the published schema
480
+
481
+ Definition version 3 rejects unknown fields and shell command strings; every step is a bounded exact argv vector. Credentials remain named references resolved by Vault or the same-named encrypted systemd fallback.
482
+
483
+ ```text
484
+ import deploySchema from '@forgezero/agent/schema/deploy-v3.json' with { type: 'json' };
485
+ import Ajv from 'ajv';
486
+
487
+ const validate = new Ajv({ allErrors: true, strict: true }).compile(deploySchema);
488
+ if (!validate(deploymentDefinition)) throw new Error(JSON.stringify(validate.errors));
489
+ ```
490
+
491
+ <a id="forgezero-agent-software"></a>
492
+ ## @forgezero/agent/software
493
+
494
+ Exact managed-software inventory, requirement and evidence contracts. Named value imports: BUN_RELEASE_SHA256, OS_CATALOG, PINNED_BUN_VERSION, SOFTWARE_CATALOG, ensureSoftwareRequirements, executeSoftwareOperation, observeSoftwareHost, validateSoftwareRequirements. Named type imports: CatalogStatus, DeploymentChannel, OsCatalogEntry, SoftwareCatalogEntry, SoftwareCommandResult, SoftwareExec, SoftwareId, SoftwareObservation, SoftwareOperation, SoftwareRequirement. Import only the names used by this file.
495
+
496
+ ```text
497
+ import { BUN_RELEASE_SHA256, OS_CATALOG, PINNED_BUN_VERSION, SOFTWARE_CATALOG, ensureSoftwareRequirements, executeSoftwareOperation } from '@forgezero/agent/software';
498
+ import { observeSoftwareHost, validateSoftwareRequirements } from '@forgezero/agent/software';
499
+ import type { CatalogStatus, DeploymentChannel, OsCatalogEntry, SoftwareCatalogEntry, SoftwareCommandResult, SoftwareExec } from '@forgezero/agent/software';
500
+ import type { SoftwareId, SoftwareObservation, SoftwareOperation, SoftwareRequirement } from '@forgezero/agent/software';
501
+ ```
502
+
503
+ <a id="forgezero-agent-software-helper"></a>
504
+ ## @forgezero/agent/software-helper
505
+
506
+ Root-owned fixed installation/update boundary for declared software. Named value imports: DEFAULT_SOFTWARE_HELPER_SOCKET, SOFTWARE_HELPER_GROUP, SOFTWARE_HELPER_UNIT_PATH, requestServiceActivation, requestSoftware, startSoftwareHelper. Named type imports: none. Import only the names used by this file.
507
+
508
+ ```text
509
+ import { DEFAULT_SOFTWARE_HELPER_SOCKET, SOFTWARE_HELPER_GROUP, SOFTWARE_HELPER_UNIT_PATH, requestServiceActivation, requestSoftware, startSoftwareHelper } from '@forgezero/agent/software-helper';
510
+ ```
511
+
512
+ <a id="forgezero-agent-ubuntu"></a>
513
+ ## @forgezero/agent/ubuntu
514
+
515
+ Ubuntu host validation and deterministic systemd/unit rendering helpers. Named value imports: SUPPORTED_GUEST_IMAGE, assertSupportedGuestImage. Named type imports: none. Import only the names used by this file.
516
+
517
+ ```text
518
+ import { SUPPORTED_GUEST_IMAGE, assertSupportedGuestImage } from '@forgezero/agent/ubuntu';
519
+ ```
520
+
521
+ <a id="fz-agent-replica"></a>
522
+ ## fz-agent (replica)
523
+
524
+ The project-scoped vault replica: resident in RAM, never on disk, invalidated by cursor rather than by timer, and refusing a read it can no longer vouch for. Run the command with `--help` before applying it.
525
+
526
+ ```text
527
+ fz-agent (replica) --help
528
+ ```
529
+
530
+ ## Install both machine commands
531
+
532
+ One public package installs `fz` and `fz-agent` at the same version. `fz` breaks the bootstrap circle from an operator machine; `fz-agent` runs managed work. Keeping them together prevents a new bootstrap command from provisioning an old daemon protocol.
533
+
534
+ ```text
535
+ bun add -g @forgezero/agent
536
+ fz --help
537
+ fz-agent --help
538
+ ```
539
+
540
+ ## One project memory for every AI tool
541
+
542
+ Conversation memory and dated audits are observations, not architecture. `fz project init` creates one strict, vendor-neutral manifest in Git; `sync` renders only the thin discovery files Claude, Codex, Gemini, Copilot and Cursor expect, and `check` fails if a named truth source disappeared or an adapter was edited independently. Teams can switch tools without restating the project and without maintaining five competing plans.
543
+
544
+ ```text
545
+ fz project init # creates .forgezero/project.json
546
+ # edit the manifest and its named truth sources
547
+ fz project sync # generate vendor adapters
548
+ fz project check # CI/handoff drift gate
549
+ ```
550
+
551
+ ## Genesis is browser-first; recovery can remain headless
552
+
553
+ The CLI starts device authorization before the founder exists and opens the one-use invitation created by `fz bootstrap platform`. The browser creates the account, registers and freshly proves its passkey, confirms the account recovery phrase, then explicitly approves the displayed terminal code and continues to custody. The CLI receives only a bounded session. Custody phrases and passkey PRF output remain in the browser. After restart, each participating custodian opens only their own phrase envelope using an owner-only phrase file or stdin and contributes the share from their own authenticated, freshly proved session. No CLI process collects several custodians’ phrases. SSH remains transport and Git interoperability only; it is not a ForgeZero authentication or custody factor. Neither path creates a privileged server bypass.
554
+
555
+ ```text
556
+ fz genesis --mode 1-of-1
557
+ fz status
558
+ fz unlock --phrase-file /secure/offline-phrase.txt
559
+ ```
560
+
561
+ ## Use website operations from a project or an AI agent
562
+
563
+ Every UI operation is an API operation. `fz ui routes --json` discovers the exact actions allowed by the signed-in account’s current realm, lifecycle stage and grants from the API’s enforced matrix, so the CLI and AI agents carry no copied route list. `fz api` (also `fz ui`) executes authenticated JSON GET, POST, PUT, PATCH and DELETE without requiring a browser visit for ordinary work. Paths are forced onto the signed-in origin, query values are repeatable, bodies can be inline, stdin or a file, and server grants plus fresh-proof rules remain authoritative. `fz project init|sync|check` separately gives AI tools one Git-persisted project memory.
564
+
565
+ ```text
566
+ fz ui routes --json
318
567
  fz ui routes pipeline
319
568
  fz ui get /workspace/pipelines --query projectKey=my-project
320
- fz api post /workspace/pipelines/status \
321
- --data '{"pipelineKey":"pl_…","enabled":false}'
569
+ fz api post /workspace/pipelines/status --data '{"pipelineKey":"pl_…","enabled":false}'
322
570
  generate-request | fz api post /workspace/action --data -
323
571
  ```
324
572
 
325
- Only realm-relative paths are accepted, so the saved session cannot be forwarded
326
- to another origin. Inline JSON, stdin and JSON files are supported. Use
327
- `fz logout` to revoke the remote session and remove the local copy.
328
-
329
- `fz ui routes --json` reads the action catalog from the API's enforced access
330
- matrix. It lists only the current account's current realm, stage and grants, so
331
- developers and AI agents can discover the available control surface without a
332
- copied CLI command list or a visit to the website. Execute any listed action
333
- with `fz ui <method> <path>`; sensitive actions open the same fresh-proof flow
334
- as the website and replay the exact request once.
335
-
336
- ## Deployment definitions
337
-
338
- A repository may commit `.fz/deploy.json` with its own profiles, prerequisite
339
- checks, commands, and the exact secret names each step needs. ForgeZero does not
340
- choose a tenant's database, framework, or deploy shape. The agent validates the
341
- file before executing any command, prepares only the selected profile, and gives a
342
- step only the vault values it explicitly names. `await` returns the complete
343
- pipeline result; no polling service or persistent queue is required.
344
-
345
- Create and validate that file with the same public package that executes it:
346
-
347
- ```bash
348
- fz deploy catalog --channel production
349
- fz deploy init --profile app --software bun@1.3.14
350
- # Replace the explicit safe blockers with this project's release and health commands.
351
- fz deploy check
352
- fz deploy sync
353
- ```
354
-
355
- After sign-in, create and operate the durable pipeline from the same checkout.
356
- The project defaults to `.fz/config.json`; compute/profile attachments remain
357
- control-plane state rather than fields in the deploy file:
358
-
359
- ```bash
360
- fz deploy connect --provider github --repository acme/web \
361
- --clone-url https://github.com/acme/web.git --auth public \
362
- --target compute-eu@api --target compute-us@api
363
- fz deploy list
364
- fz deploy runs --pipeline <pipeline-key>
365
- fz deploy release --pipeline <pipeline-key> \
366
- --revision <full-40-character-commit> --wait
367
- ```
368
-
369
- `init` refuses to invent a generic release or health check: both generated steps
370
- exit non-zero until the project replaces them. `check` validates the published
371
- v2 schema and active software coordinates, then prints a formatting-independent
372
- semantic SHA-256 digest. The schema ships at
373
- `@forgezero/agent/schema/deploy-v2.json` and is served from
374
- `https://www.forgezero.net/schemas/deploy-v2.json`.
375
-
376
- Git is the only local-to-live synchronization mechanism. `sync` validates and
377
- prints that rule; it does not create a second mutable command copy in the API.
378
- The verified webhook identifies one exact commit, and a successful Agent result
379
- persists the definition digest so the Applications screen can prove which local
380
- contract became live.
381
-
382
- Catalog status is an admission boundary, not a suggestion. `testing` coordinates
383
- are visible in the development catalog for ForgeZero qualification but cannot be
384
- selected by any deploy file. A repository cannot promote software by calling
385
- itself development; only a reviewed catalog change to `active` unlocks it.
386
-
387
- The daemon owns source checkout and command execution. Bootstrap explicitly
388
- awaits release one because the API does not exist yet, then the Agent consumes a
389
- one-use platform enrolment capability. There is no branch watcher. Every normal
390
- platform or tenant release is one durable API delivery atomically expanded to
391
- one row for every independently attached compute target. Release-scoped steps
392
- run on one target elected by stable target ordering, never on a user-declared
393
- coordinator:
394
- `pending` is written before dispatch, `running` and a fenced lease before project
395
- code, and only an awaited successful pipeline writes `deployed`. An expired
396
- claim can be recovered; its stale token cannot renew or finish.
397
-
398
- Compute replacement uses the same outbound pattern through
399
- `@forgezero/agent/migration-pull`: claim one action for this exact compute,
400
- renew its fencing lease while the awaited function runs, and acknowledge the
401
- result before accepting more work. The public function accepts the executor as
402
- an async callback so an embedding Agent can keep privilege and OS policy outside
403
- the transport. Node evidence is deliberately local-only; it cannot claim
404
- Agency quorum, replication completion, seed residency, edge exclusion or
405
- Cloudflare route existence on behalf of the controller.
406
-
407
- The managed daemon uses `@forgezero/agent/lifecycle-helper` as that executor.
408
- It is a separate root service behind a group-scoped Unix socket and accepts only
409
- fixed lifecycle operations. Unit names and loopback health endpoints come from
410
- a root-owned profile; a signed claim cannot supply a command or path. For a
411
- cross-network database member, the common installer enrolls the headless WARP
412
- client from systemd credentials materialized only in `/run`. Readiness requires
413
- WARP to be connected and the controller-selected private peer IP and database
414
- port to be reachable. Database traffic is never exposed through a public IP,
415
- public hostname, or inbound firewall rule.
416
-
417
- The same package also runs the identity-only Metal Agent. It initiates outbound
418
- hybrid-signed HTTPS and requires request-bound PQ-sealed responses while pulling
419
- only claims assigned to its enrolled hostname, then passes
420
- the fixed claim over a local Unix socket to a narrowly privileged root helper.
421
- The helper can materialize the audited QEMU profile; it cannot clone a project,
422
- read Vault data, accept arbitrary commands, or retain tenant credentials. Root
423
- SSH is an operator-only platform recovery path, not the normal tenant
424
- dispatch mechanism.
425
-
426
- New guests also call this same public `fz agent install --apply --enrol` path
427
- from cloud-init. Metal provisioning does not carry a second handwritten Agent
428
- unit or deployment runner, so platform and tenant guests cannot drift at that
429
- foundation boundary.
430
-
431
- Shutdown has one process-wide deadline. New deployment claims and background
432
- sync stop first, claimed work drains under its lease fence, and only then do the
433
- queues and application socket close. Vault/attestation calls or a stale local
434
- socket cannot consume systemd's longer stop timeout: exceeding the Agent deadline
435
- is reported and exits non-zero instead of being silently killed midway by PID 1.
436
-
437
- Repository read authorization is explicit per pipeline: public HTTPS, the
438
- compute's systemd-sealed SSH deploy key, or a fine-grained HTTPS token selected
439
- by a project-vault secret name. A signed claim contains the mode and secret name
440
- only. The agent resolves the value from its scoped memory cache, limits the Git
441
- header to the repository origin, never writes the token into a command, and
442
- never exposes it to tenant pipeline steps. These provider-neutral modes are the
443
- complete contract; a GitHub App is not a missing dependency and would be added
444
- later only as an explicit provider-specific mode with expiry and revocation tests.
445
-
446
- An operator may also force a deployment and await the complete result over the
447
- private control socket:
448
-
449
- ```bash
450
- fz-agent deploy --revision=<full-40-character-commit> --release-executor
451
- fz-agent status
452
- fz-agent pause
453
- fz-agent pause-key --key=project:production
454
- fz-agent stop-key --key=project:production # running finishes; pending work is removed
455
- fz-agent start-key --key=project:production
456
- fz-agent cancel --id=q_42
457
- ```
458
-
459
- The node seed and read-only Git private key are loaded with
460
- `LoadCredentialEncrypted=`. Their encrypted, host-bound blobs persist under
461
- `/etc/forgezero/creds`; decrypted values exist only in the service's private
462
- `$CREDENTIALS_DIRECTORY`. Platform bootstrap has no second clone/build path.
463
- Bootstrap records the forge's SSH host key during the attended access check;
464
- the daemon uses `StrictHostKeyChecking=yes` and never accepts a new host key by
465
- itself.
466
-
467
- Full documentation: **https://www.forgezero.net/docs/agent**
468
-
469
- ## Licence
470
-
471
- MIT. Part of [ForgeZero](https://www.forgezero.net) — secrets, attested compute and
472
- deploys.
573
+ ## What changes for an application
574
+
575
+ Nothing. With no agent, this needs FORGEZERO_API_KEY in the environment. With the agent, it does not — and the key that would have been on the box does not exist. `@forgezero/vault` prefers the socket automatically.
576
+
577
+ ```text
578
+ import { ForgeZero } from '@forgezero/vault';
579
+
580
+ const fz = new ForgeZero({ project: 'altpilot', environment: 'production' });
581
+ await fz.get('STRIPE_KEY');
582
+ ```
583
+
584
+ ## A local copy, not a cache
585
+
586
+ The agent holds the whole assigned project across all of its environments, not just what has already been read. Each application still supplies its environment and cannot cross the enrolled project boundary. That is the difference between surviving an outage and not: a read-through cache lacks the never-before-read value precisely when the platform is unreachable. The cost is that a compromised guest exposes everything in the enrolled project rather than only what was read — bounded by the project and by SEV-SNP keeping the host out of guest memory.
587
+
588
+ ## Local access is explicit Unix membership
589
+
590
+ The socket is mode 0660 in the dedicated forgezero-vault group. A service account must be deliberately added to that group before it can read the project replica; unrelated local users and the credential-free deployment runner cannot connect. Mode 0600 would make the advertised app integration unusable, while a world-readable socket would hand the vault to every process on the guest.
591
+
592
+ ## Never on disk
593
+
594
+ A cache file would hand an attacker with filesystem access every secret this guest has ever held, which is precisely the artefact this design exists to remove. A restart re-fetches. There is no version of "just persist it, it is encrypted" that survives the key also being on the box.
595
+
596
+ ## Invalidated by cursor, and refused when stale
597
+
598
+ A TTL alone means a rotated secret keeps working for the length of the TTL the window rotation exists to close. The agent polls a change cursor and drops what moved, so a rotation propagates regardless of TTL. And if sync has not succeeded within the staleness bound, a read is refused rather than served: an application that receives a revoked credential and succeeds with it is worse off than one that receives an error, because the error is visible.
599
+
600
+ ## Two postures, decided by the hardware
601
+
602
+ An SNP guest can produce an attestation report and the platform can refuse a node whose measurement is wrong. Anything else authenticates with its enrolment token and a hybrid Ed25519 + ML-DSA-65 signature. Both are real: enrolled is still strictly better than an API key in the application, because the key never leaves the agent, rotation reaches every process, and the socket is filesystem-scoped.
603
+
604
+ ```text
605
+ attested /dev/sev-guest present -> hardware report
606
+ enrolled no SNP device -> enrolment token + hybrid signature
607
+ ```
608
+
609
+ ## The app socket cannot impersonate the node
610
+
611
+ The group-scoped application socket exposes only replica get, held and sync operations. Node identity, hybrid signing and attestation stay inside the Agent's outbound clients. Every Agent call requires HTTPS outside loopback, signs a one-use hybrid ML-KEM-768 + X25519 recipient and refuses a successful response that is not sealed back to that request. A process allowed to read one environment therefore cannot ask the Agent to sign a deployment, heartbeat or whole-project replication request and act as the node.
612
+
613
+ ```text
614
+ get one secret in the selected environment
615
+ sync invalidate rotated values
616
+ held names held in the selected environment
617
+
618
+ identity/sign/attest refused on the application socket
619
+ ```
620
+
621
+ Full rendered documentation: https://www.forgezero.net/docs/agent