@dsh-enhanced/assistant-recovery 0.1.24 → 0.1.30
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/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/operator.d.ts +33 -0
- package/lib/operator.d.ts.map +1 -0
- package/lib/operator.js +678 -0
- package/lib/operator.js.map +1 -0
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +9 -9
package/lib/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export * from './catalog.js';
|
|
|
12
12
|
export { ConfigSchema, normalizeRecoveryConfig, } from './config.js';
|
|
13
13
|
export type { NormalizedConfig, NormalizedRecoveryJob, RecoveryActivationState, RecoveryJobConfig, } from './config.js';
|
|
14
14
|
export * from './executor.js';
|
|
15
|
+
export * from './operator.js';
|
|
15
16
|
export * from './port.js';
|
|
16
17
|
export { AssistantRecoveryError, recoveryActivationPlanDigest, recoveryAutomationDefinition, recoveryAutomationId, } from './service.js';
|
|
17
18
|
export * from './store.js';
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,wBAAwB,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAC/D,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,eAAO,MAAM,IAAI,oCAAoC,CAAA;AACrD,eAAO,MAAM,MAAM,UAOlB,CAAA;AACD,OAAO,EAAE,wBAAwB,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;AACpD,YAAY,EAAE,UAAU,IAAI,uBAAuB,EAAE,CAAA;AACrD,cAAc,kBAAkB,CAAA;AAChC,cAAc,0BAA0B,CAAA;AACxC,cAAc,cAAc,CAAA;AAC5B,OAAO,EACL,YAAY,EACZ,uBAAuB,GACxB,MAAM,aAAa,CAAA;AACpB,YAAY,EACV,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,aAAa,CAAA;AACpB,cAAc,eAAe,CAAA;AAC7B,cAAc,WAAW,CAAA;AACzB,OAAO,EACL,sBAAsB,EACtB,4BAA4B,EAC5B,4BAA4B,EAC5B,oBAAoB,GACrB,MAAM,cAAc,CAAA;AACrB,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAE1B,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAE5D;AAED,eAAe,wBAAwB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,wBAAwB,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAC/D,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,eAAO,MAAM,IAAI,oCAAoC,CAAA;AACrD,eAAO,MAAM,MAAM,UAOlB,CAAA;AACD,OAAO,EAAE,wBAAwB,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;AACpD,YAAY,EAAE,UAAU,IAAI,uBAAuB,EAAE,CAAA;AACrD,cAAc,kBAAkB,CAAA;AAChC,cAAc,0BAA0B,CAAA;AACxC,cAAc,cAAc,CAAA;AAC5B,OAAO,EACL,YAAY,EACZ,uBAAuB,GACxB,MAAM,aAAa,CAAA;AACpB,YAAY,EACV,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,aAAa,CAAA;AACpB,cAAc,eAAe,CAAA;AAC7B,cAAc,eAAe,CAAA;AAC7B,cAAc,WAAW,CAAA;AACzB,OAAO,EACL,sBAAsB,EACtB,4BAA4B,EAC5B,4BAA4B,EAC5B,oBAAoB,GACrB,MAAM,cAAc,CAAA;AACrB,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAE1B,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAE5D;AAED,eAAe,wBAAwB,CAAA"}
|
package/lib/index.js
CHANGED
|
@@ -15,6 +15,7 @@ export * from './automation-executor.js';
|
|
|
15
15
|
export * from './catalog.js';
|
|
16
16
|
export { ConfigSchema, normalizeRecoveryConfig, } from './config.js';
|
|
17
17
|
export * from './executor.js';
|
|
18
|
+
export * from './operator.js';
|
|
18
19
|
export * from './port.js';
|
|
19
20
|
export { AssistantRecoveryError, recoveryActivationPlanDigest, recoveryAutomationDefinition, recoveryAutomationId, } from './service.js';
|
|
20
21
|
export * from './store.js';
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAE/D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,MAAM,CAAC,MAAM,IAAI,GAAG,iCAAiC,CAAA;AACrD,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,sBAAsB;IACtB,mBAAmB;IACnB,qBAAqB;IACrB,oBAAoB;IACpB,6BAA6B;IAC7B,iBAAiB;CAClB,CAAA;AACD,OAAO,EAAE,wBAAwB,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;AAEpD,cAAc,kBAAkB,CAAA;AAChC,cAAc,0BAA0B,CAAA;AACxC,cAAc,cAAc,CAAA;AAC5B,OAAO,EACL,YAAY,EACZ,uBAAuB,GACxB,MAAM,aAAa,CAAA;AAOpB,cAAc,eAAe,CAAA;AAC7B,cAAc,WAAW,CAAA;AACzB,OAAO,EACL,sBAAsB,EACtB,4BAA4B,EAC5B,4BAA4B,EAC5B,oBAAoB,GACrB,MAAM,cAAc,CAAA;AACrB,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAE1B,MAAM,UAAU,KAAK,CAAC,GAAY,EAAE,MAAkB;IACpD,IAAI,wBAAwB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;AAC3C,CAAC;AAED,eAAe,wBAAwB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAE/D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,MAAM,CAAC,MAAM,IAAI,GAAG,iCAAiC,CAAA;AACrD,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,sBAAsB;IACtB,mBAAmB;IACnB,qBAAqB;IACrB,oBAAoB;IACpB,6BAA6B;IAC7B,iBAAiB;CAClB,CAAA;AACD,OAAO,EAAE,wBAAwB,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;AAEpD,cAAc,kBAAkB,CAAA;AAChC,cAAc,0BAA0B,CAAA;AACxC,cAAc,cAAc,CAAA;AAC5B,OAAO,EACL,YAAY,EACZ,uBAAuB,GACxB,MAAM,aAAa,CAAA;AAOpB,cAAc,eAAe,CAAA;AAC7B,cAAc,eAAe,CAAA;AAC7B,cAAc,WAAW,CAAA;AACzB,OAAO,EACL,sBAAsB,EACtB,4BAA4B,EAC5B,4BAA4B,EAC5B,oBAAoB,GACrB,MAAM,cAAc,CAAA;AACrB,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAE1B,MAAM,UAAU,KAAK,CAAC,GAAY,EAAE,MAAkB;IACpD,IAAI,wBAAwB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;AAC3C,CAAC;AAED,eAAe,wBAAwB,CAAA"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { recoverySchemaVersion } from './sqlite.js';
|
|
2
|
+
import type { RecoveryBootstrapState } from './types.js';
|
|
3
|
+
export declare const RECOVERY_OPERATOR_SNAPSHOT_PROTOCOL: "assistant-recovery/operator-snapshot/v1";
|
|
4
|
+
export type RecoveryOperatorSnapshotErrorCode = 'invalid-path' | 'missing-parent' | 'missing-file' | 'unsafe-parent' | 'unsafe-file' | 'unsafe-wal' | 'unsafe-shm' | 'database-busy' | 'database-unavailable' | 'schema-too-old' | 'schema-too-new' | 'database-corrupt' | 'database-drift' | 'wal-drift' | 'shm-drift';
|
|
5
|
+
export declare class RecoveryOperatorSnapshotError extends Error {
|
|
6
|
+
readonly code: RecoveryOperatorSnapshotErrorCode;
|
|
7
|
+
constructor(code: RecoveryOperatorSnapshotErrorCode, message: string);
|
|
8
|
+
}
|
|
9
|
+
export interface RecoveryOperatorDatabaseIdentity {
|
|
10
|
+
/** Decimal OS device id captured from the opened database file. */
|
|
11
|
+
readonly device: string;
|
|
12
|
+
/** Decimal OS inode id captured from the opened database file. */
|
|
13
|
+
readonly inode: string;
|
|
14
|
+
readonly size: number;
|
|
15
|
+
/** Local consistency digest over the main database and its exact WAL bytes, if present. */
|
|
16
|
+
readonly digest: string;
|
|
17
|
+
}
|
|
18
|
+
export interface RecoveryOperatorSnapshot {
|
|
19
|
+
readonly protocol: typeof RECOVERY_OPERATOR_SNAPSHOT_PROTOCOL;
|
|
20
|
+
readonly schemaVersion: typeof recoverySchemaVersion;
|
|
21
|
+
readonly database: RecoveryOperatorDatabaseIdentity;
|
|
22
|
+
readonly bootstrap: RecoveryBootstrapState;
|
|
23
|
+
/** Canonical SHA-256 consistency digest. It is not an authenticity attestation. */
|
|
24
|
+
readonly snapshotDigest: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Read the already-existing schema-v4 bootstrap state without creating,
|
|
28
|
+
* migrating, chmodding, checkpointing, or changing journal mode. The returned
|
|
29
|
+
* digests detect local source drift; they do not prove authenticity against a
|
|
30
|
+
* same-UID process or privileged attacker.
|
|
31
|
+
*/
|
|
32
|
+
export declare function inspectRecoveryOperatorSnapshot(databasePath: string): RecoveryOperatorSnapshot;
|
|
33
|
+
//# sourceMappingURL=operator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operator.d.ts","sourceRoot":"","sources":["../src/operator.ts"],"names":[],"mappings":"AA2BA,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,KAAK,EAAgC,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAEtF,eAAO,MAAM,mCAAmC,EAC5C,yCAAkD,CAAA;AAEtD,MAAM,MAAM,iCAAiC,GACvC,cAAc,GACd,gBAAgB,GAChB,cAAc,GACd,eAAe,GACf,aAAa,GACb,YAAY,GACZ,YAAY,GACZ,eAAe,GACf,sBAAsB,GACtB,gBAAgB,GAChB,gBAAgB,GAChB,kBAAkB,GAClB,gBAAgB,GAChB,WAAW,GACX,WAAW,CAAA;AAEjB,qBAAa,6BAA8B,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,EAAE,iCAAiC;gBAAvC,IAAI,EAAE,iCAAiC,EAAE,OAAO,EAAE,MAAM;CAI9E;AAED,MAAM,WAAW,gCAAgC;IAC/C,mEAAmE;IACnE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,2FAA2F;IAC3F,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,QAAQ,EAAE,OAAO,mCAAmC,CAAA;IAC7D,QAAQ,CAAC,aAAa,EAAE,OAAO,qBAAqB,CAAA;IACpD,QAAQ,CAAC,QAAQ,EAAE,gCAAgC,CAAA;IACnD,QAAQ,CAAC,SAAS,EAAE,sBAAsB,CAAA;IAC1C,mFAAmF;IACnF,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;CAChC;AA0dD;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,YAAY,EAAE,MAAM,GAAG,wBAAwB,CAiJ9F"}
|
package/lib/operator.js
ADDED
|
@@ -0,0 +1,678 @@
|
|
|
1
|
+
import { createHash, timingSafeEqual } from 'node:crypto';
|
|
2
|
+
import { closeSync, constants, existsSync, fstatSync, lstatSync, mkdtempSync, openSync, readdirSync, readSync, realpathSync, rmSync, rmdirSync, unlinkSync, writeSync, } from 'node:fs';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { basename, dirname, isAbsolute, join, resolve } from 'node:path';
|
|
5
|
+
import { pathToFileURL } from 'node:url';
|
|
6
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
7
|
+
import { canonicalRecoveryBootstrapAttestationSet, RecoveryBootstrapAttestationError, recoveryBootstrapAttestationSetDigest, } from './attestation.js';
|
|
8
|
+
import { recoverySchemaVersion } from './sqlite.js';
|
|
9
|
+
export const RECOVERY_OPERATOR_SNAPSHOT_PROTOCOL = 'assistant-recovery/operator-snapshot/v1';
|
|
10
|
+
export class RecoveryOperatorSnapshotError extends Error {
|
|
11
|
+
code;
|
|
12
|
+
constructor(code, message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.code = code;
|
|
15
|
+
this.name = 'RecoveryOperatorSnapshotError';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const DIGEST = /^[a-f0-9]{64}$/u;
|
|
19
|
+
const FAILURE_CODE = /^[a-z0-9][a-z0-9.-]{0,63}$/u;
|
|
20
|
+
const FILE_READ_BUFFER_BYTES = 64 * 1024;
|
|
21
|
+
const inodeBindSupported = process.platform === 'linux';
|
|
22
|
+
const procSelfFd = '/proc/self/fd';
|
|
23
|
+
function canonicalJson(value) {
|
|
24
|
+
if (value === null || typeof value !== 'object')
|
|
25
|
+
return JSON.stringify(value);
|
|
26
|
+
if (Array.isArray(value))
|
|
27
|
+
return `[${value.map(canonicalJson).join(',')}]`;
|
|
28
|
+
const record = value;
|
|
29
|
+
return `{${Object.keys(record).sort().map(key => `${JSON.stringify(key)}:${canonicalJson(record[key])}`).join(',')}}`;
|
|
30
|
+
}
|
|
31
|
+
function deepFreeze(value) {
|
|
32
|
+
if (value !== null && typeof value === 'object' && !Object.isFrozen(value)) {
|
|
33
|
+
for (const child of Object.values(value))
|
|
34
|
+
deepFreeze(child);
|
|
35
|
+
Object.freeze(value);
|
|
36
|
+
}
|
|
37
|
+
return value;
|
|
38
|
+
}
|
|
39
|
+
function fail(code, message) {
|
|
40
|
+
throw new RecoveryOperatorSnapshotError(code, message);
|
|
41
|
+
}
|
|
42
|
+
function fileExists(path) {
|
|
43
|
+
try {
|
|
44
|
+
lstatSync(path);
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
if (error.code === 'ENOENT')
|
|
49
|
+
return false;
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function hasControlCharacter(value) {
|
|
54
|
+
return [...value].some((character) => {
|
|
55
|
+
const point = character.codePointAt(0);
|
|
56
|
+
return point <= 0x1f || point === 0x7f;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function pinPrivateParent(path) {
|
|
60
|
+
let descriptor;
|
|
61
|
+
try {
|
|
62
|
+
descriptor = openSync(path, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
if (error.code === 'ENOENT') {
|
|
66
|
+
fail('missing-parent', 'assistant-recovery operator snapshot parent does not exist');
|
|
67
|
+
}
|
|
68
|
+
fail('unsafe-parent', 'assistant-recovery operator snapshot parent is unavailable');
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
const pathname = lstatSync(path, { bigint: true });
|
|
72
|
+
const metadata = fstatSync(descriptor, { bigint: true });
|
|
73
|
+
const uid = process.getuid?.();
|
|
74
|
+
const physical = realpathSync(path);
|
|
75
|
+
if (!pathname.isDirectory() || pathname.isSymbolicLink() || !metadata.isDirectory()
|
|
76
|
+
|| pathname.dev !== metadata.dev || pathname.ino !== metadata.ino || physical !== path
|
|
77
|
+
|| uid === undefined || metadata.uid !== BigInt(uid)
|
|
78
|
+
|| (metadata.mode & 3647n) !== 0n || (metadata.mode & 320n) !== 320n) {
|
|
79
|
+
fail('unsafe-parent', 'assistant-recovery operator snapshot parent must be a private owner directory without symlinks');
|
|
80
|
+
}
|
|
81
|
+
const pinned = { descriptor, path, device: metadata.dev, inode: metadata.ino, mode: metadata.mode };
|
|
82
|
+
descriptor = undefined;
|
|
83
|
+
return pinned;
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
if (error instanceof RecoveryOperatorSnapshotError)
|
|
87
|
+
throw error;
|
|
88
|
+
fail('unsafe-parent', 'assistant-recovery operator snapshot parent cannot be resolved');
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
if (descriptor !== undefined)
|
|
92
|
+
closeSync(descriptor);
|
|
93
|
+
}
|
|
94
|
+
throw new Error('unreachable');
|
|
95
|
+
}
|
|
96
|
+
function connectionInodes(exclude) {
|
|
97
|
+
let entries;
|
|
98
|
+
try {
|
|
99
|
+
entries = readdirSync(procSelfFd);
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
fail('database-unavailable', 'assistant-recovery cannot inspect SQLite connection descriptors');
|
|
103
|
+
}
|
|
104
|
+
const inodes = [];
|
|
105
|
+
for (const entry of entries) {
|
|
106
|
+
const descriptor = Number(entry);
|
|
107
|
+
if (!Number.isInteger(descriptor) || descriptor <= 2 || exclude.has(descriptor))
|
|
108
|
+
continue;
|
|
109
|
+
let metadata;
|
|
110
|
+
try {
|
|
111
|
+
metadata = fstatSync(descriptor, { bigint: true });
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (metadata.isFile())
|
|
117
|
+
inodes.push({ device: metadata.dev, inode: metadata.ino });
|
|
118
|
+
}
|
|
119
|
+
return inodes;
|
|
120
|
+
}
|
|
121
|
+
function assertConnectionBound(files, exclude) {
|
|
122
|
+
const held = connectionInodes(exclude);
|
|
123
|
+
for (const file of files) {
|
|
124
|
+
if (!held.some(inode => inode.device === file.device && inode.inode === file.inode)) {
|
|
125
|
+
fail('database-drift', 'assistant-recovery SQLite connection is not bound to its pinned inode');
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function pinTempDirectory(path) {
|
|
130
|
+
let descriptor;
|
|
131
|
+
try {
|
|
132
|
+
descriptor = openSync(path, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
|
|
133
|
+
const pathname = lstatSync(path, { bigint: true });
|
|
134
|
+
const metadata = fstatSync(descriptor, { bigint: true });
|
|
135
|
+
const uid = process.getuid?.();
|
|
136
|
+
if (!pathname.isDirectory() || pathname.isSymbolicLink() || !metadata.isDirectory()
|
|
137
|
+
|| pathname.dev !== metadata.dev || pathname.ino !== metadata.ino
|
|
138
|
+
|| (metadata.mode & 4095n) !== 448n
|
|
139
|
+
|| uid === undefined || metadata.uid !== BigInt(uid)) {
|
|
140
|
+
fail('database-unavailable', 'assistant-recovery temporary snapshot directory is unsafe');
|
|
141
|
+
}
|
|
142
|
+
const pinned = { path, descriptor, device: metadata.dev, inode: metadata.ino };
|
|
143
|
+
descriptor = undefined;
|
|
144
|
+
return pinned;
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
if (error instanceof RecoveryOperatorSnapshotError)
|
|
148
|
+
throw error;
|
|
149
|
+
fail('database-unavailable', 'assistant-recovery temporary snapshot directory cannot be pinned');
|
|
150
|
+
}
|
|
151
|
+
finally {
|
|
152
|
+
if (descriptor !== undefined)
|
|
153
|
+
try {
|
|
154
|
+
closeSync(descriptor);
|
|
155
|
+
}
|
|
156
|
+
catch { }
|
|
157
|
+
}
|
|
158
|
+
throw new Error('unreachable');
|
|
159
|
+
}
|
|
160
|
+
function copyAndPin(source, target, driftCode) {
|
|
161
|
+
const buffer = Buffer.allocUnsafe(FILE_READ_BUFFER_BYTES);
|
|
162
|
+
let destination;
|
|
163
|
+
try {
|
|
164
|
+
destination = openSync(target, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL, 0o600);
|
|
165
|
+
let position = 0n;
|
|
166
|
+
while (position < source.size) {
|
|
167
|
+
const length = Number(source.size - position > BigInt(buffer.length) ? BigInt(buffer.length) : source.size - position);
|
|
168
|
+
const count = readSync(source.descriptor, buffer, 0, length, Number(position));
|
|
169
|
+
if (count <= 0)
|
|
170
|
+
fail(driftCode, `${basename(source.path)} changed while it was copied`);
|
|
171
|
+
let written = 0;
|
|
172
|
+
while (written < count)
|
|
173
|
+
written += writeSync(destination, buffer, written, count - written);
|
|
174
|
+
position += BigInt(count);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
finally {
|
|
178
|
+
if (destination !== undefined)
|
|
179
|
+
try {
|
|
180
|
+
closeSync(destination);
|
|
181
|
+
}
|
|
182
|
+
catch { }
|
|
183
|
+
}
|
|
184
|
+
const copied = pinPrivateFile(target, 'unsafe-file');
|
|
185
|
+
if (copied.size !== source.size || copied.digest !== source.digest) {
|
|
186
|
+
try {
|
|
187
|
+
closeSync(copied.descriptor);
|
|
188
|
+
}
|
|
189
|
+
catch { }
|
|
190
|
+
fail(driftCode, `${basename(source.path)} private copy does not match its pinned source`);
|
|
191
|
+
}
|
|
192
|
+
return copied;
|
|
193
|
+
}
|
|
194
|
+
function removePinnedTemp(temp) {
|
|
195
|
+
const anchor = `${procSelfFd}/${temp.descriptor}`;
|
|
196
|
+
for (const name of ['recovery.sqlite', 'recovery.sqlite-wal', 'recovery.sqlite-shm']) {
|
|
197
|
+
try {
|
|
198
|
+
unlinkSync(`${anchor}/${name}`);
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
if (error.code !== 'ENOENT') {
|
|
202
|
+
fail('database-drift', 'assistant-recovery private snapshot copy cannot be removed');
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (readdirSync(anchor).length !== 0)
|
|
207
|
+
fail('database-drift', 'assistant-recovery private snapshot directory is not empty');
|
|
208
|
+
const pathname = lstatSync(temp.path, { bigint: true });
|
|
209
|
+
const metadata = fstatSync(temp.descriptor, { bigint: true });
|
|
210
|
+
if (pathname.dev !== temp.device || pathname.ino !== temp.inode
|
|
211
|
+
|| metadata.dev !== temp.device || metadata.ino !== temp.inode) {
|
|
212
|
+
fail('database-drift', 'assistant-recovery private snapshot directory was retargeted');
|
|
213
|
+
}
|
|
214
|
+
closeSync(temp.descriptor);
|
|
215
|
+
rmdirSync(temp.path);
|
|
216
|
+
}
|
|
217
|
+
function pinnedParentMatches(parent) {
|
|
218
|
+
try {
|
|
219
|
+
const pathname = lstatSync(parent.path, { bigint: true });
|
|
220
|
+
const descriptor = fstatSync(parent.descriptor, { bigint: true });
|
|
221
|
+
return pathname.isDirectory() && !pathname.isSymbolicLink() && descriptor.isDirectory()
|
|
222
|
+
&& pathname.dev === parent.device && pathname.ino === parent.inode
|
|
223
|
+
&& descriptor.dev === parent.device && descriptor.ino === parent.inode
|
|
224
|
+
&& descriptor.mode === parent.mode;
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
function digestDescriptor(descriptor, size) {
|
|
231
|
+
const digest = createHash('sha256');
|
|
232
|
+
const buffer = Buffer.allocUnsafe(FILE_READ_BUFFER_BYTES);
|
|
233
|
+
let offset = 0n;
|
|
234
|
+
while (offset < size) {
|
|
235
|
+
const remaining = size - offset;
|
|
236
|
+
const requested = remaining > BigInt(buffer.byteLength) ? buffer.byteLength : Number(remaining);
|
|
237
|
+
const count = readSync(descriptor, buffer, 0, requested, Number(offset));
|
|
238
|
+
if (count <= 0)
|
|
239
|
+
fail('database-drift', 'assistant-recovery database changed while it was inspected');
|
|
240
|
+
digest.update(buffer.subarray(0, count));
|
|
241
|
+
offset += BigInt(count);
|
|
242
|
+
}
|
|
243
|
+
return digest.digest('hex');
|
|
244
|
+
}
|
|
245
|
+
function pinPrivateFile(path, unsafeCode) {
|
|
246
|
+
let descriptor;
|
|
247
|
+
try {
|
|
248
|
+
descriptor = openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
249
|
+
const metadata = fstatSync(descriptor, { bigint: true });
|
|
250
|
+
const uid = process.getuid?.();
|
|
251
|
+
if (!metadata.isFile() || metadata.nlink !== 1n
|
|
252
|
+
|| uid === undefined || metadata.uid !== BigInt(uid)
|
|
253
|
+
|| (metadata.mode & 4095n) !== 384n || metadata.size > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
254
|
+
fail(unsafeCode, `assistant-recovery ${basename(path)} must be one private owner-readable regular file`);
|
|
255
|
+
}
|
|
256
|
+
const pinned = {
|
|
257
|
+
descriptor,
|
|
258
|
+
path,
|
|
259
|
+
device: metadata.dev,
|
|
260
|
+
inode: metadata.ino,
|
|
261
|
+
size: metadata.size,
|
|
262
|
+
mode: metadata.mode,
|
|
263
|
+
modifiedAt: metadata.mtimeNs,
|
|
264
|
+
changedAt: metadata.ctimeNs,
|
|
265
|
+
digest: digestDescriptor(descriptor, metadata.size),
|
|
266
|
+
};
|
|
267
|
+
descriptor = undefined;
|
|
268
|
+
return pinned;
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
if (error instanceof RecoveryOperatorSnapshotError)
|
|
272
|
+
throw error;
|
|
273
|
+
if (error.code === 'ENOENT') {
|
|
274
|
+
if (unsafeCode === 'unsafe-file') {
|
|
275
|
+
fail('missing-file', 'assistant-recovery database does not exist');
|
|
276
|
+
}
|
|
277
|
+
fail(unsafeCode === 'unsafe-wal' ? 'wal-drift' : 'shm-drift', `assistant-recovery ${basename(path)} disappeared while it was inspected`);
|
|
278
|
+
}
|
|
279
|
+
fail(unsafeCode, `assistant-recovery ${basename(path)} could not be opened safely`);
|
|
280
|
+
}
|
|
281
|
+
finally {
|
|
282
|
+
if (descriptor !== undefined)
|
|
283
|
+
closeSync(descriptor);
|
|
284
|
+
}
|
|
285
|
+
throw new Error('unreachable');
|
|
286
|
+
}
|
|
287
|
+
function samePinnedFile(before) {
|
|
288
|
+
try {
|
|
289
|
+
const path = lstatSync(before.path, { bigint: true });
|
|
290
|
+
const descriptor = fstatSync(before.descriptor, { bigint: true });
|
|
291
|
+
return path.isFile() && !path.isSymbolicLink() && path.nlink === 1n
|
|
292
|
+
&& path.dev === before.device && path.ino === before.inode
|
|
293
|
+
&& descriptor.dev === before.device && descriptor.ino === before.inode
|
|
294
|
+
&& descriptor.size === before.size && descriptor.mode === before.mode
|
|
295
|
+
&& descriptor.mtimeNs === before.modifiedAt && descriptor.ctimeNs === before.changedAt
|
|
296
|
+
&& digestDescriptor(before.descriptor, descriptor.size) === before.digest;
|
|
297
|
+
}
|
|
298
|
+
catch {
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
function pinnedPathIdentityMatches(file) {
|
|
303
|
+
try {
|
|
304
|
+
const path = lstatSync(file.path, { bigint: true });
|
|
305
|
+
const descriptor = fstatSync(file.descriptor, { bigint: true });
|
|
306
|
+
return path.isFile() && !path.isSymbolicLink() && path.nlink === 1n
|
|
307
|
+
&& path.dev === file.device && path.ino === file.inode
|
|
308
|
+
&& descriptor.dev === file.device && descriptor.ino === file.inode;
|
|
309
|
+
}
|
|
310
|
+
catch {
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
function pinFiles(path) {
|
|
315
|
+
if (fileExists(`${path}-journal`)) {
|
|
316
|
+
fail('database-busy', 'assistant-recovery database has an active rollback journal');
|
|
317
|
+
}
|
|
318
|
+
const hasWal = fileExists(`${path}-wal`);
|
|
319
|
+
const hasShm = fileExists(`${path}-shm`);
|
|
320
|
+
if (hasWal !== hasShm) {
|
|
321
|
+
fail(hasWal ? 'shm-drift' : 'wal-drift', 'assistant-recovery WAL sidecar set is incomplete');
|
|
322
|
+
}
|
|
323
|
+
const database = pinPrivateFile(path, 'unsafe-file');
|
|
324
|
+
try {
|
|
325
|
+
if (!hasWal)
|
|
326
|
+
return { database };
|
|
327
|
+
const wal = pinPrivateFile(`${path}-wal`, 'unsafe-wal');
|
|
328
|
+
try {
|
|
329
|
+
const shm = pinPrivateFile(`${path}-shm`, 'unsafe-shm');
|
|
330
|
+
return { database, wal, shm };
|
|
331
|
+
}
|
|
332
|
+
catch (error) {
|
|
333
|
+
closeSync(wal.descriptor);
|
|
334
|
+
throw error;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
closeSync(database.descriptor);
|
|
339
|
+
throw error;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
function closePinned(files) {
|
|
343
|
+
closeSync(files.database.descriptor);
|
|
344
|
+
if (files.wal !== undefined)
|
|
345
|
+
closeSync(files.wal.descriptor);
|
|
346
|
+
if (files.shm !== undefined)
|
|
347
|
+
closeSync(files.shm.descriptor);
|
|
348
|
+
}
|
|
349
|
+
function assertNoDrift(path, files) {
|
|
350
|
+
if (!samePinnedFile(files.database)) {
|
|
351
|
+
fail('database-drift', 'assistant-recovery database changed while it was inspected');
|
|
352
|
+
}
|
|
353
|
+
const hasWal = fileExists(`${path}-wal`);
|
|
354
|
+
const hasShm = fileExists(`${path}-shm`);
|
|
355
|
+
if ((files.wal === undefined) !== !hasWal || (files.shm === undefined) !== !hasShm) {
|
|
356
|
+
if ((files.wal === undefined) !== !hasWal)
|
|
357
|
+
fail('wal-drift', 'assistant-recovery WAL changed while it was inspected');
|
|
358
|
+
fail('shm-drift', 'assistant-recovery SHM changed while it was inspected');
|
|
359
|
+
}
|
|
360
|
+
if (files.wal !== undefined && !samePinnedFile(files.wal)) {
|
|
361
|
+
fail('wal-drift', 'assistant-recovery WAL changed while it was inspected');
|
|
362
|
+
}
|
|
363
|
+
// SQLite may update WAL-index lock/read-mark bytes even through a read-only
|
|
364
|
+
// connection. File identity, size, mode, and timestamps still detect an
|
|
365
|
+
// externally replaced, resized, or persisted SHM generation without
|
|
366
|
+
// misclassifying SQLite's own transient lock bookkeeping as state mutation.
|
|
367
|
+
if (files.shm !== undefined) {
|
|
368
|
+
try {
|
|
369
|
+
const pathState = lstatSync(files.shm.path, { bigint: true });
|
|
370
|
+
const descriptorState = fstatSync(files.shm.descriptor, { bigint: true });
|
|
371
|
+
if (!pathState.isFile() || pathState.isSymbolicLink() || pathState.nlink !== 1n
|
|
372
|
+
|| pathState.dev !== files.shm.device || pathState.ino !== files.shm.inode
|
|
373
|
+
|| descriptorState.dev !== files.shm.device || descriptorState.ino !== files.shm.inode
|
|
374
|
+
|| descriptorState.size !== files.shm.size || descriptorState.mode !== files.shm.mode
|
|
375
|
+
|| descriptorState.mtimeNs !== files.shm.modifiedAt || descriptorState.ctimeNs !== files.shm.changedAt) {
|
|
376
|
+
fail('shm-drift', 'assistant-recovery SHM changed while it was inspected');
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
catch (error) {
|
|
380
|
+
if (error instanceof RecoveryOperatorSnapshotError)
|
|
381
|
+
throw error;
|
|
382
|
+
fail('shm-drift', 'assistant-recovery SHM changed while it was inspected');
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
function boundedFailureCode(value) {
|
|
387
|
+
if (value === null)
|
|
388
|
+
return undefined;
|
|
389
|
+
if (typeof value !== 'string' || value !== value.normalize('NFC').trim()
|
|
390
|
+
|| !FAILURE_CODE.test(value)) {
|
|
391
|
+
fail('database-corrupt', 'assistant-recovery bootstrap failure code is corrupt');
|
|
392
|
+
}
|
|
393
|
+
return value;
|
|
394
|
+
}
|
|
395
|
+
function safeInteger(value, minimum) {
|
|
396
|
+
if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < minimum) {
|
|
397
|
+
fail('database-corrupt', 'assistant-recovery bootstrap numeric state is corrupt');
|
|
398
|
+
}
|
|
399
|
+
return value;
|
|
400
|
+
}
|
|
401
|
+
function bootstrapState(row) {
|
|
402
|
+
if (row === undefined || typeof row.bootstrap_attestations_json !== 'string'
|
|
403
|
+
|| typeof row.bootstrap_attestation_set_digest !== 'string'
|
|
404
|
+
|| !DIGEST.test(row.bootstrap_attestation_set_digest)) {
|
|
405
|
+
fail('database-corrupt', 'assistant-recovery bootstrap singleton is corrupt');
|
|
406
|
+
}
|
|
407
|
+
const status = row.bootstrap_status;
|
|
408
|
+
if (status !== 'failed' && status !== 'idle' && status !== 'running' && status !== 'succeeded') {
|
|
409
|
+
fail('database-corrupt', 'assistant-recovery bootstrap status is corrupt');
|
|
410
|
+
}
|
|
411
|
+
const generation = safeInteger(row.bootstrap_generation, 0);
|
|
412
|
+
const updatedAt = safeInteger(row.updated_at, 0);
|
|
413
|
+
if (status !== 'idle' && generation < 1) {
|
|
414
|
+
fail('database-corrupt', 'assistant-recovery bootstrap generation is corrupt');
|
|
415
|
+
}
|
|
416
|
+
if (row.bootstrap_attestation_valid !== 0 && row.bootstrap_attestation_valid !== 1) {
|
|
417
|
+
fail('database-corrupt', 'assistant-recovery bootstrap attestation validity is corrupt');
|
|
418
|
+
}
|
|
419
|
+
const failureCode = boundedFailureCode(row.bootstrap_failure_code);
|
|
420
|
+
if ((status === 'failed') !== (failureCode !== undefined)) {
|
|
421
|
+
fail('database-corrupt', 'assistant-recovery bootstrap failure state is inconsistent');
|
|
422
|
+
}
|
|
423
|
+
let attestations;
|
|
424
|
+
try {
|
|
425
|
+
const parsed = JSON.parse(row.bootstrap_attestations_json);
|
|
426
|
+
attestations = canonicalRecoveryBootstrapAttestationSet(parsed);
|
|
427
|
+
}
|
|
428
|
+
catch (error) {
|
|
429
|
+
if (error instanceof RecoveryBootstrapAttestationError || error instanceof SyntaxError) {
|
|
430
|
+
fail('database-corrupt', 'assistant-recovery bootstrap attestation set is corrupt');
|
|
431
|
+
}
|
|
432
|
+
throw error;
|
|
433
|
+
}
|
|
434
|
+
const canonical = JSON.stringify(attestations);
|
|
435
|
+
const actualDigest = recoveryBootstrapAttestationSetDigest(attestations);
|
|
436
|
+
const storedDigest = row.bootstrap_attestation_set_digest;
|
|
437
|
+
const valid = row.bootstrap_attestation_valid === 1;
|
|
438
|
+
if (canonical !== row.bootstrap_attestations_json
|
|
439
|
+
|| !timingSafeEqual(Buffer.from(actualDigest), Buffer.from(storedDigest))
|
|
440
|
+
|| (!valid && attestations.length !== 0) || (status === 'succeeded' && !valid)) {
|
|
441
|
+
fail('database-corrupt', 'assistant-recovery bootstrap attestation proof is inconsistent');
|
|
442
|
+
}
|
|
443
|
+
return deepFreeze({
|
|
444
|
+
status,
|
|
445
|
+
...(failureCode === undefined ? {} : { failureCode }),
|
|
446
|
+
generation,
|
|
447
|
+
attestationValid: valid,
|
|
448
|
+
attestationSetDigest: storedDigest,
|
|
449
|
+
attestations,
|
|
450
|
+
updatedAt,
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
function storageDigest(files) {
|
|
454
|
+
return createHash('sha256').update(canonicalJson({
|
|
455
|
+
protocol: 'assistant-recovery/operator-database/v1',
|
|
456
|
+
database: files.database.digest,
|
|
457
|
+
wal: files.wal?.digest ?? null,
|
|
458
|
+
})).digest('hex');
|
|
459
|
+
}
|
|
460
|
+
function classifySqliteError(error) {
|
|
461
|
+
const message = error instanceof Error ? error.message.toLowerCase() : '';
|
|
462
|
+
const sqlite = error;
|
|
463
|
+
if (sqlite.errcode === 5 || sqlite.errcode === 6 || /(?:busy|locked)/u.test(message)) {
|
|
464
|
+
fail('database-busy', 'assistant-recovery database is busy');
|
|
465
|
+
}
|
|
466
|
+
if (/(?:malformed|not a database|database disk image|file is encrypted|no such table|no such column|datatype mismatch|constraint)/u.test(message)) {
|
|
467
|
+
fail('database-corrupt', 'assistant-recovery database is corrupt');
|
|
468
|
+
}
|
|
469
|
+
fail('database-unavailable', 'assistant-recovery database could not be inspected');
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Read the already-existing schema-v4 bootstrap state without creating,
|
|
473
|
+
* migrating, chmodding, checkpointing, or changing journal mode. The returned
|
|
474
|
+
* digests detect local source drift; they do not prove authenticity against a
|
|
475
|
+
* same-UID process or privileged attacker.
|
|
476
|
+
*/
|
|
477
|
+
export function inspectRecoveryOperatorSnapshot(databasePath) {
|
|
478
|
+
if (typeof databasePath !== 'string' || !isAbsolute(databasePath)
|
|
479
|
+
|| resolve(databasePath) !== databasePath || databasePath === '/'
|
|
480
|
+
|| hasControlCharacter(databasePath)) {
|
|
481
|
+
fail('invalid-path', 'assistant-recovery operator snapshot path must be canonical and absolute');
|
|
482
|
+
}
|
|
483
|
+
const parent = dirname(databasePath);
|
|
484
|
+
const pinnedParent = pinPrivateParent(parent);
|
|
485
|
+
if (!existsSync(databasePath)) {
|
|
486
|
+
closeSync(pinnedParent.descriptor);
|
|
487
|
+
fail('missing-file', 'assistant-recovery database does not exist');
|
|
488
|
+
}
|
|
489
|
+
let physical;
|
|
490
|
+
try {
|
|
491
|
+
physical = realpathSync(databasePath);
|
|
492
|
+
}
|
|
493
|
+
catch {
|
|
494
|
+
closeSync(pinnedParent.descriptor);
|
|
495
|
+
fail('unsafe-file', 'assistant-recovery database cannot be resolved');
|
|
496
|
+
}
|
|
497
|
+
if (physical !== join(parent, basename(databasePath))) {
|
|
498
|
+
closeSync(pinnedParent.descriptor);
|
|
499
|
+
fail('unsafe-file', 'assistant-recovery database path must not contain symlinks');
|
|
500
|
+
}
|
|
501
|
+
let files;
|
|
502
|
+
try {
|
|
503
|
+
files = pinFiles(databasePath);
|
|
504
|
+
}
|
|
505
|
+
catch (error) {
|
|
506
|
+
closeSync(pinnedParent.descriptor);
|
|
507
|
+
throw error;
|
|
508
|
+
}
|
|
509
|
+
let database;
|
|
510
|
+
let temporary;
|
|
511
|
+
let temporaryPath;
|
|
512
|
+
let copies = [];
|
|
513
|
+
let transaction = false;
|
|
514
|
+
let result;
|
|
515
|
+
let deferredError;
|
|
516
|
+
const selfDescriptors = () => new Set([
|
|
517
|
+
pinnedParent.descriptor, files.database.descriptor, files.wal?.descriptor,
|
|
518
|
+
files.shm?.descriptor, temporary?.descriptor, ...copies.map(file => file.descriptor),
|
|
519
|
+
].filter((descriptor) => descriptor !== undefined));
|
|
520
|
+
try {
|
|
521
|
+
let bound;
|
|
522
|
+
let target;
|
|
523
|
+
// A clean database is opened by its already-pinned inode. A live WAL is
|
|
524
|
+
// copied into a pinned owner-only directory so SQLite never opens a source
|
|
525
|
+
// pathname or writes source SHM lock/read-mark state.
|
|
526
|
+
if (files.wal === undefined) {
|
|
527
|
+
target = inodeBindSupported
|
|
528
|
+
? `file://${procSelfFd}/${files.database.descriptor}?mode=ro&immutable=1`
|
|
529
|
+
: `${pathToFileURL(databasePath).href}?mode=ro&immutable=1`;
|
|
530
|
+
bound = [files.database];
|
|
531
|
+
}
|
|
532
|
+
else {
|
|
533
|
+
temporaryPath = mkdtempSync(join(tmpdir(), 'assistant-recovery-operator-snapshot-'));
|
|
534
|
+
temporary = pinTempDirectory(temporaryPath);
|
|
535
|
+
const anchor = `${procSelfFd}/${temporary.descriptor}`;
|
|
536
|
+
const main = copyAndPin(files.database, `${anchor}/recovery.sqlite`, 'database-drift');
|
|
537
|
+
let wal;
|
|
538
|
+
try {
|
|
539
|
+
wal = copyAndPin(files.wal, `${anchor}/recovery.sqlite-wal`, 'wal-drift');
|
|
540
|
+
}
|
|
541
|
+
catch (error) {
|
|
542
|
+
try {
|
|
543
|
+
closeSync(main.descriptor);
|
|
544
|
+
}
|
|
545
|
+
catch { }
|
|
546
|
+
;
|
|
547
|
+
throw error;
|
|
548
|
+
}
|
|
549
|
+
copies = Object.freeze([main, wal]);
|
|
550
|
+
target = `file://${anchor}/recovery.sqlite?mode=ro`;
|
|
551
|
+
bound = copies;
|
|
552
|
+
assertNoDrift(databasePath, files);
|
|
553
|
+
}
|
|
554
|
+
assertNoDrift(databasePath, files);
|
|
555
|
+
if (!pinnedPathIdentityMatches(files.database)) {
|
|
556
|
+
fail('database-drift', 'assistant-recovery database path changed before open');
|
|
557
|
+
}
|
|
558
|
+
database = new DatabaseSync(target, { readOnly: true });
|
|
559
|
+
if (inodeBindSupported)
|
|
560
|
+
assertConnectionBound([bound[0]], selfDescriptors());
|
|
561
|
+
if (!pinnedPathIdentityMatches(files.database)) {
|
|
562
|
+
fail('database-drift', 'assistant-recovery database path changed during open');
|
|
563
|
+
}
|
|
564
|
+
database.exec('PRAGMA query_only = ON; PRAGMA busy_timeout = 0; BEGIN');
|
|
565
|
+
transaction = true;
|
|
566
|
+
const queryOnly = database.prepare('PRAGMA query_only').get();
|
|
567
|
+
if (queryOnly.query_only !== 1)
|
|
568
|
+
fail('database-unavailable', 'assistant-recovery read-only guard was not enabled');
|
|
569
|
+
const versionRow = database.prepare('PRAGMA user_version').get();
|
|
570
|
+
if (typeof versionRow.user_version !== 'number' || !Number.isSafeInteger(versionRow.user_version)) {
|
|
571
|
+
fail('database-corrupt', 'assistant-recovery schema version is corrupt');
|
|
572
|
+
}
|
|
573
|
+
if (versionRow.user_version < recoverySchemaVersion) {
|
|
574
|
+
fail('schema-too-old', `assistant-recovery schema ${versionRow.user_version} is older than required schema ${recoverySchemaVersion}`);
|
|
575
|
+
}
|
|
576
|
+
if (versionRow.user_version > recoverySchemaVersion) {
|
|
577
|
+
fail('schema-too-new', `assistant-recovery schema ${versionRow.user_version} is newer than supported schema ${recoverySchemaVersion}`);
|
|
578
|
+
}
|
|
579
|
+
const rows = database.prepare(`
|
|
580
|
+
SELECT bootstrap_status, bootstrap_failure_code, bootstrap_generation,
|
|
581
|
+
bootstrap_attestation_valid, bootstrap_attestations_json,
|
|
582
|
+
bootstrap_attestation_set_digest, updated_at
|
|
583
|
+
FROM recovery_runtime_state WHERE singleton = 1 LIMIT 2
|
|
584
|
+
`).all();
|
|
585
|
+
if (rows.length !== 1)
|
|
586
|
+
fail('database-corrupt', 'assistant-recovery bootstrap singleton is missing or ambiguous');
|
|
587
|
+
const bootstrap = bootstrapState(rows[0]);
|
|
588
|
+
if (inodeBindSupported)
|
|
589
|
+
assertConnectionBound(bound, selfDescriptors());
|
|
590
|
+
assertNoDrift(databasePath, files);
|
|
591
|
+
const databaseIdentity = deepFreeze({
|
|
592
|
+
device: files.database.device.toString(10),
|
|
593
|
+
inode: files.database.inode.toString(10),
|
|
594
|
+
size: Number(files.database.size),
|
|
595
|
+
digest: storageDigest(files),
|
|
596
|
+
});
|
|
597
|
+
const unsigned = deepFreeze({
|
|
598
|
+
protocol: RECOVERY_OPERATOR_SNAPSHOT_PROTOCOL,
|
|
599
|
+
schemaVersion: recoverySchemaVersion,
|
|
600
|
+
database: databaseIdentity,
|
|
601
|
+
bootstrap,
|
|
602
|
+
});
|
|
603
|
+
result = deepFreeze({
|
|
604
|
+
...unsigned,
|
|
605
|
+
snapshotDigest: createHash('sha256').update(canonicalJson(unsigned)).digest('hex'),
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
catch (error) {
|
|
609
|
+
deferredError = error;
|
|
610
|
+
}
|
|
611
|
+
finally {
|
|
612
|
+
if (transaction) {
|
|
613
|
+
try {
|
|
614
|
+
database?.exec('ROLLBACK');
|
|
615
|
+
}
|
|
616
|
+
catch (error) {
|
|
617
|
+
deferredError ??= error;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
try {
|
|
621
|
+
database?.close();
|
|
622
|
+
}
|
|
623
|
+
catch (error) {
|
|
624
|
+
deferredError ??= error;
|
|
625
|
+
}
|
|
626
|
+
try {
|
|
627
|
+
assertNoDrift(databasePath, files);
|
|
628
|
+
}
|
|
629
|
+
catch (error) {
|
|
630
|
+
deferredError ??= error;
|
|
631
|
+
}
|
|
632
|
+
if (!pinnedParentMatches(pinnedParent)) {
|
|
633
|
+
// A parent replacement invalidates every earlier pathname observation;
|
|
634
|
+
// it deliberately overrides a deferred lower-level drift error.
|
|
635
|
+
deferredError = new RecoveryOperatorSnapshotError('unsafe-parent', 'assistant-recovery operator snapshot parent changed while it was inspected');
|
|
636
|
+
}
|
|
637
|
+
for (const copy of copies)
|
|
638
|
+
try {
|
|
639
|
+
closeSync(copy.descriptor);
|
|
640
|
+
}
|
|
641
|
+
catch { }
|
|
642
|
+
if (temporary !== undefined) {
|
|
643
|
+
try {
|
|
644
|
+
removePinnedTemp(temporary);
|
|
645
|
+
}
|
|
646
|
+
catch (error) {
|
|
647
|
+
deferredError ??= error;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
else if (temporaryPath !== undefined) {
|
|
651
|
+
try {
|
|
652
|
+
rmSync(temporaryPath, { recursive: true, force: true });
|
|
653
|
+
}
|
|
654
|
+
catch (error) {
|
|
655
|
+
deferredError ??= error;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
try {
|
|
659
|
+
closePinned(files);
|
|
660
|
+
}
|
|
661
|
+
catch (error) {
|
|
662
|
+
deferredError ??= error;
|
|
663
|
+
}
|
|
664
|
+
try {
|
|
665
|
+
closeSync(pinnedParent.descriptor);
|
|
666
|
+
}
|
|
667
|
+
catch (error) {
|
|
668
|
+
deferredError ??= error;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
if (deferredError !== undefined) {
|
|
672
|
+
if (deferredError instanceof RecoveryOperatorSnapshotError)
|
|
673
|
+
throw deferredError;
|
|
674
|
+
classifySqliteError(deferredError);
|
|
675
|
+
}
|
|
676
|
+
return result;
|
|
677
|
+
}
|
|
678
|
+
//# sourceMappingURL=operator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operator.js","sourceRoot":"","sources":["../src/operator.ts"],"names":[],"mappings":"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"}
|
package/lib/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "0.1.
|
|
1
|
+
export declare const version = "0.1.30";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/lib/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const version = '0.1.
|
|
1
|
+
export const version = '0.1.30';
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsh-enhanced/assistant-recovery",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.30",
|
|
4
4
|
"description": "Deterministic Host recovery and supervised self-evolution runbook for DeepSeek Harness.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -74,19 +74,19 @@
|
|
|
74
74
|
}
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
|
-
"@deepseek-ai/cordis": "4.0.
|
|
77
|
+
"@deepseek-ai/cordis": "4.0.2",
|
|
78
78
|
"@types/node": "22.20.0",
|
|
79
79
|
"typescript": "6.0.3",
|
|
80
80
|
"vitest": "4.1.8",
|
|
81
|
-
"@dsh-enhanced/assistant-automations": "0.1.
|
|
82
|
-
"@dsh-enhanced/assistant-evaluation": "0.1.
|
|
83
|
-
"@dsh-enhanced/assistant-
|
|
84
|
-
"@dsh-enhanced/assistant-evolution": "0.1.
|
|
85
|
-
"@dsh-enhanced/
|
|
86
|
-
"@dsh-enhanced/
|
|
81
|
+
"@dsh-enhanced/assistant-automations": "0.1.30",
|
|
82
|
+
"@dsh-enhanced/assistant-evaluation": "0.1.30",
|
|
83
|
+
"@dsh-enhanced/assistant-health": "0.1.30",
|
|
84
|
+
"@dsh-enhanced/assistant-evolution": "0.1.30",
|
|
85
|
+
"@dsh-enhanced/preference-learning": "0.1.30",
|
|
86
|
+
"@dsh-enhanced/assistant-delivery": "0.1.30"
|
|
87
87
|
},
|
|
88
88
|
"dependencies": {
|
|
89
|
-
"@deepseek-ai/schemastery": "3.18.
|
|
89
|
+
"@deepseek-ai/schemastery": "3.18.2"
|
|
90
90
|
},
|
|
91
91
|
"scripts": {
|
|
92
92
|
"build": "tsc -p tsconfig.build.json",
|