@agentvault/claude-bridge 0.3.4 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=plan-c-crux-harness.d.ts.map
@@ -0,0 +1,25 @@
1
+ import type { ServiceSpec } from "./spec.js";
2
+ export interface ServiceBackend {
3
+ install(spec: ServiceSpec): void;
4
+ uninstall(label: string): void;
5
+ status(label: string): {
6
+ loaded: boolean;
7
+ detail: string;
8
+ };
9
+ }
10
+ export interface BackendDeps {
11
+ home: string;
12
+ uid: number;
13
+ user: string;
14
+ exec: (cmd: string, args: string[]) => {
15
+ code: number;
16
+ stdout: string;
17
+ };
18
+ writeFile: (path: string, data: string) => void;
19
+ mkdir: (path: string) => void;
20
+ rm: (path: string) => void;
21
+ exists: (path: string) => boolean;
22
+ }
23
+ export declare function defaultDeps(): BackendDeps;
24
+ export declare function selectBackend(platform: NodeJS.Platform, deps?: BackendDeps): ServiceBackend;
25
+ //# sourceMappingURL=backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/service/backend.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IACjC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5D;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACxE,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CACnC;AAED,wBAAgB,WAAW,IAAI,WAAW,CAmBzC;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,cAAc,CAU3F"}
@@ -0,0 +1,17 @@
1
+ import type { ServiceSpec } from "./spec.js";
2
+ import type { BackendDeps, ServiceBackend } from "./backend.js";
3
+ /** Render a launchd LaunchAgent plist for a bridge ServiceSpec. Pure string. */
4
+ export declare function renderLaunchdPlist(spec: ServiceSpec): string;
5
+ export declare class LaunchdBackend implements ServiceBackend {
6
+ private deps;
7
+ constructor(deps: BackendDeps);
8
+ private plistPath;
9
+ private domain;
10
+ install(spec: ServiceSpec): void;
11
+ uninstall(label: string): void;
12
+ status(label: string): {
13
+ loaded: boolean;
14
+ detail: string;
15
+ };
16
+ }
17
+ //# sourceMappingURL=launchd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launchd.d.ts","sourceRoot":"","sources":["../../src/service/launchd.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAShE,gFAAgF;AAChF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAkC5D;AAED,qBAAa,cAAe,YAAW,cAAc;IACvC,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,WAAW;IAErC,OAAO,CAAC,SAAS;IAGjB,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAWhC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAM9B,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;CAI3D"}
@@ -0,0 +1,18 @@
1
+ import type { BridgeConfig } from "../config.js";
2
+ export interface ServiceSpec {
3
+ label: string;
4
+ programArgs: string[];
5
+ env: Record<string, string>;
6
+ workingDir: string;
7
+ logOut: string;
8
+ logErr: string;
9
+ keepAliveUnlessCleanExit: boolean;
10
+ runAtLoad: boolean;
11
+ }
12
+ export interface BuildSpecOptions {
13
+ nodePath: string;
14
+ entrypoint: string;
15
+ home: string;
16
+ }
17
+ export declare function buildServiceSpec(cfg: BridgeConfig, opts: BuildSpecOptions): ServiceSpec;
18
+ //# sourceMappingURL=spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../src/service/spec.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,wBAAwB,EAAE,OAAO,CAAC;IAClC,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAID,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,gBAAgB,GAAG,WAAW,CAwBvF"}
@@ -0,0 +1,11 @@
1
+ import { type ServiceBackend } from "./backend.js";
2
+ export interface ServiceCmdDeps {
3
+ backend: ServiceBackend;
4
+ entrypoint: string;
5
+ log: (msg: string) => void;
6
+ }
7
+ /** Handle `agentvault-claude-bridge <install|uninstall|status|logs>` before boot.
8
+ * Returns true when handled (caller should exit). Secrets are never placed on
9
+ * the service command line — config flows via the plist env; the token is omitted. */
10
+ export declare function maybeRunServiceSubcommand(argv: string[], env: NodeJS.ProcessEnv, deps?: ServiceCmdDeps): boolean;
11
+ //# sourceMappingURL=subcommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subcommand.d.ts","sourceRoot":"","sources":["../../src/service/subcommand.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAElE,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,cAAc,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5B;AAQD;;uFAEuF;AACvF,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,IAAI,CAAC,EAAE,cAAc,GACpB,OAAO,CA+CT"}
@@ -0,0 +1,19 @@
1
+ import type { ServiceSpec } from "./spec.js";
2
+ import type { BackendDeps, ServiceBackend } from "./backend.js";
3
+ /** Render a systemd --user service unit for a bridge ServiceSpec. Pure string.
4
+ * Restart=on-failure + SuccessExitStatus=0 is the KeepAlive={SuccessfulExit:false}
5
+ * equivalent: a clean exit(0) (revoked device) is treated as success => NOT
6
+ * restarted; a non-zero crash is restarted. WantedBy=default.target is RunAtLoad. */
7
+ export declare function renderSystemdUnit(spec: ServiceSpec): string;
8
+ export declare class SystemdBackend implements ServiceBackend {
9
+ private deps;
10
+ constructor(deps: BackendDeps);
11
+ private unitPath;
12
+ install(spec: ServiceSpec): void;
13
+ uninstall(label: string): void;
14
+ status(label: string): {
15
+ loaded: boolean;
16
+ detail: string;
17
+ };
18
+ }
19
+ //# sourceMappingURL=systemd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"systemd.d.ts","sourceRoot":"","sources":["../../src/service/systemd.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAkBhE;;;sFAGsF;AACtF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAsB3D;AAED,qBAAa,cAAe,YAAW,cAAc;IACvC,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,WAAW;IAErC,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAmBhC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAQ9B,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;CAQ3D"}
package/dist/session.d.ts CHANGED
@@ -64,6 +64,13 @@ export interface SessionOpts {
64
64
  permissionMode?: "auto" | "acceptEdits" | "bypassPermissions";
65
65
  /** AgentVault data directory — fenced off from worker tool access. */
66
66
  dataDir?: string;
67
+ /** Slice 2 Plan B — audit self-report context. When present and the turn is
68
+ * armed, each tool decision is fire-and-forget reported to /audit/entries. */
69
+ roomId?: string;
70
+ agentId?: string | null;
71
+ apiUrl?: string;
72
+ /** Lazy getter so a JWT refreshed after construction is still picked up. */
73
+ deviceJwt?: () => string | null;
67
74
  }
