@forgezero/agent 0.1.17 → 0.1.19

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 CHANGED
@@ -103,23 +103,19 @@ acknowledgement. The short-lived token is therefore not an unsigned Agent path.
103
103
  ## The socket interface
104
104
 
105
105
  ```
106
- identity who this node is
107
- sign sign a request with the node key
108
- attest a hardware report, or a refusal — never a fake
109
106
  get one secret
110
107
  sync what changed since a cursor
111
108
  held what this guest is holding, by name only
112
109
  ```
113
110
 
114
- The vault socket never accepts commands or deployment definitions. Deployment
115
- enters through the root-only control socket or the signed outbound claim path,
116
- then the deployment manager validates the checked-in definition and submits it
117
- to the common keyed queue. Keeping execution off the vault socket prevents a
118
- compromised application from turning secret-read access into a local shell.
119
-
120
- `attest` **refuses** when no source is configured rather than returning
121
- something attestation-shaped. An operator who believes they have an attestation
122
- when nothing produced one is worse off than one told plainly it is unavailable.
111
+ The application Vault socket never accepts identity, signing, attestation,
112
+ commands or deployment definitions. The Agent signs and attests only inside its
113
+ own outbound clients. Otherwise a compromised application could ask for a valid
114
+ node signature over a deployment or whole-project sync request and impersonate
115
+ the Agent without ever extracting its key. Deployment enters through the
116
+ root-only control socket or signed outbound claim path, then the deployment
117
+ manager validates the checked-in definition and submits it to the common keyed
118
+ queue.
123
119
 
124
120
  ## Deployment definitions
125
121
 
