swarm-deploy 0.1.0 → 0.3.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 (87) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +780 -50
  3. package/RELEASING.md +2 -2
  4. package/SECURITY.md +2 -3
  5. package/dist/cli.d.ts +2 -0
  6. package/dist/cli.js +182 -25
  7. package/dist/cli.js.map +1 -1
  8. package/dist/client.d.ts +32 -27
  9. package/dist/client.js +103 -54
  10. package/dist/client.js.map +1 -1
  11. package/dist/errors.d.ts +6 -0
  12. package/dist/errors.js +6 -0
  13. package/dist/errors.js.map +1 -1
  14. package/dist/files.d.ts +13 -28
  15. package/dist/files.js +13 -78
  16. package/dist/files.js.map +1 -1
  17. package/dist/hooks-module.d.ts +9 -0
  18. package/dist/hooks-module.js +118 -0
  19. package/dist/hooks-module.js.map +1 -0
  20. package/dist/hooks.d.ts +69 -0
  21. package/dist/hooks.js +88 -0
  22. package/dist/hooks.js.map +1 -0
  23. package/dist/index.d.ts +8 -4
  24. package/dist/index.js +3 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/release.d.ts +26 -0
  27. package/dist/release.js +419 -0
  28. package/dist/release.js.map +1 -0
  29. package/dist/server.d.ts +97 -0
  30. package/dist/server.js +527 -53
  31. package/dist/server.js.map +1 -1
  32. package/dist/storage/commit-journal.d.ts +39 -2
  33. package/dist/storage/commit-journal.js +140 -2
  34. package/dist/storage/commit-journal.js.map +1 -1
  35. package/dist/storage/commit-store.d.ts +69 -8
  36. package/dist/storage/commit-store.js +374 -22
  37. package/dist/storage/commit-store.js.map +1 -1
  38. package/dist/storage/layout.js +7 -1
  39. package/dist/storage/layout.js.map +1 -1
  40. package/dist/storage/link-store.d.ts +88 -0
  41. package/dist/storage/link-store.js +448 -0
  42. package/dist/storage/link-store.js.map +1 -0
  43. package/dist/storage/recovery.d.ts +2 -1
  44. package/dist/storage/recovery.js +8 -1
  45. package/dist/storage/recovery.js.map +1 -1
  46. package/dist/storage/retention.d.ts +41 -21
  47. package/dist/storage/retention.js +162 -8
  48. package/dist/storage/retention.js.map +1 -1
  49. package/dist/storage/tar-session-store.d.ts +36 -5
  50. package/dist/storage/tar-session-store.js +283 -55
  51. package/dist/storage/tar-session-store.js.map +1 -1
  52. package/dist/storage/tree-fs.d.ts +44 -0
  53. package/dist/storage/tree-fs.js +580 -0
  54. package/dist/storage/tree-fs.js.map +1 -0
  55. package/dist/storage/tree-staging.d.ts +9 -0
  56. package/dist/storage/tree-staging.js +64 -0
  57. package/dist/storage/tree-staging.js.map +1 -0
  58. package/dist/storage/types.d.ts +15 -0
  59. package/dist/symlinks.d.ts +44 -0
  60. package/dist/symlinks.js +153 -0
  61. package/dist/symlinks.js.map +1 -0
  62. package/dist/tar-protocol/controls.d.ts +52 -0
  63. package/dist/tar-protocol/controls.js +160 -2
  64. package/dist/tar-protocol/controls.js.map +1 -1
  65. package/dist/tar-protocol/direct-wire.d.ts +8 -3
  66. package/dist/tar-protocol/direct-wire.js +14 -3
  67. package/dist/tar-protocol/direct-wire.js.map +1 -1
  68. package/dist/tar-protocol/manifest.d.ts +13 -1
  69. package/dist/tar-protocol/manifest.js +26 -1
  70. package/dist/tar-protocol/manifest.js.map +1 -1
  71. package/dist/tar-protocol/tree-extract.d.ts +37 -0
  72. package/dist/tar-protocol/tree-extract.js +240 -0
  73. package/dist/tar-protocol/tree-extract.js.map +1 -0
  74. package/dist/tar-protocol/tree-manifest.d.ts +45 -0
  75. package/dist/tar-protocol/tree-manifest.js +277 -0
  76. package/dist/tar-protocol/tree-manifest.js.map +1 -0
  77. package/dist/tar-protocol/tree-path.d.ts +15 -0
  78. package/dist/tar-protocol/tree-path.js +68 -0
  79. package/dist/tar-protocol/tree-path.js.map +1 -0
  80. package/dist/tar-protocol/tree.d.ts +68 -0
  81. package/dist/tar-protocol/tree.js +269 -0
  82. package/dist/tar-protocol/tree.js.map +1 -0
  83. package/dist/tar-protocol/ustar.d.ts +14 -0
  84. package/dist/tar-protocol/ustar.js +81 -1
  85. package/dist/tar-protocol/ustar.js.map +1 -1
  86. package/dist/types.d.ts +3 -0
  87. package/package.json +3 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,66 @@
