@upx-us/shield 0.6.0 → 0.6.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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,37 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ---
6
6
 
7
+ ## [0.6.1] — 2026-03-09
8
+
9
+ ### Fixed
10
+ - **Auto-update restart resilience** — `requestGatewayRestart()` failures no longer leave the plugin in a split-brain state. The updater now tracks `pendingRestart` in `update-state.json` and retries the gateway restart on every subsequent poll cycle. After 5 failed attempts (~2.5 min), automatically rolls back to the previous backup version. Closes #112.
11
+
12
+ ---
13
+
14
+ ## [0.6.0] — 2026-03-06
15
+
16
+ ### Added
17
+ - **Transformer gap fields** — 7 new fields to unblock ~20 SIEM detection rules:
18
+ - `openclaw.secret_in_command` — detects API keys, bearer tokens, and secrets in commands (pre-redaction flag)
19
+ - `openclaw.channel` + `openclaw.chat_type` — messaging context for DLP rules
20
+ - `openclaw.message_content` — truncated outbound message content (500 chars) for DLP pattern matching
21
+ - `openclaw.browser_action` — browser tool action type (navigate, click, evaluate, etc.)
22
+ - `openclaw.config_change` — flags writes/edits to config files (.env, openclaw.json, etc.)
23
+ - `openclaw.file_size_bytes` — file size on write operations
24
+ - **`_skill_hint` in RPC responses** — all successful Shield RPCs include a machine-readable hint nudging agents to read the SKILL.md before presenting data to users.
25
+
26
+ ### Changed
27
+ - npm registry cleaned: removed 26 old 0.5.x versions (kept 0.5.38 as fallback)
28
+
29
+ ---
30
+
31
+ ## [0.5.38] — 2026-03-06
32
+
33
+ ### Added
34
+ - `_skill_hint` field in all RPC responses (agent-facing, invisible to users)
35
+
36
+ ---
37
+
7
38
  ## [0.5.18] — 2026-03-06
8
39
 
9
40
  ### Added
@@ -8,6 +8,8 @@ export interface UpdateState {
8
8
  lastError: string | null;
9
9
  rollbackVersion: string | null;
10
10
  consecutiveFailures: number;
11
+ pendingRestart: boolean;
12
+ restartAttempts: number;
11
13
  }
12
14
  export interface UpdateCheckResult {
13
15
  updateAvailable: boolean;
@@ -111,6 +111,8 @@ function loadUpdateState() {
111
111
  lastError: null,
112
112
  rollbackVersion: null,
113
113
  consecutiveFailures: 0,
114
+ pendingRestart: false,
115
+ restartAttempts: 0,
114
116
  };
115
117
  if (!(0, fs_1.existsSync)(UPDATE_STATE_FILE))
116
118
  return defaults;
@@ -242,6 +244,14 @@ function pruneBackups() {
242
244
  catch { }
243
245
  }
244
246
  }
