@byokit/openclaw 0.3.5 → 0.3.6
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 +10 -0
- package/dist/engine.js +19 -9
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.3.6 (2026-10-01)
|
|
6
|
+
|
|
7
|
+
- FIX: Live orphan gateways recover after the engine rewrites its process title. Recovery verifies the recorded launch pid and process start time with the executable and isolated store paths; ambiguous ownership preserves the saved sign-in state.
|
|
8
|
+
|
|
9
|
+
- Dependency update: pins @byokit/ui-core 0.5.0.
|
|
10
|
+
- Dependency update: pins @byokit/reach 0.5.0.
|
|
11
|
+
- Dependency update: pins @byokit/relay 0.5.0.
|
|
12
|
+
- Dependency update: pins @byokit/link 0.7.0.
|
|
13
|
+
- SECURITY: (from @byokit/link 0.7.0) `Host.shortCode()` adds a machine-key commitment to typed pairing; `pairWithCode()` verifies it before disclosing device identity or asking for approval. Legacy codes remain compatible; use the full new code when relay lookup is untrusted.
|
|
14
|
+
|
|
5
15
|
## 0.3.5 (2026-10-01)
|
|
6
16
|
|
|
7
17
|
|
package/dist/engine.js
CHANGED
|
@@ -17,6 +17,14 @@ const putChanged = (path, data) => {
|
|
|
17
17
|
if (!existsSync(path) || readFileSync(path, 'utf8') !== data)
|
|
18
18
|
writeFileSync(path, data, { mode: 0o600 });
|
|
19
19
|
};
|
|
20
|
+
function processStartTime(pid) {
|
|
21
|
+
const stat = readFileSync(`/proc/${pid}/stat`, 'utf8');
|
|
22
|
+
// comm can contain spaces and parentheses; field 22 is index 19 after its final ')'.
|
|
23
|
+
const startTime = stat.slice(stat.lastIndexOf(')') + 2).split(' ')[19];
|
|
24
|
+
if (!startTime || !/^\d+$/.test(startTime))
|
|
25
|
+
throw new Error('unverifiable engine start time');
|
|
26
|
+
return startTime;
|
|
27
|
+
}
|
|
20
28
|
const supports = (list, value) => !list ||
|
|
21
29
|
(!list.includes(`!${value}`) && (list.includes('any') || list.every(item => item.startsWith('!')) || list.includes(value)));
|
|
22
30
|
function installMatches(dir) {
|
|
@@ -175,13 +183,14 @@ export class Engine {
|
|
|
175
183
|
return false;
|
|
176
184
|
try {
|
|
177
185
|
const proc = `/proc/${pid}`;
|
|
178
|
-
const
|
|
186
|
+
const identity = JSON.parse(readFileSync(join(this.root, 'gateway.identity'), 'utf8'));
|
|
179
187
|
const env = readFileSync(`${proc}/environ`, 'utf8').split('\0');
|
|
180
188
|
const home = join(this.root, 'home');
|
|
181
189
|
const owner = join(this.root, 'auth-store.lock', 'pid');
|
|
182
190
|
return statSync(proc).uid === process.getuid()
|
|
191
|
+
&& Number(readFileSync(join(this.root, 'gateway.pid'), 'utf8')) === pid
|
|
192
|
+
&& identity.pid === pid && identity.startTime === processStartTime(pid)
|
|
183
193
|
&& realpathSync(`${proc}/exe`) === realpathSync(process.execPath)
|
|
184
|
-
&& cmd.indexOf(this.entry) > 0 && cmd[cmd.indexOf(this.entry) + 1] === 'gateway'
|
|
185
194
|
&& realpathSync(`${proc}/cwd`) === realpathSync(home)
|
|
186
195
|
&& env.includes(`HOME=${home}`)
|
|
187
196
|
&& env.includes(`OPENCLAW_STATE_DIR=${join(this.root, 'state')}`)
|
|
@@ -205,13 +214,9 @@ export class Engine {
|
|
|
205
214
|
if (!this.verifiedOrphan(pid))
|
|
206
215
|
throw occupied();
|
|
207
216
|
// Verify a stable process identity again immediately before signalling this pid, never its group.
|
|
208
|
-
const identity = () => {
|
|
209
|
-
const stat = readFileSync(`/proc/${pid}/stat`, 'utf8');
|
|
210
|
-
return stat.slice(stat.lastIndexOf(')') + 2).split(' ')[19]; // starttime, not a reusable pid alone
|
|
211
|
-
};
|
|
212
217
|
try {
|
|
213
|
-
const before =
|
|
214
|
-
if (!
|
|
218
|
+
const before = processStartTime(pid);
|
|
219
|
+
if (!this.verifiedOrphan(pid) || before !== processStartTime(pid))
|
|
215
220
|
throw occupied();
|
|
216
221
|
}
|
|
217
222
|
catch {
|
|
@@ -301,6 +306,9 @@ export class Engine {
|
|
|
301
306
|
this.state('failed', 'exited');
|
|
302
307
|
throw new Error('engine spawn failed');
|
|
303
308
|
}
|
|
309
|
+
if (process.platform === 'linux') {
|
|
310
|
+
writeFileSync(join(this.root, 'gateway.identity'), JSON.stringify({ pid: child.pid, startTime: processStartTime(child.pid) }), { mode: 0o600 });
|
|
311
|
+
}
|
|
304
312
|
writeFileSync(join(this.root, 'gateway.pid'), String(child.pid), { mode: 0o600 });
|
|
305
313
|
child.once('exit', (code) => {
|
|
306
314
|
if (this.child !== child || this.stopping)
|
|
@@ -328,8 +336,10 @@ export class Engine {
|
|
|
328
336
|
}
|
|
329
337
|
removeOwnedPid(pid) {
|
|
330
338
|
const path = join(this.root, 'gateway.pid');
|
|
331
|
-
if (pid && existsSync(path) && readFileSync(path, 'utf8') === String(pid))
|
|
339
|
+
if (pid && existsSync(path) && readFileSync(path, 'utf8') === String(pid)) {
|
|
332
340
|
rmSync(path, { force: true });
|
|
341
|
+
rmSync(join(this.root, 'gateway.identity'), { force: true });
|
|
342
|
+
}
|
|
333
343
|
}
|
|
334
344
|
withAuthStore(task) { return this.authStore.offline(task); }
|
|
335
345
|
async stop() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@byokit/openclaw",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
4
4
|
"description": "The OpenClaw runtime kit: the pinned engine's full operator surface with plain-words helpers for members, sign-in, runs and approvals.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -52,9 +52,9 @@
|
|
|
52
52
|
"prepack": "tsc -b && node ../../scripts/fix-words-dts.cjs"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@byokit/link": "0.
|
|
56
|
-
"@byokit/relay": "0.
|
|
57
|
-
"@byokit/reach": "0.
|
|
55
|
+
"@byokit/link": "0.7.0",
|
|
56
|
+
"@byokit/relay": "0.5.0",
|
|
57
|
+
"@byokit/reach": "0.5.0",
|
|
58
58
|
"@byokit/seal": "0.2.0",
|
|
59
59
|
"@byokit/secrets": "0.5.0",
|
|
60
60
|
"@openclaw/gateway-client": "2026.8.1",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"ws": "8.21.3"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
|
-
"@byokit/ui-core": "0.
|
|
65
|
+
"@byokit/ui-core": "0.5.0"
|
|
66
66
|
},
|
|
67
67
|
"publishConfig": {
|
|
68
68
|
"access": "public"
|