@push.rocks/smartdb 5.1.0 → 5.2.0
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/.smartconfig.json +26 -5
- package/dist_rust/rustdb_linux_amd64 +0 -0
- package/dist_rust/rustdb_linux_amd64.tsrust-build.json +14 -0
- package/dist_rust/rustdb_linux_arm64 +0 -0
- package/dist_rust/rustdb_linux_arm64.tsrust-build.json +14 -0
- package/dist_rust/rustdb_macos_amd64 +0 -0
- package/dist_rust/rustdb_macos_amd64.tsrust-build.json +14 -0
- package/dist_rust/rustdb_macos_arm64 +0 -0
- package/dist_rust/rustdb_macos_arm64.tsrust-build.json +14 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/ts_local/classes.localsmartdb.js +2 -2
- package/package.json +9 -4
- package/readme.hints.md +5 -4
- package/readme.md +27 -5
- package/readme.plan.md +1 -1
- package/scripts/release-artifacts.ts +626 -0
- package/third-party-notices.md +1 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/ts_local/classes.localsmartdb.ts +1 -1
package/.smartconfig.json
CHANGED
|
@@ -21,13 +21,27 @@
|
|
|
21
21
|
]
|
|
22
22
|
},
|
|
23
23
|
"release": {
|
|
24
|
+
"preflight": {
|
|
25
|
+
"test": true,
|
|
26
|
+
"testCommand": "pnpm run release:check-builders",
|
|
27
|
+
"build": true,
|
|
28
|
+
"buildCommand": "pnpm run release:build-artifacts"
|
|
29
|
+
},
|
|
24
30
|
"targets": {
|
|
31
|
+
"git": {
|
|
32
|
+
"enabled": true,
|
|
33
|
+
"remote": "origin",
|
|
34
|
+
"pushBranch": true,
|
|
35
|
+
"pushTags": true
|
|
36
|
+
},
|
|
25
37
|
"npm": {
|
|
38
|
+
"enabled": true,
|
|
26
39
|
"registries": [
|
|
27
40
|
"https://verdaccio.lossless.digital",
|
|
28
41
|
"https://registry.npmjs.org"
|
|
29
42
|
],
|
|
30
|
-
"accessLevel": "public"
|
|
43
|
+
"accessLevel": "public",
|
|
44
|
+
"alreadyPublished": "success"
|
|
31
45
|
}
|
|
32
46
|
}
|
|
33
47
|
},
|
|
@@ -51,10 +65,17 @@
|
|
|
51
65
|
]
|
|
52
66
|
},
|
|
53
67
|
"@git.zone/tsrust": {
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
|
|
57
|
-
|
|
68
|
+
"targetsByHost": {
|
|
69
|
+
"linux": [
|
|
70
|
+
"linux_amd64",
|
|
71
|
+
"linux_arm64"
|
|
72
|
+
],
|
|
73
|
+
"macos": [
|
|
74
|
+
"macos_amd64",
|
|
75
|
+
"macos_arm64"
|
|
76
|
+
]
|
|
77
|
+
},
|
|
78
|
+
"locked": true,
|
|
58
79
|
"static": true,
|
|
59
80
|
"remapLocalPaths": true
|
|
60
81
|
},
|
|
Binary file
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"format": "tsrust.build-provenance.v2",
|
|
3
|
+
"binarySha256": "c5c0a72cc3e9001b008c73ecfbc05dbcde559796eeb81ddd9b57a858f98d4515",
|
|
4
|
+
"buildInfo": {
|
|
5
|
+
"projectName": "@push.rocks/smartdb",
|
|
6
|
+
"projectVersion": "5.2.0",
|
|
7
|
+
"gitCommit": "d61180c4086a9f771765d104260f620d76b1cda0",
|
|
8
|
+
"gitDirty": false,
|
|
9
|
+
"builtAt": "2026-08-18T22:39:04.935Z",
|
|
10
|
+
"tsrustVersion": "1.9.1",
|
|
11
|
+
"binary": "rustdb",
|
|
12
|
+
"target": "linux_amd64"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"format": "tsrust.build-provenance.v2",
|
|
3
|
+
"binarySha256": "5f3878be4da5dd17eb4c269fdb3f63185d496bd84c1066ce54f47ea3b8f45321",
|
|
4
|
+
"buildInfo": {
|
|
5
|
+
"projectName": "@push.rocks/smartdb",
|
|
6
|
+
"projectVersion": "5.2.0",
|
|
7
|
+
"gitCommit": "d61180c4086a9f771765d104260f620d76b1cda0",
|
|
8
|
+
"gitDirty": false,
|
|
9
|
+
"builtAt": "2026-08-18T22:39:24.164Z",
|
|
10
|
+
"tsrustVersion": "1.9.1",
|
|
11
|
+
"binary": "rustdb",
|
|
12
|
+
"target": "linux_arm64"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"format": "tsrust.build-provenance.v2",
|
|
3
|
+
"binarySha256": "1cf98dfc94ff75ab0fad7927c5a59cec87e9623bcc8e36908e7811bd9632064c",
|
|
4
|
+
"buildInfo": {
|
|
5
|
+
"projectName": "@push.rocks/smartdb",
|
|
6
|
+
"projectVersion": "5.2.0",
|
|
7
|
+
"gitCommit": "d61180c4086a9f771765d104260f620d76b1cda0",
|
|
8
|
+
"gitDirty": false,
|
|
9
|
+
"builtAt": "2026-08-18T22:40:01.824Z",
|
|
10
|
+
"tsrustVersion": "1.9.1",
|
|
11
|
+
"binary": "rustdb",
|
|
12
|
+
"target": "macos_amd64"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"format": "tsrust.build-provenance.v2",
|
|
3
|
+
"binarySha256": "3784a0e1d125a25a714086b098018a34cef6056677da3f087992a7e76cd9d87f",
|
|
4
|
+
"buildInfo": {
|
|
5
|
+
"projectName": "@push.rocks/smartdb",
|
|
6
|
+
"projectVersion": "5.2.0",
|
|
7
|
+
"gitCommit": "d61180c4086a9f771765d104260f620d76b1cda0",
|
|
8
|
+
"gitDirty": false,
|
|
9
|
+
"builtAt": "2026-08-18T22:41:12.434Z",
|
|
10
|
+
"tsrustVersion": "1.9.1",
|
|
11
|
+
"binary": "rustdb",
|
|
12
|
+
"target": "macos_arm64"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@push.rocks/smartdb',
|
|
6
|
-
version: '5.
|
|
6
|
+
version: '5.2.0',
|
|
7
7
|
description: 'A MongoDB-compatible embedded database server with wire protocol support, backed by a high-performance Rust engine.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxxQkFBcUI7SUFDM0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHFIQUFxSDtDQUNuSSxDQUFBIn0=
|
|
@@ -89,7 +89,7 @@ export class LocalSmartDb {
|
|
|
89
89
|
if (optionsArg?.signal?.aborted) {
|
|
90
90
|
throw new LocalSmartDbStorageRootRelocationError('IO');
|
|
91
91
|
}
|
|
92
|
-
if (process.platform !== 'linux') {
|
|
92
|
+
if (process.platform !== 'linux' && process.platform !== 'darwin') {
|
|
93
93
|
throw new LocalSmartDbStorageRootRelocationError('UNSUPPORTED');
|
|
94
94
|
}
|
|
95
95
|
const deadline = optionsArg?.timeoutMs === undefined
|
|
@@ -377,4 +377,4 @@ export class LocalSmartDb {
|
|
|
377
377
|
}
|
|
378
378
|
}
|
|
379
379
|
}
|
|
380
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5sb2NhbHNtYXJ0ZGIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy90c19sb2NhbC9jbGFzc2VzLmxvY2Fsc21hcnRkYi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUNqQyxPQUFPLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNsQyxPQUFPLEtBQUssR0FBRyxNQUFNLEtBQUssQ0FBQztBQUMzQixPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLEtBQUssRUFBRSxNQUFNLElBQUksQ0FBQztBQUN6QixPQUFPLEVBQ0wsYUFBYSxHQVFkLE1BQU0sd0JBQXdCLENBQUM7QUFDaEMsT0FBTyxFQUNMLFlBQVksRUFDWixpQ0FBaUMsR0FDbEMsTUFBTSxpQ0FBaUMsQ0FBQztBQUN6QyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDM0QsT0FBTyxFQUNMLDREQUE0RCxFQUM1RCwyQ0FBMkMsRUFDM0MseUNBQXlDLEdBQzFDLE1BQU0scUNBQXFDLENBQUM7QUFDN0MsT0FBTyxFQUNMLGtEQUFrRCxFQUNsRCw0Q0FBNEMsRUFDNUMsc0NBQXNDLEVBQ3RDLHNEQUFzRCxFQUN0RCx3REFBd0QsR0FDekQsTUFBTSwwQ0FBMEMsQ0FBQztBQW1CbEQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTJCRztBQUNILE1BQU0sT0FBTyxZQUFZO2FBQ1IsOEJBQXlCLEdBQWtCLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQUFBbkMsQ0FBb0M7SUFNNUUsWUFBWSxPQUE2QjtRQUhqQyxXQUFNLEdBQXlCLElBQUksQ0FBQztRQUNwQyx3QkFBbUIsR0FBa0IsSUFBSSxDQUFDO1FBR2hELElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO0lBQ3pCLENBQUM7SUFFTyxNQUFNLENBQUMsNkJBQTZCO1FBQzFDLE9BQU8sSUFBSSxZ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
|
|
380
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5sb2NhbHNtYXJ0ZGIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy90c19sb2NhbC9jbGFzc2VzLmxvY2Fsc21hcnRkYi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUNqQyxPQUFPLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNsQyxPQUFPLEtBQUssR0FBRyxNQUFNLEtBQUssQ0FBQztBQUMzQixPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLEtBQUssRUFBRSxNQUFNLElBQUksQ0FBQztBQUN6QixPQUFPLEVBQ0wsYUFBYSxHQVFkLE1BQU0sd0JBQXdCLENBQUM7QUFDaEMsT0FBTyxFQUNMLFlBQVksRUFDWixpQ0FBaUMsR0FDbEMsTUFBTSxpQ0FBaUMsQ0FBQztBQUN6QyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDM0QsT0FBTyxFQUNMLDREQUE0RCxFQUM1RCwyQ0FBMkMsRUFDM0MseUNBQXlDLEdBQzFDLE1BQU0scUNBQXFDLENBQUM7QUFDN0MsT0FBTyxFQUNMLGtEQUFrRCxFQUNsRCw0Q0FBNEMsRUFDNUMsc0NBQXNDLEVBQ3RDLHNEQUFzRCxFQUN0RCx3REFBd0QsR0FDekQsTUFBTSwwQ0FBMEMsQ0FBQztBQW1CbEQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTJCRztBQUNILE1BQU0sT0FBTyxZQUFZO2FBQ1IsOEJBQXlCLEdBQWtCLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQUFBbkMsQ0FBb0M7SUFNNUUsWUFBWSxPQUE2QjtRQUhqQyxXQUFNLEdBQXlCLElBQUksQ0FBQztRQUNwQyx3QkFBbUIsR0FBa0IsSUFBSSxDQUFDO1FBR2hELElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO0lBQ3pCLENBQUM7SUFFTyxNQUFNLENBQUMsNkJBQTZCO1FBQzFDLE9BQU8sSUFBSSxZ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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@push.rocks/smartdb",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A MongoDB-compatible embedded database server with wire protocol support, backed by a high-performance Rust engine.",
|
|
6
6
|
"exports": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"@git.zone/tsbuild": "^4.4.2",
|
|
18
18
|
"@git.zone/tsbundle": "^2.11.4",
|
|
19
19
|
"@git.zone/tsrun": "^2.0.6",
|
|
20
|
-
"@git.zone/tsrust": "^1.
|
|
20
|
+
"@git.zone/tsrust": "^1.9.1",
|
|
21
21
|
"@git.zone/tstest": "^4.0.0",
|
|
22
22
|
"@types/node": "26.2.0",
|
|
23
23
|
"mongodb": "^7.5.0"
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
],
|
|
32
32
|
"files": [
|
|
33
33
|
"ts/**/*",
|
|
34
|
+
"scripts/**/*",
|
|
34
35
|
"ts_web/**/*",
|
|
35
36
|
"dist/**/*",
|
|
36
37
|
"dist_*/**/*",
|
|
@@ -45,7 +46,9 @@
|
|
|
45
46
|
"publishConfig": {
|
|
46
47
|
"executableFiles": [
|
|
47
48
|
"./dist_rust/rustdb_linux_amd64",
|
|
48
|
-
"./dist_rust/rustdb_linux_arm64"
|
|
49
|
+
"./dist_rust/rustdb_linux_arm64",
|
|
50
|
+
"./dist_rust/rustdb_macos_amd64",
|
|
51
|
+
"./dist_rust/rustdb_macos_arm64"
|
|
49
52
|
]
|
|
50
53
|
},
|
|
51
54
|
"keywords": [
|
|
@@ -71,6 +74,8 @@
|
|
|
71
74
|
"test": "(tstest test/. --verbose --logfile --timeout 60)",
|
|
72
75
|
"test:rust": "(cd rust && cargo test)",
|
|
73
76
|
"build": "(tsbundle) && (tsbuild tsfolders) && (tsrust)",
|
|
74
|
-
"buildDocs": "tsdoc"
|
|
77
|
+
"buildDocs": "tsdoc",
|
|
78
|
+
"release:check-builders": "tsrun scripts/release-artifacts.ts check",
|
|
79
|
+
"release:build-artifacts": "tsrun scripts/release-artifacts.ts build"
|
|
75
80
|
}
|
|
76
81
|
}
|
package/readme.hints.md
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
- `LocalSmartDb.relocateStoppedStorageRoot()` is the only supported path-changing operation. It uses a dedicated serialized mutating sidecar runner; do not route it through the disposable offline-inspection helper. A bridge whose termination is unconfirmed remains in the static cleanup gate, and no later relocation may spawn until cleanup succeeds.
|
|
6
6
|
- Rust owns the descriptor-relative operation in `rust/crates/rustdb/src/storage_root_relocation.rs`. It never constructs `RustDb`. The fixed journal phases are `preparing`, `prepared`, `exchanged`, `providerPublished`, `sentinelPublished`, and `cleaned`; retries reconcile the exact source-root/destination-absent-or-receipt topology or source-receipt/destination-root topology before continuing.
|
|
7
|
-
- The destination receipt is published with
|
|
8
|
-
- Eligibility is intentionally narrow: Linux
|
|
7
|
+
- The destination receipt is published with an exclusive rename, then exchanged with the source root using an atomic swap (`RENAME_NOREPLACE`/`RENAME_EXCHANGE` on Linux and `RENAME_EXCL`/`RENAME_SWAP` on macOS). Provider and sentinel replacement also uses checked exchanges, retaining each previous object in the workspace until the replacement is durable and verified. The original root inode ends at the destination and the original receipt inode remains at the source indefinitely. Parent, root, internal, lock, provider, and sentinel identities are revalidated around publication.
|
|
8
|
+
- Eligibility is intentionally narrow: Linux on the existing supported local-filesystem set or macOS on qualified local APFS, exact current owner/provider/sentinel metadata, no auth path digest, and no resource receipt, allocation, retired lock, durable database/transaction workspace, database marker, symlink, unknown entry, or unsafe ownership/mode/link profile. macOS additionally rejects case, Unicode, mount, and ancestry aliases by retained physical identity. Missing metadata is rejected and never initialized by relocation.
|
|
9
9
|
- Both TypeScript startup paths check for `.__rustdb_internal/storage-root-relocation` before `StorageMigrator`. Rust checks immediately after securely opening an existing root and repeats the descriptor-relative check after acquiring the owner lock, before storage initialization. This closes the interval where a relocation can create its workspace and release the lock after startup's first inspection. Occupancy or inspection ambiguity is a startup error; only an exact relocation retry performs recovery.
|
|
10
|
-
- Completed roots retain the SmartDB 5.0.1 provider/sentinel JSON shape, changing only their storage-root path digest. Interrupted state requires 5.1.0 or newer. Exact replay lasts only while the destination remains current; a later relocation supersedes the old source/destination tuple.
|
|
10
|
+
- Completed roots retain the SmartDB 5.0.1 provider/sentinel JSON shape, changing only their storage-root path digest. Interrupted Linux state requires 5.1.0 or newer; interrupted macOS state requires a macOS-capable release. Exact replay lasts only while the destination remains current; a later relocation supersedes the old source/destination tuple.
|
|
11
11
|
|
|
12
12
|
## Restricted Deny-All Views
|
|
13
13
|
|
|
@@ -39,8 +39,9 @@
|
|
|
39
39
|
|
|
40
40
|
## Static Rust Binaries
|
|
41
41
|
|
|
42
|
-
- The Rust binaries in `dist_rust/` are statically linked (static-pie) via `"static": true` in the `@git.zone/tsrust` block of `.smartconfig.json` (tsrust >= 1.4.1). They run on both glibc (Debian/Ubuntu) and musl (Alpine) systems.
|
|
42
|
+
- The Linux Rust binaries in `dist_rust/` are statically linked (static-pie) via `"static": true` in the `@git.zone/tsrust` block of `.smartconfig.json` (tsrust >= 1.4.1). They run on both glibc (Debian/Ubuntu) and musl (Alpine) systems. The macOS amd64 and arm64 binaries use the normal Apple platform linkage.
|
|
43
43
|
- tsrust injects `RUSTFLAGS="-C target-feature=+crt-static"` only into its own per-target cargo invocations and verifies the result (no `PT_INTERP` ELF header). Keep `rust/.cargo/config.toml` free of `rustflags` entries: the injected env variable would replace them, and a repo-wide `rustflags` would also break plain `cargo test`/`cargo check` (proc-macros cannot build with `+crt-static` on linux-gnu without an explicit `--target`). The repo previously carried such `rustflags` lines; they were removed when the tsrust `static` option was adopted.
|
|
44
44
|
- `pnpm run test:rust` runs the Rust unit tests; plain `cargo test` in `rust/` works as well.
|
|
45
45
|
- Verify linkage manually with `ldd dist_rust/<binary>_linux_amd64` → "statically linked".
|
|
46
46
|
- Do NOT verify feature presence in release binaries with `strings`/`grep`: on x86_64 release builds LLVM embeds short string literals (≤16 bytes, e.g. BSON doc keys like `volatileOnly`) as instruction immediates, so they are invisible to byte scans while the aarch64 binary shows them in `.rodata`. This produces false "stale binary" alarms. Verify behavior by running the binary (the wire tests spawn the host-arch binary from `dist_rust/`), or disassemble: `objdump -d <bin> | grep <hex-of-literal-LE>`.
|
|
47
|
+
- Release builds use tsrust 1.9 host partitions and strict sidecar assembly. The enabled gitzone test preflight compiles and executes a static Linux arm64 probe through `binfmt` and checks macOS Rosetta before versioning. The post-version build transfers exact HEAD by Git bundle, executes all four target binaries, and assembles separate Linux and macOS inputs. Remote cleanup is limited to the unique sentinel-owned child below `SMARTDB_RELEASE_MACOS_TEMP_ROOT`.
|
package/readme.md
CHANGED
|
@@ -358,7 +358,7 @@ Single-node transactions are supported through official MongoDB driver sessions.
|
|
|
358
358
|
|
|
359
359
|
### Durable Database Publication Holds
|
|
360
360
|
|
|
361
|
-
|
|
361
|
+
On Linux, file-backed SmartDB can keep a replaced or deleted database closed after the local mutation is durable and until a downstream coordinator confirms its own fsync. Check the explicit health contract before using this flow:
|
|
362
362
|
|
|
363
363
|
```typescript
|
|
364
364
|
const health = await server.getHealth();
|
|
@@ -400,6 +400,8 @@ const released = await server.commitDatabasePublication({
|
|
|
400
400
|
|
|
401
401
|
The held barrier survives restart and blocks wire commands, transactions, startup recovery, compaction, index restoration, and close-time hint writes for that database while unrelated databases remain available. Commit is exact and idempotent. A successful commit removes the raw capability from durable state and retains only protected verification material. Provider/root identity, durable fenced-mode markers, and bounded startup validation make copied, missing, corrupt, or legacy-active publication state fail closed. A higher fencing token compacts resolved older receipts, so long-lived coordinators do not exhaust receipt capacity.
|
|
402
402
|
|
|
403
|
+
Durable database publication holds and allocation fencing remain Linux-only. The macOS support described under stopped storage-root relocation does not enable these runtime mutation features.
|
|
404
|
+
|
|
403
405
|
Coordinators that do not yet have their own durable record can call `getDatabaseResourceFenceState({ databaseName })` before creating it. File-backed SmartDB returns the durable scope, highest token, current publication phase, and allocation lifecycle/identity when the name is allocation-managed, or `null` only when both fence state and its durable marker are absent. The inspection never returns mutation IDs, mutation payload digests, publication receipts, or publication capabilities. Treat any active phase, identity mismatch, corrupt state, unsupported storage, or unsafe token as a hard stop rather than creating coordinator state.
|
|
404
406
|
|
|
405
407
|
### Authoritative Database Allocation
|
|
@@ -539,13 +541,13 @@ const db = new LocalSmartDb({
|
|
|
539
541
|
| `getConnectionUri()` | `string` | Get the connection URI |
|
|
540
542
|
| `getServer()` | `SmartdbServer` | Access the underlying server |
|
|
541
543
|
| `running` | `boolean` | Whether the server is running |
|
|
542
|
-
| `LocalSmartDb.relocateStoppedStorageRoot(input, options?)` | `Promise<ILocalSmartDbStoppedStorageRootRelocationReceipt>` | Atomically relocate one eligible stopped Linux file-storage root and retain a source receipt |
|
|
544
|
+
| `LocalSmartDb.relocateStoppedStorageRoot(input, options?)` | `Promise<ILocalSmartDbStoppedStorageRootRelocationReceipt>` | Atomically relocate one eligible stopped Linux or macOS file-storage root and retain a source receipt |
|
|
543
545
|
| `LocalSmartDb.inspectOfflineStringValue(input, options?)` | `Promise<TLocalSmartDbOfflineStringValueInspectionResult>` | Read one exact top-level string value from stopped file storage without starting or mutating the engine |
|
|
544
546
|
| `LocalSmartDb.inspectOfflinePhysicalNamespaces(input, options?)` | `Promise<ILocalSmartDbOfflinePhysicalNamespaceInspectionResult>` | Validate stopped physical file storage and return only deterministic database and collection names |
|
|
545
547
|
|
|
546
548
|
#### Stopped Storage-Root Relocation
|
|
547
549
|
|
|
548
|
-
`relocateStoppedStorageRoot()` moves an eligible stopped file-storage root without starting `RustDb`, binding a listener, running a TypeScript migration, initializing storage or auth, or performing WAL recovery. It
|
|
550
|
+
`relocateStoppedStorageRoot()` moves an eligible stopped file-storage root without starting `RustDb`, binding a listener, running a TypeScript migration, initializing storage or auth, or performing WAL recovery. It supports Linux on the existing qualified local-filesystem set and macOS on writable local APFS volumes with ownership, persistent object identities, `flock`, and atomic exclusive/swap rename support. The source root, source parent, and destination parent must be trusted descriptor-safe objects on the same filesystem. The supplied source and destination must be absolute and resolve to distinct, non-root, non-nested physical paths, and the destination must be absent. macOS also rejects case-folded, Unicode-normalized, and ancestry aliases before creating relocation state. The trusted parents may differ.
|
|
549
551
|
|
|
550
552
|
```typescript
|
|
551
553
|
import { LocalSmartDb } from '@push.rocks/smartdb';
|
|
@@ -586,7 +588,7 @@ On success, the destination directory is the original storage-root inode and the
|
|
|
586
588
|
|
|
587
589
|
Relocation deliberately supports only the plain, unbound `LocalSmartDb` topology. The existing owner lock, `provider-identity.json`, and resource-fencing sentinel must all be present; the operation never creates missing ownership metadata. A provider identity containing `authUsersPathSha256` is unsupported. Any durable fence receipt or capability, allocation state, retired fence lock, database mutation/transaction journal, allocation/publication marker, symlink, unknown entry, unsafe mode/owner/link count, exhausted scan bound, active owner, or ambiguous identity fails closed.
|
|
588
590
|
|
|
589
|
-
The operation journals phases `preparing`, `prepared`, `exchanged`, `providerPublished`, `sentinelPublished`, and `cleaned`. If a call returns `RECOVERY_REQUIRED`, stop all startup attempts and retry the exact same normalized source path, destination path, and `relocationId` with SmartDB
|
|
591
|
+
The operation journals phases `preparing`, `prepared`, `exchanged`, `providerPublished`, `sentinelPublished`, and `cleaned`. If a call returns `RECOVERY_REQUIRED`, stop all startup attempts and retry the exact same normalized source path, destination path, and `relocationId` with the same SmartDB version that began the relocation or a newer version. Startup rejects any relocation-workspace occupancy and does not mutate or recover it. Do not delete, rename, edit, or replace either path between attempts. Linux relocation state created by SmartDB 5.1.0 remains recoverable by 5.1.0 or newer; macOS recovery requires a macOS-capable release. A completed root remains 5.0.1-compatible.
|
|
590
592
|
|
|
591
593
|
An exact completed replay returns the same receipt only while the destination remains the current root. A later successful relocation leaves another receipt at that destination path and supersedes the earlier replay topology; retry the later operation instead. Manual copy or rename remains unsupported and continues to fail provider path/inode fencing.
|
|
592
594
|
|
|
@@ -1009,7 +1011,27 @@ The Rust engine is organized as a Cargo workspace with 9 focused crates:
|
|
|
1009
1011
|
| `rustdb-auth` | SCRAM-SHA-256 credential handling, user metadata persistence, RBAC checks |
|
|
1010
1012
|
| `rustdb-commands` | 40+ command handlers wiring everything together |
|
|
1011
1013
|
|
|
1012
|
-
Cross-compiled for `linux_amd64` and `
|
|
1014
|
+
Cross-compiled for `linux_amd64`, `linux_arm64`, `macos_amd64`, and `macos_arm64` via [@git.zone/tsrust](https://www.npmjs.com/package/@git.zone/tsrust).
|
|
1015
|
+
|
|
1016
|
+
### Multi-host release artifacts
|
|
1017
|
+
|
|
1018
|
+
Normal `tsrust` builds select only the current host's partition from `targetsByHost`. Releases coordinate both partitions after the version commit exists, then publish only after every exact-commit binary has executed and passed strict provenance assembly.
|
|
1019
|
+
|
|
1020
|
+
The release coordinator must be Linux amd64 with `aarch64-linux-gnu-gcc` and a registered Linux arm64 `binfmt` interpreter. Set these environment variables to an authorized Apple Silicon builder with Rosetta and a dedicated temporary root:
|
|
1021
|
+
|
|
1022
|
+
```bash
|
|
1023
|
+
export SMARTDB_RELEASE_MACOS_SSH="release-user@mac-builder.example"
|
|
1024
|
+
export SMARTDB_RELEASE_MACOS_TEMP_ROOT="/absolute/dedicated/smartdb-release"
|
|
1025
|
+
```
|
|
1026
|
+
|
|
1027
|
+
`gitzone release` first runs `pnpm run release:check-builders`, before creating a version commit or tag. It compiles and executes a static arm64 probe and rejects missing cross-toolchain or `binfmt` execution, an unsuitable macOS host, missing Rosetta, missing tools, or an unwritable remote temporary root. The release build then:
|
|
1028
|
+
|
|
1029
|
+
1. Builds and executes the Linux amd64 and arm64 binaries.
|
|
1030
|
+
2. Transfers a Git bundle of the unpushed release commit into a unique sentinel-owned macOS workspace.
|
|
1031
|
+
3. Builds both Darwin targets from the frozen lockfile, verifies their Cargo bytes and signatures, and executes both architectures.
|
|
1032
|
+
4. Copies each host output into separate `.nogit` inputs and runs strict `tsrust assemble` into `dist_rust/`.
|
|
1033
|
+
|
|
1034
|
+
No host address or path is stored in the repository. A failed run retains its unique diagnostic directories and prints their paths. Successful cleanup can remove only the generated child whose path and random ownership sentinel both match.
|
|
1013
1035
|
|
|
1014
1036
|
### Storage Engine Reliability 🔒
|
|
1015
1037
|
|
package/readme.plan.md
CHANGED
|
@@ -287,7 +287,7 @@ Every applicable release must pass the narrowest relevant set of these gates:
|
|
|
287
287
|
- deterministic persistence failpoints and randomized process-kill tests
|
|
288
288
|
- storage/index/content-digest reconciliation after recovery
|
|
289
289
|
- 24-hour nightly and 72-hour release-candidate resource soaks
|
|
290
|
-
-
|
|
290
|
+
- all published Linux and macOS architectures
|
|
291
291
|
- automated backup/restore drills once backup exists
|
|
292
292
|
- partition, failover, and history verification once replication exists
|
|
293
293
|
- supply-chain, provenance, security, upgrade, and rollback checks for managed tiers
|
|
@@ -0,0 +1,626 @@
|
|
|
1
|
+
import * as childProcess from 'node:child_process';
|
|
2
|
+
import * as crypto from 'node:crypto';
|
|
3
|
+
import * as fs from 'node:fs';
|
|
4
|
+
import * as path from 'node:path';
|
|
5
|
+
|
|
6
|
+
type TReleaseArtifactMode = 'check' | 'build';
|
|
7
|
+
|
|
8
|
+
interface IReleaseArtifactEnvironment {
|
|
9
|
+
macosSsh: string;
|
|
10
|
+
macosTempRoot: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const provenanceSuffix = '.tsrust-build.json';
|
|
14
|
+
const defaultCommandTimeoutMs = 60 * 60 * 1000;
|
|
15
|
+
const capabilityCommandTimeoutMs = 5 * 60 * 1000;
|
|
16
|
+
const forceKillDelayMs = 10 * 1000;
|
|
17
|
+
const maximumCapturedOutputBytes = 16 * 1024 * 1024;
|
|
18
|
+
const sshConnectionArgs = [
|
|
19
|
+
'-o',
|
|
20
|
+
'ServerAliveInterval=15',
|
|
21
|
+
'-o',
|
|
22
|
+
'ServerAliveCountMax=2',
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
type TForwardedSignal = 'SIGINT' | 'SIGTERM' | 'SIGHUP';
|
|
26
|
+
|
|
27
|
+
const shellQuote = (valueArg: string): string => `'${valueArg.replace(/'/g, `'"'"'`)}'`;
|
|
28
|
+
|
|
29
|
+
const executeCommand = (
|
|
30
|
+
commandArg: string,
|
|
31
|
+
argsArg: string[],
|
|
32
|
+
optionsArg: {
|
|
33
|
+
cwd?: string;
|
|
34
|
+
capture?: boolean;
|
|
35
|
+
timeoutMs?: number;
|
|
36
|
+
heartbeatStdin?: boolean;
|
|
37
|
+
} = {},
|
|
38
|
+
): Promise<string> =>
|
|
39
|
+
new Promise((resolveArg, rejectArg) => {
|
|
40
|
+
const capture = optionsArg.capture === true;
|
|
41
|
+
const child = childProcess.spawn(commandArg, argsArg, {
|
|
42
|
+
cwd: optionsArg.cwd || process.cwd(),
|
|
43
|
+
env: process.env,
|
|
44
|
+
stdio: capture
|
|
45
|
+
? ['ignore', 'pipe', 'pipe']
|
|
46
|
+
: optionsArg.heartbeatStdin
|
|
47
|
+
? ['pipe', 'inherit', 'inherit']
|
|
48
|
+
: 'inherit',
|
|
49
|
+
detached: true,
|
|
50
|
+
});
|
|
51
|
+
let stdout = '';
|
|
52
|
+
let stderr = '';
|
|
53
|
+
let capturedOutputBytes = 0;
|
|
54
|
+
let timedOut = false;
|
|
55
|
+
let outputLimitExceeded = false;
|
|
56
|
+
let forwardedSignal: TForwardedSignal | undefined;
|
|
57
|
+
let forwardedSignalCount = 0;
|
|
58
|
+
let settled = false;
|
|
59
|
+
let forceKillTimer: NodeJS.Timeout | undefined;
|
|
60
|
+
let heartbeatTimer: NodeJS.Timeout | undefined;
|
|
61
|
+
|
|
62
|
+
const killProcessGroup = (signalArg: NodeJS.Signals): void => {
|
|
63
|
+
if (!child.pid) return;
|
|
64
|
+
try {
|
|
65
|
+
process.kill(-child.pid, signalArg);
|
|
66
|
+
} catch {
|
|
67
|
+
try {
|
|
68
|
+
child.kill(signalArg);
|
|
69
|
+
} catch {
|
|
70
|
+
// The process may already have exited.
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const terminateProcessGroup = (signalArg: NodeJS.Signals): void => {
|
|
76
|
+
killProcessGroup(signalArg);
|
|
77
|
+
if (!forceKillTimer) {
|
|
78
|
+
forceKillTimer = setTimeout(
|
|
79
|
+
() => killProcessGroup('SIGKILL'),
|
|
80
|
+
forceKillDelayMs,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const processGroupExists = (): boolean => {
|
|
86
|
+
if (!child.pid) return false;
|
|
87
|
+
try {
|
|
88
|
+
process.kill(-child.pid, 0);
|
|
89
|
+
return true;
|
|
90
|
+
} catch (error) {
|
|
91
|
+
if ((error as NodeJS.ErrnoException).code === 'ESRCH') return false;
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const waitForProcessGroupExit = async (timeoutMsArg: number): Promise<boolean> => {
|
|
97
|
+
const deadline = Date.now() + timeoutMsArg;
|
|
98
|
+
while (processGroupExists() && Date.now() < deadline) {
|
|
99
|
+
await new Promise((resolveArg) => setTimeout(resolveArg, 100));
|
|
100
|
+
}
|
|
101
|
+
return !processGroupExists();
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const ensureProcessGroupStopped = async (): Promise<void> => {
|
|
105
|
+
if (!processGroupExists()) return;
|
|
106
|
+
terminateProcessGroup('SIGTERM');
|
|
107
|
+
if (!(await waitForProcessGroupExit(forceKillDelayMs + 1000))) {
|
|
108
|
+
killProcessGroup('SIGKILL');
|
|
109
|
+
if (!(await waitForProcessGroupExit(2000))) {
|
|
110
|
+
throw new Error(`${commandArg} left a live descendant process group`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const signalHandlers = new Map<TForwardedSignal, () => void>();
|
|
116
|
+
for (const signal of ['SIGINT', 'SIGTERM', 'SIGHUP'] as TForwardedSignal[]) {
|
|
117
|
+
const handler = (): void => {
|
|
118
|
+
forwardedSignal = signal;
|
|
119
|
+
forwardedSignalCount += 1;
|
|
120
|
+
if (forwardedSignalCount === 1) terminateProcessGroup(signal);
|
|
121
|
+
else killProcessGroup('SIGKILL');
|
|
122
|
+
};
|
|
123
|
+
signalHandlers.set(signal, handler);
|
|
124
|
+
process.on(signal, handler);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const timeout = setTimeout(() => {
|
|
128
|
+
timedOut = true;
|
|
129
|
+
terminateProcessGroup('SIGTERM');
|
|
130
|
+
}, optionsArg.timeoutMs || defaultCommandTimeoutMs);
|
|
131
|
+
|
|
132
|
+
if (optionsArg.heartbeatStdin) {
|
|
133
|
+
child.stdin?.on('error', () => {
|
|
134
|
+
// Process close handles a lost stdin channel.
|
|
135
|
+
});
|
|
136
|
+
const sendHeartbeat = (): void => {
|
|
137
|
+
if (!child.stdin?.destroyed) child.stdin?.write('heartbeat\n');
|
|
138
|
+
};
|
|
139
|
+
sendHeartbeat();
|
|
140
|
+
heartbeatTimer = setInterval(sendHeartbeat, 1000);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const cleanup = (): void => {
|
|
144
|
+
clearTimeout(timeout);
|
|
145
|
+
if (forceKillTimer) clearTimeout(forceKillTimer);
|
|
146
|
+
if (heartbeatTimer) clearInterval(heartbeatTimer);
|
|
147
|
+
child.stdin?.end();
|
|
148
|
+
for (const [signal, handler] of signalHandlers) {
|
|
149
|
+
process.off(signal, handler);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const captureChunk = (targetArg: 'stdout' | 'stderr', chunkArg: Buffer): void => {
|
|
154
|
+
capturedOutputBytes += chunkArg.length;
|
|
155
|
+
if (capturedOutputBytes > maximumCapturedOutputBytes) {
|
|
156
|
+
outputLimitExceeded = true;
|
|
157
|
+
terminateProcessGroup('SIGTERM');
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (targetArg === 'stdout') stdout += chunkArg.toString('utf8');
|
|
161
|
+
else stderr += chunkArg.toString('utf8');
|
|
162
|
+
};
|
|
163
|
+
child.stdout?.on('data', (chunkArg: Buffer) => captureChunk('stdout', chunkArg));
|
|
164
|
+
child.stderr?.on('data', (chunkArg: Buffer) => captureChunk('stderr', chunkArg));
|
|
165
|
+
|
|
166
|
+
child.once('error', (errorArg) => {
|
|
167
|
+
if (settled) return;
|
|
168
|
+
settled = true;
|
|
169
|
+
cleanup();
|
|
170
|
+
rejectArg(errorArg);
|
|
171
|
+
});
|
|
172
|
+
child.once('close', (codeArg, signalArg) => {
|
|
173
|
+
if (settled) return;
|
|
174
|
+
settled = true;
|
|
175
|
+
void (async () => {
|
|
176
|
+
try {
|
|
177
|
+
await ensureProcessGroupStopped();
|
|
178
|
+
cleanup();
|
|
179
|
+
if (codeArg !== 0 && capture) {
|
|
180
|
+
if (stdout) process.stdout.write(stdout);
|
|
181
|
+
if (stderr) process.stderr.write(stderr);
|
|
182
|
+
}
|
|
183
|
+
if (timedOut) {
|
|
184
|
+
rejectArg(new Error(`${commandArg} exceeded its command timeout`));
|
|
185
|
+
} else if (outputLimitExceeded) {
|
|
186
|
+
rejectArg(new Error(`${commandArg} exceeded the captured output limit`));
|
|
187
|
+
} else if (forwardedSignal) {
|
|
188
|
+
rejectArg(new Error(`${commandArg} was interrupted by ${forwardedSignal}`));
|
|
189
|
+
} else if (codeArg !== 0) {
|
|
190
|
+
rejectArg(
|
|
191
|
+
new Error(
|
|
192
|
+
`${commandArg} exited with ${signalArg ? `signal ${signalArg}` : `status ${codeArg}`}`,
|
|
193
|
+
),
|
|
194
|
+
);
|
|
195
|
+
} else {
|
|
196
|
+
resolveArg(stdout.trim());
|
|
197
|
+
}
|
|
198
|
+
} catch (error) {
|
|
199
|
+
cleanup();
|
|
200
|
+
rejectArg(error);
|
|
201
|
+
}
|
|
202
|
+
})();
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const runCommand = async (
|
|
207
|
+
commandArg: string,
|
|
208
|
+
argsArg: string[],
|
|
209
|
+
cwdArg: string = process.cwd(),
|
|
210
|
+
timeoutMsArg: number = defaultCommandTimeoutMs,
|
|
211
|
+
heartbeatStdinArg: boolean = false,
|
|
212
|
+
): Promise<void> => {
|
|
213
|
+
await executeCommand(commandArg, argsArg, {
|
|
214
|
+
cwd: cwdArg,
|
|
215
|
+
timeoutMs: timeoutMsArg,
|
|
216
|
+
heartbeatStdin: heartbeatStdinArg,
|
|
217
|
+
});
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
const captureCommand = async (
|
|
221
|
+
commandArg: string,
|
|
222
|
+
argsArg: string[],
|
|
223
|
+
cwdArg: string = process.cwd(),
|
|
224
|
+
): Promise<string> => {
|
|
225
|
+
return executeCommand(commandArg, argsArg, {
|
|
226
|
+
cwd: cwdArg,
|
|
227
|
+
capture: true,
|
|
228
|
+
timeoutMs: capabilityCommandTimeoutMs,
|
|
229
|
+
});
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
const loadEnvironment = (): IReleaseArtifactEnvironment => {
|
|
233
|
+
const macosSsh = process.env.SMARTDB_RELEASE_MACOS_SSH?.trim() || '';
|
|
234
|
+
const macosTempRoot = (process.env.SMARTDB_RELEASE_MACOS_TEMP_ROOT?.trim() || '').replace(
|
|
235
|
+
/\/+$/,
|
|
236
|
+
'',
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
if (!/^[A-Za-z0-9._-]+@[A-Za-z0-9.-]+$/.test(macosSsh)) {
|
|
240
|
+
throw new Error(
|
|
241
|
+
'SMARTDB_RELEASE_MACOS_SSH must use the user@host form without SSH options',
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
if (
|
|
245
|
+
!/^\/[A-Za-z0-9._/-]+$/.test(macosTempRoot) ||
|
|
246
|
+
path.posix.normalize(macosTempRoot) !== macosTempRoot ||
|
|
247
|
+
macosTempRoot.split('/').filter(Boolean).length < 2
|
|
248
|
+
) {
|
|
249
|
+
throw new Error(
|
|
250
|
+
'SMARTDB_RELEASE_MACOS_TEMP_ROOT must be a non-root absolute path without spaces',
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
return { macosSsh, macosTempRoot };
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
const runRemoteLoginScript = async (
|
|
257
|
+
environmentArg: IReleaseArtifactEnvironment,
|
|
258
|
+
scriptArg: string,
|
|
259
|
+
timeoutMsArg: number = defaultCommandTimeoutMs,
|
|
260
|
+
): Promise<void> => {
|
|
261
|
+
const ownedRemoteScript = [
|
|
262
|
+
'set -u',
|
|
263
|
+
'exec 3<&0',
|
|
264
|
+
'child_pid=',
|
|
265
|
+
'watchdog_pid=',
|
|
266
|
+
'kill_tree() {',
|
|
267
|
+
' local parent_pid children child_pid_to_kill',
|
|
268
|
+
' parent_pid="$1"',
|
|
269
|
+
' kill -STOP "$parent_pid" 2>/dev/null || return 0',
|
|
270
|
+
' children="$(/usr/bin/pgrep -P "$parent_pid" 2>/dev/null || true)"',
|
|
271
|
+
' for child_pid_to_kill in $children; do kill_tree "$child_pid_to_kill"; done',
|
|
272
|
+
' kill -KILL "$parent_pid" 2>/dev/null || true',
|
|
273
|
+
'}',
|
|
274
|
+
'terminate_owned() { test -z "$child_pid" || kill_tree "$child_pid"; test -z "$watchdog_pid" || kill -KILL "$watchdog_pid" 2>/dev/null || true; }',
|
|
275
|
+
'watch_channel() { while IFS= read -r -t 45 ignored_line; do :; done; test -z "$child_pid" || kill_tree "$child_pid"; }',
|
|
276
|
+
'trap terminate_owned EXIT HUP INT TERM',
|
|
277
|
+
`/bin/zsh -lc ${shellQuote(scriptArg)} </dev/null &`,
|
|
278
|
+
'child_pid=$!',
|
|
279
|
+
'watch_channel <&3 &',
|
|
280
|
+
'watchdog_pid=$!',
|
|
281
|
+
'wait "$child_pid"',
|
|
282
|
+
'exit_status=$?',
|
|
283
|
+
'child_pid=',
|
|
284
|
+
'kill -KILL "$watchdog_pid" 2>/dev/null || true',
|
|
285
|
+
'wait "$watchdog_pid" 2>/dev/null || true',
|
|
286
|
+
'watchdog_pid=',
|
|
287
|
+
'exec 3<&-',
|
|
288
|
+
'trap - EXIT HUP INT TERM',
|
|
289
|
+
'exit "$exit_status"',
|
|
290
|
+
].join('\n');
|
|
291
|
+
await runCommand(
|
|
292
|
+
'ssh',
|
|
293
|
+
[
|
|
294
|
+
...sshConnectionArgs,
|
|
295
|
+
environmentArg.macosSsh,
|
|
296
|
+
`zsh -lic ${shellQuote(`/bin/sh -c ${shellQuote(ownedRemoteScript)}`)}`,
|
|
297
|
+
],
|
|
298
|
+
process.cwd(),
|
|
299
|
+
timeoutMsArg,
|
|
300
|
+
true,
|
|
301
|
+
);
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
const checkBuilders = async (
|
|
305
|
+
environmentArg: IReleaseArtifactEnvironment,
|
|
306
|
+
): Promise<void> => {
|
|
307
|
+
if (process.platform !== 'linux' || process.arch !== 'x64') {
|
|
308
|
+
throw new Error('SmartDB release artifact assembly requires a Linux amd64 coordinator');
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
await runCommand('git', ['--version'], process.cwd(), capabilityCommandTimeoutMs);
|
|
312
|
+
await runCommand('pnpm', ['--version'], process.cwd(), capabilityCommandTimeoutMs);
|
|
313
|
+
await captureCommand('/bin/sh', ['-c', 'command -v scp >/dev/null']);
|
|
314
|
+
const linuxProbeParent = path.join(process.cwd(), '.nogit', 'smartdb-release-probe');
|
|
315
|
+
fs.mkdirSync(linuxProbeParent, { recursive: true, mode: 0o700 });
|
|
316
|
+
const linuxProbeDirectory = fs.mkdtempSync(path.join(linuxProbeParent, 'arm64-'));
|
|
317
|
+
try {
|
|
318
|
+
const sourcePath = path.join(linuxProbeDirectory, 'probe.c');
|
|
319
|
+
const binaryPath = path.join(linuxProbeDirectory, 'probe');
|
|
320
|
+
fs.writeFileSync(sourcePath, 'int main(void) { return 0; }\n');
|
|
321
|
+
await runCommand(
|
|
322
|
+
'aarch64-linux-gnu-gcc',
|
|
323
|
+
['-static', '-O2', sourcePath, '-o', binaryPath],
|
|
324
|
+
process.cwd(),
|
|
325
|
+
capabilityCommandTimeoutMs,
|
|
326
|
+
);
|
|
327
|
+
await runCommand(binaryPath, [], process.cwd(), capabilityCommandTimeoutMs);
|
|
328
|
+
} finally {
|
|
329
|
+
fs.rmSync(linuxProbeDirectory, { recursive: true, force: true });
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const probeToken = crypto.randomUUID();
|
|
333
|
+
const probePath = `${environmentArg.macosTempRoot}/smartdb-release-check.${probeToken}`;
|
|
334
|
+
const remoteCheckScript = [
|
|
335
|
+
'set -eu',
|
|
336
|
+
'test "$(uname -s)" = "Darwin"',
|
|
337
|
+
'test "$(uname -m)" = "arm64"',
|
|
338
|
+
'command -v git >/dev/null',
|
|
339
|
+
'command -v pnpm >/dev/null',
|
|
340
|
+
'command -v codesign >/dev/null',
|
|
341
|
+
'command -v cmp >/dev/null',
|
|
342
|
+
`root=${shellQuote(environmentArg.macosTempRoot)}`,
|
|
343
|
+
`probe=${shellQuote(probePath)}`,
|
|
344
|
+
`test "$probe" = "$root/smartdb-release-check.${probeToken}"`,
|
|
345
|
+
'mkdir -p "$root"',
|
|
346
|
+
'test "$(cd "$root" && pwd -P)" = "$root"',
|
|
347
|
+
'created=0',
|
|
348
|
+
`cleanup_probe() { if [ "$created" = 1 ]; then test ! -f "$probe/.smartdb-release-owner" || test "$(cat "$probe/.smartdb-release-owner")" = ${shellQuote(probeToken)} || return; rm -f "$probe/.smartdb-release-owner"; rmdir "$probe" 2>/dev/null || true; fi; }`,
|
|
349
|
+
'trap cleanup_probe EXIT HUP INT TERM',
|
|
350
|
+
'mkdir -m 700 "$probe"',
|
|
351
|
+
'created=1',
|
|
352
|
+
`printf '%s\\n' ${shellQuote(probeToken)} > "$probe/.smartdb-release-owner"`,
|
|
353
|
+
'rm -f "$probe/.smartdb-release-owner"',
|
|
354
|
+
'rmdir "$probe"',
|
|
355
|
+
'trap - EXIT HUP INT TERM',
|
|
356
|
+
'/usr/bin/arch -x86_64 /usr/bin/true',
|
|
357
|
+
].join('\n');
|
|
358
|
+
await runRemoteLoginScript(
|
|
359
|
+
environmentArg,
|
|
360
|
+
remoteCheckScript,
|
|
361
|
+
capabilityCommandTimeoutMs,
|
|
362
|
+
);
|
|
363
|
+
console.log('All SmartDB release builders can execute their assigned architectures.');
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
const assertArtifactSet = (directoryArg: string, targetsArg: string[]): void => {
|
|
367
|
+
const expectedNames = targetsArg.flatMap((targetArg) => [
|
|
368
|
+
`rustdb_${targetArg}`,
|
|
369
|
+
`rustdb_${targetArg}${provenanceSuffix}`,
|
|
370
|
+
]);
|
|
371
|
+
const actualNames = fs.readdirSync(directoryArg).sort();
|
|
372
|
+
if (JSON.stringify(actualNames) !== JSON.stringify(expectedNames.sort())) {
|
|
373
|
+
throw new Error(
|
|
374
|
+
`Unexpected release artifact set in ${directoryArg}: ${actualNames.join(', ')}`,
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
for (const target of targetsArg) {
|
|
378
|
+
const binaryPath = path.join(directoryArg, `rustdb_${target}`);
|
|
379
|
+
const stat = fs.lstatSync(binaryPath);
|
|
380
|
+
if (!stat.isFile() || (stat.mode & 0o111) === 0) {
|
|
381
|
+
throw new Error(`Release artifact is not an executable regular file: ${binaryPath}`);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
const remoteWorkspacePath = (
|
|
387
|
+
environmentArg: IReleaseArtifactEnvironment,
|
|
388
|
+
gitCommitArg: string,
|
|
389
|
+
ownerTokenArg: string,
|
|
390
|
+
): string =>
|
|
391
|
+
`${environmentArg.macosTempRoot}/smartdb-release.${gitCommitArg}.${ownerTokenArg}`;
|
|
392
|
+
|
|
393
|
+
const assertOwnedRemoteWorkspacePath = (
|
|
394
|
+
environmentArg: IReleaseArtifactEnvironment,
|
|
395
|
+
remoteDirectoryArg: string,
|
|
396
|
+
gitCommitArg: string,
|
|
397
|
+
ownerTokenArg: string,
|
|
398
|
+
): void => {
|
|
399
|
+
const expectedDirectory = remoteWorkspacePath(
|
|
400
|
+
environmentArg,
|
|
401
|
+
gitCommitArg,
|
|
402
|
+
ownerTokenArg,
|
|
403
|
+
);
|
|
404
|
+
if (
|
|
405
|
+
remoteDirectoryArg !== expectedDirectory ||
|
|
406
|
+
path.posix.dirname(remoteDirectoryArg) !== environmentArg.macosTempRoot ||
|
|
407
|
+
path.posix.normalize(remoteDirectoryArg) !== remoteDirectoryArg
|
|
408
|
+
) {
|
|
409
|
+
throw new Error(`Refusing unsafe macOS release workspace path: ${remoteDirectoryArg}`);
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
const createRemoteWorkspace = async (
|
|
414
|
+
environmentArg: IReleaseArtifactEnvironment,
|
|
415
|
+
remoteDirectoryArg: string,
|
|
416
|
+
gitCommitArg: string,
|
|
417
|
+
ownerTokenArg: string,
|
|
418
|
+
): Promise<void> => {
|
|
419
|
+
assertOwnedRemoteWorkspacePath(
|
|
420
|
+
environmentArg,
|
|
421
|
+
remoteDirectoryArg,
|
|
422
|
+
gitCommitArg,
|
|
423
|
+
ownerTokenArg,
|
|
424
|
+
);
|
|
425
|
+
const createScript = [
|
|
426
|
+
'set -eu',
|
|
427
|
+
`root=${shellQuote(environmentArg.macosTempRoot)}`,
|
|
428
|
+
`directory=${shellQuote(remoteDirectoryArg)}`,
|
|
429
|
+
`test "$directory" = "$root/smartdb-release.${gitCommitArg}.${ownerTokenArg}"`,
|
|
430
|
+
'mkdir -p "$root"',
|
|
431
|
+
'test "$(cd "$root" && pwd -P)" = "$root"',
|
|
432
|
+
'created=0',
|
|
433
|
+
`cleanup_unowned() { if [ "$created" = 1 ]; then test ! -f "$directory/.smartdb-release-owner" || test "$(cat "$directory/.smartdb-release-owner")" = ${shellQuote(ownerTokenArg)} || return; rm -f "$directory/.smartdb-release-owner"; rmdir "$directory" 2>/dev/null || true; fi; }`,
|
|
434
|
+
'trap cleanup_unowned EXIT HUP INT TERM',
|
|
435
|
+
'mkdir -m 700 "$directory"',
|
|
436
|
+
'created=1',
|
|
437
|
+
`printf '%s\\n' ${shellQuote(ownerTokenArg)} > "$directory/.smartdb-release-owner"`,
|
|
438
|
+
'trap - EXIT HUP INT TERM',
|
|
439
|
+
].join('\n');
|
|
440
|
+
await runCommand(
|
|
441
|
+
'ssh',
|
|
442
|
+
[...sshConnectionArgs, environmentArg.macosSsh, createScript],
|
|
443
|
+
process.cwd(),
|
|
444
|
+
capabilityCommandTimeoutMs,
|
|
445
|
+
);
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
const cleanupRemoteWorkspace = async (
|
|
449
|
+
environmentArg: IReleaseArtifactEnvironment,
|
|
450
|
+
remoteDirectoryArg: string,
|
|
451
|
+
gitCommitArg: string,
|
|
452
|
+
ownerTokenArg: string,
|
|
453
|
+
): Promise<void> => {
|
|
454
|
+
assertOwnedRemoteWorkspacePath(
|
|
455
|
+
environmentArg,
|
|
456
|
+
remoteDirectoryArg,
|
|
457
|
+
gitCommitArg,
|
|
458
|
+
ownerTokenArg,
|
|
459
|
+
);
|
|
460
|
+
const cleanupScript = [
|
|
461
|
+
'set -eu',
|
|
462
|
+
`root=${shellQuote(environmentArg.macosTempRoot)}`,
|
|
463
|
+
`directory=${shellQuote(remoteDirectoryArg)}`,
|
|
464
|
+
`test "$directory" = "$root/smartdb-release.${gitCommitArg}.${ownerTokenArg}"`,
|
|
465
|
+
'test "$(cd "$root" && pwd -P)" = "$root"',
|
|
466
|
+
'test -f "$directory/.smartdb-release-owner"',
|
|
467
|
+
`test "$(cat "$directory/.smartdb-release-owner")" = ${shellQuote(ownerTokenArg)}`,
|
|
468
|
+
'rm -rf "$directory"',
|
|
469
|
+
].join('\n');
|
|
470
|
+
await runCommand('ssh', [...sshConnectionArgs, environmentArg.macosSsh, cleanupScript]);
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
const buildArtifacts = async (
|
|
474
|
+
environmentArg: IReleaseArtifactEnvironment,
|
|
475
|
+
): Promise<void> => {
|
|
476
|
+
await checkBuilders(environmentArg);
|
|
477
|
+
|
|
478
|
+
const workspace = process.cwd();
|
|
479
|
+
const branch = await captureCommand('git', ['branch', '--show-current'], workspace);
|
|
480
|
+
const gitCommit = await captureCommand('git', ['rev-parse', 'HEAD'], workspace);
|
|
481
|
+
const gitStatus = await captureCommand(
|
|
482
|
+
'git',
|
|
483
|
+
['status', '--porcelain=v1', '--untracked-files=all'],
|
|
484
|
+
workspace,
|
|
485
|
+
);
|
|
486
|
+
const packageJson = JSON.parse(
|
|
487
|
+
fs.readFileSync(path.join(workspace, 'package.json'), 'utf8'),
|
|
488
|
+
) as { version?: string };
|
|
489
|
+
const expectedTag = `v${packageJson.version || ''}`;
|
|
490
|
+
const tagsAtHead = (
|
|
491
|
+
await captureCommand('git', ['tag', '--points-at', 'HEAD'], workspace)
|
|
492
|
+
).split(/\r?\n/);
|
|
493
|
+
if (branch !== 'main') throw new Error('SmartDB releases must be built from main');
|
|
494
|
+
if (gitStatus) throw new Error('SmartDB release artifact build requires a clean worktree');
|
|
495
|
+
if (!packageJson.version || !tagsAtHead.includes(expectedTag)) {
|
|
496
|
+
throw new Error(`SmartDB release artifact build requires ${expectedTag} at HEAD`);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
const releaseParent = path.join(workspace, '.nogit', 'smartdb-release');
|
|
500
|
+
fs.mkdirSync(releaseParent, { recursive: true, mode: 0o700 });
|
|
501
|
+
const localDirectory = fs.mkdtempSync(
|
|
502
|
+
path.join(releaseParent, `${gitCommit.slice(0, 12)}-`),
|
|
503
|
+
);
|
|
504
|
+
const linuxDirectory = path.join(localDirectory, 'linux');
|
|
505
|
+
const macosDirectory = path.join(localDirectory, 'macos');
|
|
506
|
+
const bundlePath = path.join(localDirectory, 'source.bundle');
|
|
507
|
+
const ownerToken = crypto.randomUUID();
|
|
508
|
+
let remoteDirectory: string | undefined;
|
|
509
|
+
let completed = false;
|
|
510
|
+
|
|
511
|
+
try {
|
|
512
|
+
await runCommand('pnpm', ['exec', 'tsbundle'], workspace);
|
|
513
|
+
await runCommand('pnpm', ['exec', 'tsbuild', 'tsfolders'], workspace);
|
|
514
|
+
await runCommand('pnpm', ['exec', 'tsrust'], workspace);
|
|
515
|
+
|
|
516
|
+
fs.cpSync(path.join(workspace, 'dist_rust'), linuxDirectory, {
|
|
517
|
+
recursive: true,
|
|
518
|
+
preserveTimestamps: true,
|
|
519
|
+
});
|
|
520
|
+
assertArtifactSet(linuxDirectory, ['linux_amd64', 'linux_arm64']);
|
|
521
|
+
await runCommand(path.join(linuxDirectory, 'rustdb_linux_amd64'), ['--version'], workspace);
|
|
522
|
+
await runCommand(
|
|
523
|
+
path.join(linuxDirectory, 'rustdb_linux_arm64'),
|
|
524
|
+
['--version'],
|
|
525
|
+
workspace,
|
|
526
|
+
);
|
|
527
|
+
|
|
528
|
+
await runCommand('git', ['bundle', 'create', bundlePath, 'HEAD'], workspace);
|
|
529
|
+
remoteDirectory = remoteWorkspacePath(environmentArg, gitCommit, ownerToken);
|
|
530
|
+
await createRemoteWorkspace(
|
|
531
|
+
environmentArg,
|
|
532
|
+
remoteDirectory,
|
|
533
|
+
gitCommit,
|
|
534
|
+
ownerToken,
|
|
535
|
+
);
|
|
536
|
+
await runCommand('scp', [
|
|
537
|
+
'-p',
|
|
538
|
+
...sshConnectionArgs,
|
|
539
|
+
bundlePath,
|
|
540
|
+
`${environmentArg.macosSsh}:${remoteDirectory}/source.bundle`,
|
|
541
|
+
]);
|
|
542
|
+
|
|
543
|
+
const remoteWorkspace = `${remoteDirectory}/workspace`;
|
|
544
|
+
const remoteBuildScript = [
|
|
545
|
+
'set -eu',
|
|
546
|
+
`bundle=${shellQuote(`${remoteDirectory}/source.bundle`)}`,
|
|
547
|
+
`workspace=${shellQuote(remoteWorkspace)}`,
|
|
548
|
+
`expected_commit=${shellQuote(gitCommit)}`,
|
|
549
|
+
'git clone --quiet "$bundle" "$workspace"',
|
|
550
|
+
'cd "$workspace"',
|
|
551
|
+
'test "$(git rev-parse HEAD)" = "$expected_commit"',
|
|
552
|
+
'test -z "$(git status --porcelain=v1 --untracked-files=all)"',
|
|
553
|
+
'pnpm install --frozen-lockfile',
|
|
554
|
+
'pnpm exec tsrust',
|
|
555
|
+
'cmp .nogit/tsrust-target/aarch64-apple-darwin/release/rustdb dist_rust/rustdb_macos_arm64',
|
|
556
|
+
'cmp .nogit/tsrust-target/x86_64-apple-darwin/release/rustdb dist_rust/rustdb_macos_amd64',
|
|
557
|
+
'codesign --verify --deep --strict dist_rust/rustdb_macos_arm64',
|
|
558
|
+
'codesign --verify --deep --strict dist_rust/rustdb_macos_amd64',
|
|
559
|
+
'/usr/bin/arch -arm64 dist_rust/rustdb_macos_arm64 --version',
|
|
560
|
+
'/usr/bin/arch -x86_64 dist_rust/rustdb_macos_amd64 --version',
|
|
561
|
+
'test "$(git rev-parse HEAD)" = "$expected_commit"',
|
|
562
|
+
'test -z "$(git status --porcelain=v1 --untracked-files=all)"',
|
|
563
|
+
].join('\n');
|
|
564
|
+
await runRemoteLoginScript(environmentArg, remoteBuildScript);
|
|
565
|
+
await runCommand('scp', [
|
|
566
|
+
'-pr',
|
|
567
|
+
...sshConnectionArgs,
|
|
568
|
+
`${environmentArg.macosSsh}:${remoteWorkspace}/dist_rust`,
|
|
569
|
+
macosDirectory,
|
|
570
|
+
]);
|
|
571
|
+
assertArtifactSet(macosDirectory, ['macos_amd64', 'macos_arm64']);
|
|
572
|
+
|
|
573
|
+
await runCommand(
|
|
574
|
+
'pnpm',
|
|
575
|
+
['exec', 'tsrust', 'assemble', linuxDirectory, macosDirectory],
|
|
576
|
+
workspace,
|
|
577
|
+
);
|
|
578
|
+
assertArtifactSet(path.join(workspace, 'dist_rust'), [
|
|
579
|
+
'linux_amd64',
|
|
580
|
+
'linux_arm64',
|
|
581
|
+
'macos_amd64',
|
|
582
|
+
'macos_arm64',
|
|
583
|
+
]);
|
|
584
|
+
for (const target of ['linux_amd64', 'linux_arm64', 'macos_amd64', 'macos_arm64']) {
|
|
585
|
+
await runCommand(
|
|
586
|
+
'pnpm',
|
|
587
|
+
['exec', 'tsrust', 'inspect', `dist_rust/rustdb_${target}`],
|
|
588
|
+
workspace,
|
|
589
|
+
);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
await cleanupRemoteWorkspace(
|
|
593
|
+
environmentArg,
|
|
594
|
+
remoteDirectory,
|
|
595
|
+
gitCommit,
|
|
596
|
+
ownerToken,
|
|
597
|
+
);
|
|
598
|
+
remoteDirectory = undefined;
|
|
599
|
+
fs.rmSync(localDirectory, { recursive: true });
|
|
600
|
+
completed = true;
|
|
601
|
+
console.log(`Assembled and qualified SmartDB release artifacts for ${expectedTag}.`);
|
|
602
|
+
} finally {
|
|
603
|
+
if (!completed) {
|
|
604
|
+
console.error(`Retained local release diagnostics at ${localDirectory}`);
|
|
605
|
+
if (remoteDirectory) {
|
|
606
|
+
console.error(`Retained macOS release diagnostics at ${remoteDirectory}`);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
try {
|
|
613
|
+
const mode = process.argv.find((argumentArg) =>
|
|
614
|
+
['check', 'build'].includes(argumentArg),
|
|
615
|
+
) as TReleaseArtifactMode | undefined;
|
|
616
|
+
if (!mode) throw new Error('Usage: release-artifacts.ts <check|build>');
|
|
617
|
+
const environment = loadEnvironment();
|
|
618
|
+
if (mode === 'check') {
|
|
619
|
+
await checkBuilders(environment);
|
|
620
|
+
} else {
|
|
621
|
+
await buildArtifacts(environment);
|
|
622
|
+
}
|
|
623
|
+
} catch (error) {
|
|
624
|
+
console.error(error);
|
|
625
|
+
process.exitCode = 1;
|
|
626
|
+
}
|
package/third-party-notices.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Third-Party Notices
|
|
2
2
|
|
|
3
|
-
The
|
|
3
|
+
The Rust executables distributed with this package include
|
|
4
4
|
third-party components. This document covers the complete third-party package
|
|
5
5
|
set recorded by `rust/Cargo.lock`, including target-inactive and compile-time
|
|
6
6
|
components. The nine `rustdb*` workspace crates are covered by the package's
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -140,7 +140,7 @@ export class LocalSmartDb {
|
|
|
140
140
|
if (optionsArg?.signal?.aborted) {
|
|
141
141
|
throw new LocalSmartDbStorageRootRelocationError('IO');
|
|
142
142
|
}
|
|
143
|
-
if (process.platform !== 'linux') {
|
|
143
|
+
if (process.platform !== 'linux' && process.platform !== 'darwin') {
|
|
144
144
|
throw new LocalSmartDbStorageRootRelocationError('UNSUPPORTED');
|
|
145
145
|
}
|
|
146
146
|
const deadline = optionsArg?.timeoutMs === undefined
|