@securecoms/agent-bridge 0.26.4 → 0.26.6

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,23 @@
1
+ export type RoomToolClass = "room_safe_read" | "owner_credential" | "egress" | "side_effect";
2
+ /** §7A.1a, verbatim. A tool carries every class that applies; the most
3
+ * restrictive governs. `READ_ONLY_TOOLS` in the runtime is NOT this table:
4
+ * it says whether an implementation writes, not whose credential it spends
5
+ * or where it sends data (audit H-4). */
6
+ export declare const TOOL_ROOM_CLASSES: Readonly<Record<string, readonly RoomToolClass[]>>;
7
+ /** Edge statuses whose rows are channel MEMBERS for attribution and the
8
+ * existing roster consumers (today's set). The wider rows feed
9
+ * classification only. */
10
+ export declare const LIVE_MEMBER_STATUSES: ReadonlySet<string>;
11
+ /** A row that is a channel member: a live status (or an older backend with no
12
+ * status) and not a leaf row (audit M-B2: a departed member still holding a
13
+ * leaf counts for the class, never as a member). */
14
+ export declare function isLiveRow(r: {
15
+ status?: string;
16
+ left_but_in_group?: boolean | null;
17
+ }): boolean;
18
+ /** §7A.4 (1): a room is cross-org if ANY row's org differs from the agent
19
+ * owner's, leaf rows included. A row with no claim (an older backend, a
20
+ * member with no edge) makes the class unknown, which grants nothing (§7A.5). */
21
+ export declare function roomIsCrossOrg(rows: ReadonlyArray<{
22
+ is_same_org_as_agent_owner?: boolean | null;
23
+ }>): boolean | null;
@@ -35,6 +35,28 @@ export interface LocalReport {
35
35
  has_search_key: boolean;
36
36
  has_llm_key: boolean;
37
37
  legacy_memory: LegacyMemoryReport[];
38
+ /** §B.4 counts; undefined when the runtime reported none or the block was malformed. */
39
+ secret_paths?: SecretPathsReport;
40
+ }
41
+ /**
42
+ * §B.4: how many server-named secret paths in the managed config are inside
43
+ * the secrets directory, owner-allowlisted, or outside it, and the runtime's
44
+ * mode. Rebuilt field by field from the runtime's file: numbers and one enum,
45
+ * so no path (the owner's `allowed_secret_paths` sits in the same file) can
46
+ * ride along to the backend.
47
+ */
48
+ export interface SecretPathsReport {
49
+ mode: "report" | "enforce";
50
+ inside: number;
51
+ allowlisted: number;
52
+ outside: number;
53
+ /** `sqlite` (H1) is absent from a runtime that predates it; absent means unknown, not zero. */
54
+ outside_by_field: {
55
+ headers_file: number;
56
+ postgres_url_file: number;
57
+ search_key_file: number;
58
+ sqlite?: number;
59
+ };
38
60
  }
39
61
  export type LegacyMemoryKind = "global-memory" | "conversation-history" | "captured-memory";
