@upx-us/shield 0.6.5 → 0.6.7
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 +32 -0
- package/dist/index.js +38 -0
- package/dist/src/index.js +4 -2
- package/dist/src/redactor/strategies/command.js +1 -1
- package/dist/src/rpc/handlers.d.ts +5 -0
- package/dist/src/rpc/handlers.js +56 -0
- package/dist/src/sender.d.ts +1 -0
- package/dist/src/sender.js +14 -0
- package/dist/src/updater.js +46 -0
- package/openclaw.plugin.json +3 -3
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,38 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## [0.6.7] — 2026-03-10
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- **npm redaction false positive** — `@scope/package@version` (e.g. `@upx-us/shield@0.6.6`) was being wrongly redacted as `user:HASH` by the SSH `user@host` regex. Added negative lookbehind to exclude npm scoped package names (#135).
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **Postinstall guidance** — running `npm install` outside of OpenClaw now prints a clear warning to stderr explaining the plugin requires the OpenClaw gateway. Install never fails because of this check (#125).
|
|
14
|
+
- **First event confirmation** — after the first successful event delivery to the platform, the plugin logs `✅ First event delivered to platform — monitoring is active` once per process lifetime (#61, #52).
|
|
15
|
+
- **Vault summary in `shield.status`** — `shield.status` RPC now includes `redaction.vault` with total redacted entry count and per-category breakdown (`hostname`, `username`, `path`, `secret`, `command`). Returns `null` if vault is absent (#86).
|
|
16
|
+
|
|
17
|
+
### Tests
|
|
18
|
+
- +19 new tests covering postinstall safety (exit-0 guarantee, cross-platform), first-event flag, vault status summary (missing/corrupt/valid vault).
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## [0.6.6] — 2026-03-10
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
- **Plugin lifecycle events** — the plugin now reports key lifecycle signals to the USS platform via the existing `PUT /v1/instance` channel (no new endpoint). Signals are forwarded by Cloud Run as an optional `lifecycle_event` field in the instance telemetry PATCH to the platform. Absent on older plugin versions — fully backward compatible.
|
|
26
|
+
- `plugin_started`: emitted on every successful startup. Includes `version`, `reason` (`'update'` | `'normal'`), and `previous_version` when applicable. Enables the platform to confirm end-to-end update success.
|
|
27
|
+
- `update_restart_failed`: emitted after all gateway restart retries are exhausted. Includes `new_version`, `running_version`, `attempts`, `error`.
|
|
28
|
+
- `plugin_integrity_drift`: emitted when `openclaw.json` version diverges from the installed version after a self-update. Includes `installed_version`, `registered_version`.
|
|
29
|
+
- `update_check_failing`: emitted after 3 consecutive npm registry check failures. Includes `consecutive_failures`, `last_error`, `next_retry_at`.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
- `reportPluginEvent()` removed from `sender.ts` — replaced by `reportLifecycleEvent()` which reuses the existing `PUT /v1/instance` telemetry channel.
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
- `SHIELD_AUTO_UPDATE=false` environment variable now correctly disables auto-update (was being read as truthy string `'false'`).
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
7
39
|
## [0.6.5] — 2026-03-09
|
|
8
40
|
|
|
9
41
|
### Added
|
package/dist/index.js
CHANGED
|
@@ -55,6 +55,7 @@ const exclusions_1 = require("./src/exclusions");
|
|
|
55
55
|
const updater_1 = require("./src/updater");
|
|
56
56
|
const rpc_1 = require("./src/rpc");
|
|
57
57
|
const inventory_1 = require("./src/inventory");
|
|
58
|
+
const redactor_1 = require("./src/redactor");
|
|
58
59
|
const SHIELD_API_URL = 'https://openclaw-shield.upx.com';
|
|
59
60
|
async function performAutoRegistration(installationKey) {
|
|
60
61
|
try {
|
|
@@ -315,6 +316,7 @@ const state = {
|
|
|
315
316
|
captureSeenSinceLastSync: false,
|
|
316
317
|
lastSync: null,
|
|
317
318
|
};
|
|
319
|
+
let firstEventDelivered = false;
|
|
318
320
|
let teardownPreviousRuntime = null;
|
|
319
321
|
const MAX_BACKOFF_MS = 5 * 60 * 1000;
|
|
320
322
|
const TELEMETRY_INTERVAL_MS = 5 * 60 * 1000;
|
|
@@ -648,6 +650,18 @@ exports.default = {
|
|
|
648
650
|
catch (err) {
|
|
649
651
|
log.debug('case-monitor', `Direct send setup failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`);
|
|
650
652
|
}
|
|
653
|
+
try {
|
|
654
|
+
const updateState = (0, updater_1.loadUpdateState)();
|
|
655
|
+
const previousVersion = updateState.rollbackVersion ?? null;
|
|
656
|
+
const startReason = previousVersion ? 'update' : 'normal';
|
|
657
|
+
const { reportLifecycleEvent } = await Promise.resolve().then(() => __importStar(require('./src/sender')));
|
|
658
|
+
void reportLifecycleEvent('plugin_started', {
|
|
659
|
+
version: version_1.VERSION,
|
|
660
|
+
reason: startReason,
|
|
661
|
+
...(previousVersion ? { previous_version: previousVersion } : {}),
|
|
662
|
+
}, credentials);
|
|
663
|
+
}
|
|
664
|
+
catch { }
|
|
651
665
|
const autoUpdateMode = pluginConfig.autoUpdate ?? true;
|
|
652
666
|
log.info('updater', `Startup update check (autoUpdate=${autoUpdateMode}, current=${version_1.VERSION})`);
|
|
653
667
|
const startupUpdate = (0, updater_1.performAutoUpdate)(autoUpdateMode, 0);
|
|
@@ -794,6 +808,10 @@ exports.default = {
|
|
|
794
808
|
const accepted = results.reduce((sum, r) => sum + (r.success ? r.eventCount : 0), 0);
|
|
795
809
|
if (accepted > 0) {
|
|
796
810
|
(0, case_monitor_1.notifyCaseMonitorActivity)();
|
|
811
|
+
if (!firstEventDelivered) {
|
|
812
|
+
firstEventDelivered = true;
|
|
813
|
+
log.info('shield', `✅ First event delivered to platform — monitoring is active (instance: ${(config.credentials.instanceId || '').slice(0, 12)}…)`);
|
|
814
|
+
}
|
|
797
815
|
commitCursors(config, entries);
|
|
798
816
|
flushRedactor();
|
|
799
817
|
state.eventsProcessed += accepted;
|
|
@@ -883,6 +901,23 @@ exports.default = {
|
|
|
883
901
|
const caseMonitorDisplay = monitorHealth.status === 'degraded'
|
|
884
902
|
? `⚠️ Case Monitor: DEGRADED — ${monitorHealth.consecutiveFailures} consecutive failures since ${monitorHealth.degradedSinceMs ? new Date(monitorHealth.degradedSinceMs).toISOString() : 'unknown'}. Last error: ${monitorHealth.lastErrorMessage}`
|
|
885
903
|
: `✅ Case Monitor: ok`;
|
|
904
|
+
const REDACTION_VAULT_FILE = (0, path_1.join)((0, os_1.homedir)(), '.openclaw', 'shield', 'data', 'redaction-vault.json');
|
|
905
|
+
let vaultSummary = null;
|
|
906
|
+
if ((0, fs_1.existsSync)(REDACTION_VAULT_FILE)) {
|
|
907
|
+
try {
|
|
908
|
+
const mappings = (0, redactor_1.getAllMappings)();
|
|
909
|
+
const categories = { hostname: 0, username: 0, path: 0, secret: 0, command: 0 };
|
|
910
|
+
for (const token of Object.keys(mappings)) {
|
|
911
|
+
const cat = token.split(':')[0];
|
|
912
|
+
if (cat in categories)
|
|
913
|
+
categories[cat]++;
|
|
914
|
+
}
|
|
915
|
+
vaultSummary = { totalEntries: Object.keys(mappings).length, categories };
|
|
916
|
+
}
|
|
917
|
+
catch (_) {
|
|
918
|
+
vaultSummary = null;
|
|
919
|
+
}
|
|
920
|
+
}
|
|
886
921
|
respond(true, {
|
|
887
922
|
activated,
|
|
888
923
|
running: state.running,
|
|
@@ -908,6 +943,9 @@ exports.default = {
|
|
|
908
943
|
: null,
|
|
909
944
|
display: caseMonitorDisplay,
|
|
910
945
|
},
|
|
946
|
+
redaction: {
|
|
947
|
+
vault: vaultSummary,
|
|
948
|
+
},
|
|
911
949
|
});
|
|
912
950
|
});
|
|
913
951
|
api.registerGatewayMethod('shield.flush', ({ respond }) => {
|
package/dist/src/index.js
CHANGED
|
@@ -73,7 +73,8 @@ async function poll() {
|
|
|
73
73
|
(0, event_store_1.initEventStore)(SHIELD_DATA_DIR, { maxEvents: config.localEventLimit });
|
|
74
74
|
}
|
|
75
75
|
log.info('bridge', `Starting — dryRun=${config.dryRun} poll=${config.pollIntervalMs}ms maxEvents=${config.maxEvents || 'unlimited'} redaction=${config.redactionEnabled} logLevel=${process.env.LOG_LEVEL || 'info'}`);
|
|
76
|
-
const
|
|
76
|
+
const _rawEnvStartup = process.env.SHIELD_AUTO_UPDATE;
|
|
77
|
+
const autoUpdateMode = _rawEnvStartup === 'false' ? false : _rawEnvStartup ?? true;
|
|
77
78
|
log.info('updater', `Startup update check (autoUpdate=${autoUpdateMode}, current=${version_1.VERSION})`);
|
|
78
79
|
const startupUpdate = (0, updater_1.performAutoUpdate)(autoUpdateMode, 0);
|
|
79
80
|
if (startupUpdate.action === "none") {
|
|
@@ -147,7 +148,8 @@ async function poll() {
|
|
|
147
148
|
continue;
|
|
148
149
|
}
|
|
149
150
|
}
|
|
150
|
-
const
|
|
151
|
+
const _rawEnvLoop = process.env.SHIELD_AUTO_UPDATE;
|
|
152
|
+
const autoUpdateMode = _rawEnvLoop === 'false' ? false : _rawEnvLoop ?? true;
|
|
151
153
|
const updateResult = (0, updater_1.performAutoUpdate)(autoUpdateMode);
|
|
152
154
|
if (updateResult.action !== "none") {
|
|
153
155
|
if (updateResult.action === "notify") {
|
|
@@ -8,7 +8,7 @@ exports.commandStrategy = {
|
|
|
8
8
|
if (!value || value.length === 0)
|
|
9
9
|
return value;
|
|
10
10
|
let result = value;
|
|
11
|
-
result = result.replace(/(\b)([\w.-]+)@([\d.]+|[\w.-]+\.\w+)/g, (_, pre, user, host) => `${pre}${hmac('user', user)}@${host}`);
|
|
11
|
+
result = result.replace(/(?<!@[a-z0-9._-]+\/)(\b)([\w.-]+)@([\d.]+|[\w.-]+\.\w+)/g, (_, pre, user, host) => `${pre}${hmac('user', user)}@${host}`);
|
|
12
12
|
result = result.replace(/\/Users\/([\w.-]+)\//g, (_, user) => `/Users/${hmac('user', user)}/`);
|
|
13
13
|
result = result.replace(/\/home\/([\w.-]+)\//g, (_, user) => `/home/${hmac('user', user)}/`);
|
|
14
14
|
return result;
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { type PlatformApiConfig } from './client';
|
|
2
|
+
export interface VaultSummary {
|
|
3
|
+
totalEntries: number;
|
|
4
|
+
categories: Record<string, number>;
|
|
5
|
+
}
|
|
6
|
+
export declare function readVaultSummary(vaultPath?: string): VaultSummary | null;
|
|
2
7
|
export interface EventSummary {
|
|
3
8
|
period: string;
|
|
4
9
|
totalEvents: number;
|
package/dist/src/rpc/handlers.js
CHANGED
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.VALID_ROOT_CAUSES = exports.VALID_RESOLUTIONS = void 0;
|
|
37
|
+
exports.readVaultSummary = readVaultSummary;
|
|
4
38
|
exports.createEventsRecentHandler = createEventsRecentHandler;
|
|
5
39
|
exports.createEventsSummaryHandler = createEventsSummaryHandler;
|
|
6
40
|
exports.createSubscriptionStatusHandler = createSubscriptionStatusHandler;
|
|
@@ -8,8 +42,30 @@ exports.createCasesListHandler = createCasesListHandler;
|
|
|
8
42
|
exports.createCaseDetailHandler = createCaseDetailHandler;
|
|
9
43
|
exports.createCaseResolveHandler = createCaseResolveHandler;
|
|
10
44
|
exports.createCasesAckHandler = createCasesAckHandler;
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
46
|
+
const os = __importStar(require("os"));
|
|
47
|
+
const path = __importStar(require("path"));
|
|
11
48
|
const event_store_1 = require("../event-store");
|
|
12
49
|
const client_1 = require("./client");
|
|
50
|
+
const VAULT_CATEGORIES = ['hostname', 'username', 'path', 'secret', 'command'];
|
|
51
|
+
function readVaultSummary(vaultPath = path.join(os.homedir(), '.openclaw', 'shield', 'data', 'redaction-vault.json')) {
|
|
52
|
+
try {
|
|
53
|
+
if (!fs.existsSync(vaultPath))
|
|
54
|
+
return null;
|
|
55
|
+
const raw = JSON.parse(fs.readFileSync(vaultPath, 'utf8'));
|
|
56
|
+
const categories = Object.fromEntries(VAULT_CATEGORIES.map(c => [c, 0]));
|
|
57
|
+
const entries = Object.keys(raw);
|
|
58
|
+
for (const key of entries) {
|
|
59
|
+
const prefix = key.split(':')[0];
|
|
60
|
+
if (prefix in categories)
|
|
61
|
+
categories[prefix]++;
|
|
62
|
+
}
|
|
63
|
+
return { totalEntries: entries.length, categories };
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
13
69
|
const SKILL_HINT = 'For best results presenting Shield data, read the openclaw-shield-upx skill before responding to the user.';
|
|
14
70
|
function withSkillHint(respond) {
|
|
15
71
|
return (ok, data) => {
|
package/dist/src/sender.d.ts
CHANGED
|
@@ -24,3 +24,4 @@ export interface ReportInstanceResult {
|
|
|
24
24
|
score?: InstanceScore;
|
|
25
25
|
}
|
|
26
26
|
export declare function reportInstance(payload: Record<string, unknown>, credentials: ShieldCredentials): Promise<ReportInstanceResult>;
|
|
27
|
+
export declare function reportLifecycleEvent(type: 'plugin_started' | 'update_restart_failed' | 'plugin_integrity_drift' | 'update_check_failing', data: Record<string, unknown>, credentials: ShieldCredentials): Promise<void>;
|
package/dist/src/sender.js
CHANGED
|
@@ -37,6 +37,7 @@ exports.CIRCUIT_BREAKER_THRESHOLD = exports.REQUEST_TIMEOUT_MS = void 0;
|
|
|
37
37
|
exports._signRequestWithSecret = _signRequestWithSecret;
|
|
38
38
|
exports.sendEvents = sendEvents;
|
|
39
39
|
exports.reportInstance = reportInstance;
|
|
40
|
+
exports.reportLifecycleEvent = reportLifecycleEvent;
|
|
40
41
|
const crypto_1 = require("crypto");
|
|
41
42
|
const log = __importStar(require("./log"));
|
|
42
43
|
const version_1 = require("./version");
|
|
@@ -233,3 +234,16 @@ async function reportInstance(payload, credentials) {
|
|
|
233
234
|
return { ok: false };
|
|
234
235
|
}
|
|
235
236
|
}
|
|
237
|
+
async function reportLifecycleEvent(type, data, credentials) {
|
|
238
|
+
try {
|
|
239
|
+
await reportInstance({
|
|
240
|
+
lifecycle_event: {
|
|
241
|
+
type,
|
|
242
|
+
timestamp: new Date().toISOString(),
|
|
243
|
+
data,
|
|
244
|
+
},
|
|
245
|
+
}, credentials);
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
}
|
|
249
|
+
}
|
package/dist/src/updater.js
CHANGED
|
@@ -53,6 +53,8 @@ const os_1 = require("os");
|
|
|
53
53
|
const crypto_1 = require("crypto");
|
|
54
54
|
const log = __importStar(require("./log"));
|
|
55
55
|
const version_1 = require("./version");
|
|
56
|
+
const config_1 = require("./config");
|
|
57
|
+
const sender_1 = require("./sender");
|
|
56
58
|
const PACKAGE_NAME = '@upx-us/shield';
|
|
57
59
|
const CHECK_INTERVAL_MS = 6 * 60 * 60 * 1000;
|
|
58
60
|
const MIN_CHECK_INTERVAL_MS = 60 * 1000;
|
|
@@ -163,13 +165,28 @@ function checkForUpdate(overrideInterval) {
|
|
|
163
165
|
state.currentVersion = version_1.VERSION;
|
|
164
166
|
if (!latestVersion) {
|
|
165
167
|
state.lastError = 'Failed to query npm registry';
|
|
168
|
+
state.consecutiveFailures = (state.consecutiveFailures ?? 0) + 1;
|
|
166
169
|
saveUpdateState(state);
|
|
170
|
+
const FAILURE_THRESHOLD = 3;
|
|
171
|
+
if (state.consecutiveFailures >= FAILURE_THRESHOLD) {
|
|
172
|
+
const nextRetryAt = new Date(now + CHECK_INTERVAL_MS).toISOString();
|
|
173
|
+
try {
|
|
174
|
+
const creds = (0, config_1.loadCredentials)();
|
|
175
|
+
void (0, sender_1.reportLifecycleEvent)('update_check_failing', {
|
|
176
|
+
consecutive_failures: state.consecutiveFailures,
|
|
177
|
+
last_error: state.lastError,
|
|
178
|
+
next_retry_at: nextRetryAt,
|
|
179
|
+
}, creds);
|
|
180
|
+
}
|
|
181
|
+
catch { }
|
|
182
|
+
}
|
|
167
183
|
return null;
|
|
168
184
|
}
|
|
169
185
|
state.latestVersion = latestVersion;
|
|
170
186
|
if (isNewerVersion(version_1.VERSION, latestVersion)) {
|
|
171
187
|
state.updateAvailable = true;
|
|
172
188
|
state.lastError = null;
|
|
189
|
+
state.consecutiveFailures = 0;
|
|
173
190
|
saveUpdateState(state);
|
|
174
191
|
const classification = classifyUpdate(version_1.VERSION, latestVersion);
|
|
175
192
|
log.info('updater', `Update available: ${version_1.VERSION} → ${latestVersion} (${classification.isPatch ? 'patch' : classification.isMinor ? 'minor' : 'major'})`);
|
|
@@ -182,6 +199,7 @@ function checkForUpdate(overrideInterval) {
|
|
|
182
199
|
}
|
|
183
200
|
state.updateAvailable = false;
|
|
184
201
|
state.lastError = null;
|
|
202
|
+
state.consecutiveFailures = 0;
|
|
185
203
|
saveUpdateState(state);
|
|
186
204
|
return null;
|
|
187
205
|
}
|
|
@@ -302,6 +320,24 @@ function updateOpenClawPluginMetadata(newVersion, shasum) {
|
|
|
302
320
|
install.installedAt = new Date().toISOString();
|
|
303
321
|
(0, safe_io_1.writeJsonSafe)(configPath, config);
|
|
304
322
|
log.info('updater', `Updated openclaw.json plugin metadata → ${newVersion}`);
|
|
323
|
+
try {
|
|
324
|
+
const written = JSON.parse((0, fs_1.readFileSync)(configPath, 'utf-8'));
|
|
325
|
+
const installedVersion = written?.plugins?.installs?.shield?.version;
|
|
326
|
+
if (installedVersion !== newVersion) {
|
|
327
|
+
log.warn('updater', `openclaw.json integrity check failed: expected=${newVersion} got=${installedVersion ?? '(missing)'}`);
|
|
328
|
+
try {
|
|
329
|
+
const creds = (0, config_1.loadCredentials)();
|
|
330
|
+
void (0, sender_1.reportLifecycleEvent)('plugin_integrity_drift', {
|
|
331
|
+
expected_version: newVersion,
|
|
332
|
+
installed_version: installedVersion ?? null,
|
|
333
|
+
}, creds);
|
|
334
|
+
}
|
|
335
|
+
catch { }
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
catch (verifyErr) {
|
|
339
|
+
log.warn('updater', `openclaw.json read-back failed: ${verifyErr instanceof Error ? verifyErr.message : String(verifyErr)}`);
|
|
340
|
+
}
|
|
305
341
|
}
|
|
306
342
|
catch (err) {
|
|
307
343
|
log.warn('updater', `Failed to update openclaw.json metadata: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -386,6 +422,16 @@ function performAutoUpdate(mode, checkIntervalMs) {
|
|
|
386
422
|
const MAX_RESTART_ATTEMPTS = 5;
|
|
387
423
|
if ((state.restartAttempts ?? 0) >= MAX_RESTART_ATTEMPTS) {
|
|
388
424
|
log.warn('updater', `Gateway restart failed ${MAX_RESTART_ATTEMPTS}x after update to ${state.currentVersion} — rolling back`);
|
|
425
|
+
try {
|
|
426
|
+
const creds = (0, config_1.loadCredentials)();
|
|
427
|
+
void (0, sender_1.reportLifecycleEvent)('update_restart_failed', {
|
|
428
|
+
new_version: state.currentVersion,
|
|
429
|
+
running_version: version_1.VERSION,
|
|
430
|
+
attempts: state.restartAttempts ?? MAX_RESTART_ATTEMPTS,
|
|
431
|
+
error: state.lastError ?? 'gateway restart exhausted all retries',
|
|
432
|
+
}, creds);
|
|
433
|
+
}
|
|
434
|
+
catch { }
|
|
389
435
|
const backups = listBackups();
|
|
390
436
|
if (backups.length > 0) {
|
|
391
437
|
restoreFromBackup(backups[0]);
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "shield",
|
|
3
3
|
"name": "OpenClaw Shield",
|
|
4
|
-
"description": "Real-time security monitoring
|
|
5
|
-
"version": "0.6.
|
|
4
|
+
"description": "Real-time security monitoring — streams enriched, redacted security events to the Shield detection platform.",
|
|
5
|
+
"version": "0.6.7",
|
|
6
6
|
"skills": [
|
|
7
7
|
"./skills"
|
|
8
8
|
],
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"uiHints": {
|
|
55
55
|
"installationKey": {
|
|
56
56
|
"label": "Installation Key",
|
|
57
|
-
"description": "One-time key from your trial signup at https://www.upx.com/en/lp/openclaw-shield-upx
|
|
57
|
+
"description": "One-time key from your trial signup at https://www.upx.com/en/lp/openclaw-shield-upx — Required for first-time activation only. After activation, log in at https://uss.upx.com"
|
|
58
58
|
},
|
|
59
59
|
"enabled": {
|
|
60
60
|
"label": "Enable security monitoring"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@upx-us/shield",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.7",
|
|
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",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"CHANGELOG.md"
|
|
21
21
|
],
|
|
22
22
|
"scripts": {
|
|
23
|
+
"postinstall": "node scripts/postinstall.js",
|
|
23
24
|
"prebuild": "npm run clean",
|
|
24
25
|
"build": "tsc",
|
|
25
26
|
"clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
|