@skillsmith/core 0.11.4 → 0.11.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 +60 -0
- package/README.md +10 -7
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/api/client.d.ts.map +1 -1
- package/dist/src/api/client.js +20 -5
- package/dist/src/api/client.js.map +1 -1
- package/dist/src/api/client.private-registry.d.ts +80 -0
- package/dist/src/api/client.private-registry.d.ts.map +1 -0
- package/dist/src/api/client.private-registry.js +97 -0
- package/dist/src/api/client.private-registry.js.map +1 -0
- package/dist/src/api/client.private-registry.test.d.ts +9 -0
- package/dist/src/api/client.private-registry.test.d.ts.map +1 -0
- package/dist/src/api/client.private-registry.test.js +127 -0
- package/dist/src/api/client.private-registry.test.js.map +1 -0
- package/dist/src/api/client.test.js +39 -0
- package/dist/src/api/client.test.js.map +1 -1
- package/dist/src/api/client.toSkill.test.d.ts +25 -0
- package/dist/src/api/client.toSkill.test.d.ts.map +1 -0
- package/dist/src/api/client.toSkill.test.js +97 -0
- package/dist/src/api/client.toSkill.test.js.map +1 -0
- package/dist/src/api/client.token-refresh.d.ts +8 -0
- package/dist/src/api/client.token-refresh.d.ts.map +1 -1
- package/dist/src/api/client.token-refresh.js +26 -0
- package/dist/src/api/client.token-refresh.js.map +1 -1
- package/dist/src/api/client.token-refresh.test.js +82 -0
- package/dist/src/api/client.token-refresh.test.js.map +1 -1
- package/dist/src/api/index.d.ts +2 -0
- package/dist/src/api/index.d.ts.map +1 -1
- package/dist/src/api/index.js +9 -0
- package/dist/src/api/index.js.map +1 -1
- package/dist/src/api/security-summary.d.ts +73 -0
- package/dist/src/api/security-summary.d.ts.map +1 -0
- package/dist/src/api/security-summary.js +88 -0
- package/dist/src/api/security-summary.js.map +1 -0
- package/dist/src/api/security-summary.test.d.ts +9 -0
- package/dist/src/api/security-summary.test.d.ts.map +1 -0
- package/dist/src/api/security-summary.test.js +94 -0
- package/dist/src/api/security-summary.test.js.map +1 -0
- package/dist/src/compatibility/slugs.d.ts +7 -3
- package/dist/src/compatibility/slugs.d.ts.map +1 -1
- package/dist/src/compatibility/slugs.js +11 -4
- package/dist/src/compatibility/slugs.js.map +1 -1
- package/dist/src/config/config-atomic-write.d.ts +30 -10
- package/dist/src/config/config-atomic-write.d.ts.map +1 -1
- package/dist/src/config/config-atomic-write.js +33 -80
- package/dist/src/config/config-atomic-write.js.map +1 -1
- package/dist/src/config/config-atomic-write.test.d.ts +8 -0
- package/dist/src/config/config-atomic-write.test.d.ts.map +1 -1
- package/dist/src/config/config-atomic-write.test.js +64 -12
- package/dist/src/config/config-atomic-write.test.js.map +1 -1
- package/dist/src/config/owned-lock.acquire.d.ts +53 -0
- package/dist/src/config/owned-lock.acquire.d.ts.map +1 -0
- package/dist/src/config/owned-lock.acquire.js +140 -0
- package/dist/src/config/owned-lock.acquire.js.map +1 -0
- package/dist/src/config/owned-lock.claim.d.ts +84 -0
- package/dist/src/config/owned-lock.claim.d.ts.map +1 -0
- package/dist/src/config/owned-lock.claim.js +310 -0
- package/dist/src/config/owned-lock.claim.js.map +1 -0
- package/dist/src/config/owned-lock.d.ts +113 -0
- package/dist/src/config/owned-lock.d.ts.map +1 -0
- package/dist/src/config/owned-lock.js +121 -0
- package/dist/src/config/owned-lock.js.map +1 -0
- package/dist/src/config/owned-lock.test.d.ts +12 -0
- package/dist/src/config/owned-lock.test.d.ts.map +1 -0
- package/dist/src/config/owned-lock.test.js +412 -0
- package/dist/src/config/owned-lock.test.js.map +1 -0
- package/dist/src/config/owned-lock.types.d.ts +78 -0
- package/dist/src/config/owned-lock.types.d.ts.map +1 -0
- package/dist/src/config/owned-lock.types.js +30 -0
- package/dist/src/config/owned-lock.types.js.map +1 -0
- package/dist/src/db/createDatabase.d.ts.map +1 -1
- package/dist/src/db/createDatabase.js +19 -7
- package/dist/src/db/createDatabase.js.map +1 -1
- package/dist/src/db/drivers/sqljsDriver.d.ts +8 -0
- package/dist/src/db/drivers/sqljsDriver.d.ts.map +1 -1
- package/dist/src/db/drivers/sqljsDriver.js +24 -2
- package/dist/src/db/drivers/sqljsDriver.js.map +1 -1
- package/dist/src/db/migration-runner.d.ts.map +1 -1
- package/dist/src/db/migration-runner.js +23 -2
- package/dist/src/db/migration-runner.js.map +1 -1
- package/dist/src/db/schema.d.ts.map +1 -1
- package/dist/src/db/schema.js +29 -3
- package/dist/src/db/schema.js.map +1 -1
- package/dist/src/embeddings/hnsw-store.exports.d.ts +11 -0
- package/dist/src/embeddings/hnsw-store.exports.d.ts.map +1 -0
- package/dist/src/embeddings/hnsw-store.exports.js +10 -0
- package/dist/src/embeddings/hnsw-store.exports.js.map +1 -0
- package/dist/src/embeddings/index.d.ts +1 -2
- package/dist/src/embeddings/index.d.ts.map +1 -1
- package/dist/src/embeddings/index.js +17 -3
- package/dist/src/embeddings/index.js.map +1 -1
- package/dist/src/embeddings/probe.d.ts.map +1 -1
- package/dist/src/embeddings/probe.js +4 -8
- package/dist/src/embeddings/probe.js.map +1 -1
- package/dist/src/exports/services.d.ts +5 -1
- package/dist/src/exports/services.d.ts.map +1 -1
- package/dist/src/exports/services.js +27 -0
- package/dist/src/exports/services.js.map +1 -1
- package/dist/src/index.d.ts +3 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +9 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/install/index.d.ts +2 -2
- package/dist/src/install/index.d.ts.map +1 -1
- package/dist/src/install/index.js +1 -1
- package/dist/src/install/index.js.map +1 -1
- package/dist/src/install/paths.d.ts +165 -1
- package/dist/src/install/paths.d.ts.map +1 -1
- package/dist/src/install/paths.js +254 -1
- package/dist/src/install/paths.js.map +1 -1
- package/dist/src/install/paths.test.js +174 -2
- package/dist/src/install/paths.test.js.map +1 -1
- package/dist/src/security/scanner/multiline-category-closure.test.d.ts +80 -0
- package/dist/src/security/scanner/multiline-category-closure.test.d.ts.map +1 -0
- package/dist/src/security/scanner/multiline-category-closure.test.js +287 -0
- package/dist/src/security/scanner/multiline-category-closure.test.js.map +1 -0
- package/dist/src/services/context-words.d.ts +40 -0
- package/dist/src/services/context-words.d.ts.map +1 -0
- package/dist/src/services/context-words.js +178 -0
- package/dist/src/services/context-words.js.map +1 -0
- package/dist/src/services/context-words.test.d.ts +2 -0
- package/dist/src/services/context-words.test.d.ts.map +1 -0
- package/dist/src/services/context-words.test.js +94 -0
- package/dist/src/services/context-words.test.js.map +1 -0
- package/dist/src/services/recommend-guard.d.ts +28 -0
- package/dist/src/services/recommend-guard.d.ts.map +1 -0
- package/dist/src/services/recommend-guard.js +34 -0
- package/dist/src/services/recommend-guard.js.map +1 -0
- package/dist/src/services/recommend-guard.test.d.ts +2 -0
- package/dist/src/services/recommend-guard.test.d.ts.map +1 -0
- package/dist/src/services/recommend-guard.test.js +28 -0
- package/dist/src/services/recommend-guard.test.js.map +1 -0
- package/dist/src/services/skill-installation.content.d.ts +96 -0
- package/dist/src/services/skill-installation.content.d.ts.map +1 -0
- package/dist/src/services/skill-installation.content.js +319 -0
- package/dist/src/services/skill-installation.content.js.map +1 -0
- package/dist/src/services/skill-installation.helpers.d.ts +32 -1
- package/dist/src/services/skill-installation.helpers.d.ts.map +1 -1
- package/dist/src/services/skill-installation.helpers.js +62 -7
- package/dist/src/services/skill-installation.helpers.js.map +1 -1
- package/dist/src/services/skill-installation.helpers.test.js +108 -2
- package/dist/src/services/skill-installation.helpers.test.js.map +1 -1
- package/dist/src/services/skill-installation.io.d.ts +22 -1
- package/dist/src/services/skill-installation.io.d.ts.map +1 -1
- package/dist/src/services/skill-installation.io.js +110 -6
- package/dist/src/services/skill-installation.io.js.map +1 -1
- package/dist/src/services/skill-installation.service.d.ts +22 -1
- package/dist/src/services/skill-installation.service.d.ts.map +1 -1
- package/dist/src/services/skill-installation.service.js +30 -5
- package/dist/src/services/skill-installation.service.js.map +1 -1
- package/dist/src/services/skill-installation.types.d.ts +42 -1
- package/dist/src/services/skill-installation.types.d.ts.map +1 -1
- package/dist/src/services/skill-installation.types.js.map +1 -1
- package/dist/src/services/skill-manifest.d.ts +21 -0
- package/dist/src/services/skill-manifest.d.ts.map +1 -1
- package/dist/src/services/skill-manifest.js +51 -6
- package/dist/src/services/skill-manifest.js.map +1 -1
- package/dist/src/services/skill-manifest.test.d.ts +2 -0
- package/dist/src/services/skill-manifest.test.d.ts.map +1 -0
- package/dist/src/services/skill-manifest.test.js +202 -0
- package/dist/src/services/skill-manifest.test.js.map +1 -0
- package/dist/src/services/skill-resolution.d.ts +67 -0
- package/dist/src/services/skill-resolution.d.ts.map +1 -0
- package/dist/src/services/skill-resolution.js +67 -0
- package/dist/src/services/skill-resolution.js.map +1 -0
- package/dist/src/services/skill-resolution.test.d.ts +2 -0
- package/dist/src/services/skill-resolution.test.d.ts.map +1 -0
- package/dist/src/services/skill-resolution.test.js +143 -0
- package/dist/src/services/skill-resolution.test.js.map +1 -0
- package/dist/src/types/skill.d.ts +10 -0
- package/dist/src/types/skill.d.ts.map +1 -1
- package/dist/src/types.d.ts +9 -5
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/index.d.ts +1 -0
- package/dist/src/utils/index.d.ts.map +1 -1
- package/dist/src/utils/index.js +4 -0
- package/dist/src/utils/index.js.map +1 -1
- package/dist/src/utils/quiet-mode.d.ts +21 -0
- package/dist/src/utils/quiet-mode.d.ts.map +1 -0
- package/dist/src/utils/quiet-mode.js +26 -0
- package/dist/src/utils/quiet-mode.js.map +1 -0
- package/dist/tests/EmbeddingService.test.js +58 -1
- package/dist/tests/EmbeddingService.test.js.map +1 -1
- package/dist/tests/SecurityScanner.performance.test.js +5 -2
- package/dist/tests/SecurityScanner.performance.test.js.map +1 -1
- package/dist/tests/db/database-abstraction.test.js +45 -1
- package/dist/tests/db/database-abstraction.test.js.map +1 -1
- package/dist/tests/db/migration-runner-race.test.d.ts +2 -0
- package/dist/tests/db/migration-runner-race.test.d.ts.map +1 -0
- package/dist/tests/db/migration-runner-race.test.js +75 -0
- package/dist/tests/db/migration-runner-race.test.js.map +1 -0
- package/dist/tests/db/schema-async.test.js +37 -1
- package/dist/tests/db/schema-async.test.js.map +1 -1
- package/dist/tests/db/sqljsDriver.test.js +63 -1
- package/dist/tests/db/sqljsDriver.test.js.map +1 -1
- package/dist/tests/helpers/deterministic-dead-pid.d.ts +13 -0
- package/dist/tests/helpers/deterministic-dead-pid.d.ts.map +1 -0
- package/dist/tests/helpers/deterministic-dead-pid.js +31 -0
- package/dist/tests/helpers/deterministic-dead-pid.js.map +1 -0
- package/dist/tests/integration/owned-lock-lost-update.test.d.ts +12 -0
- package/dist/tests/integration/owned-lock-lost-update.test.d.ts.map +1 -0
- package/dist/tests/integration/owned-lock-lost-update.test.js +52 -0
- package/dist/tests/integration/owned-lock-lost-update.test.js.map +1 -0
- package/dist/tests/integration/owned-lock-reclaim-race.test.d.ts +19 -0
- package/dist/tests/integration/owned-lock-reclaim-race.test.d.ts.map +1 -0
- package/dist/tests/integration/owned-lock-reclaim-race.test.js +177 -0
- package/dist/tests/integration/owned-lock-reclaim-race.test.js.map +1 -0
- package/dist/tests/schema.test.js +43 -1
- package/dist/tests/schema.test.js.map +1 -1
- package/dist/tests/unit/services/skill-installation.content.test.d.ts +10 -0
- package/dist/tests/unit/services/skill-installation.content.test.d.ts.map +1 -0
- package/dist/tests/unit/services/skill-installation.content.test.js +290 -0
- package/dist/tests/unit/services/skill-installation.content.test.js.map +1 -0
- package/dist/tests/unit/services/skill-installation.io.client-agent-path.test.d.ts +34 -0
- package/dist/tests/unit/services/skill-installation.io.client-agent-path.test.d.ts.map +1 -0
- package/dist/tests/unit/services/skill-installation.io.client-agent-path.test.js +246 -0
- package/dist/tests/unit/services/skill-installation.io.client-agent-path.test.js.map +1 -0
- package/dist/tests/unit/services/skill-installation.io.symlink.test.d.ts +8 -0
- package/dist/tests/unit/services/skill-installation.io.symlink.test.d.ts.map +1 -0
- package/dist/tests/unit/services/skill-installation.io.symlink.test.js +72 -0
- package/dist/tests/unit/services/skill-installation.io.symlink.test.js.map +1 -0
- package/dist/tests/unit/services/skill-installation.service.companion-basedir.test.d.ts +17 -0
- package/dist/tests/unit/services/skill-installation.service.companion-basedir.test.d.ts.map +1 -0
- package/dist/tests/unit/services/skill-installation.service.companion-basedir.test.js +112 -0
- package/dist/tests/unit/services/skill-installation.service.companion-basedir.test.js.map +1 -0
- package/dist/tests/unit/services/skill-installation.service.error-codes.test.d.ts +15 -0
- package/dist/tests/unit/services/skill-installation.service.error-codes.test.d.ts.map +1 -0
- package/dist/tests/unit/services/skill-installation.service.error-codes.test.js +190 -0
- package/dist/tests/unit/services/skill-installation.service.error-codes.test.js.map +1 -0
- package/dist/tests/unit/services/skill-installation.service.multi-client.test.d.ts +17 -0
- package/dist/tests/unit/services/skill-installation.service.multi-client.test.d.ts.map +1 -0
- package/dist/tests/unit/services/skill-installation.service.multi-client.test.js +126 -0
- package/dist/tests/unit/services/skill-installation.service.multi-client.test.js.map +1 -0
- package/dist/tests/unit/services/skill-installation.service.test.js +7 -112
- package/dist/tests/unit/services/skill-installation.service.test.js.map +1 -1
- package/dist/tests/utils/quiet-mode.test.d.ts +12 -0
- package/dist/tests/utils/quiet-mode.test.d.ts.map +1 -0
- package/dist/tests/utils/quiet-mode.test.js +42 -0
- package/dist/tests/utils/quiet-mode.test.js.map +1 -0
- package/package.json +17 -5
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the two-level owned-lock primitive (SMI-5883 §8a).
|
|
3
|
+
* @module @skillsmith/core/config/owned-lock.test
|
|
4
|
+
*
|
|
5
|
+
* Single-process tests of `acquireOwnedLock` itself. Cross-process tests
|
|
6
|
+
* (the reclaim-race proof, the orphaned-reclaim-lock residual, and the
|
|
7
|
+
* end-to-end lost-update stress test) live in
|
|
8
|
+
* `packages/core/tests/integration/owned-lock-reclaim-race.test.ts` (§8b/8c)
|
|
9
|
+
* and `packages/core/tests/integration/owned-lock-lost-update.test.ts` (§8f).
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=owned-lock.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owned-lock.test.d.ts","sourceRoot":"","sources":["../../../src/config/owned-lock.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the two-level owned-lock primitive (SMI-5883 §8a).
|
|
3
|
+
* @module @skillsmith/core/config/owned-lock.test
|
|
4
|
+
*
|
|
5
|
+
* Single-process tests of `acquireOwnedLock` itself. Cross-process tests
|
|
6
|
+
* (the reclaim-race proof, the orphaned-reclaim-lock residual, and the
|
|
7
|
+
* end-to-end lost-update stress test) live in
|
|
8
|
+
* `packages/core/tests/integration/owned-lock-reclaim-race.test.ts` (§8b/8c)
|
|
9
|
+
* and `packages/core/tests/integration/owned-lock-lost-update.test.ts` (§8f).
|
|
10
|
+
*/
|
|
11
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
12
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
13
|
+
import { hostname } from 'node:os';
|
|
14
|
+
import * as path from 'node:path';
|
|
15
|
+
import * as os from 'node:os';
|
|
16
|
+
import { acquireOwnedLock, StuckLockError } from './owned-lock.js';
|
|
17
|
+
import { createLockExclusive } from './owned-lock.claim.js';
|
|
18
|
+
import { mintDeadPid } from '../../tests/helpers/deterministic-dead-pid.js';
|
|
19
|
+
let dir;
|
|
20
|
+
let target;
|
|
21
|
+
let lockPath;
|
|
22
|
+
let reclaimPath;
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
dir =
|
|
25
|
+
os.tmpdir() + path.sep + `owned-lock-test-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
26
|
+
mkdirSync(dir, { recursive: true });
|
|
27
|
+
target = path.join(dir, 'store.json');
|
|
28
|
+
lockPath = `${target}.lock`;
|
|
29
|
+
reclaimPath = `${lockPath}.reclaim`;
|
|
30
|
+
});
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
rmSync(dir, { recursive: true, force: true });
|
|
33
|
+
});
|
|
34
|
+
function seed(content, at = lockPath) {
|
|
35
|
+
writeFileSync(at, content);
|
|
36
|
+
}
|
|
37
|
+
function v1(pid, opts = {}) {
|
|
38
|
+
return (JSON.stringify({
|
|
39
|
+
v: 1,
|
|
40
|
+
pid,
|
|
41
|
+
token: opts.token ?? 'a'.repeat(16),
|
|
42
|
+
host: opts.host ?? hostname(),
|
|
43
|
+
acquiredAt: opts.acquiredAt ?? Date.now(),
|
|
44
|
+
}) + '\n');
|
|
45
|
+
}
|
|
46
|
+
describe('acquireOwnedLock', () => {
|
|
47
|
+
it('1. acquire on a free path succeeds; the lock file is 0600, v1, this pid/host, 16-hex token', () => {
|
|
48
|
+
const release = acquireOwnedLock(target, { timeoutMs: 1_000 });
|
|
49
|
+
const raw = readFileSync(lockPath, 'utf-8');
|
|
50
|
+
const parsed = JSON.parse(raw);
|
|
51
|
+
expect(parsed.v).toBe(1);
|
|
52
|
+
expect(parsed.pid).toBe(process.pid);
|
|
53
|
+
expect(parsed.host).toBe(hostname());
|
|
54
|
+
expect(/^[0-9a-f]{16}$/.test(parsed.token)).toBe(true);
|
|
55
|
+
release();
|
|
56
|
+
});
|
|
57
|
+
it('2. a second acquire while held times out with reason held; the lock file is byte-identical afterwards', () => {
|
|
58
|
+
const release = acquireOwnedLock(target, { timeoutMs: 5_000 });
|
|
59
|
+
const before = readFileSync(lockPath);
|
|
60
|
+
try {
|
|
61
|
+
let caught;
|
|
62
|
+
try {
|
|
63
|
+
acquireOwnedLock(target, { timeoutMs: 200 });
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
caught = err;
|
|
67
|
+
}
|
|
68
|
+
expect(caught).toBeInstanceOf(StuckLockError);
|
|
69
|
+
expect(caught?.reason).toBe('held');
|
|
70
|
+
expect(readFileSync(lockPath).equals(before)).toBe(true);
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
release();
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
it('3. release removes the lock; a subsequent acquire succeeds immediately', () => {
|
|
77
|
+
const release = acquireOwnedLock(target, { timeoutMs: 1_000 });
|
|
78
|
+
release();
|
|
79
|
+
expect(existsSync(lockPath)).toBe(false);
|
|
80
|
+
const release2 = acquireOwnedLock(target, { timeoutMs: 200 });
|
|
81
|
+
release2();
|
|
82
|
+
});
|
|
83
|
+
it('4. release is idempotent — a second call neither throws nor unlinks', () => {
|
|
84
|
+
const release = acquireOwnedLock(target, { timeoutMs: 1_000 });
|
|
85
|
+
release();
|
|
86
|
+
expect(() => release()).not.toThrow();
|
|
87
|
+
});
|
|
88
|
+
it('5. ownership-verified release: a foreign token in the lock file is never unlinked', () => {
|
|
89
|
+
const release = acquireOwnedLock(target, { timeoutMs: 1_000 });
|
|
90
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => undefined);
|
|
91
|
+
// Overwrite the lock file out-of-band with a DIFFERENT v1 token.
|
|
92
|
+
seed(v1(process.pid, { token: 'f'.repeat(16) }));
|
|
93
|
+
release();
|
|
94
|
+
expect(existsSync(lockPath)).toBe(true);
|
|
95
|
+
expect(JSON.parse(readFileSync(lockPath, 'utf-8')).token).toBe('f'.repeat(16));
|
|
96
|
+
expect(warnSpy.mock.calls.some((c) => String(c[0]).includes('lock_release_not_owner'))).toBe(true);
|
|
97
|
+
warnSpy.mockRestore();
|
|
98
|
+
rmSync(lockPath);
|
|
99
|
+
});
|
|
100
|
+
it('6. v1 dead-PID reclaim: acquire succeeds well inside a tight budget; the reclaim lock is gone afterwards', () => {
|
|
101
|
+
const deadPid = mintDeadPid();
|
|
102
|
+
seed(v1(deadPid));
|
|
103
|
+
const start = Date.now();
|
|
104
|
+
const release = acquireOwnedLock(target, { timeoutMs: 5_000, reclaimProbeAfterMs: 0 });
|
|
105
|
+
expect(Date.now() - start).toBeLessThan(2_000);
|
|
106
|
+
expect(existsSync(reclaimPath)).toBe(false);
|
|
107
|
+
release();
|
|
108
|
+
});
|
|
109
|
+
it('7. v1 live-PID refusal: times out, reason held, file byte-identical', () => {
|
|
110
|
+
seed(v1(process.pid));
|
|
111
|
+
const before = readFileSync(lockPath);
|
|
112
|
+
let caught;
|
|
113
|
+
try {
|
|
114
|
+
acquireOwnedLock(target, { timeoutMs: 200, reclaimProbeAfterMs: 0 });
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
caught = err;
|
|
118
|
+
}
|
|
119
|
+
expect(caught?.reason).toBe('held');
|
|
120
|
+
expect(readFileSync(lockPath).equals(before)).toBe(true);
|
|
121
|
+
});
|
|
122
|
+
it('H-11: a live-PID lock with a 10-minute-old acquiredAt still times out (age is irrelevant, D-2 regression test)', () => {
|
|
123
|
+
seed(v1(process.pid, { acquiredAt: Date.now() - 10 * 60 * 1000 }));
|
|
124
|
+
const before = readFileSync(lockPath);
|
|
125
|
+
let caught;
|
|
126
|
+
try {
|
|
127
|
+
acquireOwnedLock(target, { timeoutMs: 200, reclaimProbeAfterMs: 0 });
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
caught = err;
|
|
131
|
+
}
|
|
132
|
+
expect(caught).toBeInstanceOf(StuckLockError);
|
|
133
|
+
expect(caught?.message).toContain(String(process.pid));
|
|
134
|
+
expect(caught?.message).toContain(hostname());
|
|
135
|
+
expect(readFileSync(lockPath).equals(before)).toBe(true);
|
|
136
|
+
});
|
|
137
|
+
it('8. EPERM from the liveness probe counts as alive — no reclaim, timeout', () => {
|
|
138
|
+
const deadPid = mintDeadPid(); // would otherwise be reclaimed
|
|
139
|
+
seed(v1(deadPid));
|
|
140
|
+
const killProbe = () => {
|
|
141
|
+
const err = new Error('EPERM');
|
|
142
|
+
err.code = 'EPERM';
|
|
143
|
+
throw err;
|
|
144
|
+
};
|
|
145
|
+
let caught;
|
|
146
|
+
try {
|
|
147
|
+
// The kill-probe override is threaded via the internal claim module in
|
|
148
|
+
// production; here we assert behaviourally via the public surface by
|
|
149
|
+
// making `process.kill` itself throw EPERM for this one PID.
|
|
150
|
+
const spy = vi.spyOn(process, 'kill').mockImplementation((pid) => {
|
|
151
|
+
if (pid === deadPid)
|
|
152
|
+
return killProbe();
|
|
153
|
+
return true;
|
|
154
|
+
});
|
|
155
|
+
try {
|
|
156
|
+
acquireOwnedLock(target, { timeoutMs: 200, reclaimProbeAfterMs: 0 });
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
caught = err;
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
spy.mockRestore();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
finally {
|
|
166
|
+
/* no-op */
|
|
167
|
+
}
|
|
168
|
+
expect(caught?.reason).toBe('held');
|
|
169
|
+
});
|
|
170
|
+
it('9. pid <= 0 rejected without probing (kill(0,0) would signal the process group)', () => {
|
|
171
|
+
for (const pid of [0, -1]) {
|
|
172
|
+
rmSync(lockPath, { force: true });
|
|
173
|
+
seed(v1(pid));
|
|
174
|
+
const spy = vi.spyOn(process, 'kill').mockImplementation(() => true);
|
|
175
|
+
let caught;
|
|
176
|
+
try {
|
|
177
|
+
acquireOwnedLock(target, { timeoutMs: 150, reclaimProbeAfterMs: 0 });
|
|
178
|
+
}
|
|
179
|
+
catch (err) {
|
|
180
|
+
caught = err;
|
|
181
|
+
}
|
|
182
|
+
expect(caught?.reason).toBe('held');
|
|
183
|
+
expect(spy).not.toHaveBeenCalled();
|
|
184
|
+
spy.mockRestore();
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
it('10. host mismatch: a dead PID on another host is never reclaimed', () => {
|
|
188
|
+
const deadPid = mintDeadPid();
|
|
189
|
+
seed(v1(deadPid, { host: 'some-other-host' }));
|
|
190
|
+
const before = readFileSync(lockPath);
|
|
191
|
+
let caught;
|
|
192
|
+
try {
|
|
193
|
+
acquireOwnedLock(target, { timeoutMs: 200, reclaimProbeAfterMs: 0 });
|
|
194
|
+
}
|
|
195
|
+
catch (err) {
|
|
196
|
+
caught = err;
|
|
197
|
+
}
|
|
198
|
+
expect(caught?.reason).toBe('held');
|
|
199
|
+
expect(readFileSync(lockPath).equals(before)).toBe(true);
|
|
200
|
+
});
|
|
201
|
+
it('11. unparseable claims (empty / truncated / garbage / wrong version) refuse with a byte-identical file (H-13 a-d)', () => {
|
|
202
|
+
const deadPid = mintDeadPid();
|
|
203
|
+
const cases = [
|
|
204
|
+
'', // (c) empty
|
|
205
|
+
'{"v":1,"pid":', // (c) truncated
|
|
206
|
+
'not json at all {{{', // (b) garbage bytes
|
|
207
|
+
JSON.stringify({
|
|
208
|
+
v: 2,
|
|
209
|
+
pid: deadPid,
|
|
210
|
+
token: 'a'.repeat(16),
|
|
211
|
+
host: hostname(),
|
|
212
|
+
acquiredAt: Date.now(),
|
|
213
|
+
}), // (d) valid JSON, wrong version -- never auto-reclaimed even with a genuinely dead PID
|
|
214
|
+
];
|
|
215
|
+
for (const content of cases) {
|
|
216
|
+
rmSync(lockPath, { force: true });
|
|
217
|
+
seed(content);
|
|
218
|
+
const before = readFileSync(lockPath);
|
|
219
|
+
let caught;
|
|
220
|
+
try {
|
|
221
|
+
acquireOwnedLock(target, { timeoutMs: 150, reclaimProbeAfterMs: 0 });
|
|
222
|
+
}
|
|
223
|
+
catch (err) {
|
|
224
|
+
caught = err;
|
|
225
|
+
}
|
|
226
|
+
expect(caught?.reason, `content: ${JSON.stringify(content)}`).toBe('unreclaimable_unparseable');
|
|
227
|
+
expect(readFileSync(lockPath).equals(before)).toBe(true);
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
it('12. legacy refusal, dead PID (D-5): a bare minted-dead PID is never reclaimed', () => {
|
|
231
|
+
const deadPid = mintDeadPid();
|
|
232
|
+
seed(String(deadPid));
|
|
233
|
+
const before = readFileSync(lockPath);
|
|
234
|
+
let caught;
|
|
235
|
+
try {
|
|
236
|
+
acquireOwnedLock(target, { timeoutMs: 150, reclaimProbeAfterMs: 0 });
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
caught = err;
|
|
240
|
+
}
|
|
241
|
+
expect(caught?.reason).toBe('unreclaimable_legacy');
|
|
242
|
+
expect(readFileSync(lockPath).equals(before)).toBe(true);
|
|
243
|
+
});
|
|
244
|
+
it('13. SKILLSMITH_LOCK_NO_AUTO_RECLAIM=1: a v1 dead-PID lock is not reclaimed; reason reclaim_disabled', () => {
|
|
245
|
+
const deadPid = mintDeadPid();
|
|
246
|
+
seed(v1(deadPid));
|
|
247
|
+
process.env['SKILLSMITH_LOCK_NO_AUTO_RECLAIM'] = '1';
|
|
248
|
+
let caught;
|
|
249
|
+
try {
|
|
250
|
+
acquireOwnedLock(target, { timeoutMs: 150, reclaimProbeAfterMs: 0 });
|
|
251
|
+
}
|
|
252
|
+
catch (err) {
|
|
253
|
+
caught = err;
|
|
254
|
+
}
|
|
255
|
+
finally {
|
|
256
|
+
delete process.env['SKILLSMITH_LOCK_NO_AUTO_RECLAIM'];
|
|
257
|
+
}
|
|
258
|
+
expect(caught?.reason).toBe('reclaim_disabled');
|
|
259
|
+
});
|
|
260
|
+
it('14. hardlink-unavailable (R2 branch): a linkSync throwing ENOSYS fails CLOSED, no lock file left behind', () => {
|
|
261
|
+
// SMI-5883 code-review round 1 finding 1: the original fallback
|
|
262
|
+
// (openSync('wx') + a separate writeFileSync) was NOT content-complete --
|
|
263
|
+
// a crash or observer between those two steps would see an empty/
|
|
264
|
+
// truncated lock file, which is then PERMANENTLY unreclaimable (an
|
|
265
|
+
// `unparseable` claim is never auto-reclaimed by design). Fixed by
|
|
266
|
+
// failing closed instead: a filesystem without hardlink support cannot
|
|
267
|
+
// provide the atomic-and-content-complete creation this primitive
|
|
268
|
+
// requires, so `createLockExclusive` now throws rather than falling back.
|
|
269
|
+
const enosys = () => {
|
|
270
|
+
const err = new Error('ENOSYS');
|
|
271
|
+
err.code = 'ENOSYS';
|
|
272
|
+
throw err;
|
|
273
|
+
};
|
|
274
|
+
// Exercised directly against createLockExclusive (owned-lock.claim.ts) --
|
|
275
|
+
// the internal primitive this test targets -- rather than through the
|
|
276
|
+
// public acquireOwnedLock(), which no longer accepts a linkSyncOverride.
|
|
277
|
+
expect(() => createLockExclusive(lockPath, '{"v":1}\n', enosys)).toThrow(/does not support hardlinks/);
|
|
278
|
+
expect(existsSync(lockPath)).toBe(false);
|
|
279
|
+
// No stray temp file left behind either.
|
|
280
|
+
expect(readdirSync(dir).some((f) => f.endsWith('.tmp'))).toBe(false);
|
|
281
|
+
});
|
|
282
|
+
it('15. no litter: after acquire/release cycles above, the directory holds no *.tmp and no *.reclaim', () => {
|
|
283
|
+
const release = acquireOwnedLock(target, { timeoutMs: 1_000 });
|
|
284
|
+
release();
|
|
285
|
+
const entries = readdirSync(dir);
|
|
286
|
+
expect(entries.some((f) => f.endsWith('.tmp'))).toBe(false);
|
|
287
|
+
expect(entries.some((f) => f.endsWith('.reclaim'))).toBe(false);
|
|
288
|
+
});
|
|
289
|
+
it('16. public acquireOwnedLock() strips injected unsafe properties before reaching the core loop (SMI-5883 code-review round 2)', async () => {
|
|
290
|
+
// Round 2 finding: TypeScript's excess-property check only fires on an
|
|
291
|
+
// object LITERAL passed directly at the call site -- a caller passing a
|
|
292
|
+
// variable (or a plain-JavaScript caller with no type checking at all)
|
|
293
|
+
// is NOT constrained by AcquireOwnedLockOptions omitting the two unsafe
|
|
294
|
+
// fields, and the core loop reads them by property name at runtime.
|
|
295
|
+
// owned-lock.ts's public acquireOwnedLock() must therefore reconstruct a
|
|
296
|
+
// FRESH, allowlisted object rather than forward `opts` as-is. Verified
|
|
297
|
+
// here by spying on the core loop itself and asserting neither unsafe
|
|
298
|
+
// key ever reaches it, regardless of what the caller injects.
|
|
299
|
+
const acquireModule = await import('./owned-lock.acquire.js');
|
|
300
|
+
const spy = vi.spyOn(acquireModule, 'acquireOwnedLockCore');
|
|
301
|
+
const maliciousOpts = {
|
|
302
|
+
timeoutMs: 1_000,
|
|
303
|
+
unsafeSkipReclaimRevalidation: true,
|
|
304
|
+
linkSyncOverride: () => {
|
|
305
|
+
throw new Error('should never be called -- injected via a non-literal cast');
|
|
306
|
+
},
|
|
307
|
+
};
|
|
308
|
+
const release = acquireOwnedLock(target, maliciousOpts);
|
|
309
|
+
release();
|
|
310
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
311
|
+
const forwarded = spy.mock.calls[0]?.[1];
|
|
312
|
+
// Round 3: the reconstructed object sets both unsafe fields to an
|
|
313
|
+
// explicit OWN `undefined` (to shadow a polluted Object.prototype --
|
|
314
|
+
// see item 17), so the property now exists but must never be truthy /
|
|
315
|
+
// never be the injected function.
|
|
316
|
+
expect(forwarded?.unsafeSkipReclaimRevalidation).toBeUndefined();
|
|
317
|
+
expect(forwarded?.linkSyncOverride).toBeUndefined();
|
|
318
|
+
spy.mockRestore();
|
|
319
|
+
});
|
|
320
|
+
it('17. public acquireOwnedLock() is immune to a globally-polluted Object.prototype (SMI-5883 code-review round 3)', async () => {
|
|
321
|
+
// Round 3 finding: a plain `{ ...safeFields }` reconstruction still
|
|
322
|
+
// inherits from Object.prototype -- if that prototype were ever globally
|
|
323
|
+
// polluted (a distinct, severe vulnerability class in its own right,
|
|
324
|
+
// reachable only by an attacker who already has arbitrary code execution
|
|
325
|
+
// in this process), ordinary property access on an object with no OWN
|
|
326
|
+
// `unsafeSkipReclaimRevalidation`/`linkSyncOverride` would still resolve
|
|
327
|
+
// them via the prototype chain. Fixed by explicitly setting both to
|
|
328
|
+
// `undefined` as OWN properties, which shadows any inherited value.
|
|
329
|
+
// Always restored in `finally` -- this is global, shared mutable state.
|
|
330
|
+
// Round 4 (test-hygiene finding): restore the ORIGINAL descriptors
|
|
331
|
+
// (undefined if the key was absent beforehand) rather than unconditionally
|
|
332
|
+
// deleting -- unconditional delete would be wrong if either key somehow
|
|
333
|
+
// already had a legitimate descriptor on Object.prototype before this test.
|
|
334
|
+
const acquireModule = await import('./owned-lock.acquire.js');
|
|
335
|
+
const spy = vi.spyOn(acquireModule, 'acquireOwnedLockCore');
|
|
336
|
+
const pollutedLinkSync = () => {
|
|
337
|
+
throw new Error('should never be called -- reached via Object.prototype pollution');
|
|
338
|
+
};
|
|
339
|
+
const origUnsafeSkip = Object.getOwnPropertyDescriptor(Object.prototype, 'unsafeSkipReclaimRevalidation');
|
|
340
|
+
const origLinkSync = Object.getOwnPropertyDescriptor(Object.prototype, 'linkSyncOverride');
|
|
341
|
+
try {
|
|
342
|
+
;
|
|
343
|
+
Object.prototype['unsafeSkipReclaimRevalidation'] = true;
|
|
344
|
+
Object.prototype['linkSyncOverride'] = pollutedLinkSync;
|
|
345
|
+
const release = acquireOwnedLock(target, { timeoutMs: 1_000 });
|
|
346
|
+
release();
|
|
347
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
348
|
+
const forwarded = spy.mock.calls[0]?.[1];
|
|
349
|
+
expect(forwarded?.unsafeSkipReclaimRevalidation).toBeUndefined();
|
|
350
|
+
expect(forwarded?.linkSyncOverride).toBeUndefined();
|
|
351
|
+
}
|
|
352
|
+
finally {
|
|
353
|
+
if (origUnsafeSkip) {
|
|
354
|
+
Object.defineProperty(Object.prototype, 'unsafeSkipReclaimRevalidation', origUnsafeSkip);
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
delete Object.prototype['unsafeSkipReclaimRevalidation'];
|
|
358
|
+
}
|
|
359
|
+
if (origLinkSync) {
|
|
360
|
+
Object.defineProperty(Object.prototype, 'linkSyncOverride', origLinkSync);
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
delete Object.prototype['linkSyncOverride'];
|
|
364
|
+
}
|
|
365
|
+
spy.mockRestore();
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
});
|
|
369
|
+
// ---------------------------------------------------------------------------
|
|
370
|
+
// §8c — orphaned reclaim lock (residual R1). Single-process: the "orphan" is
|
|
371
|
+
// simulated by hand-planting a live-owner reclaim-lock file, not by a real
|
|
372
|
+
// crash — the assertions are about R1's documented BLAST RADIUS (auto-reclaim
|
|
373
|
+
// disabled, locking itself unaffected), not about producing a real orphan.
|
|
374
|
+
// ---------------------------------------------------------------------------
|
|
375
|
+
describe('orphaned reclaim lock (residual R1, §8c)', () => {
|
|
376
|
+
it('1. a pre-existing (live-owner) reclaim lock blocks reclaim of a genuinely dead-PID main lock', () => {
|
|
377
|
+
const deadPid = mintDeadPid();
|
|
378
|
+
seed(v1(deadPid), lockPath);
|
|
379
|
+
seed(v1(process.pid), reclaimPath); // "orphan" stand-in: live-owner reclaim lock
|
|
380
|
+
const beforeLock = readFileSync(lockPath);
|
|
381
|
+
const beforeReclaim = readFileSync(reclaimPath);
|
|
382
|
+
let caught;
|
|
383
|
+
try {
|
|
384
|
+
acquireOwnedLock(target, { timeoutMs: 800, reclaimProbeAfterMs: 0 });
|
|
385
|
+
}
|
|
386
|
+
catch (err) {
|
|
387
|
+
caught = err;
|
|
388
|
+
}
|
|
389
|
+
expect(caught).toBeInstanceOf(StuckLockError);
|
|
390
|
+
expect(caught?.reason).toBe('reclaim_unavailable');
|
|
391
|
+
expect(caught?.message).toContain(lockPath);
|
|
392
|
+
expect(caught?.message).toContain(reclaimPath);
|
|
393
|
+
expect(caught?.message.toLowerCase()).toContain('manual unstick');
|
|
394
|
+
expect(readFileSync(lockPath).equals(beforeLock)).toBe(true);
|
|
395
|
+
expect(readFileSync(reclaimPath).equals(beforeReclaim)).toBe(true);
|
|
396
|
+
});
|
|
397
|
+
it('2. with no main lock present, acquisition succeeds despite an orphaned reclaim lock (locking unaffected)', () => {
|
|
398
|
+
seed(v1(process.pid), reclaimPath); // orphan stand-in; no `.lock` file exists
|
|
399
|
+
const release = acquireOwnedLock(target, { timeoutMs: 1_000 });
|
|
400
|
+
release();
|
|
401
|
+
});
|
|
402
|
+
it('3. removing the orphan restores service — the dead-PID lock reclaims normally afterward', () => {
|
|
403
|
+
const deadPid = mintDeadPid();
|
|
404
|
+
seed(v1(deadPid), lockPath);
|
|
405
|
+
seed(v1(process.pid), reclaimPath);
|
|
406
|
+
rmSync(reclaimPath); // the documented manual unstick
|
|
407
|
+
const release = acquireOwnedLock(target, { timeoutMs: 2_000, reclaimProbeAfterMs: 0 });
|
|
408
|
+
expect(existsSync(reclaimPath)).toBe(false);
|
|
409
|
+
release();
|
|
410
|
+
});
|
|
411
|
+
});
|
|
412
|
+
//# sourceMappingURL=owned-lock.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owned-lock.test.js","sourceRoot":"","sources":["../../../src/config/owned-lock.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types + tuning constants for the two-level owned-lock primitive.
|
|
3
|
+
* @module @skillsmith/core/config/owned-lock.types
|
|
4
|
+
* @see owned-lock.ts for the full soundness argument and public API.
|
|
5
|
+
*/
|
|
6
|
+
/** Max time to wait for the MAIN lock before giving up (ms). Unchanged from today's `acquireConfigLock` default. */
|
|
7
|
+
export declare const LOCK_ACQUIRE_TIMEOUT_MS = 5000;
|
|
8
|
+
/** Backoff between lock-acquisition retries (ms). */
|
|
9
|
+
export declare const LOCK_RETRY_DELAY_MS = 20;
|
|
10
|
+
/** Delay before the FIRST reclaim probe -- keeps the reclaim lock off the hot path when the holder is alive. */
|
|
11
|
+
export declare const RECLAIM_PROBE_AFTER_MS = 250;
|
|
12
|
+
/** Backoff between reclaim probe attempts once contention is established. */
|
|
13
|
+
export declare const RECLAIM_PROBE_INTERVAL_MS = 250;
|
|
14
|
+
/** Max time to wait for the RECLAIM lock. Its critical section is 3 syscalls with no caller code -- a longer wait would itself indicate an orphan (R1). */
|
|
15
|
+
export declare const RECLAIM_LOCK_TIMEOUT_MS = 500;
|
|
16
|
+
/** Bounded read cap for a lock claim file -- refuses (never crashes on) an oversized/garbage lock file. */
|
|
17
|
+
export declare const MAX_LOCK_BYTES = 4096;
|
|
18
|
+
export declare const HARDLINK_UNAVAILABLE_CODES: Set<string>;
|
|
19
|
+
/** A live, current-format claim: `{"v":1,"pid":...,"token":"<16 hex>","host":"...","acquiredAt":...}`. */
|
|
20
|
+
export interface V1Claim {
|
|
21
|
+
kind: 'v1';
|
|
22
|
+
pid: number;
|
|
23
|
+
token: string;
|
|
24
|
+
host: string;
|
|
25
|
+
acquiredAt: number;
|
|
26
|
+
}
|
|
27
|
+
/** A bare-decimal-PID claim (today's `acquireConfigLock` format). Carries no `host` -- NEVER auto-reclaimed (D-5). */
|
|
28
|
+
export interface LegacyClaim {
|
|
29
|
+
kind: 'legacy';
|
|
30
|
+
pid: number;
|
|
31
|
+
}
|
|
32
|
+
/** Empty, garbage, truncated, or valid-JSON-but-wrong-shape/version. NEVER auto-reclaimed. */
|
|
33
|
+
export interface UnparseableClaim {
|
|
34
|
+
kind: 'unparseable';
|
|
35
|
+
}
|
|
36
|
+
/** No lock file present at the path read. */
|
|
37
|
+
export interface AbsentClaim {
|
|
38
|
+
kind: 'absent';
|
|
39
|
+
}
|
|
40
|
+
export type Claim = V1Claim | LegacyClaim | UnparseableClaim | AbsentClaim;
|
|
41
|
+
/** Outcome of a single reclaim attempt (`tryReclaimUnderLock`). */
|
|
42
|
+
export type ReclaimOutcome = 'reclaimed' | 'not-stale' | 'gone' | 'unavailable';
|
|
43
|
+
/** Why the pre-filter (outside the reclaim critical section) declined to even attempt a reclaim. */
|
|
44
|
+
export type RefusalCategory = 'held' | 'legacy' | 'unparseable' | 'reclaim-disabled';
|
|
45
|
+
export type StuckLockReason = 'held' | 'unreclaimable_legacy' | 'unreclaimable_unparseable' | 'reclaim_unavailable' | 'reclaim_disabled';
|
|
46
|
+
/**
|
|
47
|
+
* Public, SAFE option set for `acquireOwnedLock` (owned-lock.ts). Does NOT
|
|
48
|
+
* include the two destructive test-only seams (`unsafeSkipReclaimRevalidation`,
|
|
49
|
+
* `linkSyncOverride`) -- those live only on the internal
|
|
50
|
+
* `AcquireOwnedLockCoreOptions` (owned-lock.acquire.ts, no public subpath
|
|
51
|
+
* export), so a package consumer can never pass them through the public
|
|
52
|
+
* `acquireOwnedLock()` entry point. See owned-lock.acquire.ts's module comment
|
|
53
|
+
* for the full rationale.
|
|
54
|
+
*/
|
|
55
|
+
export interface AcquireOwnedLockOptions {
|
|
56
|
+
/** Override the acquire timeout. Production callers should omit this and use the default. */
|
|
57
|
+
timeoutMs?: number;
|
|
58
|
+
/** Human label used in the timeout message, e.g. `'config lock'` -> "Timed out waiting for config lock at ...". Defaults to `'lock'`. */
|
|
59
|
+
label?: string;
|
|
60
|
+
/** Delay before the first reclaim probe (ms). Production callers should omit this; test-only override. */
|
|
61
|
+
reclaimProbeAfterMs?: number;
|
|
62
|
+
/**
|
|
63
|
+
* @internal Test seam (owned-lock-reclaim-race.test.ts §8b). Fires AFTER
|
|
64
|
+
* the pre-filter has validated a dead claim and BEFORE any reclaim-lock
|
|
65
|
+
* acquisition or removal is attempted. Never set in production code.
|
|
66
|
+
* (Read-only observability -- unlike the two omitted options above, this
|
|
67
|
+
* cannot affect the locking safety properties, so it's safe to leave on
|
|
68
|
+
* the public type.)
|
|
69
|
+
*/
|
|
70
|
+
onReclaimBoundary?: () => void;
|
|
71
|
+
/**
|
|
72
|
+
* @internal Test seam (owned-lock-reclaim-race.test.ts §8b). Fires
|
|
73
|
+
* immediately after `tryReclaimUnderLock` returns, with its outcome.
|
|
74
|
+
* Never set in production code. Read-only, same rationale as above.
|
|
75
|
+
*/
|
|
76
|
+
onReclaimOutcome?: (outcome: ReclaimOutcome) => void;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=owned-lock.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owned-lock.types.d.ts","sourceRoot":"","sources":["../../../src/config/owned-lock.types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,oHAAoH;AACpH,eAAO,MAAM,uBAAuB,OAAQ,CAAA;AAC5C,qDAAqD;AACrD,eAAO,MAAM,mBAAmB,KAAK,CAAA;AACrC,gHAAgH;AAChH,eAAO,MAAM,sBAAsB,MAAM,CAAA;AACzC,6EAA6E;AAC7E,eAAO,MAAM,yBAAyB,MAAM,CAAA;AAC5C,2JAA2J;AAC3J,eAAO,MAAM,uBAAuB,MAAM,CAAA;AAC1C,2GAA2G;AAC3G,eAAO,MAAM,cAAc,OAAQ,CAAA;AAEnC,eAAO,MAAM,0BAA0B,aAQrC,CAAA;AAMF,0GAA0G;AAC1G,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,IAAI,CAAA;IACV,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;CACnB;AACD,sHAAsH;AACtH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;CACZ;AACD,8FAA8F;AAC9F,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,aAAa,CAAA;CACpB;AACD,6CAA6C;AAC7C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,CAAA;CACf;AACD,MAAM,MAAM,KAAK,GAAG,OAAO,GAAG,WAAW,GAAG,gBAAgB,GAAG,WAAW,CAAA;AAE1E,mEAAmE;AACnE,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,WAAW,GAAG,MAAM,GAAG,aAAa,CAAA;AAE/E,oGAAoG;AACpG,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,QAAQ,GAAG,aAAa,GAAG,kBAAkB,CAAA;AAMpF,MAAM,MAAM,eAAe,GACvB,MAAM,GACN,sBAAsB,GACtB,2BAA2B,GAC3B,qBAAqB,GACrB,kBAAkB,CAAA;AAEtB;;;;;;;;GAQG;AACH,MAAM,WAAW,uBAAuB;IACtC,6FAA6F;IAC7F,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,yIAAyI;IACzI,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,0GAA0G;IAC1G,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B;;;;;;;OAOG;IACH,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAA;IAC9B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAA;CACrD"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types + tuning constants for the two-level owned-lock primitive.
|
|
3
|
+
* @module @skillsmith/core/config/owned-lock.types
|
|
4
|
+
* @see owned-lock.ts for the full soundness argument and public API.
|
|
5
|
+
*/
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// Tuning constants
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
/** Max time to wait for the MAIN lock before giving up (ms). Unchanged from today's `acquireConfigLock` default. */
|
|
10
|
+
export const LOCK_ACQUIRE_TIMEOUT_MS = 5_000;
|
|
11
|
+
/** Backoff between lock-acquisition retries (ms). */
|
|
12
|
+
export const LOCK_RETRY_DELAY_MS = 20;
|
|
13
|
+
/** Delay before the FIRST reclaim probe -- keeps the reclaim lock off the hot path when the holder is alive. */
|
|
14
|
+
export const RECLAIM_PROBE_AFTER_MS = 250;
|
|
15
|
+
/** Backoff between reclaim probe attempts once contention is established. */
|
|
16
|
+
export const RECLAIM_PROBE_INTERVAL_MS = 250;
|
|
17
|
+
/** Max time to wait for the RECLAIM lock. Its critical section is 3 syscalls with no caller code -- a longer wait would itself indicate an orphan (R1). */
|
|
18
|
+
export const RECLAIM_LOCK_TIMEOUT_MS = 500;
|
|
19
|
+
/** Bounded read cap for a lock claim file -- refuses (never crashes on) an oversized/garbage lock file. */
|
|
20
|
+
export const MAX_LOCK_BYTES = 4_096;
|
|
21
|
+
export const HARDLINK_UNAVAILABLE_CODES = new Set([
|
|
22
|
+
'EPERM',
|
|
23
|
+
'EACCES',
|
|
24
|
+
'ENOSYS',
|
|
25
|
+
'EXDEV',
|
|
26
|
+
'EMLINK',
|
|
27
|
+
'EOPNOTSUPP',
|
|
28
|
+
'ENOTSUP',
|
|
29
|
+
]);
|
|
30
|
+
//# sourceMappingURL=owned-lock.types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owned-lock.types.js","sourceRoot":"","sources":["../../../src/config/owned-lock.types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,oHAAoH;AACpH,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,CAAA;AAC5C,qDAAqD;AACrD,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAA;AACrC,gHAAgH;AAChH,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAA;AACzC,6EAA6E;AAC7E,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,CAAA;AAC5C,2JAA2J;AAC3J,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAA;AAC1C,2GAA2G;AAC3G,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAA;AAEnC,MAAM,CAAC,MAAM,0BAA0B,GAAG,IAAI,GAAG,CAAC;IAChD,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,YAAY;IACZ,SAAS;CACV,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createDatabase.d.ts","sourceRoot":"","sources":["../../../src/db/createDatabase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"createDatabase.d.ts","sourceRoot":"","sources":["../../../src/db/createDatabase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAmBxE;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,gBAAgB,GAAG,QAAQ,CAAA;AAEpD;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,UAAU,CAAA;IAChB,SAAS,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,UAAU,EAAE,CA0BrD;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,UAAU,GAAG,IAAI,CAiBjD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,MAAmB,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,QAAQ,CAgBjG;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,GAAE,MAAmB,EACzB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,QAAQ,CAAC,CAkDnB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,cAAc,2BAAqB,CAAA"}
|
|
@@ -18,6 +18,11 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { createBetterSqlite3Database, isBetterSqlite3Available, getBetterSqlite3FailureReason, } from './drivers/betterSqlite3Driver.js';
|
|
20
20
|
import { createSqlJsDatabase, isSqlJsAvailable } from './drivers/sqljsDriver.js';
|
|
21
|
+
// SMI-5897 (C-18/C-19, Wave 4 fix): shared SKILLSMITH_QUIET guard — this was
|
|
22
|
+
// the second, unguarded fallback-warning path C-18/C-19 didn't originally
|
|
23
|
+
// cover; the WASM-driver notice below always printed at least once per
|
|
24
|
+
// process regardless of SKILLSMITH_QUIET.
|
|
25
|
+
import { isQuietModeEnabled } from '../utils/quiet-mode.js';
|
|
21
26
|
/**
|
|
22
27
|
* SMI-4807: guard so the WASM-fallback notice is emitted at most once per
|
|
23
28
|
* process, no matter how many database connections are opened.
|
|
@@ -135,15 +140,22 @@ export async function createDatabaseAsync(path = ':memory:', options) {
|
|
|
135
140
|
if (isSqlJsAvailable()) {
|
|
136
141
|
if (!wasmFallbackNoticeEmitted) {
|
|
137
142
|
wasmFallbackNoticeEmitted = true;
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
143
|
+
// SMI-5897 (Wave 4 fix): honor SKILLSMITH_QUIET, same as the
|
|
144
|
+
// embeddings-layer fallback warnings — the notice still guards
|
|
145
|
+
// print-once-per-process via wasmFallbackNoticeEmitted above (set
|
|
146
|
+
// regardless of quiet mode, so a later non-quiet caller doesn't get a
|
|
147
|
+
// stale re-print of a decision already made this process).
|
|
148
|
+
if (!isQuietModeEnabled()) {
|
|
149
|
+
let message = '[Skillsmith] Using WASM SQLite driver ' +
|
|
150
|
+
'(native better-sqlite3 not loaded — expected on direct macOS/npx installs).';
|
|
151
|
+
if (process.env.SKILLSMITH_DEBUG) {
|
|
152
|
+
const reason = getBetterSqlite3FailureReason();
|
|
153
|
+
if (reason) {
|
|
154
|
+
message += ` Reason: ${reason}`;
|
|
155
|
+
}
|
|
144
156
|
}
|
|
157
|
+
console.warn(message);
|
|
145
158
|
}
|
|
146
|
-
console.warn(message);
|
|
147
159
|
}
|
|
148
160
|
return await createSqlJsDatabase(path, options);
|
|
149
161
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createDatabase.js","sourceRoot":"","sources":["../../../src/db/createDatabase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,EACxB,6BAA6B,GAC9B,MAAM,kCAAkC,CAAA;AACzC,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"createDatabase.js","sourceRoot":"","sources":["../../../src/db/createDatabase.ts"],"names":[],"mappings":"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"}
|