@weave_protocol/ward 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -160,6 +160,19 @@ const result = evaluateToolCall(policy, "Bash", { command: "curl https://a.examp
160
160
  - **Relative paths** resolve against `cwd`.
161
161
  - **Strictness:** the strictest result wins (deny, then require_approval, then allow).
162
162
 
163
+ ### Reporting decisions to the dashboard (0.3.0+)
164
+
165
+ `reportEvent()` sends an enforcement decision to a local Weave API (`@weave_protocol/api`), which shows it on its dashboard. The Weave adapters, browser guard and Hundredmen call it for you.
166
+
167
+ ```bash
168
+ export WEAVE_DASHBOARD_URL=http://localhost:3000 # where the API runs
169
+ export WEAVE_API_KEY=... # the API's key
170
+ ```
171
+
172
+ - **Off by default.** Nothing is sent unless `WEAVE_DASHBOARD_URL` is set.
173
+ - **Sent:** the surface, the decision, the tool name or a URL with its query string removed, and a truncated reason with any argument value stripped. Command text and argument contents are never sent.
174
+ - **Never in the way.** A report never changes a decision, gives up after 250 ms, and never throws.
175
+
163
176
  ---
164
177
 
165
178
  ## Policy sections
package/dist/index.d.ts CHANGED
@@ -25,5 +25,7 @@ export { splitSections, normalizeKey } from "./parser/markdown.js";
25
25
  export { checkFilesystem, checkNetwork, checkCapability, checkDataEgress, checkBehavioral, matchGlob, normalizePath, canonicalUrl, } from "./enforcer/index.js";
26
26
  export type { Decision, CheckResult, RuntimeState } from "./enforcer/index.js";
27
27
  export { evaluateToolCall } from "./enforcer/toolcall.js";
28
+ export { reportEvent, dashboardUrl } from "./report.js";
29
+ export type { EnforcementEvent, ReportOptions, ReportSurface, ReportDecision } from "./report.js";
28
30
  export type { ToolMapping, ToolCallCheck, ToolCallEvaluation, EvaluateOptions } from "./enforcer/toolcall.js";
29
31
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,mBAAmB,YAAY,CAAC;AAGhC,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGnE,OAAO,EACL,eAAe,EACf,YAAY,EACZ,eAAe,EACf,eAAe,EACf,eAAe,EACf,SAAS,EACT,aAAa,EACb,YAAY,GACb,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,mBAAmB,YAAY,CAAC;AAGhC,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGnE,OAAO,EACL,eAAe,EACf,YAAY,EACZ,eAAe,EACf,eAAe,EACf,eAAe,EACf,SAAS,EACT,aAAa,EACb,YAAY,GACb,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClG,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC"}
package/dist/index.js CHANGED
@@ -25,4 +25,5 @@ export { splitSections, normalizeKey } from "./parser/markdown.js";
25
25
  // Enforcer
26
26
  export { checkFilesystem, checkNetwork, checkCapability, checkDataEgress, checkBehavioral, matchGlob, normalizePath, canonicalUrl, } from "./enforcer/index.js";
27
27
  export { evaluateToolCall } from "./enforcer/toolcall.js";
28
+ export { reportEvent, dashboardUrl } from "./report.js";
28
29
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,SAAS;AACT,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEnE,WAAW;AACX,OAAO,EACL,eAAe,EACf,YAAY,EACZ,eAAe,EACf,eAAe,EACf,eAAe,EACf,SAAS,EACT,aAAa,EACb,YAAY,GACb,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,SAAS;AACT,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEnE,WAAW;AACX,OAAO,EACL,eAAe,EACf,YAAY,EACZ,eAAe,EACf,eAAe,EACf,eAAe,EACf,SAAS,EACT,aAAa,EACb,YAAY,GACb,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Report enforcement decisions to a local Weave API dashboard.
3
+ *
4
+ * Off unless a dashboard URL is configured (WEAVE_DASHBOARD_URL, or the
5
+ * `url` option). Reporting never changes a decision and never holds the
6
+ * caller longer than a short timeout: failures are swallowed.
7
+ *
8
+ * Only a summary is sent: the surface, the decision, the tool name or a
9
+ * URL without its query string, and a truncated reason with any quoted
10
+ * argument removed. Command text and argument contents are never sent.
11
+ *
12
+ * Uses fetch, so it works in Node 18+ and in browsers (no Node built-ins).
13
+ */
14
+ import type { Decision } from "./enforcer/index.js";
15
+ export type ReportSurface = "mcp" | "claude-code" | "antigravity" | "msaf" | "browser";
16
+ export type ReportDecision = Decision | "ipi_detected" | "scan";
17
+ export interface EnforcementEvent {
18
+ surface: ReportSurface;
19
+ decision: ReportDecision;
20
+ /** Tool name, or a URL (its query string and fragment are dropped) */
21
+ subject: string;
22
+ reason?: string;
23
+ /** ms since epoch; defaults to now */
24
+ timestamp?: number;
25
+ }
26
+ export interface ReportOptions {
27
+ /** Dashboard base URL, e.g. http://localhost:3000. Default: $WEAVE_DASHBOARD_URL */
28
+ url?: string;
29
+ /** API key. Default: $WEAVE_API_KEY */
30
+ apiKey?: string;
31
+ /** Default 250ms */
32
+ timeoutMs?: number;
33
+ }
34
+ /** The dashboard URL reportEvent would use, or undefined when reporting is off. */
35
+ export declare function dashboardUrl(opts?: ReportOptions): string | undefined;
36
+ /**
37
+ * Send one event to the dashboard. Resolves when sent, failed or timed out;
38
+ * never rejects. A no-op when no dashboard URL is configured.
39
+ */
40
+ export declare function reportEvent(event: EnforcementEvent, opts?: ReportOptions): Promise<void>;
41
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,aAAa,GAAG,aAAa,GAAG,MAAM,GAAG,SAAS,CAAC;AACvF,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,cAAc,GAAG,MAAM,CAAC;AAEhE,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,cAAc,CAAC;IACzB,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,oFAAoF;IACpF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oBAAoB;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD,mFAAmF;AACnF,wBAAgB,YAAY,CAAC,IAAI,GAAE,aAAkB,GAAG,MAAM,GAAG,SAAS,CAGzE;AAqBD;;;GAGG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,gBAAgB,EAAE,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BlG"}
package/dist/report.js ADDED
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Report enforcement decisions to a local Weave API dashboard.
3
+ *
4
+ * Off unless a dashboard URL is configured (WEAVE_DASHBOARD_URL, or the
5
+ * `url` option). Reporting never changes a decision and never holds the
6
+ * caller longer than a short timeout: failures are swallowed.
7
+ *
8
+ * Only a summary is sent: the surface, the decision, the tool name or a
9
+ * URL without its query string, and a truncated reason with any quoted
10
+ * argument removed. Command text and argument contents are never sent.
11
+ *
12
+ * Uses fetch, so it works in Node 18+ and in browsers (no Node built-ins).
13
+ */
14
+ const MAX = 200;
15
+ const env = (key) => globalThis.process?.env?.[key];
16
+ /** The dashboard URL reportEvent would use, or undefined when reporting is off. */
17
+ export function dashboardUrl(opts = {}) {
18
+ const url = opts.url ?? env("WEAVE_DASHBOARD_URL");
19
+ return url ? url.replace(/\/+$/, "") : undefined;
20
+ }
21
+ /** Strip a URL to origin + path, so tokens in query strings never leave. */
22
+ function safeSubject(subject) {
23
+ if (/^[a-z][a-z0-9+.-]*:\/\//i.test(subject)) {
24
+ try {
25
+ const u = new URL(subject);
26
+ return `${u.origin}${u.pathname}`.slice(0, MAX);
27
+ }
28
+ catch {
29
+ return "(unparseable URL)";
30
+ }
31
+ }
32
+ return subject.slice(0, MAX);
33
+ }
34
+ /** Drop the "(arg=value)" suffix evaluateToolCall adds, which can hold argument contents. */
35
+ function safeReason(reason) {
36
+ if (!reason)
37
+ return undefined;
38
+ return reason.replace(/\s*\([^()]*\)\s*$/, "").slice(0, MAX);
39
+ }
40
+ /**
41
+ * Send one event to the dashboard. Resolves when sent, failed or timed out;
42
+ * never rejects. A no-op when no dashboard URL is configured.
43
+ */
44
+ export async function reportEvent(event, opts = {}) {
45
+ const base = dashboardUrl(opts);
46
+ const doFetch = globalThis.fetch;
47
+ if (!base || !doFetch)
48
+ return;
49
+ const apiKey = opts.apiKey ?? env("WEAVE_API_KEY");
50
+ const controller = new AbortController();
51
+ const timer = setTimeout(() => controller.abort(), opts.timeoutMs ?? 250);
52
+ try {
53
+ await doFetch(`${base}/api/v1/events`, {
54
+ method: "POST",
55
+ headers: { "Content-Type": "application/json", ...(apiKey ? { "X-API-Key": apiKey } : {}) },
56
+ body: JSON.stringify({
57
+ surface: event.surface,
58
+ decision: event.decision,
59
+ subject: safeSubject(event.subject),
60
+ reason: safeReason(event.reason),
61
+ timestamp: event.timestamp ?? Date.now(),
62
+ }),
63
+ signal: controller.signal,
64
+ });
65
+ }
66
+ catch {
67
+ // The dashboard is optional: never let it affect enforcement.
68
+ }
69
+ finally {
70
+ clearTimeout(timer);
71
+ }
72
+ }
73
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA0BH,MAAM,GAAG,GAAG,GAAG,CAAC;AAChB,MAAM,GAAG,GAAG,CAAC,GAAW,EAAsB,EAAE,CAC7C,UAAyE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;AAEjG,mFAAmF;AACnF,MAAM,UAAU,YAAY,CAAC,IAAI,GAAkB,EAAE;IACnD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,qBAAqB,CAAC,CAAC;IACnD,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACnD,CAAC;AAED,4EAA4E;AAC5E,SAAS,WAAW,CAAC,OAAe;IAClC,IAAI,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7C,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;YAC3B,OAAO,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,mBAAmB,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC/B,CAAC;AAED,6FAA6F;AAC7F,SAAS,UAAU,CAAC,MAA0B;IAC5C,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,OAAO,MAAM,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC/D,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAuB,EAAE,IAAI,GAAkB,EAAE;IACjF,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,OAAO,GAAI,UAAuC,CAAC,KAAK,CAAC;IAC/D,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO;QAAE,OAAO;IAE9B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,eAAe,CAAC,CAAC;IACnD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,SAAS,IAAI,GAAG,CAAC,CAAC;IAC1E,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,GAAG,IAAI,gBAAgB,EAAE;YACrC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE;YAC3F,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC;gBACnC,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC;gBAChC,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE;aACzC,CAAC;YACF,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,8DAA8D;IAChE,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weave_protocol/ward",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "WARD.md — the agent security policy standard. Define what your agents can and cannot do, version-controlled alongside AGENTS.md and SKILL.md.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",