@upx-us/shield 0.7.10 → 0.7.12
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 +16 -0
- package/dist/index.js +51 -1
- package/openclaw.plugin.json +10 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,22 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## [0.7.12] — 2026-03-16
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **Plugin showing permanently "Disconnected" after gateway hot-reload** — when the OpenClaw gateway reloaded the plugin module, a race condition between teardown and startup caused new startup attempts to silently abort. The previous instance's timers kept running but were invisible to the status command, resulting in permanent "Disconnected" status and missed telemetry cycles. The teardown is now properly awaited before startup proceeds.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## [0.7.11] — 2026-03-16
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **Debug logging mode** (`debugLog: true`) — writes timestamped logs to `~/.openclaw/shield/logs/shield-debug.log`. Captures the full startup sequence with numbered checkpoints (1–11 + SIGTERM) so disconnection issues can be pinpointed exactly. Off by default — safe on all existing installs.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
7
23
|
## [0.7.10] — 2026-03-16
|
|
8
24
|
|
|
9
25
|
### Added
|
package/dist/index.js
CHANGED
|
@@ -319,6 +319,7 @@ const state = {
|
|
|
319
319
|
};
|
|
320
320
|
let firstEventDelivered = false;
|
|
321
321
|
let teardownPreviousRuntime = null;
|
|
322
|
+
let pendingTeardown = null;
|
|
322
323
|
let serviceStartFn = null;
|
|
323
324
|
const MAX_BACKOFF_MS = 5 * 60 * 1000;
|
|
324
325
|
const TELEMETRY_INTERVAL_MS = 5 * 60 * 1000;
|
|
@@ -488,6 +489,38 @@ exports.default = {
|
|
|
488
489
|
(0, log_1.setAdapter)(gatewayAdapter);
|
|
489
490
|
const pluginConfig = (api.pluginConfig ?? {});
|
|
490
491
|
log.debug('shield', 'Plugin config received', maskPluginConfigForLogs(pluginConfig));
|
|
492
|
+
const debugLogEnabled = pluginConfig.debugLog === true;
|
|
493
|
+
if (debugLogEnabled) {
|
|
494
|
+
try {
|
|
495
|
+
const { appendFileSync, mkdirSync } = require('fs');
|
|
496
|
+
const { join: pathJoin } = require('path');
|
|
497
|
+
const debugLogDir = pathJoin((0, os_1.homedir)(), '.openclaw', 'shield', 'logs');
|
|
498
|
+
const debugLogPath = pathJoin(debugLogDir, 'shield-debug.log');
|
|
499
|
+
mkdirSync(debugLogDir, { recursive: true });
|
|
500
|
+
const ts = () => new Date().toISOString();
|
|
501
|
+
const writeLine = (level, tag, msg, extra) => {
|
|
502
|
+
try {
|
|
503
|
+
const line = `${ts()} [${level.padEnd(5)}] [${tag}] ${msg}${extra !== undefined ? ' ' + JSON.stringify(extra) : ''}\n`;
|
|
504
|
+
appendFileSync(debugLogPath, line);
|
|
505
|
+
}
|
|
506
|
+
catch { }
|
|
507
|
+
};
|
|
508
|
+
const teeAdapter = {
|
|
509
|
+
debug(tag, msg, data) { gatewayAdapter.debug(tag, msg, data); writeLine('DEBUG', tag, msg, data); },
|
|
510
|
+
info(tag, msg) { gatewayAdapter.info(tag, msg); writeLine('INFO', tag, msg); },
|
|
511
|
+
warn(tag, msg) { gatewayAdapter.warn(tag, msg); writeLine('WARN', tag, msg); },
|
|
512
|
+
error(tag, msg, err) { gatewayAdapter.error(tag, msg, err); writeLine('ERROR', tag, msg, err ? String(err) : undefined); },
|
|
513
|
+
};
|
|
514
|
+
(0, log_1.setAdapter)(teeAdapter);
|
|
515
|
+
appendFileSync(debugLogPath, `\n${'─'.repeat(80)}\n` +
|
|
516
|
+
`${ts()} [SHIELD DEBUG SESSION START] v${version_1.VERSION}\n` +
|
|
517
|
+
`${'─'.repeat(80)}\n`);
|
|
518
|
+
log.info('shield', `Debug logging active → ${debugLogPath}`);
|
|
519
|
+
}
|
|
520
|
+
catch (err) {
|
|
521
|
+
log.warn('shield', `Failed to init debug log file: ${err instanceof Error ? err.message : String(err)}`);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
491
524
|
if (pluginConfig.enabled === false) {
|
|
492
525
|
log.info('shield', 'Monitoring disabled via config (enabled: false)');
|
|
493
526
|
return;
|
|
@@ -543,13 +576,17 @@ exports.default = {
|
|
|
543
576
|
}
|
|
544
577
|
};
|
|
545
578
|
if (teardownPreviousRuntime) {
|
|
546
|
-
|
|
579
|
+
pendingTeardown = teardownPreviousRuntime()
|
|
547
580
|
.catch((err) => log.warn('shield', `Runtime cleanup before re-register failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
548
581
|
}
|
|
549
582
|
teardownPreviousRuntime = () => cleanupRuntime({ markStopped: true, resetGuard: true, flushRedactor: false });
|
|
550
583
|
const serviceDefinition = {
|
|
551
584
|
id: 'shield-monitor',
|
|
552
585
|
async start() {
|
|
586
|
+
if (pendingTeardown) {
|
|
587
|
+
await pendingTeardown.catch(() => { });
|
|
588
|
+
pendingTeardown = null;
|
|
589
|
+
}
|
|
553
590
|
if (!startGuard.begin()) {
|
|
554
591
|
log.debug('shield', 'Start requested while service is already started or in progress');
|
|
555
592
|
return;
|
|
@@ -557,8 +594,10 @@ exports.default = {
|
|
|
557
594
|
try {
|
|
558
595
|
await cleanupRuntime({ markStopped: false, resetGuard: false, flushRedactor: false });
|
|
559
596
|
const activeGeneration = ++runtimeGeneration;
|
|
597
|
+
log.info('shield', `[checkpoint:1] Service start() entered — generation=${activeGeneration}`);
|
|
560
598
|
let credentials = (0, config_1.loadCredentials)();
|
|
561
599
|
let validCreds = hasValidCredentials(credentials);
|
|
600
|
+
log.info('shield', `[checkpoint:2] Credentials loaded — valid=${validCreds} instanceId=${credentials?.instanceId ? credentials.instanceId.slice(0, 8) + '…' : 'missing'}`);
|
|
562
601
|
if (!validCreds && installationKey) {
|
|
563
602
|
log.info('shield', 'Installation key found — activating Shield (first-time setup)...');
|
|
564
603
|
const autoCreds = await performAutoRegistration(installationKey);
|
|
@@ -594,9 +633,12 @@ exports.default = {
|
|
|
594
633
|
const persistedStats = readAllTimeStats();
|
|
595
634
|
if (persistedStats.lastSync)
|
|
596
635
|
state.lastSync = persistedStats.lastSync;
|
|
636
|
+
log.info('shield', `[checkpoint:3] Config loaded — sessionDirs=${config.sessionDirs.length} poll=${config.pollIntervalMs}ms dryRun=${config.dryRun}`);
|
|
597
637
|
log.info('shield', `Starting Shield v${version_1.VERSION} (poll: ${config.pollIntervalMs}ms, dryRun: ${config.dryRun})`);
|
|
598
638
|
(0, exclusions_1.initExclusions)((0, path_1.join)((0, os_1.homedir)(), '.openclaw', 'shield', 'data'));
|
|
639
|
+
log.info('shield', '[checkpoint:4] Exclusions initialized');
|
|
599
640
|
(0, case_monitor_1.initCaseMonitor)((0, path_1.join)((0, os_1.homedir)(), '.openclaw', 'shield', 'data'));
|
|
641
|
+
log.info('shield', '[checkpoint:5] Case monitor initialized');
|
|
600
642
|
if (config.localEventBuffer) {
|
|
601
643
|
(0, event_store_1.initEventStore)((0, path_1.join)((0, os_1.homedir)(), '.openclaw', 'shield', 'data'), { maxEvents: config.localEventLimit });
|
|
602
644
|
}
|
|
@@ -670,8 +712,10 @@ exports.default = {
|
|
|
670
712
|
catch { }
|
|
671
713
|
const autoUpdateMode = pluginConfig.autoUpdate ?? true;
|
|
672
714
|
const _bootState = (0, updater_1.loadUpdateState)();
|
|
715
|
+
log.info('shield', `[checkpoint:6] Pre-update-check — autoUpdate=${autoUpdateMode} pendingRestart=${_bootState.pendingRestart} updateAvailable=${_bootState.updateAvailable} latestVersion=${_bootState.latestVersion}`);
|
|
673
716
|
log.info('updater', `Startup update check (autoUpdate=${autoUpdateMode}, current=${version_1.VERSION}, pendingRestart=${_bootState.pendingRestart})`);
|
|
674
717
|
const startupUpdate = (0, updater_1.performAutoUpdate)(autoUpdateMode, _bootState.pendingRestart ? undefined : 0);
|
|
718
|
+
log.info('shield', `[checkpoint:7] Update check done — action=${startupUpdate.action}`);
|
|
675
719
|
if (startupUpdate.action === 'updated') {
|
|
676
720
|
log.info('updater', startupUpdate.message);
|
|
677
721
|
const restarted = (0, updater_1.requestGatewayRestart)();
|
|
@@ -703,10 +747,12 @@ exports.default = {
|
|
|
703
747
|
const { sendEvents, reportInstance } = await Promise.resolve().then(() => __importStar(require('./src/sender')));
|
|
704
748
|
const { init: initRedactor, flush: flushRedactor, redactEvent } = await Promise.resolve().then(() => __importStar(require('./src/redactor')));
|
|
705
749
|
const { validate } = await Promise.resolve().then(() => __importStar(require('./src/validator')));
|
|
750
|
+
log.info('shield', '[checkpoint:8] Dynamic imports loaded');
|
|
706
751
|
if (config.redactionEnabled)
|
|
707
752
|
initRedactor();
|
|
708
753
|
state.running = true;
|
|
709
754
|
persistState();
|
|
755
|
+
log.info('shield', '[checkpoint:9] state.running=true — entering poll loop');
|
|
710
756
|
const runTelemetry = async () => {
|
|
711
757
|
if (!state.running || activeGeneration !== runtimeGeneration)
|
|
712
758
|
return;
|
|
@@ -748,6 +794,7 @@ exports.default = {
|
|
|
748
794
|
}
|
|
749
795
|
};
|
|
750
796
|
const runTelemetrySingleflight = createSingleflightRunner(runTelemetry);
|
|
797
|
+
log.info('shield', '[checkpoint:9a] Firing initial telemetry');
|
|
751
798
|
runTelemetrySingleflight().catch((err) => log.error('shield', `Telemetry error: ${err instanceof Error ? err.message : String(err)}`));
|
|
752
799
|
telemetryHandle = setInterval(() => {
|
|
753
800
|
if (activeGeneration !== runtimeGeneration || !state.running)
|
|
@@ -904,15 +951,18 @@ exports.default = {
|
|
|
904
951
|
});
|
|
905
952
|
}, interval);
|
|
906
953
|
};
|
|
954
|
+
log.info('shield', '[checkpoint:10] First poll scheduled');
|
|
907
955
|
schedulePoll();
|
|
908
956
|
onSignalHandler = async () => {
|
|
909
957
|
if (!state.running)
|
|
910
958
|
return;
|
|
959
|
+
log.info('shield', '[checkpoint:SIGTERM] SIGTERM received — shutting down');
|
|
911
960
|
await cleanupRuntime({ markStopped: true, resetGuard: true, flushRedactor: true });
|
|
912
961
|
log.info('shield', 'Service stopped (signal)');
|
|
913
962
|
};
|
|
914
963
|
process.once('SIGTERM', onSignalHandler);
|
|
915
964
|
process.once('SIGINT', onSignalHandler);
|
|
965
|
+
log.info('shield', '[checkpoint:11] Startup complete — service running');
|
|
916
966
|
startGuard.endSuccess();
|
|
917
967
|
}
|
|
918
968
|
catch (err) {
|
package/openclaw.plugin.json
CHANGED
|
@@ -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.7.
|
|
5
|
+
"version": "0.7.12",
|
|
6
6
|
"skills": [
|
|
7
7
|
"./skills"
|
|
8
8
|
],
|
|
@@ -48,6 +48,11 @@
|
|
|
48
48
|
],
|
|
49
49
|
"default": true,
|
|
50
50
|
"description": "Auto-update mode: true (auto-update patch versions), false (disabled), or 'notify-only' (log available updates without installing)."
|
|
51
|
+
},
|
|
52
|
+
"debugLog": {
|
|
53
|
+
"type": "boolean",
|
|
54
|
+
"default": false,
|
|
55
|
+
"description": "Enable verbose debug logging to ~/.openclaw/shield/logs/shield-debug.log. Use only when diagnosing connectivity issues."
|
|
51
56
|
}
|
|
52
57
|
}
|
|
53
58
|
},
|
|
@@ -74,6 +79,10 @@
|
|
|
74
79
|
"autoUpdate": {
|
|
75
80
|
"label": "Auto-update mode",
|
|
76
81
|
"description": "true = auto-install patch updates, 'notify-only' = log only, false = disabled"
|
|
82
|
+
},
|
|
83
|
+
"debugLog": {
|
|
84
|
+
"label": "Debug logging",
|
|
85
|
+
"description": "Writes detailed startup and lifecycle logs to a file for support diagnosis"
|
|
77
86
|
}
|
|
78
87
|
},
|
|
79
88
|
"clawhub": {
|
package/package.json
CHANGED