@axonflow/openclaw 1.3.2 → 2.0.1

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/CHANGELOG.md +71 -0
  2. package/README.md +111 -7
  3. package/dist/audit.d.ts +2 -2
  4. package/dist/audit.d.ts.map +1 -1
  5. package/dist/audit.js +2 -2
  6. package/dist/audit.js.map +1 -1
  7. package/dist/axonflow-client.d.ts +22 -0
  8. package/dist/axonflow-client.d.ts.map +1 -1
  9. package/dist/axonflow-client.js +56 -0
  10. package/dist/axonflow-client.js.map +1 -1
  11. package/dist/cache-dir.d.ts +34 -0
  12. package/dist/cache-dir.d.ts.map +1 -0
  13. package/dist/cache-dir.js +106 -0
  14. package/dist/cache-dir.js.map +1 -0
  15. package/dist/client-ref.d.ts +19 -0
  16. package/dist/client-ref.d.ts.map +1 -0
  17. package/dist/client-ref.js +16 -0
  18. package/dist/client-ref.js.map +1 -0
  19. package/dist/community-saas-bootstrap.d.ts +85 -0
  20. package/dist/community-saas-bootstrap.d.ts.map +1 -0
  21. package/dist/community-saas-bootstrap.js +256 -0
  22. package/dist/community-saas-bootstrap.js.map +1 -0
  23. package/dist/community-saas-context.d.ts +82 -0
  24. package/dist/community-saas-context.d.ts.map +1 -0
  25. package/dist/community-saas-context.js +196 -0
  26. package/dist/community-saas-context.js.map +1 -0
  27. package/dist/config.d.ts +26 -1
  28. package/dist/config.d.ts.map +1 -1
  29. package/dist/config.js +60 -30
  30. package/dist/config.js.map +1 -1
  31. package/dist/governance.d.ts +3 -2
  32. package/dist/governance.d.ts.map +1 -1
  33. package/dist/governance.js +2 -2
  34. package/dist/governance.js.map +1 -1
  35. package/dist/index.d.ts +1 -1
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +98 -12
  38. package/dist/index.js.map +1 -1
  39. package/dist/llm-audit.d.ts +3 -3
  40. package/dist/llm-audit.d.ts.map +1 -1
  41. package/dist/llm-audit.js +3 -3
  42. package/dist/llm-audit.js.map +1 -1
  43. package/dist/message-guard.d.ts +2 -2
  44. package/dist/message-guard.d.ts.map +1 -1
  45. package/dist/message-guard.js +2 -2
  46. package/dist/message-guard.js.map +1 -1
  47. package/dist/plugin-version-check.d.ts +50 -0
  48. package/dist/plugin-version-check.d.ts.map +1 -0
  49. package/dist/plugin-version-check.js +89 -0
  50. package/dist/plugin-version-check.js.map +1 -0
  51. package/dist/telemetry-config.d.ts +5 -3
  52. package/dist/telemetry-config.d.ts.map +1 -1
  53. package/dist/telemetry-config.js +1 -15
  54. package/dist/telemetry-config.js.map +1 -1
  55. package/dist/telemetry-context.d.ts +65 -0
  56. package/dist/telemetry-context.d.ts.map +1 -0
  57. package/dist/telemetry-context.js +116 -0
  58. package/dist/telemetry-context.js.map +1 -0
  59. package/dist/telemetry.d.ts +42 -18
  60. package/dist/telemetry.d.ts.map +1 -1
  61. package/dist/telemetry.js +113 -54
  62. package/dist/telemetry.js.map +1 -1
  63. package/openclaw.plugin.json +60 -6
  64. package/package.json +10 -5
