@agent-teams/engineering-foundation 0.12.0 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +23 -12
- package/dist/cli.js.map +1 -1
- package/dist/foundation-state-contract.d.ts +7 -0
- package/dist/foundation-state-contract.d.ts.map +1 -0
- package/dist/foundation-state-contract.js +7 -0
- package/dist/foundation-state-contract.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/local-mode/attach-transaction.d.ts.map +1 -1
- package/dist/local-mode/attach-transaction.js +13 -7
- package/dist/local-mode/attach-transaction.js.map +1 -1
- package/dist/local-mode/inspection.d.ts +4 -1
- package/dist/local-mode/inspection.d.ts.map +1 -1
- package/dist/local-mode/inspection.js +20 -0
- package/dist/local-mode/inspection.js.map +1 -1
- package/dist/local-mode/local-state-store.d.ts.map +1 -1
- package/dist/local-mode/local-state-store.js +8 -105
- package/dist/local-mode/local-state-store.js.map +1 -1
- package/dist/local-mode/service.d.ts.map +1 -1
- package/dist/local-mode/service.js +17 -4
- package/dist/local-mode/service.js.map +1 -1
- package/dist/local-mode/types.d.ts +7 -4
- package/dist/local-mode/types.d.ts.map +1 -1
- package/dist/local-mode/types.js +1 -4
- package/dist/local-mode/types.js.map +1 -1
- package/dist/package-version.d.ts +2 -0
- package/dist/package-version.d.ts.map +1 -0
- package/dist/package-version.js +10 -0
- package/dist/package-version.js.map +1 -0
- package/dist/process-execution/windows-managed-process.d.ts.map +1 -1
- package/dist/process-execution/windows-managed-process.js +1 -0
- package/dist/process-execution/windows-managed-process.js.map +1 -1
- package/dist/repository-mutation/adapters/node/node-absent-file-publication.d.ts +31 -0
- package/dist/repository-mutation/adapters/node/node-absent-file-publication.d.ts.map +1 -0
- package/dist/repository-mutation/adapters/node/node-absent-file-publication.js +272 -0
- package/dist/repository-mutation/adapters/node/node-absent-file-publication.js.map +1 -0
- package/dist/repository-mutation/adapters/node/node-bounded-regular-file.d.ts +20 -0
- package/dist/repository-mutation/adapters/node/node-bounded-regular-file.d.ts.map +1 -0
- package/dist/repository-mutation/adapters/node/node-bounded-regular-file.js +123 -0
- package/dist/repository-mutation/adapters/node/node-bounded-regular-file.js.map +1 -0
- package/dist/repository-mutation/adapters/node/node-directory-durability.d.ts +12 -0
- package/dist/repository-mutation/adapters/node/node-directory-durability.d.ts.map +1 -0
- package/dist/repository-mutation/adapters/node/node-directory-durability.js +32 -0
- package/dist/repository-mutation/adapters/node/node-directory-durability.js.map +1 -0
- package/dist/repository-mutation/adapters/node/node-existing-repository-ancestors.d.ts +13 -0
- package/dist/repository-mutation/adapters/node/node-existing-repository-ancestors.d.ts.map +1 -0
- package/dist/repository-mutation/adapters/node/node-existing-repository-ancestors.js +67 -0
- package/dist/repository-mutation/adapters/node/node-existing-repository-ancestors.js.map +1 -0
- package/dist/repository-mutation/adapters/node/node-repository-path.d.ts +2 -0
- package/dist/repository-mutation/adapters/node/node-repository-path.d.ts.map +1 -0
- package/dist/repository-mutation/adapters/node/node-repository-path.js +7 -0
- package/dist/repository-mutation/adapters/node/node-repository-path.js.map +1 -0
- package/dist/repository-mutation/application/model/exact-postimage.d.ts +17 -0
- package/dist/repository-mutation/application/model/exact-postimage.d.ts.map +1 -0
- package/dist/repository-mutation/application/model/exact-postimage.js +11 -0
- package/dist/repository-mutation/application/model/exact-postimage.js.map +1 -0
- package/dist/repository-mutation/application/model/path-identity.d.ts +7 -0
- package/dist/repository-mutation/application/model/path-identity.d.ts.map +1 -0
- package/dist/repository-mutation/application/model/path-identity.js +2 -0
- package/dist/repository-mutation/application/model/path-identity.js.map +1 -0
- package/dist/repository-mutation/application/model/repository-path.d.ts +8 -0
- package/dist/repository-mutation/application/model/repository-path.d.ts.map +1 -0
- package/dist/repository-mutation/application/model/repository-path.js +74 -0
- package/dist/repository-mutation/application/model/repository-path.js.map +1 -0
- package/dist/scaffolding/adapters/node/filesystem-authority-workspace.d.ts.map +1 -1
- package/dist/scaffolding/adapters/node/filesystem-authority-workspace.js +52 -8
- package/dist/scaffolding/adapters/node/filesystem-authority-workspace.js.map +1 -1
- package/dist/scaffolding/adapters/node/filesystem-file-identity.d.ts +3 -19
- package/dist/scaffolding/adapters/node/filesystem-file-identity.d.ts.map +1 -1
- package/dist/scaffolding/adapters/node/filesystem-file-identity.js +1 -121
- package/dist/scaffolding/adapters/node/filesystem-file-identity.js.map +1 -1
- package/dist/scaffolding/adapters/node/filesystem-journal.d.ts +1 -1
- package/dist/scaffolding/adapters/node/filesystem-journal.d.ts.map +1 -1
- package/dist/scaffolding/adapters/node/filesystem-journal.js +4 -20
- package/dist/scaffolding/adapters/node/filesystem-journal.js.map +1 -1
- package/dist/scaffolding/adapters/node/filesystem-operation-state.d.ts +2 -1
- package/dist/scaffolding/adapters/node/filesystem-operation-state.d.ts.map +1 -1
- package/dist/scaffolding/adapters/node/filesystem-operation-state.js +73 -122
- package/dist/scaffolding/adapters/node/filesystem-operation-state.js.map +1 -1
- package/dist/scaffolding/adapters/node/filesystem-path-guard.d.ts.map +1 -1
- package/dist/scaffolding/adapters/node/filesystem-path-guard.js +27 -68
- package/dist/scaffolding/adapters/node/filesystem-path-guard.js.map +1 -1
- package/dist/scaffolding/adapters/node/installed-foundation-version.d.ts +1 -1
- package/dist/scaffolding/adapters/node/installed-foundation-version.d.ts.map +1 -1
- package/dist/scaffolding/adapters/node/installed-foundation-version.js +1 -9
- package/dist/scaffolding/adapters/node/installed-foundation-version.js.map +1 -1
- package/dist/scaffolding/application/policies/legacy-scaffolding-repository-path.d.ts +4 -0
- package/dist/scaffolding/application/policies/legacy-scaffolding-repository-path.d.ts.map +1 -0
- package/dist/scaffolding/application/policies/legacy-scaffolding-repository-path.js +48 -0
- package/dist/scaffolding/application/policies/legacy-scaffolding-repository-path.js.map +1 -0
- package/dist/scaffolding/kernel/authority-journal-validation.d.ts +4 -0
- package/dist/scaffolding/kernel/authority-journal-validation.d.ts.map +1 -0
- package/dist/scaffolding/kernel/authority-journal-validation.js +24 -0
- package/dist/scaffolding/kernel/authority-journal-validation.js.map +1 -0
- package/dist/transaction-coordination/adapters/node/installed-foundation-build-identity.d.ts +11 -0
- package/dist/transaction-coordination/adapters/node/installed-foundation-build-identity.d.ts.map +1 -0
- package/dist/transaction-coordination/adapters/node/installed-foundation-build-identity.js +130 -0
- package/dist/transaction-coordination/adapters/node/installed-foundation-build-identity.js.map +1 -0
- package/dist/transaction-coordination/adapters/node/node-foundation-operation-lock.d.ts +7 -0
- package/dist/transaction-coordination/adapters/node/node-foundation-operation-lock.d.ts.map +1 -0
- package/dist/transaction-coordination/adapters/node/node-foundation-operation-lock.js +336 -0
- package/dist/transaction-coordination/adapters/node/node-foundation-operation-lock.js.map +1 -0
- package/dist/transaction-coordination/adapters/node/node-foundation-state-directory.d.ts +4 -0
- package/dist/transaction-coordination/adapters/node/node-foundation-state-directory.d.ts.map +1 -0
- package/dist/transaction-coordination/adapters/node/node-foundation-state-directory.js +76 -0
- package/dist/transaction-coordination/adapters/node/node-foundation-state-directory.js.map +1 -0
- package/dist/transaction-coordination/adapters/node/node-foundation-transaction-coordinator.d.ts +3 -0
- package/dist/transaction-coordination/adapters/node/node-foundation-transaction-coordinator.d.ts.map +1 -0
- package/dist/transaction-coordination/adapters/node/node-foundation-transaction-coordinator.js +23 -0
- package/dist/transaction-coordination/adapters/node/node-foundation-transaction-coordinator.js.map +1 -0
- package/dist/transaction-coordination/adapters/node/node-foundation-transaction-slot.d.ts +12 -0
- package/dist/transaction-coordination/adapters/node/node-foundation-transaction-slot.d.ts.map +1 -0
- package/dist/transaction-coordination/adapters/node/node-foundation-transaction-slot.js +332 -0
- package/dist/transaction-coordination/adapters/node/node-foundation-transaction-slot.js.map +1 -0
- package/dist/transaction-coordination/application/foundation-transaction-coordinator.d.ts +22 -0
- package/dist/transaction-coordination/application/foundation-transaction-coordinator.d.ts.map +1 -0
- package/dist/transaction-coordination/application/foundation-transaction-coordinator.js +78 -0
- package/dist/transaction-coordination/application/foundation-transaction-coordinator.js.map +1 -0
- package/dist/transaction-coordination/application/foundation-transaction-error.d.ts +16 -0
- package/dist/transaction-coordination/application/foundation-transaction-error.d.ts.map +1 -0
- package/dist/transaction-coordination/application/foundation-transaction-error.js +19 -0
- package/dist/transaction-coordination/application/foundation-transaction-error.js.map +1 -0
- package/dist/transaction-coordination/application/model/transaction-status.d.ts +47 -0
- package/dist/transaction-coordination/application/model/transaction-status.d.ts.map +1 -0
- package/dist/transaction-coordination/application/model/transaction-status.js +2 -0
- package/dist/transaction-coordination/application/model/transaction-status.js.map +1 -0
- package/dist/transaction-coordination/application/ports/foundation-operation-lock.d.ts +7 -0
- package/dist/transaction-coordination/application/ports/foundation-operation-lock.d.ts.map +1 -0
- package/dist/transaction-coordination/application/ports/foundation-operation-lock.js +2 -0
- package/dist/transaction-coordination/application/ports/foundation-operation-lock.js.map +1 -0
- package/dist/transaction-coordination/application/ports/foundation-transaction-slot.d.ts +5 -0
- package/dist/transaction-coordination/application/ports/foundation-transaction-slot.d.ts.map +1 -0
- package/dist/transaction-coordination/application/ports/foundation-transaction-slot.js +2 -0
- package/dist/transaction-coordination/application/ports/foundation-transaction-slot.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,20 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
readonly dev: bigint;
|
|
5
|
-
readonly ino: bigint;
|
|
6
|
-
}
|
|
7
|
-
export type BoundedRegularFileRead = {
|
|
8
|
-
readonly outcome: "read";
|
|
9
|
-
readonly bytes: Buffer;
|
|
10
|
-
readonly identity: PortableFileIdentity;
|
|
11
|
-
readonly mode: number;
|
|
12
|
-
} | {
|
|
13
|
-
readonly outcome: "changed";
|
|
14
|
-
} | {
|
|
15
|
-
readonly outcome: "invalid";
|
|
16
|
-
};
|
|
17
|
-
export declare function readBoundedRegularFile(path: string, maximumBytes: number): Promise<BoundedRegularFileRead>;
|
|
18
|
-
export declare function captureFileHandleIdentity(handle: FileHandle): Promise<PortableFileIdentity>;
|
|
19
|
-
export declare function pathMatchesFileIdentity(path: string, expected: PortableFileIdentity): Promise<"different" | "match" | "missing">;
|
|
1
|
+
export { captureFileHandleIdentity, pathMatchesRegularFileIdentity as pathMatchesFileIdentity, readBoundedRegularFile } from "../../../repository-mutation/adapters/node/node-bounded-regular-file.js";
|
|
2
|
+
export type { BoundedRegularFileRead, BoundedRegularFileReadFaultInjector } from "../../../repository-mutation/adapters/node/node-bounded-regular-file.js";
|
|
3
|
+
export type { PortablePathIdentity as PortableFileIdentity } from "../../../repository-mutation/application/model/path-identity.js";
|
|
20
4
|
//# sourceMappingURL=filesystem-file-identity.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filesystem-file-identity.d.ts","sourceRoot":"","sources":["../../../../src/scaffolding/adapters/node/filesystem-file-identity.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"filesystem-file-identity.d.ts","sourceRoot":"","sources":["../../../../src/scaffolding/adapters/node/filesystem-file-identity.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,8BAA8B,IAAI,uBAAuB,EACzD,sBAAsB,EACvB,MAAM,yEAAyE,CAAC;AACjF,YAAY,EACV,sBAAsB,EACtB,mCAAmC,EACpC,MAAM,yEAAyE,CAAC;AACjF,YAAY,EAAE,oBAAoB,IAAI,oBAAoB,EAAE,MAAM,iEAAiE,CAAC"}
|
|
@@ -1,122 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
function identityFromStat(metadata) {
|
|
3
|
-
return {
|
|
4
|
-
birthtimeNs: metadata.birthtimeNs,
|
|
5
|
-
dev: metadata.dev,
|
|
6
|
-
ino: metadata.ino
|
|
7
|
-
};
|
|
8
|
-
}
|
|
9
|
-
function isMissing(error) {
|
|
10
|
-
return (error instanceof Error &&
|
|
11
|
-
"code" in error &&
|
|
12
|
-
error.code === "ENOENT");
|
|
13
|
-
}
|
|
14
|
-
function hasErrorCode(error, code) {
|
|
15
|
-
return (error instanceof Error &&
|
|
16
|
-
"code" in error &&
|
|
17
|
-
error.code === code);
|
|
18
|
-
}
|
|
19
|
-
async function isExistingNonRegularPath(path) {
|
|
20
|
-
try {
|
|
21
|
-
const metadata = await lstat(path);
|
|
22
|
-
return metadata.isSymbolicLink() || !metadata.isFile();
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
return false;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
function sameFileObservation(left, right) {
|
|
29
|
-
return (left.dev === right.dev &&
|
|
30
|
-
left.ino === right.ino &&
|
|
31
|
-
left.birthtimeNs === right.birthtimeNs &&
|
|
32
|
-
left.ctimeNs === right.ctimeNs &&
|
|
33
|
-
left.mtimeNs === right.mtimeNs &&
|
|
34
|
-
left.size === right.size);
|
|
35
|
-
}
|
|
36
|
-
async function readAtMost(handle, maximumBytes) {
|
|
37
|
-
const chunks = [];
|
|
38
|
-
let total = 0;
|
|
39
|
-
while (total <= maximumBytes) {
|
|
40
|
-
const remaining = maximumBytes + 1 - total;
|
|
41
|
-
const buffer = Buffer.allocUnsafe(Math.min(64 * 1024, remaining));
|
|
42
|
-
const { bytesRead } = await handle.read(buffer, 0, buffer.byteLength, null);
|
|
43
|
-
if (bytesRead === 0) {
|
|
44
|
-
return Buffer.concat(chunks, total);
|
|
45
|
-
}
|
|
46
|
-
chunks.push(buffer.subarray(0, bytesRead));
|
|
47
|
-
total += bytesRead;
|
|
48
|
-
}
|
|
49
|
-
return undefined;
|
|
50
|
-
}
|
|
51
|
-
export async function readBoundedRegularFile(path, maximumBytes) {
|
|
52
|
-
if (!Number.isSafeInteger(maximumBytes) || maximumBytes < 0) {
|
|
53
|
-
throw new TypeError("maximumBytes must be a non-negative safe integer.");
|
|
54
|
-
}
|
|
55
|
-
if (await isExistingNonRegularPath(path)) {
|
|
56
|
-
return { outcome: "invalid" };
|
|
57
|
-
}
|
|
58
|
-
const noFollow = process.platform === "win32" ? 0 : constants.O_NOFOLLOW;
|
|
59
|
-
const nonBlocking = process.platform === "win32" ? 0 : constants.O_NONBLOCK;
|
|
60
|
-
let handle;
|
|
61
|
-
try {
|
|
62
|
-
handle = await open(path, constants.O_RDONLY | noFollow | nonBlocking);
|
|
63
|
-
}
|
|
64
|
-
catch (error) {
|
|
65
|
-
if (hasErrorCode(error, "ELOOP") ||
|
|
66
|
-
(await isExistingNonRegularPath(path))) {
|
|
67
|
-
return { outcome: "invalid" };
|
|
68
|
-
}
|
|
69
|
-
throw error;
|
|
70
|
-
}
|
|
71
|
-
try {
|
|
72
|
-
const before = await handle.stat({ bigint: true });
|
|
73
|
-
if (!before.isFile() || before.size > BigInt(maximumBytes)) {
|
|
74
|
-
return { outcome: "invalid" };
|
|
75
|
-
}
|
|
76
|
-
const identity = identityFromStat(before);
|
|
77
|
-
const bytes = await readAtMost(handle, maximumBytes);
|
|
78
|
-
if (bytes === undefined) {
|
|
79
|
-
return { outcome: "invalid" };
|
|
80
|
-
}
|
|
81
|
-
const after = await handle.stat({ bigint: true });
|
|
82
|
-
if (!after.isFile() ||
|
|
83
|
-
!sameFileObservation(before, after) ||
|
|
84
|
-
after.size !== BigInt(bytes.byteLength) ||
|
|
85
|
-
(await pathMatchesFileIdentity(path, identity)) !== "match") {
|
|
86
|
-
return { outcome: "changed" };
|
|
87
|
-
}
|
|
88
|
-
return {
|
|
89
|
-
outcome: "read",
|
|
90
|
-
bytes,
|
|
91
|
-
identity,
|
|
92
|
-
mode: Number(after.mode)
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
finally {
|
|
96
|
-
await handle.close();
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
export async function captureFileHandleIdentity(handle) {
|
|
100
|
-
return identityFromStat(await handle.stat({ bigint: true }));
|
|
101
|
-
}
|
|
102
|
-
export async function pathMatchesFileIdentity(path, expected) {
|
|
103
|
-
try {
|
|
104
|
-
const metadata = await lstat(path, { bigint: true });
|
|
105
|
-
if (metadata.isSymbolicLink() || !metadata.isFile()) {
|
|
106
|
-
return "different";
|
|
107
|
-
}
|
|
108
|
-
const observed = identityFromStat(metadata);
|
|
109
|
-
return observed.dev === expected.dev &&
|
|
110
|
-
observed.ino === expected.ino &&
|
|
111
|
-
observed.birthtimeNs === expected.birthtimeNs
|
|
112
|
-
? "match"
|
|
113
|
-
: "different";
|
|
114
|
-
}
|
|
115
|
-
catch (error) {
|
|
116
|
-
if (isMissing(error)) {
|
|
117
|
-
return "missing";
|
|
118
|
-
}
|
|
119
|
-
throw error;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
1
|
+
export { captureFileHandleIdentity, pathMatchesRegularFileIdentity as pathMatchesFileIdentity, readBoundedRegularFile } from "../../../repository-mutation/adapters/node/node-bounded-regular-file.js";
|
|
122
2
|
//# sourceMappingURL=filesystem-file-identity.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filesystem-file-identity.js","sourceRoot":"","sources":["../../../../src/scaffolding/adapters/node/filesystem-file-identity.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"filesystem-file-identity.js","sourceRoot":"","sources":["../../../../src/scaffolding/adapters/node/filesystem-file-identity.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,8BAA8B,IAAI,uBAAuB,EACzD,sBAAsB,EACvB,MAAM,yEAAyE,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AuthorityScaffoldJournal } from "../../contract/types.js";
|
|
2
2
|
import { type PortableFileIdentity } from "./filesystem-file-identity.js";
|
|
3
|
-
export declare const SCAFFOLD_JOURNAL_FILE
|
|
3
|
+
export declare const SCAFFOLD_JOURNAL_FILE: "scaffolding-transaction.json";
|
|
4
4
|
export declare function writeAuthorityScaffoldJournal(path: string, journal: AuthorityScaffoldJournal, faultInjector?: () => Promise<void> | void): Promise<PortableFileIdentity>;
|
|
5
5
|
export declare function readScaffoldJournalEnvelope(path: string): Promise<AuthorityScaffoldJournal | undefined>;
|
|
6
6
|
export declare function captureExpectedAuthorityScaffoldJournal(path: string, expected: AuthorityScaffoldJournal): Promise<PortableFileIdentity>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filesystem-journal.d.ts","sourceRoot":"","sources":["../../../../src/scaffolding/adapters/node/filesystem-journal.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAMxE,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"filesystem-journal.d.ts","sourceRoot":"","sources":["../../../../src/scaffolding/adapters/node/filesystem-journal.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAMxE,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,+BAA+B,CAAC;AAIvC,eAAO,MAAM,qBAAqB,gCAA8B,CAAC;AAsEjE,wBAAsB,6BAA6B,CACjD,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,wBAAwB,EACjC,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GACzC,OAAO,CAAC,oBAAoB,CAAC,CAE/B;AAgFD,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,wBAAwB,GAAG,SAAS,CAAC,CAE/C;AAED,wBAAsB,uCAAuC,CAC3D,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,wBAAwB,GACjC,OAAO,CAAC,oBAAoB,CAAC,CAY/B;AAED,wBAAsB,6CAA6C,CACjE,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED,wBAAsB,sCAAsC,CAC1D,IAAI,EAAE,MAAM,EACZ,gBAAgB,EAAE,oBAAoB,EACtC,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GACzC,OAAO,CAAC,IAAI,CAAC,CAUf"}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { lstat, mkdir, open, rename, rm } from "node:fs/promises";
|
|
2
2
|
import { dirname } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { assertAuthorityScaffoldJournal } from "../../kernel/authority-journal-validation.js";
|
|
4
4
|
import { ScaffoldError } from "../../scaffold-error.js";
|
|
5
5
|
import { assertSchema } from "../../../schema-catalog.js";
|
|
6
6
|
import { parseStrictYamlSource } from "../../../strict-yaml.js";
|
|
7
7
|
import { syncDirectory } from "./filesystem-path-guard.js";
|
|
8
8
|
import { captureFileHandleIdentity, pathMatchesFileIdentity, readBoundedRegularFile } from "./filesystem-file-identity.js";
|
|
9
9
|
import { MAX_SCAFFOLD_PLAN_BYTES } from "./node-scaffold-limits.js";
|
|
10
|
-
|
|
10
|
+
import { FOUNDATION_TRANSACTION_FILE } from "../../../foundation-state-contract.js";
|
|
11
|
+
export const SCAFFOLD_JOURNAL_FILE = FOUNDATION_TRANSACTION_FILE;
|
|
11
12
|
function isMissing(error) {
|
|
12
13
|
return (error instanceof Error &&
|
|
13
14
|
"code" in error &&
|
|
@@ -79,22 +80,6 @@ async function readJournalSource(path) {
|
|
|
79
80
|
throw error;
|
|
80
81
|
}
|
|
81
82
|
}
|
|
82
|
-
function assertAuthorityJournalOperationBindings(journal) {
|
|
83
|
-
if (journal.operations.length !== journal.plan.operations.length) {
|
|
84
|
-
throw new ScaffoldError("SCAFFOLD_RECOVERY_REQUIRED", "Scaffolding recovery journal operation evidence does not match its Plan.");
|
|
85
|
-
}
|
|
86
|
-
const planOperations = new Map(journal.plan.operations.map((operation) => [operation.id, operation]));
|
|
87
|
-
const seen = new Set();
|
|
88
|
-
for (const operation of journal.operations) {
|
|
89
|
-
const planned = planOperations.get(operation.operationId);
|
|
90
|
-
if (planned === undefined ||
|
|
91
|
-
planned.path !== operation.path ||
|
|
92
|
-
seen.has(operation.operationId)) {
|
|
93
|
-
throw new ScaffoldError("SCAFFOLD_RECOVERY_REQUIRED", "Scaffolding recovery journal operation evidence is invalid.");
|
|
94
|
-
}
|
|
95
|
-
seen.add(operation.operationId);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
83
|
async function readScaffoldJournalRecord(path) {
|
|
99
84
|
const record = await readJournalSource(path);
|
|
100
85
|
if (record === undefined) {
|
|
@@ -113,8 +98,7 @@ async function readScaffoldJournalRecord(path) {
|
|
|
113
98
|
await assertSchema("scaffold-recovery-journal/v1", value, "scaffold-recovery-journal");
|
|
114
99
|
const journal = value;
|
|
115
100
|
await assertSchema("scaffold-plan/v1", journal.plan, "scaffold-recovery-journal");
|
|
116
|
-
|
|
117
|
-
assertAuthorityJournalOperationBindings(journal);
|
|
101
|
+
assertAuthorityScaffoldJournal(journal);
|
|
118
102
|
return { identity: record.identity, journal };
|
|
119
103
|
}
|
|
120
104
|
export async function readScaffoldJournalEnvelope(path) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filesystem-journal.js","sourceRoot":"","sources":["../../../../src/scaffolding/adapters/node/filesystem-journal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"filesystem-journal.js","sourceRoot":"","sources":["../../../../src/scaffolding/adapters/node/filesystem-journal.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { type AbsentFilePublicationFaultPoint } from "../../../repository-mutation/adapters/node/node-absent-file-publication.js";
|
|
1
2
|
import type { MaterializeFileOperation } from "../../contract/scaffold-contract.js";
|
|
2
3
|
export type FilesystemOperationState = "absent" | "after" | "conflict";
|
|
3
4
|
interface FilesystemPublicationFaultPoint {
|
|
4
|
-
readonly phase: "
|
|
5
|
+
readonly phase: AbsentFilePublicationFaultPoint["phase"];
|
|
5
6
|
readonly operationIndex: number;
|
|
6
7
|
readonly operationPath: string;
|
|
7
8
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filesystem-operation-state.d.ts","sourceRoot":"","sources":["../../../../src/scaffolding/adapters/node/filesystem-operation-state.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"filesystem-operation-state.d.ts","sourceRoot":"","sources":["../../../../src/scaffolding/adapters/node/filesystem-operation-state.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,+BAA+B,EACrC,MAAM,4EAA4E,CAAC;AAEpF,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AASpF,MAAM,MAAM,wBAAwB,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;AAEvE,UAAU,+BAA+B;IACvC,QAAQ,CAAC,KAAK,EAAE,+BAA+B,CAAC,OAAO,CAAC,CAAC;IACzD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,MAAM,kCAAkC,GAAG,CAC/C,KAAK,EAAE,+BAA+B,KACnC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAW1B,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,wBAAwB,GAClC,OAAO,CAAC,wBAAwB,CAAC,CAOnC;AAYD,wBAAsB,kCAAkC,CACtD,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;IACJ,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,SAAS,wBAAwB,EAAE,CAAC;CAC1D,GACA,OAAO,CAAC,IAAI,CAAC,CA8Bf;AAyDD,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,wBAAwB,EACnC,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,EACtB,aAAa,CAAC,EAAE,kCAAkC,GACjD,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC,CAwC1C"}
|
|
@@ -1,58 +1,74 @@
|
|
|
1
|
-
import { link, lstat, open, rm } from "node:fs/promises";
|
|
2
1
|
import { basename, dirname, join, resolve } from "node:path";
|
|
3
|
-
import {
|
|
2
|
+
import { assertTemporaryPathsAbsent, classifyExactFilePostimage, publishAbsentFile } from "../../../repository-mutation/adapters/node/node-absent-file-publication.js";
|
|
3
|
+
import { AbsentFilePublicationError } from "../../../repository-mutation/application/model/exact-postimage.js";
|
|
4
|
+
import { sha256Text } from "../../kernel/canonical-json.js";
|
|
4
5
|
import { ScaffoldError } from "../../scaffold-error.js";
|
|
5
|
-
import { assertSafeExistingAncestors, ensureSafeParent, isContainedPath
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return (error instanceof Error &&
|
|
14
|
-
"code" in error &&
|
|
15
|
-
error.code === code);
|
|
6
|
+
import { assertSafeExistingAncestors, ensureSafeParent, isContainedPath } from "./filesystem-path-guard.js";
|
|
7
|
+
function postimage(operation) {
|
|
8
|
+
return {
|
|
9
|
+
bytes: Buffer.from(operation.after.contentBase64, "base64"),
|
|
10
|
+
digest: operation.after.digest,
|
|
11
|
+
mode: 0o644,
|
|
12
|
+
size: operation.after.size
|
|
13
|
+
};
|
|
16
14
|
}
|
|
17
15
|
export async function classifyFilesystemOperation(root, operation) {
|
|
18
16
|
const destination = resolve(root, operation.path);
|
|
19
17
|
if (!isContainedPath(root, destination)) {
|
|
20
18
|
return "conflict";
|
|
21
19
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (result.outcome !== "read") {
|
|
25
|
-
return "conflict";
|
|
26
|
-
}
|
|
27
|
-
const modeMatches = process.platform === "win32" || (result.mode & 0o777) === 0o644;
|
|
28
|
-
return sha256Bytes(result.bytes) === operation.after.digest && modeMatches
|
|
29
|
-
? "after"
|
|
30
|
-
: "conflict";
|
|
31
|
-
}
|
|
32
|
-
catch (error) {
|
|
33
|
-
if (isMissing(error)) {
|
|
34
|
-
return "absent";
|
|
35
|
-
}
|
|
36
|
-
throw error;
|
|
37
|
-
}
|
|
20
|
+
const state = await classifyExactFilePostimage(destination, postimage(operation));
|
|
21
|
+
return state === "exact" ? "after" : state;
|
|
38
22
|
}
|
|
39
23
|
function transactionTemporaryName(planDigest, operation) {
|
|
40
24
|
const identity = sha256Text(`${planDigest}:${operation.id}`).slice("sha256:".length);
|
|
41
25
|
return `.foundation-${identity}.tmp`;
|
|
42
26
|
}
|
|
43
27
|
export async function assertTransactionTemporariesAbsent(root, plan) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
28
|
+
try {
|
|
29
|
+
await assertTemporaryPathsAbsent(plan.operations.map((operation) => {
|
|
30
|
+
const parent = dirname(resolve(root, operation.path));
|
|
31
|
+
return {
|
|
32
|
+
displayPath: operation.path,
|
|
33
|
+
temporaryPath: join(parent, transactionTemporaryName(plan.planDigest, operation))
|
|
34
|
+
};
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
if (error instanceof AbsentFilePublicationError &&
|
|
39
|
+
error.code === "TEMPORARY_EXISTS") {
|
|
40
|
+
const operationPath = error.message.slice("Temporary path already exists: ".length, -1);
|
|
41
|
+
throw new ScaffoldError("SCAFFOLD_APPLY_CONFLICT", `Scaffolding transaction temporary path already exists: ${operationPath}.`);
|
|
55
42
|
}
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function translatePublicationError(error, operation) {
|
|
47
|
+
if (!(error instanceof AbsentFilePublicationError)) {
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
const causeOptions = error.cause === undefined ? undefined : { cause: error.cause };
|
|
51
|
+
switch (error.code) {
|
|
52
|
+
case "CONFLICT":
|
|
53
|
+
throw new ScaffoldError("SCAFFOLD_APPLY_CONFLICT", `Scaffolding output changed concurrently: ${operation.path}.`, [], causeOptions);
|
|
54
|
+
case "TEMPORARY_EXISTS":
|
|
55
|
+
throw new ScaffoldError("SCAFFOLD_APPLY_CONFLICT", `Scaffolding transaction temporary path already exists: ${operation.path}.`, [], causeOptions);
|
|
56
|
+
case "TEMPORARY_REPLACED":
|
|
57
|
+
throw new ScaffoldError("SCAFFOLD_RECOVERY_REQUIRED", `Scaffolding temporary path was replaced concurrently: ${operation.path}.`);
|
|
58
|
+
case "CLEANUP_FAILED":
|
|
59
|
+
// Preserve the frozen scaffolding contract: cleanup failures were exposed
|
|
60
|
+
// directly before publication mechanics moved into the neutral kernel.
|
|
61
|
+
throw error.cleanupError;
|
|
62
|
+
case "INVALID_ERROR":
|
|
63
|
+
case "INVALID_POSTIMAGE":
|
|
64
|
+
case "PUBLICATION_INVALID":
|
|
65
|
+
throw new ScaffoldError("SCAFFOLD_RECOVERY_REQUIRED", `Scaffolding publication failed with an invalid error value: ${operation.path}.`);
|
|
66
|
+
case "PUBLICATION_INCOMPLETE":
|
|
67
|
+
throw new ScaffoldError("SCAFFOLD_RECOVERY_REQUIRED", `Scaffolding publication did not reach a terminal state: ${operation.path}.`);
|
|
68
|
+
case "VERIFICATION_FAILED":
|
|
69
|
+
throw new ScaffoldError("SCAFFOLD_RECOVERY_REQUIRED", `Published scaffolding output failed digest verification: ${operation.path}.`);
|
|
70
|
+
case "PUBLICATION_UNSUPPORTED":
|
|
71
|
+
throw error.cause instanceof Error ? error.cause : error;
|
|
56
72
|
}
|
|
57
73
|
}
|
|
58
74
|
export async function publishFilesystemOperation(root, operation, planDigest, operationIndex, faultInjector) {
|
|
@@ -67,92 +83,27 @@ export async function publishFilesystemOperation(root, operation, planDigest, op
|
|
|
67
83
|
const parent = await ensureSafeParent(root, operation.path);
|
|
68
84
|
const destination = join(parent, basename(operation.path));
|
|
69
85
|
const temporary = join(parent, transactionTemporaryName(planDigest, operation));
|
|
70
|
-
const bytes = Buffer.from(operation.after.contentBase64, "base64");
|
|
71
|
-
let temporaryIdentity;
|
|
72
|
-
let concurrentSatisfied = false;
|
|
73
|
-
let published = false;
|
|
74
|
-
let publicationError;
|
|
75
86
|
try {
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
temporaryIdentity = await captureFileHandleIdentity(handle);
|
|
92
|
-
}
|
|
93
|
-
finally {
|
|
94
|
-
await handle.close();
|
|
95
|
-
}
|
|
96
|
-
await faultInjector?.({
|
|
97
|
-
phase: "after-temporary-synced",
|
|
98
|
-
operationIndex,
|
|
99
|
-
operationPath: operation.path
|
|
87
|
+
const outcome = await publishAbsentFile({
|
|
88
|
+
allowUnsupportedDirectoryDurability: true,
|
|
89
|
+
destinationPath: destination,
|
|
90
|
+
displayPath: operation.path,
|
|
91
|
+
...(faultInjector === undefined
|
|
92
|
+
? {}
|
|
93
|
+
: {
|
|
94
|
+
faultInjector: async (point) => faultInjector({
|
|
95
|
+
...point,
|
|
96
|
+
operationIndex,
|
|
97
|
+
operationPath: operation.path
|
|
98
|
+
})
|
|
99
|
+
}),
|
|
100
|
+
postimage: postimage(operation),
|
|
101
|
+
temporaryPath: temporary
|
|
100
102
|
});
|
|
101
|
-
|
|
102
|
-
await link(temporary, destination);
|
|
103
|
-
}
|
|
104
|
-
catch (error) {
|
|
105
|
-
if (hasErrorCode(error, "EEXIST")) {
|
|
106
|
-
const concurrentState = await classifyFilesystemOperation(root, operation);
|
|
107
|
-
if (concurrentState === "after") {
|
|
108
|
-
concurrentSatisfied = true;
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
throw new ScaffoldError("SCAFFOLD_APPLY_CONFLICT", `Scaffolding output changed concurrently: ${operation.path}.`, [], { cause: error });
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
throw error;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
if (!concurrentSatisfied) {
|
|
119
|
-
published = true;
|
|
120
|
-
await faultInjector?.({
|
|
121
|
-
phase: "after-hard-link",
|
|
122
|
-
operationIndex,
|
|
123
|
-
operationPath: operation.path
|
|
124
|
-
});
|
|
125
|
-
await syncDirectory(parent);
|
|
126
|
-
}
|
|
103
|
+
return outcome === "published" ? "applied" : "already-satisfied";
|
|
127
104
|
}
|
|
128
105
|
catch (error) {
|
|
129
|
-
|
|
130
|
-
}
|
|
131
|
-
const temporaryOwnership = temporaryIdentity === undefined
|
|
132
|
-
? "missing"
|
|
133
|
-
: await pathMatchesFileIdentity(temporary, temporaryIdentity);
|
|
134
|
-
if (temporaryOwnership === "match") {
|
|
135
|
-
await rm(temporary);
|
|
136
|
-
await syncDirectory(parent);
|
|
137
|
-
}
|
|
138
|
-
else if (temporaryOwnership === "different") {
|
|
139
|
-
throw new ScaffoldError("SCAFFOLD_RECOVERY_REQUIRED", `Scaffolding temporary path was replaced concurrently: ${operation.path}.`);
|
|
140
|
-
}
|
|
141
|
-
if (publicationError !== undefined) {
|
|
142
|
-
if (!(publicationError instanceof Error)) {
|
|
143
|
-
throw new ScaffoldError("SCAFFOLD_RECOVERY_REQUIRED", `Scaffolding publication failed with an invalid error value: ${operation.path}.`);
|
|
144
|
-
}
|
|
145
|
-
throw publicationError;
|
|
146
|
-
}
|
|
147
|
-
if (concurrentSatisfied) {
|
|
148
|
-
return "already-satisfied";
|
|
149
|
-
}
|
|
150
|
-
if (!published) {
|
|
151
|
-
throw new ScaffoldError("SCAFFOLD_RECOVERY_REQUIRED", `Scaffolding publication did not reach a terminal state: ${operation.path}.`);
|
|
152
|
-
}
|
|
153
|
-
if ((await classifyFilesystemOperation(root, operation)) !== "after") {
|
|
154
|
-
throw new ScaffoldError("SCAFFOLD_RECOVERY_REQUIRED", `Published scaffolding output failed digest verification: ${operation.path}.`);
|
|
106
|
+
translatePublicationError(error, operation);
|
|
155
107
|
}
|
|
156
|
-
return "applied";
|
|
157
108
|
}
|
|
158
109
|
//# sourceMappingURL=filesystem-operation-state.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filesystem-operation-state.js","sourceRoot":"","sources":["../../../../src/scaffolding/adapters/node/filesystem-operation-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"filesystem-operation-state.js","sourceRoot":"","sources":["../../../../src/scaffolding/adapters/node/filesystem-operation-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filesystem-path-guard.d.ts","sourceRoot":"","sources":["../../../../src/scaffolding/adapters/node/filesystem-path-guard.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"filesystem-path-guard.d.ts","sourceRoot":"","sources":["../../../../src/scaffolding/adapters/node/filesystem-path-guard.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAaxE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAExE;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAmCjE;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/D;AA4BD,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,MAAM,CAAC,CAgCjB;AAED,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CA6Bf"}
|