sporades 0.9.28 → 0.9.29
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/CHANGES.md +11 -157
- package/bin/sporades-host-helper.js +5 -1
- package/bin/sporades.js +167 -30
- package/dist/cli/cli-version.d.ts +1 -1
- package/dist/cli/cli-version.js +1 -1
- package/dist/file-ingress-runtime.d.ts.map +1 -1
- package/dist/file-ingress-runtime.js +148 -35
- package/dist/file-ingress-runtime.js.map +1 -1
- package/dist/generated-source-manifest.json +2 -2
- package/dist/server-runtime-source.d.ts +3 -1
- package/dist/server-runtime-source.d.ts.map +1 -1
- package/dist/server-runtime-source.js +37 -1
- package/dist/server-runtime-source.js.map +1 -1
- package/package.json +1 -1
package/CHANGES.md
CHANGED
|
@@ -2,172 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased - 2026-09-23
|
|
4
4
|
|
|
5
|
-
Changes since v0.9.
|
|
6
|
-
|
|
7
|
-
### 🚀 Features
|
|
8
|
-
|
|
9
|
-
- Verify prerender parity and track renderer dependencies in Dev (392b1bf2).
|
|
10
|
-
- Expose deliberate prerender browser handover (daa88f83).
|
|
11
|
-
- Complete ordered prerender placement and diagnostics (d5aa8bbe).
|
|
12
|
-
- Emit one Vite prerender fragment (769f523d).
|
|
5
|
+
Changes since v0.9.28.
|
|
13
6
|
|
|
14
7
|
### 🐛 Bug Fixes
|
|
15
8
|
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
- Observe alternatives to successful renderer imports (6030a36d).
|
|
23
|
-
- Keep declarative shadow hosts within fragment ownership (a4684e8e).
|
|
24
|
-
- Reject inert reserved boundaries in final HTML (7fd93332).
|
|
25
|
-
- Observe nearer manifestless renderer packages (fdced03b).
|
|
26
|
-
- Bound and normalize unknown marker diagnostics (f695fea2).
|
|
27
|
-
- Bound module-scope Annex B wrapper aliases (fe313576).
|
|
28
|
-
- Normalize CommonJS renderer default exports (20d92eb4).
|
|
29
|
-
- Track renderer tsconfig mappings and config inputs (51c875ed).
|
|
30
|
-
- Separate parameter and body environments (da3772a5).
|
|
31
|
-
- Reject synthetic CommonJS wrapper arguments (adbc8ba3).
|
|
32
|
-
- Verify final Vite fragment ownership (ce8a333e).
|
|
33
|
-
- Reject dynamic CommonJS with scope (9183e3c2).
|
|
34
|
-
- Verify dismissal restores the authored DOM (9edefe18).
|
|
35
|
-
- Preserve source import.meta through aliases (ea6f8a2c).
|
|
36
|
-
- Diagnose malformed named marker directives (30083989).
|
|
37
|
-
- Reject shadowed direct-eval call syntax (341c4a49).
|
|
38
|
-
- Preserve author ancestors and implicit wrapper ownership (bb4733a5).
|
|
39
|
-
- Watch successful package-resolution manifests (c8c7070d).
|
|
40
|
-
- Use browser HTML parsing and reject direct CJS eval (75b44468).
|
|
41
|
-
- Watch package-import alias manifests and targets (0ceff350).
|
|
42
|
-
- Observe runtime module resolution attempts (2dd1181c).
|
|
43
|
-
- Reject fragment document-root mutations (525fcd9c).
|
|
44
|
-
- Finalize HTML before output-derived Vite assets (4cb4703c).
|
|
45
|
-
- Detect reserved comments through HTML parsing (b0a753de).
|
|
46
|
-
- Retain all root CommonJS wrapper redeclarations (42f0a7a8).
|
|
47
|
-
- Watch missing computed package export roots (b512d596).
|
|
48
|
-
- Initialize CommonJS source module locations (6631c412).
|
|
49
|
-
- Place fragments after Vite composes deferred tags (95a5fdff).
|
|
50
|
-
- Track failed local imports without duplicate rebuilds (122c92d8).
|
|
51
|
-
- Preserve failure envelopes and diagnose empty configurations (389159b1).
|
|
52
|
-
- Preserve module.require and TypeScript CommonJS semantics (0483d227).
|
|
53
|
-
- Retain worker until private completion is consumed (6db56268).
|
|
54
|
-
- Recover failed renderer builds after package installation (2924c02c).
|
|
55
|
-
- Reject fragment-created ancestors spanning boundary ends (c2678825).
|
|
56
|
-
- Isolate bootstrap completion from renderer progress messages (3a21a2e4).
|
|
57
|
-
- Redact computed runtime dependency diagnostics (9b5c776e).
|
|
58
|
-
- Track attempted CommonJS renderer dependencies before evaluation (f647e116).
|
|
59
|
-
- Reject parser-moved fragment content before publication (688e3ca4).
|
|
60
|
-
- Preserve quoted doctype identifiers during placement (efd3b86f).
|
|
61
|
-
- Reject untrackable runtime require of ESM render dependencies (d09a8737).
|
|
62
|
-
- Preserve foreign-content CDATA during placement (0aa70731).
|
|
63
|
-
- Validate source boundaries and dismiss parsed DOM ranges (054aebb3).
|
|
64
|
-
- Retain CommonJS wrapper values through var declarations (d1154712).
|
|
65
|
-
- Protect prerender boundaries and regenerate public API docs (635070d8).
|
|
66
|
-
- Preserve writable require and bound dynamic imports (9fdf7bf8).
|
|
67
|
-
- Isolate prerender execution and writable module locations (d7e83717).
|
|
68
|
-
- Merge renderer diagnostic aliases (07b0d17f).
|
|
69
|
-
- Apply file URL alias boundaries (5c030678).
|
|
70
|
-
- Redact project-root file URL equality (0f6545e8).
|
|
71
|
-
- Map raw file URL diagnostic aliases (5eb2954d).
|
|
72
|
-
- Bound raw file URL redaction (413ec06d).
|
|
73
|
-
- Bound prerender diagnostic aliases (d290f59d).
|
|
74
|
-
- Redact unresolved external file URLs (6516e18a).
|
|
75
|
-
- Redact unresolved external renderer imports (8891bc7a).
|
|
76
|
-
- Preserve nested prerender diagnostic paths (5f5e3fff).
|
|
77
|
-
- Redact hoisted renderer runtime paths (b520367e).
|
|
78
|
-
- Load plain hoisted prerender modules (4d762255).
|
|
79
|
-
- Reject early prerender worker exit (f5aec1a1).
|
|
80
|
-
- Classify ambiguous renderer modules (a10445fd).
|
|
81
|
-
- Classify package-scoped CommonJS renderers (9c3dff53).
|
|
82
|
-
- Preserve renderer hashbang and directives (95b5807c).
|
|
83
|
-
- Preserve renderer class member names (29810c22).
|
|
84
|
-
- Preserve CommonJS wrapper delete semantics (14da5e3e).
|
|
85
|
-
- Preserve CommonJS wrapper assignments (86d06b58).
|
|
86
|
-
- Resolve renderer lexical bindings accurately (e249665d).
|
|
87
|
-
- Preserve static CommonJS renderer imports (513995da).
|
|
88
|
-
- Preserve nested CTS module locations (ebf0db8f).
|
|
89
|
-
- Treat noscript as raw prerender text (e5ed75f4).
|
|
90
|
-
- Preserve nested CommonJS module locations (5920306e).
|
|
91
|
-
- Track HTML attribute value states (aac17b2e).
|
|
92
|
-
- Return honest renderer transform loaders (dc0f509a).
|
|
93
|
-
- Tokenize less-than text safely (96fc6a42).
|
|
94
|
-
- Fail closed on incomplete prerender HTML (b87c34ad).
|
|
95
|
-
- Discover renderer tsconfig per module (930f3f64).
|
|
96
|
-
- Reject Windows renderer module roots (f5400ef0).
|
|
97
|
-
- Bound malformed prerender HTML scanning (9b25a1c7).
|
|
98
|
-
- Preserve renderer tsconfig authority (c6b965e0).
|
|
99
|
-
- Redact encoded project file URLs (0a184995).
|
|
100
|
-
- Preserve renderer import meta URLs (03df87e1).
|
|
101
|
-
- Replace only HTML prerender markers (5020a1f3).
|
|
102
|
-
- Bound hostile renderer message access (17fc79ed).
|
|
103
|
-
- Preserve HTML offsets during case folding (a6a1bbe8).
|
|
104
|
-
- Contain renderer-owned error details (89f91139).
|
|
105
|
-
- Locate prerender fallback body safely (78bf529c).
|
|
106
|
-
- Redact prerender runtime project paths (556df1d4).
|
|
107
|
-
- Execute prerender bundles without ESM cache growth (62506646).
|
|
108
|
-
|
|
109
|
-
### 🔧 Improvements
|
|
110
|
-
|
|
111
|
-
- Expose internal renderer loader mapping (be8d5303).
|
|
112
|
-
|
|
113
|
-
### 📝 Documentation
|
|
114
|
-
|
|
115
|
-
- Link canonical module reference and assert parity (fce2ad85).
|
|
116
|
-
- Verify package-import manifest retargeting (91bb7996).
|
|
117
|
-
- Complete canonical client API requirements (8690e560).
|
|
118
|
-
- Specify prerender in canonical configuration reference (0fee4c1e).
|
|
119
|
-
- Expose multipart limits and runtime bounds (#98) (ad023b9e).
|
|
9
|
+
- Evict only on an unanswered ping and document the heartbeat (66f964e0).
|
|
10
|
+
- Ping idle WebSockets so proxy idle timeouts do not strand pages (7ee9c7f8).
|
|
11
|
+
- Start no freshclam after retained-updater cleanup once shutdown began (0185fc01).
|
|
12
|
+
- Close ClamAV refresh shutdown race and recover crashed clamd (6c23b686).
|
|
13
|
+
- Start degraded on stale ClamAV signatures and allow 26h freshness (79dd3ece).
|
|
14
|
+
- Own ClamAV signature refresh in the Capsule runtime (17193be4).
|
|
120
15
|
|
|
121
16
|
### 🧪 Tests
|
|
122
17
|
|
|
123
|
-
-
|
|
124
|
-
-
|
|
125
|
-
- Redact bare project-root file URLs (6283b5d9).
|
|
126
|
-
- Redact project-root file URL equality (848d96c9).
|
|
127
|
-
- Redact contained and mixed-case file URLs (c242cc3b).
|
|
128
|
-
- Preserve sibling file URL prefixes (5495bdfa).
|
|
129
|
-
- Bound prerender diagnostic root aliases (fbb5c3b1).
|
|
130
|
-
- Redact unresolved external file URLs (004832b6).
|
|
131
|
-
- Redact unresolved external renderer imports (b7c7dabb).
|
|
132
|
-
- Preserve nested prerender diagnostic context (4b42f056).
|
|
133
|
-
- Redact hoisted prerender runtime paths (11b1d918).
|
|
134
|
-
- Cover prerender namespace and worker outcomes (2936ae6e).
|
|
135
|
-
- Fail closed when prerender worker exits (08a703cc).
|
|
136
|
-
- Detect ambiguous renderer module formats (af1963c3).
|
|
137
|
-
- Preserve renderer hashbang and directives (2008d12c).
|
|
138
|
-
- Preserve non-computed renderer member names (a11d2822).
|
|
139
|
-
- Preserve CommonJS wrapper delete semantics (9ef87b2e).
|
|
140
|
-
- Preserve CommonJS wrapper write targets (1de31e18).
|
|
141
|
-
- Preserve renderer lexical shadowing (9452a5cb).
|
|
142
|
-
- Preserve static renderer requires and cache bounds (f572e4ff).
|
|
143
|
-
- Preserve nested CTS renderer paths (3bb7d4a8).
|
|
144
|
-
- Ignore prerender markers inside noscript (f7172af4).
|
|
145
|
-
- Preserve nested CommonJS renderer paths (d40f2302).
|
|
146
|
-
- Specify renderer output loader mapping (cdcd65b2).
|
|
147
|
-
- Tokenize prose and HTML declarations safely (0e71c4e6).
|
|
148
|
-
- Prove extended TSX renderer config (a4da6b3f).
|
|
149
|
-
- Preserve less-than text during marker scanning (3481ad1e).
|
|
150
|
-
- Reject unterminated prerender HTML tags (fdcc0c5f).
|
|
151
|
-
- Discover extended renderer tsconfig (21bc1984).
|
|
152
|
-
- Reject Windows renderer module paths (0f4ea77f).
|
|
153
|
-
- Bound malformed HTML comment recovery (644acc13).
|
|
154
|
-
- Preserve renderer tsconfig semantics (4d1e98a9).
|
|
155
|
-
- Redact encoded renderer file URLs (59c22625).
|
|
156
|
-
- Preserve transitive renderer import meta URL (fad9ea03).
|
|
157
|
-
- Ignore prerender marker text in raw HTML (4d2948d4).
|
|
158
|
-
- Contain hostile renderer message access (d74c1372).
|
|
159
|
-
- Cover Unicode-safe prerender body offsets (77d2d1c4).
|
|
160
|
-
- Reject renderer-owned structured errors (589ab6e9).
|
|
161
|
-
- Cover HTML-aware prerender fallback placement (93a48e19).
|
|
162
|
-
- Cover prerender runtime path redaction (5e2dadb4).
|
|
163
|
-
- Cover prerender execution edge cases (6667a916).
|
|
164
|
-
- Specify one Vite prerender fragment (69ea0c58).
|
|
18
|
+
- Buffer raw WebSocket frames across TCP chunks (e07288dd).
|
|
19
|
+
- Describe the ClamAV freshness gate without a fixed age (b180ac1a).
|
|
165
20
|
|
|
166
21
|
### 📦 Packaging
|
|
167
22
|
|
|
168
|
-
-
|
|
169
|
-
- Include regenerated prerender declaration map (a655d0fc).
|
|
170
|
-
- Specialize package-scoped CommonJS helpers (de79f9ba).
|
|
23
|
+
- Regenerate runtime artifacts for the WebSocket heartbeat (d0b1193b).
|
|
171
24
|
|
|
172
25
|
## v0.9.11 - 2026-09-02
|
|
173
26
|
|
|
@@ -269,3 +122,4 @@ generated artifacts, and documentation.
|
|
|
269
122
|
|
|
270
123
|
|
|
271
124
|
|
|
125
|
+
|
|
@@ -42692,6 +42692,10 @@ var bash52CommandVocabulary = Object.freeze([
|
|
|
42692
42692
|
"}"
|
|
42693
42693
|
]);
|
|
42694
42694
|
var bashCommandNames = new Set(bash52CommandVocabulary);
|
|
42695
|
+
var clamavSignatureMaxAgeMs = 26 * 60 * 60 * 1e3;
|
|
42696
|
+
var clamavRefreshIntervalMs = 60 * 60 * 1e3;
|
|
42697
|
+
var clamavRefreshRetryMs = 15 * 60 * 1e3;
|
|
42698
|
+
var clamavRefreshTimeoutMs = 5 * 60 * 1e3;
|
|
42695
42699
|
|
|
42696
42700
|
// src/teams-runtime.ts
|
|
42697
42701
|
var TEAM_JOIN_LINK_DEFAULT_TTL_SECONDS = 60 * 60 * 24;
|
|
@@ -42985,7 +42989,7 @@ var MutationExecutionStorage = process.getBuiltinModule("node:async_hooks").Asyn
|
|
|
42985
42989
|
var mutationExecution = new MutationExecutionStorage();
|
|
42986
42990
|
|
|
42987
42991
|
// src/cli/cli-version.ts
|
|
42988
|
-
var CLI_VERSION = "0.9.
|
|
42992
|
+
var CLI_VERSION = "0.9.29";
|
|
42989
42993
|
|
|
42990
42994
|
// src/cli/schedule-inspection-envelope.ts
|
|
42991
42995
|
var SCHEDULE_DIAGNOSTIC_FIELDS = /* @__PURE__ */ new Set([
|
package/bin/sporades.js
CHANGED
|
@@ -106223,9 +106223,10 @@ async function contentPolicyOutcome(row, bytes) {
|
|
|
106223
106223
|
if (bytes.subarray(0, 5).toString("ascii") === "%PDF-") return await validatePdfIngress(bytes) && /\.pdf$/.test(name2) && type === "application/pdf" ? "clean" : "rejected";
|
|
106224
106224
|
return safeUntrustedText(bytes) && /\.txt$/.test(name2) && type === "text/plain" ? "clean" : "rejected";
|
|
106225
106225
|
}
|
|
106226
|
+
var clamavSignatureMaxAgeMs = 26 * 60 * 60 * 1e3;
|
|
106226
106227
|
function isCurrentClamavSignature(signature, now2 = Date.now()) {
|
|
106227
106228
|
const builtAt = Date.parse(signature?.updatedAt);
|
|
106228
|
-
return Boolean(signature) && typeof signature?.version === "string" && /^daily:\d{1,12}$/.test(signature.version) && Number.isFinite(builtAt) && builtAt <= now2 && now2 - builtAt <=
|
|
106229
|
+
return Boolean(signature) && typeof signature?.version === "string" && /^daily:\d{1,12}$/.test(signature.version) && Number.isFinite(builtAt) && builtAt <= now2 && now2 - builtAt <= clamavSignatureMaxAgeMs;
|
|
106229
106230
|
}
|
|
106230
106231
|
function collectBoundedToolOutput(child, timeoutMs, maximumBytes = 8192) {
|
|
106231
106232
|
return new Promise((resolve) => {
|
|
@@ -106529,6 +106530,108 @@ async function stopOwnedClamavChildren(database) {
|
|
|
106529
106530
|
});
|
|
106530
106531
|
if (failures.length) throw new AggregateError(failures, "ClamAV child cleanup failed.");
|
|
106531
106532
|
}
|
|
106533
|
+
var clamavBootRetryDelaysMs = [5e3, 15e3];
|
|
106534
|
+
var clamavRefreshIntervalMs = 60 * 60 * 1e3;
|
|
106535
|
+
var clamavRefreshRetryMs = 15 * 60 * 1e3;
|
|
106536
|
+
var clamavRefreshTimeoutMs = 5 * 60 * 1e3;
|
|
106537
|
+
function clamavSpawn(database, command, args) {
|
|
106538
|
+
return database.__clamavTest?.spawn ? database.__clamavTest.spawn(command, args) : childProcess.spawn(command, args, { stdio: "ignore" });
|
|
106539
|
+
}
|
|
106540
|
+
function clamavSchedule(database, callback, delayMs) {
|
|
106541
|
+
if (database.__clamavTest?.schedule) return database.__clamavTest.schedule(callback, delayMs);
|
|
106542
|
+
const timer = setTimeout(callback, delayMs);
|
|
106543
|
+
timer.unref?.();
|
|
106544
|
+
return () => clearTimeout(timer);
|
|
106545
|
+
}
|
|
106546
|
+
async function runFreshclam(database, deadline) {
|
|
106547
|
+
const retained = database.__clamavUpdateProcess;
|
|
106548
|
+
if (retained) {
|
|
106549
|
+
await terminateChild(retained, clamavTerminateTimeout(database), database);
|
|
106550
|
+
unobserveClamavChild(database, retained);
|
|
106551
|
+
if (database.__clamavUpdateProcess === retained) database.__clamavUpdateProcess = null;
|
|
106552
|
+
if (database.__clamavRefreshStopped) return false;
|
|
106553
|
+
}
|
|
106554
|
+
if (clamavRemaining(database, deadline) <= 0) return false;
|
|
106555
|
+
const update = clamavSpawn(database, "/usr/bin/freshclam", ["--config-file=/etc/clamav/freshclam.conf"]);
|
|
106556
|
+
database.__clamavUpdateProcess = update;
|
|
106557
|
+
const completed = await waitForChild(update, clamavRemaining(database, deadline));
|
|
106558
|
+
if (!completed) await terminateChild(update, Math.min(clamavTerminateTimeout(database), clamavRemaining(database, deadline)), database);
|
|
106559
|
+
if (database.__clamavUpdateProcess === update) database.__clamavUpdateProcess = null;
|
|
106560
|
+
return completed;
|
|
106561
|
+
}
|
|
106562
|
+
function nextClamavRefreshDelay(database, signature, refreshed) {
|
|
106563
|
+
if (!refreshed) return clamavRefreshRetryMs;
|
|
106564
|
+
const expiresIn = Date.parse(signature?.updatedAt) + clamavSignatureMaxAgeMs - clamavNow(database);
|
|
106565
|
+
return Math.max(1e3, Math.min(clamavRefreshIntervalMs, expiresIn + 1e3));
|
|
106566
|
+
}
|
|
106567
|
+
async function startClamd(database, deadline) {
|
|
106568
|
+
if (clamavRemaining(database, deadline) <= 0) return false;
|
|
106569
|
+
const daemon = clamavSpawn(database, "/usr/sbin/clamd", ["--foreground", "--config-file=/etc/clamav/clamd.conf"]);
|
|
106570
|
+
database.__clamavProcess = daemon;
|
|
106571
|
+
observeClamavChild(database, daemon);
|
|
106572
|
+
if (await waitForClamavReadiness(database, daemon, deadline, "/tmp/sporades-clamd.sock")) {
|
|
106573
|
+
database.clamavReady = true;
|
|
106574
|
+
return true;
|
|
106575
|
+
}
|
|
106576
|
+
await stopOwnedClamavChildren(database);
|
|
106577
|
+
return false;
|
|
106578
|
+
}
|
|
106579
|
+
async function refreshClamavSignatures(database) {
|
|
106580
|
+
const deadline = clamavNow(database) + clamavRefreshTimeoutMs;
|
|
106581
|
+
const refreshed = await runFreshclam(database, deadline);
|
|
106582
|
+
if (database.__clamavRefreshStopped) return clamavRefreshRetryMs;
|
|
106583
|
+
const signature = await verifiedClamavSignature(database, deadline);
|
|
106584
|
+
if (database.__clamavRefreshStopped) return clamavRefreshRetryMs;
|
|
106585
|
+
if (!isCurrentClamavSignature(signature, clamavNow(database))) {
|
|
106586
|
+
database.clamavReady = false;
|
|
106587
|
+
await emitClamavRefreshWarning(database, "CLAMAV_SIGNATURE_STALE_AFTER_REFRESH");
|
|
106588
|
+
return clamavRefreshRetryMs;
|
|
106589
|
+
}
|
|
106590
|
+
const crashed = database.__clamavProcess;
|
|
106591
|
+
if (crashed && clamavChildTerminated(crashed)) {
|
|
106592
|
+
unobserveClamavChild(database, crashed);
|
|
106593
|
+
database.__clamavProcess = null;
|
|
106594
|
+
await emitClamavRefreshWarning(database, "CLAMAV_DAEMON_EXITED");
|
|
106595
|
+
if (database.__clamavRefreshStopped) return clamavRefreshRetryMs;
|
|
106596
|
+
}
|
|
106597
|
+
if (!database.__clamavProcess) {
|
|
106598
|
+
const started = await startClamd(database, clamavNow(database) + (database.__clamavTest?.startupTimeoutMs ?? 12e4));
|
|
106599
|
+
if (database.__clamavRefreshStopped) return clamavRefreshRetryMs;
|
|
106600
|
+
if (!started) {
|
|
106601
|
+
await emitClamavRefreshWarning(database, "CLAMAV_DAEMON_START_FAILED");
|
|
106602
|
+
return clamavRefreshRetryMs;
|
|
106603
|
+
}
|
|
106604
|
+
return nextClamavRefreshDelay(database, signature, refreshed);
|
|
106605
|
+
}
|
|
106606
|
+
if (await loadedClamavSignatureVersion(database) !== signature.version) await clamavSocketCommand(database, Buffer.from("zRELOAD\0"), 64);
|
|
106607
|
+
if (!refreshed) await emitClamavRefreshWarning(database, "CLAMAV_SIGNATURE_REFRESH_FAILED");
|
|
106608
|
+
return nextClamavRefreshDelay(database, signature, refreshed);
|
|
106609
|
+
}
|
|
106610
|
+
async function emitClamavRefreshWarning(database, code) {
|
|
106611
|
+
try {
|
|
106612
|
+
await database.log?.emit?.({ category: "platform", event: "file.inspection.signature-refresh-failed", level: "warn", message: "ClamAV signature refresh did not leave file inspection ready", data: { schema: "v1", outcome: "failed", code } });
|
|
106613
|
+
} catch {
|
|
106614
|
+
}
|
|
106615
|
+
}
|
|
106616
|
+
function scheduleClamavRefresh(database, delayMs) {
|
|
106617
|
+
if (database.__clamavRefreshStopped) return;
|
|
106618
|
+
database.__clamavRefreshCancel = clamavSchedule(database, () => {
|
|
106619
|
+
database.__clamavRefreshCancel = null;
|
|
106620
|
+
const pending = refreshClamavSignatures(database).catch(async () => {
|
|
106621
|
+
await emitClamavRefreshWarning(database, "CLAMAV_SIGNATURE_REFRESH_FAILED");
|
|
106622
|
+
return clamavRefreshRetryMs;
|
|
106623
|
+
}).then((nextDelayMs) => {
|
|
106624
|
+
if (database.__clamavRefreshPending === pending) database.__clamavRefreshPending = null;
|
|
106625
|
+
scheduleClamavRefresh(database, nextDelayMs);
|
|
106626
|
+
});
|
|
106627
|
+
database.__clamavRefreshPending = pending;
|
|
106628
|
+
}, delayMs);
|
|
106629
|
+
}
|
|
106630
|
+
function stopClamavRefresh(database) {
|
|
106631
|
+
database.__clamavRefreshStopped = true;
|
|
106632
|
+
database.__clamavRefreshCancel?.();
|
|
106633
|
+
database.__clamavRefreshCancel = null;
|
|
106634
|
+
}
|
|
106532
106635
|
async function initializeClamavRuntime(database) {
|
|
106533
106636
|
const required = database.endpoints?.some((endpoint) => endpoint?.options?.body?.multipart?.inspection?.requiredInspectors?.includes("clamav"));
|
|
106534
106637
|
database.clamavRequired = Boolean(required);
|
|
@@ -106540,43 +106643,46 @@ async function initializeClamavRuntime(database) {
|
|
|
106540
106643
|
database.clamavReady = await waitForClamavReadiness(database, database.__clamavDevSidecar.process, deadline, database.__clamavDevSidecar.socketPath);
|
|
106541
106644
|
return database.clamavReady;
|
|
106542
106645
|
}
|
|
106543
|
-
if (database.__clamavTest) {
|
|
106646
|
+
if (database.__clamavTest && !database.__clamavTest.managed) {
|
|
106544
106647
|
database.clamavReady = Boolean(await currentLoadedClamavSignature(database, deadline));
|
|
106545
106648
|
return database.clamavReady;
|
|
106546
106649
|
}
|
|
106547
|
-
if (process.env.SPORADES_CLAMAV_MANAGED !== "1") return false;
|
|
106548
|
-
try {
|
|
106650
|
+
if (!database.__clamavTest && process.env.SPORADES_CLAMAV_MANAGED !== "1") return false;
|
|
106651
|
+
if (!database.__clamavTest) try {
|
|
106549
106652
|
fs.mkdirSync("/app/data/clamav", { recursive: true });
|
|
106550
106653
|
fs.mkdirSync("/tmp/sporades-clamav", { recursive: true });
|
|
106551
106654
|
} catch {
|
|
106552
106655
|
return false;
|
|
106553
106656
|
}
|
|
106554
|
-
|
|
106555
|
-
|
|
106556
|
-
|
|
106557
|
-
|
|
106558
|
-
|
|
106559
|
-
|
|
106560
|
-
|
|
106561
|
-
|
|
106562
|
-
|
|
106563
|
-
|
|
106564
|
-
|
|
106565
|
-
|
|
106566
|
-
|
|
106567
|
-
|
|
106568
|
-
|
|
106569
|
-
database.__clamavUpdateProcess = updater;
|
|
106570
|
-
observeClamavChild(database, updater);
|
|
106571
|
-
return true;
|
|
106657
|
+
database.__clamavRefreshStopped = false;
|
|
106658
|
+
let refreshed = false;
|
|
106659
|
+
let signature = null;
|
|
106660
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
106661
|
+
refreshed = await runFreshclam(database, deadline);
|
|
106662
|
+
signature = await verifiedClamavSignature(database, deadline);
|
|
106663
|
+
if (isCurrentClamavSignature(signature, clamavNow(database))) break;
|
|
106664
|
+
const delayMs = clamavBootRetryDelaysMs[attempt];
|
|
106665
|
+
if (delayMs === void 0 || clamavRemaining(database, deadline) <= delayMs) {
|
|
106666
|
+
database.clamavReady = false;
|
|
106667
|
+
await emitClamavRefreshWarning(database, "CLAMAV_STARTUP_DEGRADED");
|
|
106668
|
+
scheduleClamavRefresh(database, clamavRefreshRetryMs);
|
|
106669
|
+
return true;
|
|
106670
|
+
}
|
|
106671
|
+
await clamavDelay(database, delayMs);
|
|
106572
106672
|
}
|
|
106573
|
-
await
|
|
106574
|
-
|
|
106673
|
+
if (!await startClamd(database, deadline)) return false;
|
|
106674
|
+
scheduleClamavRefresh(database, nextClamavRefreshDelay(database, signature, refreshed));
|
|
106675
|
+
return true;
|
|
106575
106676
|
}
|
|
106576
106677
|
async function shutdownClamavRuntime(database) {
|
|
106577
106678
|
database.clamavReady = false;
|
|
106578
|
-
|
|
106579
|
-
|
|
106679
|
+
stopClamavRefresh(database);
|
|
106680
|
+
if (!database.__clamavDevSidecar?.externallyManaged) {
|
|
106681
|
+
await stopOwnedClamavChildren(database);
|
|
106682
|
+
await database.__clamavRefreshPending;
|
|
106683
|
+
if (database.__clamavProcess || database.__clamavUpdateProcess) await stopOwnedClamavChildren(database);
|
|
106684
|
+
database.clamavReady = false;
|
|
106685
|
+
} else {
|
|
106580
106686
|
unobserveClamavChild(database, database.__clamavDevSidecar.process);
|
|
106581
106687
|
database.__clamavProcess = null;
|
|
106582
106688
|
database.__clamavUpdateProcess = null;
|
|
@@ -106584,7 +106690,7 @@ async function shutdownClamavRuntime(database) {
|
|
|
106584
106690
|
}
|
|
106585
106691
|
async function checkClamavRuntime(database) {
|
|
106586
106692
|
if (!database.clamavRequired) return { ok: true };
|
|
106587
|
-
const children = [database.__clamavDevSidecar?.process, database.__clamavProcess
|
|
106693
|
+
const children = [database.__clamavDevSidecar?.process, database.__clamavProcess];
|
|
106588
106694
|
for (const child of children) observeClamavChild(database, child);
|
|
106589
106695
|
if (children.some(clamavChildTerminated)) {
|
|
106590
106696
|
database.clamavReady = false;
|
|
@@ -122065,7 +122171,9 @@ async function runClientAccessKeyOperation(database, auth, message, sessionToken
|
|
|
122065
122171
|
};
|
|
122066
122172
|
}
|
|
122067
122173
|
}
|
|
122068
|
-
|
|
122174
|
+
var WEBSOCKET_HEARTBEAT_MS = 3e4;
|
|
122175
|
+
function createWebSocketHub(getDatabase, trustedRefresh = null, options = {}) {
|
|
122176
|
+
const heartbeatMs = options.heartbeatMs ?? WEBSOCKET_HEARTBEAT_MS;
|
|
122069
122177
|
const clients = /* @__PURE__ */ new Set();
|
|
122070
122178
|
const journeys = /* @__PURE__ */ new Map();
|
|
122071
122179
|
const connectionTokens = /* @__PURE__ */ new Map();
|
|
@@ -122134,15 +122242,33 @@ function createWebSocketHub(getDatabase, trustedRefresh = null) {
|
|
|
122134
122242
|
connectedAt: now2,
|
|
122135
122243
|
lastSeenAt: now2,
|
|
122136
122244
|
journey: null,
|
|
122137
|
-
journeySubscriptions: /* @__PURE__ */ new Set()
|
|
122245
|
+
journeySubscriptions: /* @__PURE__ */ new Set(),
|
|
122246
|
+
lastFrameAt: Date.now(),
|
|
122247
|
+
pingSentAt: null,
|
|
122248
|
+
heartbeat: null
|
|
122138
122249
|
};
|
|
122139
122250
|
clients.add(client);
|
|
122251
|
+
const unanswered = () => client.pingSentAt !== null && client.lastFrameAt < client.pingSentAt;
|
|
122252
|
+
client.heartbeat = setInterval(() => {
|
|
122253
|
+
if (client.closing || socket.destroyed) return;
|
|
122254
|
+
if (unanswered()) {
|
|
122255
|
+
setImmediate(() => {
|
|
122256
|
+
if (unanswered()) socket.destroy();
|
|
122257
|
+
});
|
|
122258
|
+
return;
|
|
122259
|
+
}
|
|
122260
|
+
client.pingSentAt = Date.now();
|
|
122261
|
+
socket.write(Buffer.from([137, 0]));
|
|
122262
|
+
}, heartbeatMs);
|
|
122263
|
+
client.heartbeat.unref?.();
|
|
122140
122264
|
socket.on("data", (chunk) => {
|
|
122265
|
+
client.lastFrameAt = Date.now();
|
|
122141
122266
|
client.lastSeenAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
122142
122267
|
client.buffer = Buffer.concat([client.buffer, chunk]);
|
|
122143
122268
|
drainWebSocketFrames(client, (message) => enqueueClientMessage(client, message));
|
|
122144
122269
|
});
|
|
122145
122270
|
const removeClient = () => {
|
|
122271
|
+
clearInterval(client.heartbeat);
|
|
122146
122272
|
clients.delete(client);
|
|
122147
122273
|
trustedRefresh?.disconnected(client.id);
|
|
122148
122274
|
client.subscriptions.clear();
|
|
@@ -123265,6 +123391,16 @@ function drainWebSocketFrames(client, onMessage) {
|
|
|
123265
123391
|
closeWebSocketClient(client);
|
|
123266
123392
|
return;
|
|
123267
123393
|
}
|
|
123394
|
+
if (opcode === 9) {
|
|
123395
|
+
const pong = Buffer.alloc(payload.length);
|
|
123396
|
+
for (let index = 0; index < payload.length; index += 1) {
|
|
123397
|
+
pong[index] = mask ? payload[index] ^ mask[index % 4] : payload[index];
|
|
123398
|
+
}
|
|
123399
|
+
if (!client.closing && !client.socket.destroyed && pong.length < 126) {
|
|
123400
|
+
client.socket.write(Buffer.concat([Buffer.from([138, pong.length]), pong]));
|
|
123401
|
+
}
|
|
123402
|
+
continue;
|
|
123403
|
+
}
|
|
123268
123404
|
if (opcode !== 1) {
|
|
123269
123405
|
continue;
|
|
123270
123406
|
}
|
|
@@ -123280,6 +123416,7 @@ function closeWebSocketClient(client) {
|
|
|
123280
123416
|
return;
|
|
123281
123417
|
}
|
|
123282
123418
|
client.closing = true;
|
|
123419
|
+
clearInterval(client.heartbeat);
|
|
123283
123420
|
try {
|
|
123284
123421
|
client.socket.write(Buffer.from([136, 0]), () => {
|
|
123285
123422
|
client.socket.end();
|
|
@@ -131112,7 +131249,7 @@ jobs:
|
|
|
131112
131249
|
}
|
|
131113
131250
|
|
|
131114
131251
|
// src/cli/cli-version.ts
|
|
131115
|
-
var CLI_VERSION = "0.9.
|
|
131252
|
+
var CLI_VERSION = "0.9.29";
|
|
131116
131253
|
|
|
131117
131254
|
// src/cli/sporades.ts
|
|
131118
131255
|
var SUPPORTED_TEMPLATES = new Set(CLIENT_TEMPLATES);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const CLI_VERSION = "0.9.
|
|
1
|
+
export declare const CLI_VERSION = "0.9.29";
|
|
2
2
|
//# sourceMappingURL=cli-version.d.ts.map
|
package/dist/cli/cli-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-ingress-runtime.d.ts","sourceRoot":"","sources":["../src/file-ingress-runtime.ts"],"names":[],"mappings":"AAWA,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAWtC,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,MAAM,WAAoN;AAgrBpR,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,oBAoF/E;AAoCD,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,WAW5D;AAmCD,wBAAgB,mCAAmC,CAAC,IAAI,EAAE,MAAM,WAE/D;AACD,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,WAwB5D;AAMD,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,WAmBxD;AAaD,eAAO,MAAM,uBAAuB,mBAElC,CAAC;AAgOH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,WAgDvD;
|
|
1
|
+
{"version":3,"file":"file-ingress-runtime.d.ts","sourceRoot":"","sources":["../src/file-ingress-runtime.ts"],"names":[],"mappings":"AAWA,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAWtC,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,MAAM,WAAoN;AAgrBpR,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,oBAoF/E;AAoCD,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,WAW5D;AAmCD,wBAAgB,mCAAmC,CAAC,IAAI,EAAE,MAAM,WAE/D;AACD,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,WAwB5D;AAMD,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,WAmBxD;AAaD,eAAO,MAAM,uBAAuB,mBAElC,CAAC;AAgOH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,WAgDvD;AAsBD,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,UAAU,GAAG,IAAI,EAAE,GAAG,SAAa,WAAoQ;AAC3V,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,SAAO;QAA6B,OAAO;YAAU,MAAM;GAAy2B;AA4Hx/B,wBAAsB,sBAAsB,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,oBASnH;AA4DD,wBAAsB,uBAAuB,CAAC,QAAQ,EAAE,UAAU,gBAuBjE;AACD,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,UAAU,iBAAse;AACtiB,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,UAAU;;GAA+hB;AAyE5lB,wBAAuB,cAAc,CAAC,OAAO,EAAE,aAAa,CAAC,UAAU,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,UAAU,UAAO;;;kBAyCrO;AAED,sHAAsH;AACtH,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,EAAE,eAAe,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,iBAAiB,CAAC,EAAE,UAAU,EAAE,UAAU,UAAO;;;;;;;;;;;;;;;;;;;GA4FtM;AAED,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,UAAU,cAiBhE;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU;iBAU9G,UAAU,WAAW,UAAU;;;;;;;;;sBAyD1B,UAAU;;;;6BASH,MAAM,WAAW,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgBzD;AAED,wGAAwG;AACxG,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,QAEpF;AAED,6FAA6F;AAC7F,wBAAsB,8BAA8B,CAAC,QAAQ,EAAE,UAAU,oBAQxE;AAED,4EAA4E;AAC5E,wBAAsB,4BAA4B,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,GAAE,UAAe,iBAsChG;AAwCD,wGAAwG;AACxG,wBAAsB,uBAAuB,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,GAAE,UAAe;;;;;;;;;;IAuB3F"}
|