package/dist/cache.d.ts CHANGED
@@ -60,7 +60,8 @@ export interface CacheOptions {
60
60
  * Every name in the assigned scope. Present means REPLICA mode.
61
61
  *
62
62
  * Absent means the old behaviour — fetch on demand, hold what was asked for.
63
- * Present means the agent pulls the whole project+environment at startup and
63
+ * Present means the agent pulls the whole bound project across every
64
+ * environment at startup and
64
65
  * on every resync, so an application reads with no round trip and keeps
65
66
  * working while the platform is unreachable.
66
67
  *
package/dist/fz-agent.js CHANGED
@@ -255,6 +255,13 @@ function startNodeVaultSync(cache, options = {}) {
255
255
  }
256
256
 
257
257
  // src/socket.ts
258
+ var APPLICATION_VAULT_OPS = new Set(["get", "held", "sync"]);
259
+ function handleApplicationRequest(options, request) {
260
+ if (!APPLICATION_VAULT_OPS.has(request?.op)) {
261
+ return Promise.resolve(refuse("APP_OPERATION_REFUSED", "The application Vault socket serves scoped replica reads only; node signing and attestation are internal."));
262
+ }
263
+ return handleRequest(options, request);
264
+ }
258
265
  var MAX_LINE_BYTES = 64 * 1024;
259
266
  function handleRequest(options, request) {
260
267
  switch (request?.op) {
@@ -390,7 +397,7 @@ async function respond(options, socket, line) {
390
397
  return;
391
398
  let response;
392
399
  try {
393
- response = await handleRequest(options, JSON.parse(line));
400
+ response = await handleApplicationRequest(options, JSON.parse(line));
394
401
  } catch (cause) {
395
402
  response = refuse("MALFORMED", cause instanceof Error ? cause.message : "Malformed request.");
396
403
  }
@@ -1516,7 +1523,7 @@ ExecStartPre=+/usr/bin/rm -f ${DEPLOYMENT_RUNNER_SOCKET}
1516
1523
  ExecStart=${bin} deploy-runner --root=${root} --home=${root}/runner-home
1517
1524
  ExecStartPost=+/usr/bin/chown ${agentUser}:${agentUser} ${DEPLOYMENT_RUNNER_SOCKET}
1518
1525
  ExecStartPost=+/usr/bin/chmod 0600 ${DEPLOYMENT_RUNNER_SOCKET}
1519
- ExecStartPost=+/usr/bin/chown root:root /run/forgezero-deploy
1526
+ ExecStartPost=+/usr/bin/chown root:${VAULT_GROUP} /run/forgezero-deploy
1520
1527
  ExecStopPost=+/usr/bin/rm -f ${DEPLOYMENT_RUNNER_SOCKET}
1521
1528
  Restart=always
1522
1529
  RestartSec=2
@@ -2711,7 +2718,7 @@ async function applyMetalIsolation(profile, exec = defaultExec) {
2711
2718
  }
2712
2719
 
2713
2720
  // src/version.ts
2714
- var VERSION = "0.1.17";
2721
+ var VERSION = "0.1.19";
2715
2722
 
2716
2723
  // src/index.ts
2717
2724
  function loadOrCreateSeed(path) {
@@ -3215,6 +3222,7 @@ export {
3215
3222
  loadOrCreateSeed,
3216
3223
  loadGuestBinding,
3217
3224
  handleRequest,
3225
+ handleApplicationRequest,
3218
3226
  guestNameFor,
3219
3227
  enrolGuestIdentity,
3220
3228
  createSystemdDeploymentSecrets,
package/dist/fz.js CHANGED
@@ -217,7 +217,7 @@ ExecStartPre=+/usr/bin/rm -f ${DEPLOYMENT_RUNNER_SOCKET}
217
217
  ExecStart=${bin} deploy-runner --root=${root} --home=${root}/runner-home
218
218
  ExecStartPost=+/usr/bin/chown ${agentUser}:${agentUser} ${DEPLOYMENT_RUNNER_SOCKET}
219
219
  ExecStartPost=+/usr/bin/chmod 0600 ${DEPLOYMENT_RUNNER_SOCKET}
220
- ExecStartPost=+/usr/bin/chown root:root /run/forgezero-deploy
220
+ ExecStartPost=+/usr/bin/chown root:${VAULT_GROUP} /run/forgezero-deploy
221
221
  ExecStopPost=+/usr/bin/rm -f ${DEPLOYMENT_RUNNER_SOCKET}
222
222
  Restart=always
223
223
  RestartSec=2
@@ -774,7 +774,7 @@ async function resolveIdentity(selector, socketPath) {
774
774
  }
775
775
 
776
776
  // src/version.ts
777
- var VERSION = "0.1.17";
777
+ var VERSION = "0.1.19";
778
778
 
779
779
  // src/cli/index.ts
780
780
  var DEFAULT_MODE = THRESHOLD_MODES[0].id;
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import { type NodeKeyPair } from '@forgezero/runtime/identity';
3
3
  import { startAgent, type AgentOptions, type AttestationSource } from './socket';
4
4
  import type { SecretCache } from './cache';
5
5
  export { VERSION } from './version';
6
- export { startAgent, handleRequest } from './socket';
6
+ export { startAgent, handleRequest, handleApplicationRequest } from './socket';
7
7
  export type { AgentOptions, AttestationSource, Request, Response } from './socket';
8
8
  export { createSecretCache, CacheError } from './cache';
9
9
  export type { SecretCache, CacheOptions } from './cache';
@@ -250,7 +250,7 @@ ExecStartPre=+/usr/bin/rm -f ${DEPLOYMENT_RUNNER_SOCKET}
250
250
  ExecStart=${bin} deploy-runner --root=${root} --home=${root}/runner-home
251
251
  ExecStartPost=+/usr/bin/chown ${agentUser}:${agentUser} ${DEPLOYMENT_RUNNER_SOCKET}
252
252
  ExecStartPost=+/usr/bin/chmod 0600 ${DEPLOYMENT_RUNNER_SOCKET}
253
- ExecStartPost=+/usr/bin/chown root:root /run/forgezero-deploy
253
+ ExecStartPost=+/usr/bin/chown root:${VAULT_GROUP} /run/forgezero-deploy
254
254
  ExecStopPost=+/usr/bin/rm -f ${DEPLOYMENT_RUNNER_SOCKET}
255
255
  Restart=always
256
256
  RestartSec=2
@@ -250,7 +250,7 @@ ExecStartPre=+/usr/bin/rm -f ${DEPLOYMENT_RUNNER_SOCKET}
250
250
  ExecStart=${bin} deploy-runner --root=${root} --home=${root}/runner-home
251
251
  ExecStartPost=+/usr/bin/chown ${agentUser}:${agentUser} ${DEPLOYMENT_RUNNER_SOCKET}
252
252
  ExecStartPost=+/usr/bin/chmod 0600 ${DEPLOYMENT_RUNNER_SOCKET}
253
- ExecStartPost=+/usr/bin/chown root:root /run/forgezero-deploy
253
+ ExecStartPost=+/usr/bin/chown root:${VAULT_GROUP} /run/forgezero-deploy
254
254
  ExecStopPost=+/usr/bin/rm -f ${DEPLOYMENT_RUNNER_SOCKET}
255
255
  Restart=always
256
256
  RestartSec=2
package/dist/provision.js CHANGED
@@ -110,7 +110,7 @@ ExecStartPre=+/usr/bin/rm -f ${DEPLOYMENT_RUNNER_SOCKET}
110
110
  ExecStart=${bin} deploy-runner --root=${root} --home=${root}/runner-home
111
111
  ExecStartPost=+/usr/bin/chown ${agentUser}:${agentUser} ${DEPLOYMENT_RUNNER_SOCKET}
112
112
  ExecStartPost=+/usr/bin/chmod 0600 ${DEPLOYMENT_RUNNER_SOCKET}
113
- ExecStartPost=+/usr/bin/chown root:root /run/forgezero-deploy
113
+ ExecStartPost=+/usr/bin/chown root:${VAULT_GROUP} /run/forgezero-deploy
114
114
  ExecStopPost=+/usr/bin/rm -f ${DEPLOYMENT_RUNNER_SOCKET}
115
115
  Restart=always
116
116
  RestartSec=2
package/dist/socket.d.ts CHANGED
@@ -2,7 +2,7 @@ import { type Server } from 'node:net';
2
2
  import { signRequest, type NodeKeyPair } from '@forgezero/runtime/identity';
3
3
  import type { SecretCache } from './cache';
4
4
  /**
5
- * The signing socket — why the application on managed compute holds nothing.
5
+ * The application Vault socket — why managed code holds no remote credential.
6
6
  *
7
7
  * `@forgezero/vault` discovers `/run/forgezero/vault.sock` and prefers it over
8
8
  * `FORGEZERO_API_KEY`, so moving an app onto managed compute is DELETING an
@@ -10,20 +10,14 @@ import type { SecretCache } from './cache';
10
10
  * for a long time nothing was: the client knew how to prefer the socket and the
11
11
  * agent was a version constant.
12
12
  *
13
- * ## The key never leaves
13
+ * ## The node identity never becomes an application signing oracle
14
14
  *
15
- * There is no `getKey` operation and there is deliberately no way to add one:
16
- * the socket signs, and signing is all it does. An application that could ask
17
- * for the key is an application that holds the key the moment it is compromised,
18
- * which is the entire difference between this and an API key in the environment.
19
- *
20
- * ## Why a signature and not a token
21
- *
22
- * A token would have to be handed to the caller, which puts it in a process we
23
- * do not control, in memory we do not own, for as long as the process lives. A
24
- * signature is bound to one method, one path and one body digest by
25
- * `canonicalString`, so a caller that captures one cannot reuse it for anything
26
- * else — and it expires with the clock-skew window rather than with the process.
15
+ * The Agent hybrid-signs its own outbound HTTPS requests internally. This
16
+ * socket never exposes `identity`, `sign` or `attest`: otherwise any tenant
17
+ * process admitted to the Vault group could ask the Agent to sign a deployment,
18
+ * heartbeat or whole-project replication request and act as the node without
19
+ * ever extracting its key. Applications receive only the environment they ask
20
+ * for from the already-bound, memory-only project replica.
27
21
  *
28
22
  * ## Peer credentials, not a shared secret
29
23
  *
@@ -99,6 +93,8 @@ export type Response = {
99
93
  message: string;
100
94
  };
101
95
  };
96
+ /** The real Unix-socket boundary; privileged machine operations stay in-process. */
97
+ export declare function handleApplicationRequest(options: AgentOptions, request: Request): Promise<Response>;
102
98
  /**
103
99
  * Produces a hardware attestation report for this guest.
104
100
  *
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  /** One package version shared by both public binaries. Pinned to package.json by tests. */
2
- export declare const VERSION = "0.1.17";
2
+ export declare const VERSION = "0.1.19";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "//": "Publishing happens from an operator's machine, not CI \u2014 CLAUDE.md records that the absence of CI is deliberate. npm's `provenance` attests a tarball was built by a recognised CI provider from a named commit, so it cannot be produced here: it was set, and the first publish failed with `Automatic provenance generation not supported for provider: null`. A setting that can never be satisfied is worse than none, because it reads as a guarantee nobody is getting. Restore it the day this publishes from CI, and not before.",
3
3
  "name": "@forgezero/agent",
4
- "version": "0.1.17",
4
+ "version": "0.1.19",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "check": "tsc --noEmit",