2
2
 
3
3
  All notable changes to this package are documented here.
4
4
 
5
+ ## 0.3.0
6
+
7
+ - Add authenticated client-managed symlinks: one-argument
8
+ `--symlink <selector>` rules authorize current managed file or directory
9
+ targets, `Client.link(target, name)` and `swarm-deploy link` create or
10
+ idempotently repoint durable manual links, and `LINKED`/`UNCHANGED` results,
11
+ typed link events, stable policy/target errors, retention pinning, and v2
12
+ mode-aware ledger records preserve fail-closed managed ownership.
13
+ - **Rollback warning.** After an upgraded server creates, repairs, or repoints
14
+ any managed link, its v2 ledger record is unreadable by v0.2.0. Rollback
15
+ requires restoring the complete pre-upgrade storage backup or staying on the
16
+ upgraded server. `swarm-deploy link` also requires an upgraded server.
17
+ - **Type change.** `SymlinkRule` is now a closed union of automatic
18
+ `{ selector, name }` and manual `{ selector }` rule shapes, rather than an
19
+ extendable interface.
20
+
21
+ ## 0.2.0
22
+
23
+ - **Behavior change.** A directory upload now commits exactly one recursive managed directory artifact instead of a batch of immediate-child file uploads. `BatchUploadResult`, `BatchUploadFailure`, `SkippedUploadEntry`, `SkippedUploadReason`, and the client `skipped` event are removed, `ClientUploadResult` is now `UploadResult`, and `UploadResult` gains `kind` and, for a directory, `entryCount`. Direct file upload stays byte-compatible. Automation that relied on per-child results must now treat the directory as one artifact.
24
+ - Add recursive directory artifacts: a canonical deterministic multi-entry USTAR archive with normalized file mode `0644`, directory mode `0755`, fixed uid, gid, mtime, uname, and gname; bytewise entry ordering with parents before children; empty directories preserved; and symlinks, hardlinks, devices, sockets, FIFOs, cycles, traversal, duplicate, and case-fold-colliding paths rejected. Limits are 100 UTF-8 bytes per component, 100 UTF-8 bytes per stored TAR name, depth 32, 10,000 entries, `maxFileBytes` aggregate payload, and `maxStagingBytes` aggregate staging.
25
+ - Add directory offer metadata with `kind: 'directory'`, `entryCount`, `payloadBytes`, and a canonical `treeSha256`, and the `swarm-deploy/direct-tree/v1` transfer-ID domain. The key set is disjoint from the file record's, so an older server rejects it without mutating storage. Upgrade servers before clients.
26
+ - Add directory sessions at persisted version 4, verified into `.swarm-deploy/staging/<transfer-id>.tree/` by rebuilding and byte-comparing every canonical header and independently recomputing the tree digest. File sessions keep versions 2 and 3.
27
+ - Add directory commit records at version 3 and directory journals at version 3. A directory is published by renaming its verified staging tree under the name and root leases, with explicit recovery for crashes before the rename, after the rename, after the sidecar, and during symlink reconciliation.
28
+ - Directory artifacts are create-only. A directory offer for a configured `replaceNames` entry, a file-to-directory kind change, and a directory-to-file kind change are all rejected. Directory replacement and history are deferred because a directory cannot use the file hardlink replacement transaction safely.
29
+ - Delete a managed directory by renaming it into `.swarm-deploy/trash/<transfer-id>.tree` and then removing it recursively with `lstat`, `unlink`, and `rmdir` without following symlinks. Startup sweeps proven trash residue.
30
+ - Make storage scrubbing kind aware: scheduled and pre-commit passes validate type, sidecar, and root identity, while startup recovery recursively hashes a directory artifact and verifies its canonical tree digest. A mutated managed directory is preserved as unknown and its invalid metadata removed.
31
+ - Add server-managed symlinks: `ServerOptions.symlinks` and the repeatable two-value CLI option `--symlink <selector> <link-name>`. A selector that begins and ends with `/` is an unflagged regular expression matched against managed artifact basenames; anything else is an exact managed basename. Selection uses only validated commit records and picks the newest `committedAt`, tie-broken by transfer ID then name. A rule is dormant until its target exists and replacement history names never match.
32
+ - Persist managed-link ownership in `.swarm-deploy/links/<sha256(link-name)>.json`. A destination is replaced only when a valid record exists, the destination is a symbolic link, and `readlink()` returns the recorded or desired target. A pre-existing file, directory, unrecorded symlink, changed symlink, or foreign ownership record is unmanaged: it is never replaced, moved, or deleted, and the server fails closed. Reconciliation is level-triggered from startup, commit, already-committed retry, recovery, and retention.
33
+ - Reject an upload whose artifact name equals a configured symlink name before session admission, so a configured link never masks a managed artifact.
34
+ - Pin every selected symlink target against age, count, SemVer, and quota retention. Pinned targets still count toward the quota, and the desired-link set is recomputed under the root lease before any deletion, so a repoint always precedes the old target becoming eligible. Removing a rule removes its ownership record and visible link only while ownership is still proven.
35
+ - Add optional `StorageAdapter.symlink` and `readlink`. Configuring symlink rules requires both; the Node and Bare default adapters provide them, and a custom adapter without symlink rules stays source-compatible.
36
+ - Add `HookArtifact.kind` and optional `entryCount`, and the artifact kind to server transfer, offer, progress, and client result events. For a directory, `beforeCommit.path` is the verified `.tree` staging directory and `afterCommit.path` is the final committed directory; configured links are reconciled before `afterCommit`, so a hook observes the new link.
37
+ - Add the `LINK_CONFLICT`, `LINK_FAILED`, and `UNSUPPORTED_STORAGE` error codes. A link reconciliation failure after a durable commit behaves like other post-commit deployment failures: the artifact stays committed, the client receives a stable failure, and an already-committed retry reruns reconciliation before succeeding.
38
+ - Add the private `.swarm-deploy/links` and `.swarm-deploy/trash` directories, protected, identity-checked, and synchronized like the existing internal directories.
39
+ - Directory metadata, session version 4, commit record version 3, directory journals, and directory trash are not downgrade-compatible. Drain uploads before upgrading and do not roll back after committing a directory artifact without restoring from backup.
40
+ - The package exposes no user-facing "atomic directory" term or option; atomicity is an internal commit and recovery guarantee.
41
+ - Add server-configured artifact patterns (`artifactPatterns`, repeatable `--artifact-pattern`) with `{series}` and strict SemVer `{version}` placeholders over basenames and the immediate source parent. Configuring patterns makes matching mandatory: unmatched offers are rejected with `INVALID_FILENAME` before admission.
42
+ - Give a template without `{series}` the fixed series key `fixed-<lowercase hex SHA-256 of the template text>`. The previous key was the raw template, whose braces and slashes failed commit-record validation and made every version-only pattern fail at runtime.
43
+ - Reject an artifact pattern whose literal text still contains `{` or `}` after the exact `{series}` and `{version}` placeholders are removed.
44
+ - Add optional authenticated `sourceParent` offer metadata, sent only when it is a safe single component. Upgrade servers before clients: older servers reject the new metadata field.
45
+ - Add `ClientOptions.includeSourceParent` (default `true`) and the valueless upload CLI flag `--no-source-parent` to suppress `sourceParent` where the staging folder name is itself sensitive. An opted-out upload keeps the legacy transfer identity and is rejected by server patterns that need a parent segment.
46
+ - Persist normalized release coordinates in commit records, replacement history, journals, and recovery. Legacy records without coordinates are not count or version rotated.
47
+ - Add count rotation (`maxCount`, `--max-count`) and SemVer major/minor rotation (`maxVersions`, `versionGranularity`, `--max-versions`, `--version-granularity`) running after age and before storage-quota retention, with `countDeleted` and `versionDeleted` retention counters.
48
+ - Add `beforeCommit`, `afterCommit`, and `onFailure` server hooks (`ServerOptions.hooks` and `--hooks <module>` for `.js`, `.mjs`, and `.cjs` modules), the `HOOK_FAILED` error code, and exported hook and release types. Hooks run again on retries and must be idempotent by transfer ID; `afterCommit` can fail after the artifact is durably committed.
49
+ - Defer post-commit rotation until a configured `afterCommit` hook succeeds. The final path exists when `afterCommit` begins in the sequential server flow, but a concurrent commit's retention pass, a scheduled pass, or a manual pass can remove it while the callback runs, so hooks needing stable bytes should open or copy it promptly. The deferred pass runs before `COMMITTED` or `ALREADY_COMMITTED`, so a slow retention pass can delay the reply. Servers without `afterCommit` rotate immediately as before.
50
+ - Run the deferred post-commit retention pass from an already-committed offer only for a transfer this process committed whose `afterCommit` has not yet succeeded. Other duplicate offers still invoke `afterCommit` but start no retention pass, so they cannot force repeated full scans. The owed-transfer set is in memory only and is cleared by server close.
51
+ - Reject a `--hooks` path whose extension is not exactly `.js`, `.mjs`, or `.cjs` before the module is loaded, so an unsupported extension gives a precise startup error instead of a runtime loader message.
52
+ - **Behavior change.** Give an authenticated transfer ID a single in-flight owner. A second connection offering a transfer another connection already owns is rejected with `FILE_BUSY` during the offer phase, so staging, commit, `beforeCommit`, and `afterCommit` never run concurrently for one transfer identity. Sequential retries, resumes, and verified reconnects are unaffected, but automation that uploads one artifact from several workers at once must now treat `FILE_BUSY` as "retry once the in-flight attempt finishes". The guard is per process, bounded by the connection limit, and released when the connection ends or the server closes.
53
+ - Release the transfer guard before awaiting `onFailure`, so a slow or hung failure callback cannot reject the client's legitimate retry. `onFailure` is observational and may therefore overlap the next attempt's lifecycle hooks; each connection still reports at most once, and the serialization of `beforeCommit`/`afterCommit` per transfer is unchanged.
54
+ - Bound the owed post-commit retention set at 1024 transfers, matching the connection ceiling, evicting the oldest owed transfer first. An evicted transfer keeps its committed artifact and leaves rotation to the next startup, scheduled, or commit-triggered pass.
55
+ - Reserve the derived fixed-series namespace: a captured `{series}` of exactly `fixed-` plus 64 lowercase hex characters never matches, so an uploaded filename cannot place itself in a version-only pattern's rotation group.
56
+ - Export `fixedSeriesKey` from the root API so operators can map a series in a commit sidecar or log line back to the template that produced it.
57
+ - Retrying a failed `afterCommit` normally takes the `ALREADY_COMMITTED` path, but there is no persistent hook-pending marker: any intervening retention pass (startup after a restart, scheduled or manual cleanup, or a concurrent commit's retention) can remove an out-of-window artifact first, and the retry is then a fresh upload.
58
+ - Write a resumable session at on-disk version 3 only when it carries a `sourceParent`, and at version 2 otherwise. Both are readable. A downgrade therefore loses the resumability of parent-bearing sessions only, instead of every session written by this version; draining in-flight uploads before a rollback still avoids it.
59
+ - Never rewrite the durable release identity of a commit record. Enabling or changing `artifactPatterns` while uploads are in flight makes a retry of already-committed bytes fail closed (`FILE_EXISTS` for a create-only name, a release-identity conflict for a replaceable name retried under the same transfer ID), so drain in-flight uploads before changing patterns.
60
+ - Commit-record compatibility is asserted only in the reading direction: records without release coordinates are read and excluded from count and version rotation. Whether older code tolerates records this version writes is untested.
61
+ - Document that a hung hook callback on a fresh or resumed upload also holds an active-upload slot and its staging reservation, so enough hung callbacks exhaust upload capacity until the server closes. Bounded timeout and anti-spam controls are tracked in issue #8.
62
+ - Document that an `offer`-phase `onFailure` context is built before the transfer ID is authenticated and is delivered even when that authentication failed, so its artifact fields must not be used as audit or idempotency keys.
63
+ - Document rollout, retry, path, and compatibility semantics.
64
+
5
65
  ## 0.1.0
6
66
 
7
67
  - Initial public release.