40
62
  export declare const LEGACY_MEMORY_FACT_MAX_BYTES = 1024;
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const BRIDGE_VERSION = "0.26.4";
1
+ export declare const BRIDGE_VERSION = "0.26.6";
@@ -1,80 +1,3 @@
1
- /**
2
- * Agent-facing keepalive WebSocket (/v1/ws).
3
- *
4
- * Adds a single persistent bidirectional socket for the AGENT⇄DAEMON hop,
5
- * modeled on AgentVault's keepalive WS (token in `?token=` query OR
6
- * `Authorization: Bearer`). This replaces the curl/long-poll loop: the agent
7
- * receives live inbound messages as JSON frames and sends/reports status over
8
- * the same socket.
9
- *
10
- * Protocol (all frames are JSON text):
11
- * Daemon → agent:
12
- * { "type":"message", channel_id, message_id, sender_id, text, ts,
13
- * authorization:{version,audience,sender_membership,tool_grants} } // inbound, decrypted
14
- * { "type":"sent", message_id } // ack of a send
15
- * { "type":"ok" } // ack of a status report
16
- * { "type":"error", error, message, detail? } // canonical codes (see errors.ts):
17
- * // channel_pending | rate_limited |
18
- * // invalid_request | agent_paused |
19
- * // send_forbidden (those two are
20
- * // TERMINAL: the in_reply_to message
21
- * // is acked by the daemon, no retry) |
22
- * // group_superseded (NOT terminal:
23
- * // the reply is republished after
24
- * // the agent rejoins)
25
- * Agent → daemon:
26
- * { "type":"send", channel_id, text?, a2a?, idempotency_key?,
27
- * in_reply_to? } // exactly one of text | a2a. SEC-06 #18: in_reply_to
28
- * // and/or idempotency_key make the send idempotent — a
29
- * // deterministic keyed message_id and a durable reply
30
- * // intent written before the publish, so a retry or a
31
- * // redelivery republishes the SAME reply
32
- * { "type":"status", channel_id, state, detail? }
33
- * { "type":"ack", message_id } // confirms a delivered `message` was consumed
34
- * { "type":"nack", message_id, reason? } // final-wave I1(b): THIS message's turn
35
- * // failed — requeued behind a backoff; the
36
- * // socket and other channels' turns stay up
37
- * { "type":"hello", features? } // → { "type":"hello", features:["nack"] }; a
38
- * // runtime nacks only after seeing "nack" here
39
- * { "type":"action_begin", channel_id } // → { "type":"action_begun", run_id }
40
- * { "type":"action_start", run_id, node_type, title, parent_id? } // → { "type":"action_started", node_id }
41
- * { "type":"action_update", run_id, node_id, status?, detail? } // → { "type":"ok" }
42
- * { "type":"action_finish", run_id, node_id, status, detail? } // → { "type":"ok" }
43
- * { "type":"action_settle", run_id, result_message_id? } // → { "type":"action_settled", run_id }
44
- *
45
- * Inbound delivery is at-least-once. A delivered `message` is held in-flight
46
- * until the agent sends a matching `ack`; if the socket drops first, the frame
47
- * is re-buffered and redelivered to the next consumer. The agent dedups by
48
- * message_id. SEC-06 #18: a redelivered message whose reply already has a
49
- * durable intent is NOT handed to the agent again; the daemon republishes that
50
- * reply itself (same message_id), so the model does not run twice.
51
- *
52
- * Bounded work (Phase 3):
53
- * - F2 ordering: at most ONE message per channel is in flight on a socket;
54
- * the next message for that channel is sent only after the previous one is
55
- * acked (or retired). A backlog replays in order instead of flooding the
56
- * runtime, which used to answer the overflow with a "busy" reply and ack it.
57
- * - F1 attempt cap: every delivery is counted durably; a message that
58
- * reaches the cap is dead-lettered (content-free log + ack + one
59
- * content-free notice to the channel per hour) rather than redelivered
60
- * forever, and a channel where the agent is paused is not delivered at
61
- * all (no model call).
62
- * - Final-wave I1: a FAILED delivery (a `nack`, or the socket closing with
63
- * it in flight — older runtimes close on any failed turn) is requeued
64
- * behind a 2^attempts × 5 s backoff. A nack fails only its own message.
65
- * Messages never handed over (mid-flush close, a failed frame write) go
66
- * back without that penalty.
67
- * - #842: a delivery still un-acked after INFLIGHT_STALE_AFTER_MS is LOGGED
68
- * once (`runtime_inbox.inflight_stale`) and otherwise left alone. There
69
- * is deliberately no lease: see INFLIGHT_STALE_AFTER_MS.
70
- *
71
- * Single consumer: the daemon serves one agent per process. A new `/v1/ws`
72
- * connection replaces the prior one (newest wins, mirroring the SSE path); the
73
- * replaced socket's un-acked in-flight messages are re-buffered.
74
- *
75
- * Keepalive uses the ws library's server-side ping (the protocol-level ping
76
- * frame, not an application message); dead sockets are reaped via pong tracking.
77
- */
78
1
  import type { Server as HttpServer } from "node:http";
79
2
  import type { BridgeAgent } from "./bridge-agent.js";
80
3
  export interface AgentWebSocketOptions {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@securecoms/agent-bridge",
3
- "version": "0.26.4",
3
+ "version": "0.26.6",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=22.5.0"