247
+ function listBackups() {
248
+ if (!(0, fs_1.existsSync)(BACKUP_DIR))
249
+ return [];
250
+ return (0, fs_1.readdirSync)(BACKUP_DIR)
251
+ .filter(d => d.startsWith('shield-'))
252
+ .map(d => (0, path_1.join)(BACKUP_DIR, d))
253
+ .sort((a, b) => (0, fs_1.statSync)(b).mtimeMs - (0, fs_1.statSync)(a).mtimeMs);
254
+ }
245
255
  function restoreFromBackup(backupPath) {
246
256
  if (!(0, fs_1.existsSync)(backupPath)) {
247
257
  log.error('updater', `Backup not found: ${backupPath}`);
@@ -370,6 +380,36 @@ function performAutoUpdate(mode, checkIntervalMs) {
370
380
  const noOp = { action: 'none', fromVersion: version_1.VERSION, toVersion: null, message: '', requiresRestart: false };
371
381
  if (mode === false)
372
382
  return noOp;
383
+ {
384
+ const state = loadUpdateState();
385
+ if (state.pendingRestart && state.currentVersion && state.currentVersion !== version_1.VERSION) {
386
+ const MAX_RESTART_ATTEMPTS = 5;
387
+ if ((state.restartAttempts ?? 0) >= MAX_RESTART_ATTEMPTS) {
388
+ log.warn('updater', `Gateway restart failed ${MAX_RESTART_ATTEMPTS}x after update to ${state.currentVersion} — rolling back`);
389
+ const backups = listBackups();
390
+ if (backups.length > 0) {
391
+ restoreFromBackup(backups[0]);
392
+ }
393
+ state.pendingRestart = false;
394
+ state.restartAttempts = 0;
395
+ saveUpdateState(state);
396
+ }
397
+ else {
398
+ log.info('updater', `Retrying gateway restart (attempt ${(state.restartAttempts ?? 0) + 1}/${MAX_RESTART_ATTEMPTS})...`);
399
+ const restarted = requestGatewayRestart();
400
+ if (restarted) {
401
+ state.pendingRestart = false;
402
+ state.restartAttempts = 0;
403
+ saveUpdateState(state);
404
+ }
405
+ else {
406
+ state.restartAttempts = (state.restartAttempts ?? 0) + 1;
407
+ saveUpdateState(state);
408
+ }
409
+ }
410
+ return noOp;
411
+ }
412
+ }
373
413
  const check = checkForUpdate(checkIntervalMs);
374
414
  if (!check || !check.updateAvailable)
375
415
  return noOp;
@@ -445,6 +485,26 @@ function performAutoUpdate(mode, checkIntervalMs) {
445
485
  requiresRestart: false,
446
486
  };
447
487
  }
488
+ const restarted = requestGatewayRestart();
489
+ if (!restarted) {
490
+ state.pendingRestart = true;
491
+ state.restartAttempts = (state.restartAttempts ?? 0) + 1;
492
+ state.currentVersion = check.latestVersion;
493
+ state.lastUpdateAt = Date.now();
494
+ state.consecutiveFailures = 0;
495
+ state.lastError = null;
496
+ saveUpdateState(state);
497
+ log.warn('updater', `Gateway restart failed after update to ${check.latestVersion} — will retry on next poll cycle.`);
498
+ return {
499
+ action: 'updated',
500
+ fromVersion: version_1.VERSION,
501
+ toVersion: check.latestVersion,
502
+ message: `Shield updated to ${check.latestVersion} on disk. Gateway restart failed — will retry on next poll cycle.`,
503
+ requiresRestart: true,
504
+ };
505
+ }
506
+ state.pendingRestart = false;
507
+ state.restartAttempts = 0;
448
508
  state.lastUpdateAt = Date.now();
449
509
  state.updateAvailable = false;
450
510
  state.rollbackVersion = version_1.VERSION;
@@ -452,12 +512,12 @@ function performAutoUpdate(mode, checkIntervalMs) {
452
512
  state.consecutiveFailures = 0;
453
513
  state.lastError = null;
454
514
  saveUpdateState(state);
455
- log.info('updater', `✅ Auto-updated: ${version_1.VERSION} → ${check.latestVersion}. Gateway restart required to load new version.`);
515
+ log.info('updater', `✅ Auto-updated: ${version_1.VERSION} → ${check.latestVersion}. Gateway restart initiated.`);
456
516
  return {
457
517
  action: 'updated',
458
518
  fromVersion: version_1.VERSION,
459
519
  toVersion: check.latestVersion,
460
- message: `Shield auto-updated: ${version_1.VERSION} → ${check.latestVersion}. Gateway restart required.`,
520
+ message: `Shield auto-updated: ${version_1.VERSION} → ${check.latestVersion}. Gateway restart initiated.`,
461
521
  requiresRestart: true,
462
522
  };
463
523
  }
@@ -2,7 +2,7 @@
2
2
  "id": "shield",
3
3
  "name": "OpenClaw Shield",
4
4
  "description": "Real-time security monitoring — streams enriched, redacted security events to the Shield detection platform.",
5
- "version": "0.6.0",
5
+ "version": "0.6.1",
6
6
  "skills": [
7
7
  "./skills"
8
8
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@upx-us/shield",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Security monitoring plugin for OpenClaw agents — streams enriched security events to the Shield detection platform",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -0,0 +1,38 @@
1
+ Copyright (c) 2026 UPX Technologies, Inc. All rights reserved.
2
+
3
+ PROPRIETARY SOFTWARE LICENSE
4
+
5
+ This software and associated documentation files (the "Software") are the
6
+ proprietary and confidential property of UPX Technologies, Inc. ("UPX").
7
+
8
+ GRANT OF USE
9
+ Subject to the terms of a valid, active subscription agreement with UPX for
10
+ the OpenClaw Shield service, UPX grants you a limited, non-exclusive,
11
+ non-transferable, non-sublicensable license to install and use the Software
12
+ solely for the purpose of connecting to the OpenClaw Shield platform as part
13
+ of your subscription.
14
+
15
+ RESTRICTIONS
16
+ You may not, and you may not permit others to:
17
+ - Copy, modify, adapt, translate, or create derivative works of the Software
18
+ - Distribute, transfer, sublicense, lease, lend, or rent the Software
19
+ - Reverse engineer, disassemble, or decompile the Software
20
+ - Remove or alter any proprietary notices, labels, or marks on the Software
21
+ - Use the Software without an active OpenClaw Shield subscription
22
+
23
+ TERMINATION
24
+ This license is effective until terminated. It will terminate automatically
25
+ if you breach any term of this agreement or your subscription expires. Upon
26
+ termination, you must destroy all copies of the Software in your possession.
27
+
28
+ DISCLAIMER
29
+ THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. UPX DISCLAIMS
30
+ ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES
31
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
32
+
33
+ IN NO EVENT SHALL UPX BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
34
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION WITH
35
+ THE SOFTWARE OR ITS USE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
+
37
+ For licensing inquiries: legal@upx.com
38
+ For support: https://upx.com
@@ -3,6 +3,7 @@ name: openclaw-shield-upx
3
3
  description: "Security monitoring for OpenClaw agents — check Shield health, review events, inspect vault. Use when: user asks about security status, Shield health, event logs, or redaction vault. NOT for: general OS hardening, firewall config, or network security."
4
4
  homepage: https://www.upx.com/en/lp/openclaw-shield-upx
5
5
  source: https://www.npmjs.com/package/@upx-us/shield
6
+ license: "Proprietary — UPX Technologies, Inc. All rights reserved."
6
7
  metadata: {"openclaw": {"requires": {"config": ["plugins.entries.shield"]}, "homepage": "https://clawhub.ai/brunopradof/openclaw-shield-upx", "emoji": "🛡️"}}
7
8
  ---
8
9