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.
Files changed (115) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/LICENSE.md +201 -0
  3. package/NOTICE.md +13 -0
  4. package/README.md +652 -0
  5. package/RELEASING.md +71 -0
  6. package/SECURITY.md +41 -0
  7. package/dist/abort.d.ts +16 -0
  8. package/dist/abort.js +52 -0
  9. package/dist/abort.js.map +1 -0
  10. package/dist/allowlist.d.ts +2 -0
  11. package/dist/allowlist.js +21 -0
  12. package/dist/allowlist.js.map +1 -0
  13. package/dist/bin/swarm-deploy.d.ts +2 -0
  14. package/dist/bin/swarm-deploy.js +41 -0
  15. package/dist/bin/swarm-deploy.js.map +1 -0
  16. package/dist/cli.d.ts +25 -0
  17. package/dist/cli.js +694 -0
  18. package/dist/cli.js.map +1 -0
  19. package/dist/client.d.ts +121 -0
  20. package/dist/client.js +285 -0
  21. package/dist/client.js.map +1 -0
  22. package/dist/direct-dht.d.ts +81 -0
  23. package/dist/direct-dht.js +254 -0
  24. package/dist/direct-dht.js.map +1 -0
  25. package/dist/error-code.d.ts +15 -0
  26. package/dist/error-code.js +30 -0
  27. package/dist/error-code.js.map +1 -0
  28. package/dist/errors.d.ts +27 -0
  29. package/dist/errors.js +33 -0
  30. package/dist/errors.js.map +1 -0
  31. package/dist/events-node.d.ts +2 -0
  32. package/dist/events-node.js +7 -0
  33. package/dist/events-node.js.map +1 -0
  34. package/dist/files.d.ts +47 -0
  35. package/dist/files.js +150 -0
  36. package/dist/files.js.map +1 -0
  37. package/dist/fs-node.d.ts +2 -0
  38. package/dist/fs-node.js +7 -0
  39. package/dist/fs-node.js.map +1 -0
  40. package/dist/identity.d.ts +7 -0
  41. package/dist/identity.js +50 -0
  42. package/dist/identity.js.map +1 -0
  43. package/dist/index.d.ts +8 -0
  44. package/dist/index.js +19 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/os-node.d.ts +2 -0
  47. package/dist/os-node.js +7 -0
  48. package/dist/os-node.js.map +1 -0
  49. package/dist/path-node.d.ts +2 -0
  50. package/dist/path-node.js +7 -0
  51. package/dist/path-node.js.map +1 -0
  52. package/dist/process-node.d.ts +2 -0
  53. package/dist/process-node.js +7 -0
  54. package/dist/process-node.js.map +1 -0
  55. package/dist/server.d.ts +153 -0
  56. package/dist/server.js +576 -0
  57. package/dist/server.js.map +1 -0
  58. package/dist/storage/atomic-file.d.ts +15 -0
  59. package/dist/storage/atomic-file.js +172 -0
  60. package/dist/storage/atomic-file.js.map +1 -0
  61. package/dist/storage/commit-journal.d.ts +83 -0
  62. package/dist/storage/commit-journal.js +279 -0
  63. package/dist/storage/commit-journal.js.map +1 -0
  64. package/dist/storage/commit-store.d.ts +246 -0
  65. package/dist/storage/commit-store.js +1339 -0
  66. package/dist/storage/commit-store.js.map +1 -0
  67. package/dist/storage/layout.d.ts +16 -0
  68. package/dist/storage/layout.js +403 -0
  69. package/dist/storage/layout.js.map +1 -0
  70. package/dist/storage/recovery.d.ts +99 -0
  71. package/dist/storage/recovery.js +253 -0
  72. package/dist/storage/recovery.js.map +1 -0
  73. package/dist/storage/retention.d.ts +163 -0
  74. package/dist/storage/retention.js +465 -0
  75. package/dist/storage/retention.js.map +1 -0
  76. package/dist/storage/root-coordinator.d.ts +7 -0
  77. package/dist/storage/root-coordinator.js +27 -0
  78. package/dist/storage/root-coordinator.js.map +1 -0
  79. package/dist/storage/session-store.d.ts +2 -0
  80. package/dist/storage/session-store.js +7 -0
  81. package/dist/storage/session-store.js.map +1 -0
  82. package/dist/storage/tar-session-store.d.ts +116 -0
  83. package/dist/storage/tar-session-store.js +816 -0
  84. package/dist/storage/tar-session-store.js.map +1 -0
  85. package/dist/storage/types.d.ts +62 -0
  86. package/dist/storage/types.js +3 -0
  87. package/dist/storage/types.js.map +1 -0
  88. package/dist/tar-protocol/controls.d.ts +48 -0
  89. package/dist/tar-protocol/controls.js +185 -0
  90. package/dist/tar-protocol/controls.js.map +1 -0
  91. package/dist/tar-protocol/direct-wire.d.ts +43 -0
  92. package/dist/tar-protocol/direct-wire.js +194 -0
  93. package/dist/tar-protocol/direct-wire.js.map +1 -0
  94. package/dist/tar-protocol/extract.d.ts +18 -0
  95. package/dist/tar-protocol/extract.js +124 -0
  96. package/dist/tar-protocol/extract.js.map +1 -0
  97. package/dist/tar-protocol/hash.d.ts +10 -0
  98. package/dist/tar-protocol/hash.js +44 -0
  99. package/dist/tar-protocol/hash.js.map +1 -0
  100. package/dist/tar-protocol/lifecycle.d.ts +13 -0
  101. package/dist/tar-protocol/lifecycle.js +90 -0
  102. package/dist/tar-protocol/lifecycle.js.map +1 -0
  103. package/dist/tar-protocol/manifest.d.ts +46 -0
  104. package/dist/tar-protocol/manifest.js +287 -0
  105. package/dist/tar-protocol/manifest.js.map +1 -0
  106. package/dist/tar-protocol/ustar.d.ts +22 -0
  107. package/dist/tar-protocol/ustar.js +87 -0
  108. package/dist/tar-protocol/ustar.js.map +1 -0
  109. package/dist/types.d.ts +58 -0
  110. package/dist/types.js +3 -0
  111. package/dist/types.js.map +1 -0
  112. package/dist/validation.d.ts +4 -0
  113. package/dist/validation.js +26 -0
  114. package/dist/validation.js.map +1 -0
  115. package/package.json +101 -1