68
75
  export declare class PersistentClaudeSession {
69
76
  private opts;
@@ -73,16 +80,25 @@ export declare class PersistentClaudeSession {
73
80
  * message is handed to the model so the say tool routes to the right place. */
74
81
  private activeReply?;
75
82
  /**
76
- * Per-turn state for the #416 DM auto-reply fallback.
83
+ * Per-turn state for the #416 DM auto-reply fallback and the worker tool gate.
77
84
  *
78
- * LOAD-BEARING for the worker tool gate: `currentAutoReply` is true ONLY on
79
- * owner DM turns (`autoReplyOnText:true` from wireBridge) and false on room
80
- * turns (`autoReplyOnText:false`). `makeWorkerPermission` calls
81
- * `isOwnerTurn: () => this.currentAutoReply` to decide whether tools are
82
- * allowed. A room-origin turn MUST keep this false or untrusted input gains
83
- * full tool access. See worker-permission.test.ts for the covering assertion.
85
+ * LOAD-BEARING (one of two tool-enabling signals): `currentAutoReply` is true
86
+ * ONLY on owner DM turns (`autoReplyOnText:true` from wireBridge) and false on
87
+ * room turns (`autoReplyOnText:false`). The gate allows tools when EITHER
88
+ * `currentAutoReply` (owner DM) OR `currentArmedGetter()` (armed room turn, Slice 2)
89
+ * is true. A room-origin turn MUST keep `currentAutoReply` false; an unarmed
90
+ * room turn's `currentArmedGetter()` MUST return false or untrusted input gains full
91
+ * tool access. See worker-permission.test.ts for the covering assertion.
84
92
  */
85
93
  private currentAutoReply;
94
+ /** Per-turn: a LIVE getter answering "is this turn's room armed right now?"
95
+ * (Slice 2 Plan C D5). Independent of currentAutoReply (which is owner-DM-only
96
+ * and also drives the #416 plain-text fallback). The gate allows tools when
97
+ * EITHER currentAutoReply OR this getter is true. CRITICAL: the gate CALLS this
98
+ * getter at each tool-call decision (not a boolean captured once), so a mid-turn
99
+ * disarm denies the very next tool call. wireBridge binds it to the ArmingState
100
+ * for this turn's room; an unarmed room turn's getter returns false. */
101
+ private currentArmedGetter;
86
102
  private saidThisTurn;
87
103
  private turnText;
88
104
  /** In-process room MCP server — hoisted so buildSdkOptions can reference it. */
@@ -94,9 +110,15 @@ export declare class PersistentClaudeSession {
94
110
  * reply): if the turn produces assistant text but never calls the say tool,
95
111
  * send that text as the reply instead of silently dropping it (#416). Rooms
96
112
  * omit this so the agent can still choose silence.
113
+ * @param opts.armed — for armed room turns (Slice 2 Plan C): a LIVE getter that
114
+ * the gate calls at each tool-call decision. When it returns true this room
115
+ * turn is granted full worker tool access (same as an owner DM turn). Reading
116
+ * it live (not capturing a boolean) is what lets a mid-turn disarm deny the
117
+ * next tool call. Bound by wireBridge to the ArmingState for this turn's room.
97
118
  */
98
119
  push(text: string, reply?: ReplySink, opts?: {
99
120
  autoReplyOnText?: boolean;
121
+ armed?: () => boolean;
100
122
  }): void;
101
123
  /** Route a say-tool message to the reply bound to the in-flight message, falling
102
124
  * back to opts.onSay. This is what closes the DM→room leak: the destination is
@@ -8,7 +8,17 @@ import type { CanUseTool, HookCallbackMatcher } from "@anthropic-ai/claude-agent
8
8
  */
9
9
  export declare function makeWorkerPreToolUseHook(opts: {
10
10
  dataDir: string;
11
- isOwnerTurn: () => boolean;
11
+ isToolTurn: () => boolean;
12
+ /** Slice 2 Plan B: true when this turn comes from an armed room. When set,
13
+ * each tool decision (allow AND deny) is forwarded to onToolDecision for
14
+ * audit self-reporting. room_say is always excluded (it is the reply
15
+ * mechanism, not a user-initiated tool action). */
16
+ isArmedTurn?: () => boolean;
17
+ onToolDecision?: (d: {
18
+ tool: string;
19
+ decision: "allow" | "deny";
20
+ reason?: string;
21
+ }) => void;
12
22
  }): HookCallbackMatcher;
13
23
  /**
14
24
  * SECONDARY (defense-in-depth): the canUseTool callback covers the SDK's "ask"
@@ -17,6 +27,6 @@ export declare function makeWorkerPreToolUseHook(opts: {
17
27
  */
18
28
  export declare function makeWorkerPermission(opts: {
19
29
  dataDir: string;
20
- isOwnerTurn: () => boolean;
30
+ isToolTurn: () => boolean;
21
31
  }): CanUseTool;
22
32
  //# sourceMappingURL=worker-permission.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentvault/claude-bridge",
3
- "version": "0.3.4",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "description": "AgentVault Claude Bridge — daemon for bridging a Claude agent into secure E2E-encrypted AgentVault 1:1 direct messages and rooms.",
6
6
  "main": "dist/index.js",
@@ -8,6 +8,9 @@
8
8
  "bin": {
9
9
  "agentvault-claude-bridge": "dist/index.js"
10
10
  },
11
+ "engines": {
12
+ "node": ">=18"
13
+ },
11
14
  "files": [
12
15
  "dist",
13
16
  "README.md",