package/dist/telemetry.js CHANGED
@@ -1,24 +1,39 @@
1
1
  /**
2
- * Anonymous usage telemetry for the OpenClaw plugin.
2
+ * Anonymous usage telemetry 7-day heartbeat (TypeScript).
3
3
  *
4
- * Sends a single fire-and-forget ping on plugin initialization to
5
- * checkpoint.getaxonflow.com. Collects SDK version, platform info,
6
- * and OpenClaw version. No PII, no tool arguments, no policy data.
4
+ * Sends an anonymous POST to checkpoint.getaxonflow.com on plugin
5
+ * initialization, at most once every 7 days per machine.
7
6
  *
8
- * Opt out: AXONFLOW_TELEMETRY=off (canonical)
9
- * Also honored for backward compatibility: DO_NOT_TRACK=1 (deprecated — removed
10
- * after 2026-05-05 in the next major release; a one-time warning emits when
11
- * it's the active opt-out so operators can migrate).
7
+ * Design rules (per feedback_telemetry_heartbeat_design_rules.md):
8
+ * 1. Stamp-on-delivery, not stamp-on-attempt. Stamp file mtime
9
+ * advances ONLY after the HTTP POST returns 2xx. A transient
10
+ * network failure does not silence telemetry for 7 days.
11
+ * 2. In-flight gate via a per-process Promise. Concurrent plugin
12
+ * loads do not race to send duplicate pings.
13
+ * 3. Opt-out check FIRST, before any rate-limit or filesystem ops.
14
+ * AXONFLOW_TELEMETRY=off is re-evaluated every call.
15
+ * 4. mtime as the freshness source; stamp body holds instance_id.
16
+ * 5. Atomic stamp write: tmp + rename.
17
+ * 6. Persistent instance_id across heartbeats.
18
+ * 7. Defensive against future-dated stamps (clock skew → treat absent).
19
+ * 8. Cross-platform cache dir resolution (cache-dir.ts).
12
20
  *
13
- * Configuration resolution (opt-out flags and checkpoint URL) lives in
14
- * telemetry-config.ts so this file only handles the network-sending side.
21
+ * Configuration resolution (opt-out flags, checkpoint URL) lives in
22
+ * telemetry-config.ts. Environment + filesystem reads (harness probe
23
+ * endpoint, stamp inspection, atomic stamp write) live in
24
+ * telemetry-context.ts. This module is the network-only side of the
25
+ * heartbeat: it imports plain values from the context modules and only
26
+ * issues HTTP requests.
15
27
  */
28
+ import { axonflowCacheDir } from "./cache-dir.js";
16
29
  import { loadTelemetryConfig } from "./telemetry-config.js";
30
+ import { captureRuntimeInfo, ensureCacheDir, readStampMetadata, resolveProbeEndpoint, stampPath, writeStampAtomic, } from "./telemetry-context.js";
17
31
  const TELEMETRY_TIMEOUT_MS = 3000;
32
+ const HEARTBEAT_INTERVAL_MS = 7 * 24 * 60 * 60 * 1000;
33
+ let inFlight = null;
18
34
  function generateInstanceId() {
19
35
  try {
20
- if (typeof crypto !== "undefined" &&
21
- typeof crypto.randomUUID === "function") {
36
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
22
37
  return crypto.randomUUID();
23
38
  }
24
39
  }
@@ -31,9 +46,6 @@ function generateInstanceId() {
31
46
  return v.toString(16);
32
47
  });
33
48
  }
