swarm-deploy 0.0.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/LICENSE.md +201 -0
- package/NOTICE.md +13 -0
- package/README.md +652 -0
- package/RELEASING.md +71 -0
- package/SECURITY.md +41 -0
- package/dist/abort.d.ts +16 -0
- package/dist/abort.js +52 -0
- package/dist/abort.js.map +1 -0
- package/dist/allowlist.d.ts +2 -0
- package/dist/allowlist.js +21 -0
- package/dist/allowlist.js.map +1 -0
- package/dist/bin/swarm-deploy.d.ts +2 -0
- package/dist/bin/swarm-deploy.js +41 -0
- package/dist/bin/swarm-deploy.js.map +1 -0
- package/dist/cli.d.ts +25 -0
- package/dist/cli.js +694 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +121 -0
- package/dist/client.js +285 -0
- package/dist/client.js.map +1 -0
- package/dist/direct-dht.d.ts +81 -0
- package/dist/direct-dht.js +254 -0
- package/dist/direct-dht.js.map +1 -0
- package/dist/error-code.d.ts +15 -0
- package/dist/error-code.js +30 -0
- package/dist/error-code.js.map +1 -0
- package/dist/errors.d.ts +27 -0
- package/dist/errors.js +33 -0
- package/dist/errors.js.map +1 -0
- package/dist/events-node.d.ts +2 -0
- package/dist/events-node.js +7 -0
- package/dist/events-node.js.map +1 -0
- package/dist/files.d.ts +47 -0
- package/dist/files.js +150 -0
- package/dist/files.js.map +1 -0
- package/dist/fs-node.d.ts +2 -0
- package/dist/fs-node.js +7 -0
- package/dist/fs-node.js.map +1 -0
- package/dist/identity.d.ts +7 -0
- package/dist/identity.js +50 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/os-node.d.ts +2 -0
- package/dist/os-node.js +7 -0
- package/dist/os-node.js.map +1 -0
- package/dist/path-node.d.ts +2 -0
- package/dist/path-node.js +7 -0
- package/dist/path-node.js.map +1 -0
- package/dist/process-node.d.ts +2 -0
- package/dist/process-node.js +7 -0
- package/dist/process-node.js.map +1 -0
- package/dist/server.d.ts +153 -0
- package/dist/server.js +576 -0
- package/dist/server.js.map +1 -0
- package/dist/storage/atomic-file.d.ts +15 -0
- package/dist/storage/atomic-file.js +172 -0
- package/dist/storage/atomic-file.js.map +1 -0
- package/dist/storage/commit-journal.d.ts +83 -0
- package/dist/storage/commit-journal.js +279 -0
- package/dist/storage/commit-journal.js.map +1 -0
- package/dist/storage/commit-store.d.ts +246 -0
- package/dist/storage/commit-store.js +1339 -0
- package/dist/storage/commit-store.js.map +1 -0
- package/dist/storage/layout.d.ts +16 -0
- package/dist/storage/layout.js +403 -0
- package/dist/storage/layout.js.map +1 -0
- package/dist/storage/recovery.d.ts +99 -0
- package/dist/storage/recovery.js +253 -0
- package/dist/storage/recovery.js.map +1 -0
- package/dist/storage/retention.d.ts +163 -0
- package/dist/storage/retention.js +465 -0
- package/dist/storage/retention.js.map +1 -0
- package/dist/storage/root-coordinator.d.ts +7 -0
- package/dist/storage/root-coordinator.js +27 -0
- package/dist/storage/root-coordinator.js.map +1 -0
- package/dist/storage/session-store.d.ts +2 -0
- package/dist/storage/session-store.js +7 -0
- package/dist/storage/session-store.js.map +1 -0
- package/dist/storage/tar-session-store.d.ts +116 -0
- package/dist/storage/tar-session-store.js +816 -0
- package/dist/storage/tar-session-store.js.map +1 -0
- package/dist/storage/types.d.ts +62 -0
- package/dist/storage/types.js +3 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/tar-protocol/controls.d.ts +48 -0
- package/dist/tar-protocol/controls.js +185 -0
- package/dist/tar-protocol/controls.js.map +1 -0
- package/dist/tar-protocol/direct-wire.d.ts +43 -0
- package/dist/tar-protocol/direct-wire.js +194 -0
- package/dist/tar-protocol/direct-wire.js.map +1 -0
- package/dist/tar-protocol/extract.d.ts +18 -0
- package/dist/tar-protocol/extract.js +124 -0
- package/dist/tar-protocol/extract.js.map +1 -0
- package/dist/tar-protocol/hash.d.ts +10 -0
- package/dist/tar-protocol/hash.js +44 -0
- package/dist/tar-protocol/hash.js.map +1 -0
- package/dist/tar-protocol/lifecycle.d.ts +13 -0
- package/dist/tar-protocol/lifecycle.js +90 -0
- package/dist/tar-protocol/lifecycle.js.map +1 -0
- package/dist/tar-protocol/manifest.d.ts +46 -0
- package/dist/tar-protocol/manifest.js +287 -0
- package/dist/tar-protocol/manifest.js.map +1 -0
- package/dist/tar-protocol/ustar.d.ts +22 -0
- package/dist/tar-protocol/ustar.js +87 -0
- package/dist/tar-protocol/ustar.js.map +1 -0
- package/dist/types.d.ts +58 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/validation.d.ts +4 -0
- package/dist/validation.js +26 -0
- package/dist/validation.js.map +1 -0
- package/package.json +101 -1
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MAX_SESSION_METADATA_BYTES = exports.MetadataFormatError = exports.ATOMIC_WRITE_PHASE = void 0;
|
|
7
|
+
exports.atomicWriteRenamed = atomicWriteRenamed;
|
|
8
|
+
exports.writeAtomic = writeAtomic;
|
|
9
|
+
exports.readJson = readJson;
|
|
10
|
+
const b4a_1 = __importDefault(require("b4a"));
|
|
11
|
+
const error_code_js_1 = require("../error-code.js");
|
|
12
|
+
const _fs_1 = __importDefault(require("#fs"));
|
|
13
|
+
const _path_1 = __importDefault(require("#path"));
|
|
14
|
+
const sodium_native_1 = __importDefault(require("sodium-native"));
|
|
15
|
+
const errors_js_1 = require("../errors.js");
|
|
16
|
+
const layout_js_1 = require("./layout.js");
|
|
17
|
+
// Bounds untrusted on-disk metadata before allocation.
|
|
18
|
+
const MAX_SESSION_METADATA_BYTES = 32 * 1024 * 1024;
|
|
19
|
+
exports.MAX_SESSION_METADATA_BYTES = MAX_SESSION_METADATA_BYTES;
|
|
20
|
+
exports.ATOMIC_WRITE_PHASE = Object.freeze({
|
|
21
|
+
BEFORE_RENAME: 'before-rename',
|
|
22
|
+
AFTER_RENAME: 'after-rename'
|
|
23
|
+
});
|
|
24
|
+
class MetadataFormatError extends errors_js_1.SwarmDeployError {
|
|
25
|
+
metadataFormat;
|
|
26
|
+
constructor(message, cause = null) {
|
|
27
|
+
super(errors_js_1.ERRORS.PROTOCOL_INVALID, message, cause);
|
|
28
|
+
this.metadataFormat = true;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.MetadataFormatError = MetadataFormatError;
|
|
32
|
+
function storageError(message, cause = null) {
|
|
33
|
+
return new errors_js_1.SwarmDeployError(errors_js_1.ERRORS.PROTOCOL_INVALID, message, cause);
|
|
34
|
+
}
|
|
35
|
+
function markAtomicWriteError(error, phase) {
|
|
36
|
+
const marked = error instanceof Error ? error : new Error(String(error));
|
|
37
|
+
marked.atomicWritePhase = phase;
|
|
38
|
+
return marked;
|
|
39
|
+
}
|
|
40
|
+
function atomicWriteRenamed(error) {
|
|
41
|
+
return (typeof error === 'object' &&
|
|
42
|
+
error !== null &&
|
|
43
|
+
'atomicWritePhase' in error &&
|
|
44
|
+
error.atomicWritePhase === exports.ATOMIC_WRITE_PHASE.AFTER_RENAME);
|
|
45
|
+
}
|
|
46
|
+
function randomSuffix() {
|
|
47
|
+
const bytes = b4a_1.default.allocUnsafe(16);
|
|
48
|
+
sodium_native_1.default.randombytes_buf(bytes);
|
|
49
|
+
return b4a_1.default.toString(bytes, 'hex');
|
|
50
|
+
}
|
|
51
|
+
async function assertRegularOrAbsent(filePath, storage) {
|
|
52
|
+
try {
|
|
53
|
+
const stat = await storage.lstat(filePath);
|
|
54
|
+
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
55
|
+
throw storageError(`Unsafe metadata file: ${filePath}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if ((0, error_code_js_1.errorCode)(error) === 'ENOENT')
|
|
60
|
+
return;
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async function writeAll(handle, bytes) {
|
|
65
|
+
let offset = 0;
|
|
66
|
+
while (offset < bytes.byteLength) {
|
|
67
|
+
const written = await handle.write(bytes, offset, bytes.byteLength - offset, offset);
|
|
68
|
+
const count = typeof written === 'number' ? written : written.bytesWritten;
|
|
69
|
+
if (!Number.isSafeInteger(count) || count <= 0) {
|
|
70
|
+
throw storageError('Unable to write atomic metadata');
|
|
71
|
+
}
|
|
72
|
+
offset += count;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async function readAll(handle, size) {
|
|
76
|
+
const bytes = b4a_1.default.alloc(size);
|
|
77
|
+
let offset = 0;
|
|
78
|
+
while (offset < size) {
|
|
79
|
+
const read = await handle.read(bytes, offset, size - offset, offset);
|
|
80
|
+
const count = typeof read === 'number' ? read : read.bytesRead;
|
|
81
|
+
if (!Number.isSafeInteger(count) || count <= 0) {
|
|
82
|
+
throw storageError('Truncated metadata file');
|
|
83
|
+
}
|
|
84
|
+
offset += count;
|
|
85
|
+
}
|
|
86
|
+
return bytes;
|
|
87
|
+
}
|
|
88
|
+
async function syncDirectory(directory, storage) {
|
|
89
|
+
const handle = await storage.open(directory, 'r');
|
|
90
|
+
try {
|
|
91
|
+
await handle.sync();
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
await handle.close();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async function writeAtomic(filePath, bytes, storage = _fs_1.default.promises) {
|
|
98
|
+
if (!(b4a_1.default.isBuffer(bytes) || bytes instanceof Uint8Array)) {
|
|
99
|
+
throw storageError('Atomic metadata must be bytes');
|
|
100
|
+
}
|
|
101
|
+
const directory = _path_1.default.dirname(filePath);
|
|
102
|
+
const temporary = _path_1.default.join(directory, `.${_path_1.default.basename(filePath)}.${randomSuffix()}.tmp`);
|
|
103
|
+
let renamed = false;
|
|
104
|
+
try {
|
|
105
|
+
await (0, layout_js_1.withSafeDirectoryIdentity)(directory, storage, () => assertRegularOrAbsent(filePath, storage));
|
|
106
|
+
await (0, layout_js_1.withSafeDirectoryIdentity)(directory, storage, async () => {
|
|
107
|
+
const handle = await storage.open(temporary, 'wx', 0o600);
|
|
108
|
+
try {
|
|
109
|
+
await writeAll(handle, bytes);
|
|
110
|
+
await handle.sync();
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
await handle.close();
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
await (0, layout_js_1.withSafeDirectoryIdentity)(directory, storage, () => assertRegularOrAbsent(filePath, storage));
|
|
117
|
+
await (0, layout_js_1.withSafeDirectoryIdentity)(directory, storage, async () => {
|
|
118
|
+
await storage.rename(temporary, filePath);
|
|
119
|
+
renamed = true;
|
|
120
|
+
});
|
|
121
|
+
await (0, layout_js_1.withSafeDirectoryIdentity)(directory, storage, () => syncDirectory(directory, storage));
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
if (!renamed) {
|
|
125
|
+
await (0, layout_js_1.withSafeDirectoryIdentity)(directory, storage, () => storage.unlink(temporary)).catch(() => { });
|
|
126
|
+
}
|
|
127
|
+
throw markAtomicWriteError(error, renamed ? exports.ATOMIC_WRITE_PHASE.AFTER_RENAME : exports.ATOMIC_WRITE_PHASE.BEFORE_RENAME);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function readJson(filePath, storage = _fs_1.default.promises, maxBytes = MAX_SESSION_METADATA_BYTES) {
|
|
131
|
+
try {
|
|
132
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < 0) {
|
|
133
|
+
return Promise.reject(storageError('Invalid metadata size limit'));
|
|
134
|
+
}
|
|
135
|
+
const directory = _path_1.default.dirname(filePath);
|
|
136
|
+
return (0, layout_js_1.withSafeDirectoryIdentity)(directory, storage, async () => {
|
|
137
|
+
let handle = null;
|
|
138
|
+
try {
|
|
139
|
+
handle = await (0, layout_js_1.openSafeRegularFile)(filePath, 'read', storage);
|
|
140
|
+
const stat = await handle.stat();
|
|
141
|
+
if (!Number.isSafeInteger(stat.size) || stat.size < 0 || stat.size > maxBytes) {
|
|
142
|
+
throw storageError(`Metadata file exceeds ${maxBytes} byte limit`);
|
|
143
|
+
}
|
|
144
|
+
const bytes = await readAll(handle, stat.size);
|
|
145
|
+
let parsed;
|
|
146
|
+
try {
|
|
147
|
+
parsed = JSON.parse(b4a_1.default.toString(bytes, 'utf8'));
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
throw new MetadataFormatError(`Malformed metadata file: ${filePath}`, error);
|
|
151
|
+
}
|
|
152
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
153
|
+
throw new MetadataFormatError(`Malformed metadata file: ${filePath}`);
|
|
154
|
+
}
|
|
155
|
+
return parsed;
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
if (error instanceof errors_js_1.SwarmDeployError || error instanceof MetadataFormatError)
|
|
159
|
+
throw error;
|
|
160
|
+
throw error;
|
|
161
|
+
}
|
|
162
|
+
finally {
|
|
163
|
+
if (handle)
|
|
164
|
+
await handle.close();
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
return Promise.reject(error);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=atomic-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atomic-file.js","sourceRoot":"","sources":["../../src/storage/atomic-file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { StorageAdapter, StorageLayout, StorageStat } from './types.js';
|
|
2
|
+
declare const COMMIT_VERSION = 1;
|
|
3
|
+
declare const REPLACEMENT_COMMIT_VERSION = 2;
|
|
4
|
+
declare const JOURNAL_VERSION = 1;
|
|
5
|
+
declare const REPLACEMENT_JOURNAL_VERSION = 2;
|
|
6
|
+
declare const MAX_COMMIT_METADATA_BYTES: number;
|
|
7
|
+
/** Ordered v2 transaction boundaries; each one is durable before the next. */
|
|
8
|
+
export declare const REPLACEMENT_PHASES: readonly ['journaled', 'deduped', 'history-linked', 'publication-linked', 'final-renamed', 'current-sidecar', 'history-sidecar', 'cleanup'];
|
|
9
|
+
export type ReplacementPhase = (typeof REPLACEMENT_PHASES)[number];
|
|
10
|
+
export declare class CorruptJournalError extends Error {
|
|
11
|
+
cause: unknown | null;
|
|
12
|
+
constructor(message: string, cause?: unknown | null);
|
|
13
|
+
}
|
|
14
|
+
export declare function isHex(value: unknown): value is string;
|
|
15
|
+
export declare function fileIdentity(stat: StorageStat): {
|
|
16
|
+
dev: string;
|
|
17
|
+
ino: string;
|
|
18
|
+
};
|
|
19
|
+
export declare function identitiesEqual(left: {
|
|
20
|
+
dev: string;
|
|
21
|
+
ino: string;
|
|
22
|
+
}, right: {
|
|
23
|
+
dev: string;
|
|
24
|
+
ino: string;
|
|
25
|
+
}): boolean;
|
|
26
|
+
/** The mutable name, transfer, and history path one replacement superseded. */
|
|
27
|
+
export interface CommitReplacement {
|
|
28
|
+
name: string;
|
|
29
|
+
transferId: string;
|
|
30
|
+
historyName: string;
|
|
31
|
+
}
|
|
32
|
+
export interface CommitRecord {
|
|
33
|
+
version: number;
|
|
34
|
+
name: string;
|
|
35
|
+
size: number;
|
|
36
|
+
sha256: string;
|
|
37
|
+
committedAt: number;
|
|
38
|
+
uploaderFingerprint: string;
|
|
39
|
+
transferId: string;
|
|
40
|
+
replaces?: CommitReplacement;
|
|
41
|
+
}
|
|
42
|
+
/** Validates in place so unknown persisted fields survive a read/write round-trip. */
|
|
43
|
+
export declare function assertCommitRecord(record: unknown): CommitRecord;
|
|
44
|
+
export interface FileIdentity {
|
|
45
|
+
dev: string;
|
|
46
|
+
ino: string;
|
|
47
|
+
}
|
|
48
|
+
export interface CommitJournal {
|
|
49
|
+
version: 1;
|
|
50
|
+
record: CommitRecord;
|
|
51
|
+
attemptId: string;
|
|
52
|
+
sourceStagingIdentity: FileIdentity;
|
|
53
|
+
state: 'committing' | 'aborting';
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The v2 transaction. It names the mutable final, the pinned old record and
|
|
57
|
+
* inode, the destination history path, the private publication, every owned
|
|
58
|
+
* inode identity, and the phase the attempt reached.
|
|
59
|
+
*/
|
|
60
|
+
export interface ReplacementJournal {
|
|
61
|
+
version: 2;
|
|
62
|
+
intent: 'replace';
|
|
63
|
+
state: 'committing' | 'aborting';
|
|
64
|
+
phase: ReplacementPhase;
|
|
65
|
+
transferId: string;
|
|
66
|
+
attemptId: string;
|
|
67
|
+
name: string;
|
|
68
|
+
historyName: string;
|
|
69
|
+
publicationName: string;
|
|
70
|
+
sourceStagingIdentity: FileIdentity;
|
|
71
|
+
finalIdentity: FileIdentity;
|
|
72
|
+
historyIdentity: FileIdentity;
|
|
73
|
+
publicationIdentity: FileIdentity;
|
|
74
|
+
dedupHistoryName: string | null;
|
|
75
|
+
oldRecord: CommitRecord;
|
|
76
|
+
record: CommitRecord;
|
|
77
|
+
}
|
|
78
|
+
export type AnyCommitJournal = CommitJournal | ReplacementJournal;
|
|
79
|
+
export declare function isReplacementJournal(journal: AnyCommitJournal | null): journal is ReplacementJournal;
|
|
80
|
+
/** The exact durable shape of a journal, for creation and phase transitions. */
|
|
81
|
+
export declare function serializeJournal(journal: AnyCommitJournal): Record<string, unknown>;
|
|
82
|
+
export declare function readCommitJournal(id: string, layout: StorageLayout, storage: StorageAdapter): Promise<AnyCommitJournal | null>;
|
|
83
|
+
export { COMMIT_VERSION, REPLACEMENT_COMMIT_VERSION, JOURNAL_VERSION, REPLACEMENT_JOURNAL_VERSION, MAX_COMMIT_METADATA_BYTES };
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MAX_COMMIT_METADATA_BYTES = exports.REPLACEMENT_JOURNAL_VERSION = exports.JOURNAL_VERSION = exports.REPLACEMENT_COMMIT_VERSION = exports.COMMIT_VERSION = exports.CorruptJournalError = exports.REPLACEMENT_PHASES = void 0;
|
|
7
|
+
exports.isHex = isHex;
|
|
8
|
+
exports.fileIdentity = fileIdentity;
|
|
9
|
+
exports.identitiesEqual = identitiesEqual;
|
|
10
|
+
exports.assertCommitRecord = assertCommitRecord;
|
|
11
|
+
exports.isReplacementJournal = isReplacementJournal;
|
|
12
|
+
exports.serializeJournal = serializeJournal;
|
|
13
|
+
exports.readCommitJournal = readCommitJournal;
|
|
14
|
+
const b4a_1 = __importDefault(require("b4a"));
|
|
15
|
+
const error_code_js_1 = require("../error-code.js");
|
|
16
|
+
const _path_1 = __importDefault(require("#path"));
|
|
17
|
+
const sodium_native_1 = __importDefault(require("sodium-native"));
|
|
18
|
+
const errors_js_1 = require("../errors.js");
|
|
19
|
+
const files_js_1 = require("../files.js");
|
|
20
|
+
const validation_js_1 = require("../validation.js");
|
|
21
|
+
const atomic_file_js_1 = require("./atomic-file.js");
|
|
22
|
+
const layout_js_1 = require("./layout.js");
|
|
23
|
+
const COMMIT_VERSION = 1;
|
|
24
|
+
exports.COMMIT_VERSION = COMMIT_VERSION;
|
|
25
|
+
const REPLACEMENT_COMMIT_VERSION = 2;
|
|
26
|
+
exports.REPLACEMENT_COMMIT_VERSION = REPLACEMENT_COMMIT_VERSION;
|
|
27
|
+
const JOURNAL_VERSION = 1;
|
|
28
|
+
exports.JOURNAL_VERSION = JOURNAL_VERSION;
|
|
29
|
+
const REPLACEMENT_JOURNAL_VERSION = 2;
|
|
30
|
+
exports.REPLACEMENT_JOURNAL_VERSION = REPLACEMENT_JOURNAL_VERSION;
|
|
31
|
+
const MAX_COMMIT_METADATA_BYTES = 16 * 1024;
|
|
32
|
+
exports.MAX_COMMIT_METADATA_BYTES = MAX_COMMIT_METADATA_BYTES;
|
|
33
|
+
function sameTransferId(left, right) {
|
|
34
|
+
return (isHex(left) &&
|
|
35
|
+
isHex(right) &&
|
|
36
|
+
sodium_native_1.default.sodium_memcmp(b4a_1.default.from(left, 'hex'), b4a_1.default.from(right, 'hex')));
|
|
37
|
+
}
|
|
38
|
+
/** Ordered v2 transaction boundaries; each one is durable before the next. */
|
|
39
|
+
exports.REPLACEMENT_PHASES = [
|
|
40
|
+
'journaled',
|
|
41
|
+
'deduped',
|
|
42
|
+
'history-linked',
|
|
43
|
+
'publication-linked',
|
|
44
|
+
'final-renamed',
|
|
45
|
+
'current-sidecar',
|
|
46
|
+
'history-sidecar',
|
|
47
|
+
'cleanup'
|
|
48
|
+
];
|
|
49
|
+
function isReplacementPhase(value) {
|
|
50
|
+
return typeof value === 'string' && exports.REPLACEMENT_PHASES.includes(value);
|
|
51
|
+
}
|
|
52
|
+
class CorruptJournalError extends Error {
|
|
53
|
+
cause;
|
|
54
|
+
constructor(message, cause = null) {
|
|
55
|
+
super(message);
|
|
56
|
+
this.name = 'CorruptJournalError';
|
|
57
|
+
this.cause = cause;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.CorruptJournalError = CorruptJournalError;
|
|
61
|
+
function storageError(message, cause = null) {
|
|
62
|
+
return new errors_js_1.SwarmDeployError(errors_js_1.ERRORS.PROTOCOL_INVALID, message, cause);
|
|
63
|
+
}
|
|
64
|
+
function isHex(value) {
|
|
65
|
+
return typeof value === 'string' && /^[0-9a-f]{64}$/.test(value);
|
|
66
|
+
}
|
|
67
|
+
function identityValue(value) {
|
|
68
|
+
if ((typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0) &&
|
|
69
|
+
(typeof value !== 'bigint' || value < 0n)) {
|
|
70
|
+
throw storageError('Storage file identity is unavailable');
|
|
71
|
+
}
|
|
72
|
+
return String(value);
|
|
73
|
+
}
|
|
74
|
+
function fileIdentity(stat) {
|
|
75
|
+
return { dev: identityValue(stat.dev), ino: identityValue(stat.ino) };
|
|
76
|
+
}
|
|
77
|
+
function identitiesEqual(left, right) {
|
|
78
|
+
return left.dev === right.dev && left.ino === right.ino;
|
|
79
|
+
}
|
|
80
|
+
function isRecordLike(value) {
|
|
81
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
82
|
+
}
|
|
83
|
+
function assertReplacement(value) {
|
|
84
|
+
if (!isRecordLike(value))
|
|
85
|
+
throw storageError('Invalid commit replacement metadata');
|
|
86
|
+
if (typeof value.name !== 'string' || (0, files_js_1.isReservedHistoryName)(value.name)) {
|
|
87
|
+
throw storageError('Invalid replaced name');
|
|
88
|
+
}
|
|
89
|
+
(0, files_js_1.validateBasename)(value.name);
|
|
90
|
+
if (!isHex(value.transferId))
|
|
91
|
+
throw storageError('Invalid replaced transfer ID');
|
|
92
|
+
if (value.historyName !== (0, files_js_1.historyName)(value.transferId)) {
|
|
93
|
+
throw storageError('Invalid replacement history name');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function assertCommitRecordShape(record) {
|
|
97
|
+
if (!isRecordLike(record))
|
|
98
|
+
throw storageError('Invalid commit record');
|
|
99
|
+
const candidate = record;
|
|
100
|
+
if (candidate.version !== COMMIT_VERSION && candidate.version !== REPLACEMENT_COMMIT_VERSION) {
|
|
101
|
+
throw storageError('Invalid commit record version');
|
|
102
|
+
}
|
|
103
|
+
(0, files_js_1.validateBasename)(typeof candidate.name === 'string' ? candidate.name : '');
|
|
104
|
+
(0, validation_js_1.assertSafeUint)(candidate.size, 'commit size');
|
|
105
|
+
if (!isHex(candidate.sha256))
|
|
106
|
+
throw storageError('Invalid commit digest');
|
|
107
|
+
(0, validation_js_1.assertSafeUint)(candidate.committedAt, 'commit timestamp');
|
|
108
|
+
if (!isHex(candidate.uploaderFingerprint))
|
|
109
|
+
throw storageError('Invalid uploader fingerprint');
|
|
110
|
+
if (!isHex(candidate.transferId))
|
|
111
|
+
throw storageError('Invalid commit transfer ID');
|
|
112
|
+
if (candidate.version === REPLACEMENT_COMMIT_VERSION) {
|
|
113
|
+
assertReplacement(candidate.replaces);
|
|
114
|
+
}
|
|
115
|
+
else if (candidate.replaces !== undefined) {
|
|
116
|
+
throw storageError('Unexpected commit replacement metadata');
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/** Validates in place so unknown persisted fields survive a read/write round-trip. */
|
|
120
|
+
function assertCommitRecord(record) {
|
|
121
|
+
assertCommitRecordShape(record);
|
|
122
|
+
return record;
|
|
123
|
+
}
|
|
124
|
+
function isReplacementJournal(journal) {
|
|
125
|
+
return journal !== null && journal.version === REPLACEMENT_JOURNAL_VERSION;
|
|
126
|
+
}
|
|
127
|
+
function parseIdentity(value) {
|
|
128
|
+
if (!isRecordLike(value))
|
|
129
|
+
throw new CorruptJournalError('Invalid commit journal');
|
|
130
|
+
const { dev, ino } = value;
|
|
131
|
+
if (typeof dev !== 'string' ||
|
|
132
|
+
typeof ino !== 'string' ||
|
|
133
|
+
!/^(0|[1-9][0-9]*)$/.test(dev) ||
|
|
134
|
+
!/^(0|[1-9][0-9]*)$/.test(ino)) {
|
|
135
|
+
throw new CorruptJournalError('Invalid commit journal');
|
|
136
|
+
}
|
|
137
|
+
return { dev, ino };
|
|
138
|
+
}
|
|
139
|
+
function parseRecord(value) {
|
|
140
|
+
try {
|
|
141
|
+
return assertCommitRecord(value);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
throw new CorruptJournalError('Invalid commit journal record', error);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function parseReplacementJournal(id, journal) {
|
|
148
|
+
if (journal.intent !== 'replace' ||
|
|
149
|
+
(journal.state !== 'committing' && journal.state !== 'aborting') ||
|
|
150
|
+
!isReplacementPhase(journal.phase) ||
|
|
151
|
+
!sameTransferId(journal.transferId, id) ||
|
|
152
|
+
!isHex(journal.attemptId) ||
|
|
153
|
+
typeof journal.name !== 'string' ||
|
|
154
|
+
journal.publicationName !== `${journal.attemptId}.part`) {
|
|
155
|
+
throw new CorruptJournalError('Invalid replacement journal');
|
|
156
|
+
}
|
|
157
|
+
let name;
|
|
158
|
+
try {
|
|
159
|
+
name = (0, files_js_1.validateBasename)(journal.name);
|
|
160
|
+
if ((0, files_js_1.isReservedHistoryName)(name))
|
|
161
|
+
throw storageError('Reserved replacement name');
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
throw new CorruptJournalError('Invalid replacement journal name', error);
|
|
165
|
+
}
|
|
166
|
+
const record = parseRecord(journal.record);
|
|
167
|
+
const oldRecord = parseRecord(journal.oldRecord);
|
|
168
|
+
if (!sameTransferId(record.transferId, id)) {
|
|
169
|
+
throw new CorruptJournalError('Commit journal ID mismatch');
|
|
170
|
+
}
|
|
171
|
+
if (record.name !== name)
|
|
172
|
+
throw new CorruptJournalError('Replacement journal name mismatch');
|
|
173
|
+
if (journal.historyName !== (0, files_js_1.historyName)(oldRecord.transferId)) {
|
|
174
|
+
throw new CorruptJournalError('Invalid replacement history name');
|
|
175
|
+
}
|
|
176
|
+
if (sameTransferId(oldRecord.transferId, record.transferId)) {
|
|
177
|
+
throw new CorruptJournalError('Replacement journal replaces its own transfer');
|
|
178
|
+
}
|
|
179
|
+
if (journal.dedupHistoryName !== null &&
|
|
180
|
+
journal.dedupHistoryName !== (0, files_js_1.historyName)(record.transferId)) {
|
|
181
|
+
throw new CorruptJournalError('Invalid replacement dedup name');
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
version: REPLACEMENT_JOURNAL_VERSION,
|
|
185
|
+
intent: 'replace',
|
|
186
|
+
state: journal.state,
|
|
187
|
+
phase: journal.phase,
|
|
188
|
+
transferId: id,
|
|
189
|
+
attemptId: journal.attemptId,
|
|
190
|
+
name,
|
|
191
|
+
historyName: journal.historyName,
|
|
192
|
+
publicationName: journal.publicationName,
|
|
193
|
+
sourceStagingIdentity: parseIdentity(journal.sourceStagingIdentity),
|
|
194
|
+
finalIdentity: parseIdentity(journal.finalIdentity),
|
|
195
|
+
historyIdentity: parseIdentity(journal.historyIdentity),
|
|
196
|
+
publicationIdentity: parseIdentity(journal.publicationIdentity),
|
|
197
|
+
dedupHistoryName: journal.dedupHistoryName,
|
|
198
|
+
oldRecord,
|
|
199
|
+
record
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
/** The exact durable shape of a journal, for creation and phase transitions. */
|
|
203
|
+
function serializeJournal(journal) {
|
|
204
|
+
if (journal.version === REPLACEMENT_JOURNAL_VERSION) {
|
|
205
|
+
return {
|
|
206
|
+
version: REPLACEMENT_JOURNAL_VERSION,
|
|
207
|
+
intent: journal.intent,
|
|
208
|
+
state: journal.state,
|
|
209
|
+
phase: journal.phase,
|
|
210
|
+
transferId: journal.transferId,
|
|
211
|
+
attemptId: journal.attemptId,
|
|
212
|
+
name: journal.name,
|
|
213
|
+
historyName: journal.historyName,
|
|
214
|
+
publicationName: journal.publicationName,
|
|
215
|
+
sourceStagingIdentity: journal.sourceStagingIdentity,
|
|
216
|
+
finalIdentity: journal.finalIdentity,
|
|
217
|
+
historyIdentity: journal.historyIdentity,
|
|
218
|
+
publicationIdentity: journal.publicationIdentity,
|
|
219
|
+
dedupHistoryName: journal.dedupHistoryName,
|
|
220
|
+
oldRecord: journal.oldRecord,
|
|
221
|
+
record: journal.record
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
version: JOURNAL_VERSION,
|
|
226
|
+
state: journal.state,
|
|
227
|
+
transferId: journal.record.transferId,
|
|
228
|
+
attemptId: journal.attemptId,
|
|
229
|
+
sourceStagingIdentity: journal.sourceStagingIdentity,
|
|
230
|
+
record: journal.record
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
async function readCommitJournal(id, layout, storage) {
|
|
234
|
+
if (!isHex(id))
|
|
235
|
+
throw storageError('Invalid journal ID');
|
|
236
|
+
const journalPath = _path_1.default.join(layout.journals, `${id}.json`);
|
|
237
|
+
let journal;
|
|
238
|
+
try {
|
|
239
|
+
try {
|
|
240
|
+
await (0, layout_js_1.assertSafeFile)(journalPath, storage);
|
|
241
|
+
}
|
|
242
|
+
catch (err) {
|
|
243
|
+
if ((0, error_code_js_1.isMissing)(err))
|
|
244
|
+
return null;
|
|
245
|
+
throw err;
|
|
246
|
+
}
|
|
247
|
+
journal = await (0, atomic_file_js_1.readJson)(journalPath, storage, MAX_COMMIT_METADATA_BYTES);
|
|
248
|
+
if (journal.version === REPLACEMENT_JOURNAL_VERSION) {
|
|
249
|
+
return parseReplacementJournal(id, journal);
|
|
250
|
+
}
|
|
251
|
+
if (journal.version !== JOURNAL_VERSION ||
|
|
252
|
+
(journal.state !== 'committing' && journal.state !== 'aborting') ||
|
|
253
|
+
!sameTransferId(journal.transferId, id) ||
|
|
254
|
+
!isHex(journal.attemptId)) {
|
|
255
|
+
throw new CorruptJournalError('Invalid commit journal');
|
|
256
|
+
}
|
|
257
|
+
const sourceStagingIdentity = parseIdentity(journal.sourceStagingIdentity);
|
|
258
|
+
const record = parseRecord(journal.record);
|
|
259
|
+
if (!sameTransferId(record.transferId, id)) {
|
|
260
|
+
throw new CorruptJournalError('Commit journal ID mismatch');
|
|
261
|
+
}
|
|
262
|
+
return {
|
|
263
|
+
version: JOURNAL_VERSION,
|
|
264
|
+
record,
|
|
265
|
+
attemptId: journal.attemptId,
|
|
266
|
+
sourceStagingIdentity,
|
|
267
|
+
state: journal.state
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
if (error instanceof CorruptJournalError)
|
|
272
|
+
throw error;
|
|
273
|
+
if (error instanceof atomic_file_js_1.MetadataFormatError) {
|
|
274
|
+
throw new CorruptJournalError('Malformed commit journal', error);
|
|
275
|
+
}
|
|
276
|
+
throw error;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=commit-journal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commit-journal.js","sourceRoot":"","sources":["../../src/storage/commit-journal.ts"],"names":[],"mappings":"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"}
|