@byokit/openclaw 0.3.0 → 0.3.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 +7 -0
- package/README.md +3 -1
- package/dist/auth-store.js +25 -6
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.3.1 (2026-09-30)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
- FIX: `authSeal` no longer rejects retained-login migration when engine state contains symlinks or runtime entries. File symlinks whose fully resolved targets are regular files inside the isolated engine root are sealed and restored as regular files at the link paths; outside-root, dangling and directory symlinks (including loops), sockets, FIFOs and devices are skipped without reading their contents.
|
|
10
|
+
- Depends on @byokit/ui-core 0.4.0.
|
|
11
|
+
|
|
5
12
|
## 0.3.0 (2026-09-30)
|
|
6
13
|
|
|
7
14
|
|
package/README.md
CHANGED
|
@@ -196,7 +196,9 @@ const server = new OpenClawKit({
|
|
|
196
196
|
Without `authSeal`, engine credentials remain plaintext. With it, successful `prepare()` and `stop()` leave
|
|
197
197
|
only a sealed snapshot, `auth-store.sealed`, for those directories. The adapter authenticates the snapshot
|
|
198
198
|
before any restoration; a wrong key, tampering, or a missing adapter rejects. Files restored for the engine
|
|
199
|
-
have mode 0600 and directories 0700.
|
|
199
|
+
have mode 0600 and directories 0700. File symlinks are sealed only when their fully resolved targets are
|
|
200
|
+
regular files inside the isolated engine root; they restore as regular files at the link paths. Outside-root,
|
|
201
|
+
dangling and directory symlinks (including loops), sockets, FIFOs and devices are skipped.
|
|
200
202
|
One kit owns the store at a time; a live owner or orphan gateway blocks preparation instead of racing its writes.
|
|
201
203
|
Sealing copies the whole store through memory, so startup and stop cost grows with session history.
|
|
202
204
|
|
package/dist/auth-store.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// The pin persists OAuth JSON in both shared and agent SQLite. There is no public persistence hook.
|
|
2
2
|
// Seal the complete isolated stores, including journals, only after their writer has exited.
|
|
3
|
-
import { chmodSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync, closeSync, fsyncSync, openSync } from 'node:fs';
|
|
4
|
-
import { dirname, join, relative, resolve } from 'node:path';
|
|
3
|
+
import { chmodSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, writeFileSync, closeSync, fsyncSync, openSync } from 'node:fs';
|
|
4
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
5
5
|
const encoder = new TextEncoder();
|
|
6
6
|
const archive = (name) => /^(auth-profiles|auth-state|auth|oauth)\.json\.(migrated-.+|sqlite-import\..+\.bak)$/.test(name)
|
|
7
7
|
|| name.endsWith('.moved-to-engine');
|
|
@@ -18,7 +18,7 @@ const live = (pid) => {
|
|
|
18
18
|
};
|
|
19
19
|
function regular(path) {
|
|
20
20
|
if (!lstatSync(path).isFile())
|
|
21
|
-
throw new Error(
|
|
21
|
+
throw new Error(`credential store requires regular files: ${path}`);
|
|
22
22
|
}
|
|
23
23
|
function syncDir(path) {
|
|
24
24
|
if (process.platform === 'win32')
|
|
@@ -153,6 +153,7 @@ export class AuthStore {
|
|
|
153
153
|
}
|
|
154
154
|
collect() {
|
|
155
155
|
const s = { v: 1, dirs: [], files: [] };
|
|
156
|
+
const root = realpathSync(this.o.root);
|
|
156
157
|
const walk = (path) => {
|
|
157
158
|
const name = relative(this.o.root, path).split('\\').join('/');
|
|
158
159
|
const stat = lstatSync(path);
|
|
@@ -163,9 +164,27 @@ export class AuthStore {
|
|
|
163
164
|
walk(join(path, child));
|
|
164
165
|
return;
|
|
165
166
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
167
|
+
let file = path;
|
|
168
|
+
if (stat.isSymbolicLink()) {
|
|
169
|
+
try {
|
|
170
|
+
file = realpathSync(path);
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
if (['ENOENT', 'ENOTDIR', 'ELOOP'].includes(error.code ?? ''))
|
|
174
|
+
return;
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
177
|
+
const target = relative(root, file);
|
|
178
|
+
if (isAbsolute(target) || target === '..' || target.startsWith(`..${sep}`))
|
|
179
|
+
return;
|
|
180
|
+
if (!lstatSync(file).isFile())
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
else if (!stat.isFile())
|
|
184
|
+
return;
|
|
185
|
+
// Read the checked target, but save the link's path: restore materializes a regular file there.
|
|
186
|
+
chmodSync(file, 0o600);
|
|
187
|
+
s.files.push([name, readFileSync(file).toString('base64')]);
|
|
169
188
|
};
|
|
170
189
|
for (const dir of ['state', 'home'])
|
|
171
190
|
if (existsSync(join(this.o.root, dir)))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@byokit/openclaw",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
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",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"ws": "8.21.3"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
|
-
"@byokit/ui-core": "0.
|
|
64
|
+
"@byokit/ui-core": "0.4.0"
|
|
65
65
|
},
|
|
66
66
|
"publishConfig": {
|
|
67
67
|
"access": "public"
|