34
- /**
35
- * Detect the AxonFlow platform version via /health endpoint.
36
- */
37
49
  async function detectPlatformVersion(endpoint) {
38
50
  const controller = new AbortController();
39
51
  const timeoutId = setTimeout(() => controller.abort(), 2000);
@@ -46,9 +58,7 @@ async function detectPlatformVersion(endpoint) {
46
58
  if (!resp.ok)
47
59
  return null;
48
60
  const body = (await resp.json());
49
- return typeof body.version === "string" && body.version
50
- ? body.version
51
- : null;
61
+ return typeof body.version === "string" && body.version ? body.version : null;
52
62
  }
53
63
  catch {
54
64
  clearTimeout(timeoutId);
@@ -56,63 +66,112 @@ async function detectPlatformVersion(endpoint) {
56
66
  }
57
67
  }
58
68
  /**
59
- * Send an anonymous telemetry ping on plugin initialization.
69
+ * Send an anonymous telemetry heartbeat. Concurrent calls are de-duplicated
70
+ * via a per-process in-flight gate; the second concurrent caller awaits the
71
+ * first's promise rather than firing a duplicate.
60
72
  *
61
- * Fire-and-forget: errors are silently swallowed, 3-second timeout
62
- * prevents blocking. Never affects plugin behavior.
73
+ * Returns a promise that resolves when the heartbeat completes (success,
74
+ * skip, or failure). Production callers should treat as fire-and-forget;
75
+ * tests can await for assertions.
63
76
  */
64
77
  export function sendTelemetryPing(options) {
78
+ if (inFlight) {
79
+ return inFlight;
80
+ }
81
+ inFlight = sendInner(options).finally(() => {
82
+ inFlight = null;
83
+ });
84
+ return inFlight;
85
+ }
86
+ async function sendInner(options) {
87
+ // 1. Opt-out check FIRST.
65
88
  const config = loadTelemetryConfig();
66
89
  if (config.optedOut) {
67
90
  return;
68
91
  }
69
- if (typeof console !== "undefined") {
70
- console.log("[AxonFlow] Anonymous telemetry enabled for local and self-hosted use. Opt out: AXONFLOW_TELEMETRY=off | https://docs.getaxonflow.com/docs/telemetry");
92
+ // 2. Resolve the stamp file location and ensure the cache dir is private.
93
+ const cacheDir = ensureCacheDir(axonflowCacheDir());
94
+ const stampFile = stampPath(cacheDir);
95
+ const now = options.now ?? (() => new Date());
96
+ const nowMs = now().getTime();
97
+ // 3. mtime check, defensive against future-dated stamps. The stamp read
98
+ // is done in telemetry-context.ts so this module stays free of fs
99
+ // read calls co-located with fetch.
100
+ const stamp = readStampMetadata(stampFile);
101
+ if (stamp.exists && stamp.mtimeMs > 0 && stamp.mtimeMs <= nowMs) {
102
+ const age = nowMs - stamp.mtimeMs;
103
+ if (age < HEARTBEAT_INTERVAL_MS) {
104
+ return; // fresh — skip
105
+ }
106
+ }
107
+ const priorInstanceId = stamp.priorInstanceId;
108
+ const instanceId = priorInstanceId && /^[a-f0-9-]{8,64}$/i.test(priorInstanceId)
109
+ ? priorInstanceId
110
+ : generateInstanceId();
111
+ // 4. Detect platform version (best-effort). The harness override is
112
+ // resolved in telemetry-context.ts so AXONFLOW_HARNESS env reads do
113
+ // not co-locate with fetch in this file.
114
+ const probeEndpoint = resolveProbeEndpoint(options.endpoint);
115
+ let platformVersion = null;
116
+ try {
117
+ platformVersion = await detectPlatformVersion(probeEndpoint);
118
+ }
119
+ catch {
120
+ platformVersion = null;
71
121
  }
72
- // Runtime metadata (platform, arch, runtime version) for the payload.
73
- const proc = typeof process !== "undefined" ? process : null;
122
+ const runtime = captureRuntimeInfo();
123
+ // Community-SaaS users are first-class for analytics; classifying them as
124
+ // "production" (because plugin-generated auth is present) hides them inside
125
+ // the self-hosted bucket. Surface them explicitly here.
126
+ const deploymentMode = options.mode === "community-saas"
127
+ ? "community-saas"
128
+ : options.onError === "block"
129
+ ? "production"
130
+ : "development";
74
131
  const payload = {
75
132
  sdk: "openclaw-plugin",
76
133
  sdk_version: options.pluginVersion,
77
- platform_version: null,
78
- os: proc ? proc.platform : "unknown",
79
- arch: proc ? proc.arch : "unknown",
80
- runtime_version: proc ? proc.version.replace(/^v/, "") : "unknown",
81
- deployment_mode: options.onError === "block" ? "production" : "development",
134
+ platform_version: platformVersion,
135
+ os: runtime.os,
136
+ arch: runtime.arch,
137
+ runtime_version: runtime.runtimeVersion,
138
+ deployment_mode: deploymentMode,
82
139
  features: [
83
140
  `hooks:${options.hookCount}`,
84
141
  `high_risk_tools:${options.highRiskToolCount}`,
85
142
  `on_error:${options.onError}`,
143
+ `mode:${options.mode}`,
86
144
  ],
87
- instance_id: generateInstanceId(),
145
+ instance_id: instanceId,
88
146
  };
147
+ // 5. Fire the heartbeat.
148
+ const controller = new AbortController();
149
+ const timeoutId = setTimeout(() => controller.abort(), TELEMETRY_TIMEOUT_MS);
150
+ let delivered = false;
89
151
  try {
90
- void (async () => {
91
- try {
92
- payload.platform_version = await detectPlatformVersion(options.endpoint);
93
- }
94
- catch {
95
- // Silent — platform version remains null
96
- }
97
- const controller = new AbortController();
98
- const timeoutId = setTimeout(() => controller.abort(), TELEMETRY_TIMEOUT_MS);
99
- try {
100
- await fetch(config.checkpointUrl, {
101
- method: "POST",
102
- headers: { "Content-Type": "application/json" },
103
- body: JSON.stringify(payload),
104
- signal: controller.signal,
105
- });
106
- }
107
- finally {
108
- clearTimeout(timeoutId);
109
- }
110
- })().catch(() => {
111
- // Silent failure — telemetry should never affect plugin behavior
152
+ const resp = await fetch(config.checkpointUrl, {
153
+ method: "POST",
154
+ headers: { "Content-Type": "application/json" },
155
+ body: JSON.stringify(payload),
156
+ signal: controller.signal,
112
157
  });
158
+ delivered = resp.ok;
113
159
  }
114
160
  catch {
115
- // Silent failure
161
+ delivered = false;
162
+ }
163
+ finally {
164
+ clearTimeout(timeoutId);
116
165
  }
166
+ // 6. Stamp-on-delivery. The atomic write lives in telemetry-context.ts.
167
+ if (delivered) {
168
+ writeStampAtomic(stampFile, instanceId);
169
+ }
170
+ }
171
+ /**
172
+ * Test-only: clear the in-flight gate between tests.
173
+ */
174
+ export function _resetTelemetryInFlightForTests() {
175
+ inFlight = null;
117
176
  }
118
177
  //# sourceMappingURL=telemetry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,62 @@
1
1
  {
2
2
  "id": "axonflow-governance",
3
+ "envVars": {
4
+ "AXONFLOW_TELEMETRY": {
5
+ "required": false,
6
+ "description": "Set to 'off', '0', 'false', or 'no' to disable the 7-day anonymous telemetry heartbeat. When unset (default), the plugin sends a lightweight ping to checkpoint.getaxonflow.com once every 7 days per machine.",
7
+ "values": ["off", "0", "false", "no"]
8
+ },
9
+ "AXONFLOW_COMMUNITY_SAAS": {
10
+ "required": false,
11
+ "description": "Set to '0', 'false', 'off', or 'no' to disable auto-registration with try.getaxonflow.com Community SaaS. When opted out, configure pluginConfig.endpoint to point at a self-hosted AxonFlow instance — otherwise the plugin loads but cannot enforce policy.",
12
+ "values": ["0", "false", "off", "no"]
13
+ },
14
+ "AXONFLOW_CACHE_DIR": {
15
+ "required": false,
16
+ "description": "Override the per-user cache directory used for telemetry stamps and rate-limit backoffs. Defaults to OS conventions: $XDG_CACHE_HOME/axonflow on Linux, ~/Library/Caches/axonflow on macOS, %LOCALAPPDATA%\\axonflow on Windows."
17
+ },
18
+ "AXONFLOW_CONFIG_DIR": {
19
+ "required": false,
20
+ "description": "Override the per-user config directory used for the Community-SaaS registration file (mode 0o600). Defaults to OS conventions: $XDG_CONFIG_HOME/axonflow on Linux, ~/Library/Application Support/axonflow on macOS, %APPDATA%\\axonflow on Windows."
21
+ }
22
+ },
23
+ "runtimeBehavior": {
24
+ "autoBootstrap": {
25
+ "enabled": true,
26
+ "description": "When pluginConfig.endpoint is unset and AXONFLOW_COMMUNITY_SAAS is not opted out, the plugin POSTs to https://try.getaxonflow.com/api/v1/register on first load to obtain Community-SaaS credentials, persists them at $AXONFLOW_CONFIG_DIR/try-registration.json (mode 0o600), and uses them for subsequent governance calls. The 7-day rotation refresh window keeps tenants from lapsing silently.",
27
+ "optOut": "Set AXONFLOW_COMMUNITY_SAAS=0 OR set pluginConfig.endpoint to a self-hosted AxonFlow instance.",
28
+ "userDisclosure": "First-load disclosure banner emitted via plugin logger (warn level), one time per machine, before the registration POST fires."
29
+ },
30
+ "outboundData": {
31
+ "atGovernanceTime": "Tool name + arguments (before execution) and outbound message bodies (before delivery) are sent to the configured AxonFlow endpoint for policy evaluation and audit. With Community SaaS, the endpoint is try.getaxonflow.com; with self-hosted, traffic stays on your network.",
32
+ "telemetry": "Anonymous 7-day heartbeat to checkpoint.getaxonflow.com containing plugin version, OS, arch, runtime version, deployment mode, hook count, and a per-machine instance_id (UUID v4). No tool inputs, no message bodies, no LLM provider keys.",
33
+ "neverTransmitted": ["LLM provider API keys", "OpenClaw conversation history outside governed tools", "Files outside the OpenClaw runtime"]
34
+ },
35
+ "persistence": {
36
+ "files": [
37
+ {
38
+ "path": "$AXONFLOW_CONFIG_DIR/try-registration.json",
39
+ "mode": "0o600",
40
+ "purpose": "Community-SaaS registration credentials (tenant_id, secret, expires_at). Refused at load time if permissions are not 0o600 on POSIX."
41
+ },
42
+ {
43
+ "path": "$AXONFLOW_CONFIG_DIR/openclaw-plugin-community-saas-disclosure-shown",
44
+ "mode": "0o600",
45
+ "purpose": "First-load disclosure stamp. Empty file; presence prevents re-warning on subsequent loads."
46
+ },
47
+ {
48
+ "path": "$AXONFLOW_CACHE_DIR/openclaw-plugin-telemetry-sent",
49
+ "mode": "0o600",
50
+ "purpose": "Heartbeat stamp file. Body is the per-machine instance_id (UUID v4); mtime drives the 7-day rate limit."
51
+ },
52
+ {
53
+ "path": "$AXONFLOW_CACHE_DIR/openclaw-plugin-register-backoff",
54
+ "mode": "0o600",
55
+ "purpose": "Rate-limit backoff stamp written when /api/v1/register returns 429. Body is a Unix timestamp (seconds) until which the bootstrap will not retry."
56
+ }
57
+ ]
58
+ }
59
+ },
3
60
  "uiHints": {
4
61
  "endpoint": {
5
62
  "label": "AxonFlow Endpoint",
@@ -52,16 +109,13 @@
52
109
  "additionalProperties": false,
53
110
  "properties": {
54
111
  "endpoint": {
55
- "type": "string",
56
- "default": "http://localhost:8080"
112
+ "type": "string"
57
113
  },
58
114
  "clientId": {
59
- "type": "string",
60
- "default": "community"
115
+ "type": "string"
61
116
  },
62
117
  "clientSecret": {
63
- "type": "string",
64
- "default": "community"
118
+ "type": "string"
65
119
  },
66
120
  "highRiskTools": {
67
121
  "type": "array",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axonflow/openclaw",
3
- "version": "1.3.2",
3
+ "version": "2.0.1",
4
4
  "description": "Policy enforcement, approval gates, and audit trails for OpenClaw — govern tool inputs before execution, scan outbound messages for PII/secrets, and record agent activity for review and compliance",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -26,6 +26,7 @@
26
26
  "lint": "eslint src/ tests/",
27
27
  "test": "jest",
28
28
  "test:coverage": "jest --coverage",
29
+ "scan": "node scripts/scan-tarball.mjs",
29
30
  "prepublishOnly": "npm run build"
30
31
  },
31
32
  "keywords": [
@@ -62,7 +63,10 @@
62
63
  },
63
64
  "peerDependencies": {
64
65
  "@axonflow/sdk": ">=4.3.0",
65
- "openclaw": ">=1.0.0"
66
+ "openclaw": ">=2026.4.15"
67
+ },
68
+ "overrides": {
69
+ "openclaw": ">=2026.4.15"
66
70
  },
67
71
  "devDependencies": {
68
72
  "@types/jest": "^29.5.0",
@@ -71,7 +75,8 @@
71
75
  "jest": "^29.7.0",
72
76
  "ts-jest": "^29.1.0",
73
77
  "typescript": "^5.4.0",
74
- "typescript-eslint": "^8.58.0"
78
+ "typescript-eslint": "^8.58.0",
79
+ "yaml": "^2.8.3"
75
80
  },
76
81
  "publishConfig": {
77
82
  "access": "public",
@@ -88,10 +93,10 @@
88
93
  ],
89
94
  "compat": {
90
95
  "pluginApi": ">=2026.3.22",
91
- "minGatewayVersion": "2026.3.22"
96
+ "minGatewayVersion": "2026.4.15"
92
97
  },
93
98
  "build": {
94
- "openclawVersion": "2026.3.22",
99
+ "openclawVersion": "2026.4.15",
95
100
  "pluginSdkVersion": "2026.3.22"
96
101
  }
97
102
  }