@@ -0,0 +1,246 @@
1
+ import { CorruptJournalError, COMMIT_VERSION, MAX_COMMIT_METADATA_BYTES } from './commit-journal.js';
2
+ import type { AnyCommitJournal, CommitJournal, CommitRecord, FileIdentity, ReplacementJournal, ReplacementPhase } from './commit-journal.js';
3
+ import type { StorageAdapter, StorageLayout, StorageStat } from './types.js';
4
+ interface AbortSignalLike {
5
+ aborted: boolean;
6
+ }
7
+ interface CommitSession {
8
+ id: string;
9
+ transferId: Uint8Array;
10
+ ownerKey: Uint8Array;
11
+ name: string;
12
+ size: number;
13
+ digest: Uint8Array;
14
+ /** Direct-TAR sessions carry these immutable archive fields. */
15
+ tarSize: number;
16
+ tarDigest: Uint8Array;
17
+ state: string;
18
+ }
19
+ interface CommitOffer {
20
+ name: string;
21
+ size: number;
22
+ digest: Uint8Array;
23
+ transferId: Uint8Array;
24
+ }
25
+ interface RetentionManager {
26
+ run(options?: {
27
+ trigger?: string;
28
+ }): Promise<unknown>;
29
+ afterCommit(): Promise<unknown>;
30
+ _runUnlocked(options: {
31
+ incomingBytes: number;
32
+ trigger: 'commit';
33
+ }): Promise<unknown>;
34
+ _afterCommitUnlocked(): Promise<unknown>;
35
+ }
36
+ interface SessionStore {
37
+ readVerified(transferId: Uint8Array): Promise<CommitSession>;
38
+ sessions?: Map<string, CommitSession>;
39
+ }
40
+ interface Logger {
41
+ warn?: (message: string, details: Record<string, unknown>) => void;
42
+ }
43
+ interface CommitStoreOptions {
44
+ layout: StorageLayout;
45
+ clock?: {
46
+ now(): number;
47
+ };
48
+ storage?: StorageAdapter;
49
+ logger?: Logger | null;
50
+ }
51
+ interface ReplacePolicy {
52
+ replaceNames?: Iterable<string>;
53
+ }
54
+ /** The visible state of one top-level path, without following symlinks. */
55
+ interface RootPathState {
56
+ present: boolean;
57
+ /** Set only for a regular file; an unmanaged non-regular path leaves it null. */
58
+ stat: StorageStat | null;
59
+ }
60
+ type ReplacementPlan = {
61
+ mode: 'create';
62
+ } | {
63
+ mode: 'idempotent';
64
+ record: CommitRecord;
65
+ } | {
66
+ mode: 'replace';
67
+ oldRecord: CommitRecord;
68
+ finalIdentity: FileIdentity;
69
+ };
70
+ declare class CommitStore {
71
+ layout: StorageLayout;
72
+ clock: {
73
+ now(): number;
74
+ };
75
+ storage: StorageAdapter;
76
+ logger: Logger | null;
77
+ journalAttempts: Map<string, string>;
78
+ constructor({ layout, clock, storage, logger }: CommitStoreOptions);
79
+ _stagingPath(id: string): string;
80
+ _tarStagingPath(id: string): string;
81
+ _sessionPath(id: string): string;
82
+ _journalPath(id: string): string;
83
+ _recordPath(id: string): string;
84
+ _finalPath(name: string): string;
85
+ _publicationPath(name: string): string;
86
+ _assertLayout(): Promise<void>;
87
+ /** Inspects one top-level path without following or trusting symlinks. */
88
+ _rootPathState(name: string): Promise<RootPathState>;
89
+ _syncRoot(): Promise<void>;
90
+ _safeFileOrAbsent(filePath: string, directory: string): Promise<StorageStat | null>;
91
+ _readRecordOrAbsent(recordPath: string): Promise<CommitRecord | null>;
92
+ _writeRecord(record: CommitRecord): Promise<boolean>;
93
+ /** Persists a sidecar transition over its own previous durable content. */
94
+ _rewriteRecord(record: CommitRecord): Promise<void>;
95
+ _removeFile(filePath: string, directory: string): Promise<boolean>;
96
+ _removeManagedFinalOrAbsent(record: CommitRecord): Promise<{
97
+ removed: boolean;
98
+ preservedPath: boolean;
99
+ }>;
100
+ _linkJournal(id: string, journal: AnyCommitJournal, attempt: string): Promise<void>;
101
+ _writeJournal(record: CommitRecord, sourceStagingIdentity: FileIdentity): Promise<string>;
102
+ /** A replacement always starts a fresh attempt; leftovers belong to recovery. */
103
+ _writeReplacementJournal(journal: ReplacementJournal): Promise<void>;
104
+ /**
105
+ * Records the boundary an attempt has already passed. The observable
106
+ * filesystem state stays authoritative during recovery; the phase is the
107
+ * durable intent trail the journal must carry.
108
+ */
109
+ _setReplacementPhase(journal: ReplacementJournal, phase: ReplacementPhase): Promise<ReplacementJournal>;
110
+ retireCorruptJournal(id: string): Promise<boolean>;
111
+ retireCorruptAttempt(id: string): Promise<{
112
+ retired: boolean;
113
+ removedStaging: boolean;
114
+ }>;
115
+ _discardJournal(id: string, expectedAttemptId: string): Promise<boolean>;
116
+ _markAttemptAborting(id: string, expectedAttemptId: string): Promise<AnyCommitJournal>;
117
+ _linkStaging(stagingPath: string, finalPath: string, expectedIdentity: FileIdentity, signal: AbortSignalLike | null): Promise<void>;
118
+ _removeAbortedPublication(record: CommitRecord, expectedIdentity: FileIdentity): Promise<void>;
119
+ _reportCleanupPending(record: CommitRecord, err: unknown): void;
120
+ _abortAttempt(record: CommitRecord, expectedIdentity: FileIdentity, attemptId: string, aborted: unknown): Promise<never>;
121
+ _removeOwnedFile(filePath: string, directory: string, identity: FileIdentity): Promise<boolean>;
122
+ _matchesRecord(filePath: string, directory: string, record: CommitRecord, syncFirst?: boolean): Promise<boolean>;
123
+ _recordFromSession(session: CommitSession): CommitRecord;
124
+ inspect(name: string, offer: CommitOffer, { replaceNames }?: ReplacePolicy): Promise<{
125
+ status: 'AVAILABLE';
126
+ } | {
127
+ status: 'ALREADY_COMMITTED';
128
+ record: CommitRecord;
129
+ } | {
130
+ status: 'REPLACEABLE';
131
+ record: CommitRecord;
132
+ } | {
133
+ status: 'FILE_EXISTS';
134
+ }>;
135
+ _inspect(name: string, offer: CommitOffer, mutable: Set<string>): Promise<{
136
+ status: 'AVAILABLE';
137
+ } | {
138
+ status: 'ALREADY_COMMITTED';
139
+ record: CommitRecord;
140
+ } | {
141
+ status: 'REPLACEABLE';
142
+ record: CommitRecord;
143
+ } | {
144
+ status: 'FILE_EXISTS';
145
+ }>;
146
+ /** The managed record whose verified content currently owns a visible name. */
147
+ _managedCurrent(name: string): Promise<{
148
+ record: CommitRecord;
149
+ identity: FileIdentity;
150
+ } | null>;
151
+ _assertSessionMatchesRecord(session: CommitSession, record: CommitRecord, message: string): void;
152
+ _validateAttemptLeftovers(id: string, journal: CommitJournal, sessionStore: SessionStore): Promise<{
153
+ sessionFile: StorageStat | null;
154
+ staging: StorageStat | null;
155
+ }>;
156
+ commit(session: CommitSession, { retentionManager, signal, replaceNames }?: {
157
+ retentionManager?: RetentionManager | null;
158
+ signal?: AbortSignalLike | null;
159
+ replaceNames?: Iterable<string>;
160
+ }): Promise<CommitRecord>;
161
+ _commit(session: CommitSession, retentionManager: RetentionManager | null, signal: AbortSignalLike | null, mutable?: Set<string>): Promise<CommitRecord>;
162
+ /**
163
+ * Classifies a configured mutable name. Only an exact managed current record
164
+ * whose verified content owns the visible path may be replaced; every other
165
+ * occupied path is an existing-name conflict.
166
+ */
167
+ _planReplacement(record: CommitRecord): Promise<ReplacementPlan>;
168
+ /**
169
+ * A repeated A→B→A sequence reuses a transfer ID that already owns a history
170
+ * artifact of identical content. The superseded duplicate is dropped inside
171
+ * the transaction so the returning content becomes the only copy.
172
+ */
173
+ _dedupHistory(record: CommitRecord): Promise<{
174
+ name: string;
175
+ identity: FileIdentity | null;
176
+ } | null>;
177
+ _replace(record: CommitRecord, stagingIdentity: FileIdentity, plan: {
178
+ oldRecord: CommitRecord;
179
+ finalIdentity: FileIdentity;
180
+ }, retentionManager: RetentionManager | null, signal: AbortSignalLike | null): Promise<CommitRecord>;
181
+ /**
182
+ * Restores the exact pinned old inode at the mutable name and removes only
183
+ * transaction-owned history, publication, and sidecar paths. A foreign
184
+ * destination is never overwritten or removed.
185
+ */
186
+ _rollbackReplacement(journal: ReplacementJournal): Promise<void>;
187
+ _readJournal(id: string): Promise<AnyCommitJournal | null>;
188
+ /** Every parsable v2 journal, used to explain transient duplicate names. */
189
+ _pendingReplacements(): Promise<ReplacementJournal[]>;
190
+ /**
191
+ * Finalizes or rolls back one v2 attempt. The durable new current sidecar is
192
+ * the linearization point: before it the old content is restored, after it
193
+ * the new content is preserved while history metadata and cleanup converge.
194
+ */
195
+ _convergeReplacement(id: string, journal: ReplacementJournal, sessionStore: SessionStore | null, { forceAbort }?: {
196
+ forceAbort?: boolean;
197
+ }): Promise<{
198
+ status: 'COMMITTED' | 'ABORTED' | 'RESUMABLE';
199
+ record: CommitRecord;
200
+ }>;
201
+ /**
202
+ * Startup recovery for one v2 attempt. Revocation of a still-live session
203
+ * aborts the attempt first so the same rollback path converges.
204
+ */
205
+ _recoverReplacementJournal(id: string, journal: ReplacementJournal, sessionStore: SessionStore, isAuthorized: ((ownerKey: Uint8Array) => boolean) | null): Promise<{
206
+ status: 'COMMITTED' | 'ABORTED' | 'RESUMABLE';
207
+ record: CommitRecord;
208
+ }>;
209
+ /** Writes or drops the history sidecar for an already linearized attempt. */
210
+ _repairHistorySidecar(journal: ReplacementJournal): Promise<void>;
211
+ _cleanupReplacementLeftovers(id: string, journal: ReplacementJournal, sessionStore: SessionStore | null): Promise<void>;
212
+ /** Proves the verified session and staging an aborted attempt must retain. */
213
+ _assertReplacementRetryable(id: string, journal: ReplacementJournal, sessionStore: SessionStore | null): Promise<boolean>;
214
+ recoverJournal(id: string, sessionStore: SessionStore, { isAuthorized }?: {
215
+ isAuthorized?: ((ownerKey: Uint8Array) => boolean) | null;
216
+ }): Promise<{
217
+ status: 'MISSING' | 'FILE_EXISTS' | 'COMMITTED' | 'ABORTED' | 'RESUMABLE';
218
+ record?: CommitRecord;
219
+ }>;
220
+ _scanRecords(): Promise<CommitRecord[]>;
221
+ scrubRecords(): Promise<{
222
+ records: CommitRecord[];
223
+ deleted: number;
224
+ }>;
225
+ _resolveRecords(records: CommitRecord[]): Promise<CommitRecord[]>;
226
+ /**
227
+ * A replacement makes the old sidecar the history record after its new
228
+ * current sidecar is durable, so one name can briefly carry two records.
229
+ * Only a journal-owned duplicate is tolerated, reported at the history name
230
+ * that recovery will persist; anything else fails closed.
231
+ */
232
+ list(): Promise<CommitRecord[]>;
233
+ /**
234
+ * Locates the durable record a caller is deleting. A pending replacement may
235
+ * still carry the mutable name on the sidecar the caller knows as history.
236
+ */
237
+ _storedRecordFor(record: CommitRecord): Promise<CommitRecord | null>;
238
+ delete(record: CommitRecord): Promise<boolean>;
239
+ purge(record: CommitRecord, { preservePath }?: {
240
+ preservePath?: boolean;
241
+ }): Promise<false | {
242
+ purged: true;
243
+ preservedPath: boolean;
244
+ }>;
245
+ }
246
+ export { CommitStore, CorruptJournalError, COMMIT_VERSION, MAX_COMMIT_METADATA_BYTES };