@smthrs/journal 0.0.0-stage → 1.0.0-rc.3

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 (257) hide show
  1. package/CHANGELOG.md +149 -0
  2. package/LICENSE +21 -0
  3. package/README.md +206 -2
  4. package/dist/cjs/CallFact.d.ts +129 -0
  5. package/dist/cjs/CallFact.d.ts.map +1 -0
  6. package/dist/cjs/CallFact.js +106 -0
  7. package/dist/cjs/CallFact.js.map +7 -0
  8. package/dist/cjs/Consensus.d.ts +440 -0
  9. package/dist/cjs/Consensus.d.ts.map +1 -0
  10. package/dist/cjs/Consensus.js +251 -0
  11. package/dist/cjs/Consensus.js.map +7 -0
  12. package/dist/cjs/EngineEvent.d.ts +890 -0
  13. package/dist/cjs/EngineEvent.d.ts.map +1 -0
  14. package/dist/cjs/EngineEvent.js +383 -0
  15. package/dist/cjs/EngineEvent.js.map +7 -0
  16. package/dist/cjs/ExecutionFact.d.ts +216 -0
  17. package/dist/cjs/ExecutionFact.d.ts.map +1 -0
  18. package/dist/cjs/ExecutionFact.js +303 -0
  19. package/dist/cjs/ExecutionFact.js.map +7 -0
  20. package/dist/cjs/Journal.d.ts +617 -0
  21. package/dist/cjs/Journal.d.ts.map +1 -0
  22. package/dist/cjs/Journal.js +190 -0
  23. package/dist/cjs/Journal.js.map +7 -0
  24. package/dist/cjs/JournalEvent.d.ts +421 -0
  25. package/dist/cjs/JournalEvent.d.ts.map +1 -0
  26. package/dist/cjs/JournalEvent.js +281 -0
  27. package/dist/cjs/JournalEvent.js.map +7 -0
  28. package/dist/cjs/JournalGeneration.d.ts +34 -0
  29. package/dist/cjs/JournalGeneration.d.ts.map +1 -0
  30. package/dist/cjs/JournalGeneration.js +72 -0
  31. package/dist/cjs/JournalGeneration.js.map +7 -0
  32. package/dist/cjs/JournalMetrics.d.ts +72 -0
  33. package/dist/cjs/JournalMetrics.d.ts.map +1 -0
  34. package/dist/cjs/JournalMetrics.js +55 -0
  35. package/dist/cjs/JournalMetrics.js.map +7 -0
  36. package/dist/cjs/Migrations.d.ts +42 -0
  37. package/dist/cjs/Migrations.d.ts.map +1 -0
  38. package/dist/cjs/Migrations.js +58 -0
  39. package/dist/cjs/Migrations.js.map +7 -0
  40. package/dist/cjs/OwnerId.d.ts +40 -0
  41. package/dist/cjs/OwnerId.d.ts.map +1 -0
  42. package/dist/cjs/OwnerId.js +40 -0
  43. package/dist/cjs/OwnerId.js.map +7 -0
  44. package/dist/cjs/Projection.d.ts +29 -0
  45. package/dist/cjs/Projection.d.ts.map +1 -0
  46. package/dist/cjs/Projection.js +25 -0
  47. package/dist/cjs/Projection.js.map +7 -0
  48. package/dist/cjs/RedactedLogger.d.ts +121 -0
  49. package/dist/cjs/RedactedLogger.d.ts.map +1 -0
  50. package/dist/cjs/RedactedLogger.js +235 -0
  51. package/dist/cjs/RedactedLogger.js.map +7 -0
  52. package/dist/cjs/Redaction.d.ts +350 -0
  53. package/dist/cjs/Redaction.d.ts.map +1 -0
  54. package/dist/cjs/Redaction.js +928 -0
  55. package/dist/cjs/Redaction.js.map +7 -0
  56. package/dist/cjs/SqlConsensus.d.ts +44 -0
  57. package/dist/cjs/SqlConsensus.d.ts.map +1 -0
  58. package/dist/cjs/SqlConsensus.js +243 -0
  59. package/dist/cjs/SqlConsensus.js.map +7 -0
  60. package/dist/cjs/SqlJournal.d.ts +173 -0
  61. package/dist/cjs/SqlJournal.d.ts.map +1 -0
  62. package/dist/cjs/SqlJournal.js +1568 -0
  63. package/dist/cjs/SqlJournal.js.map +7 -0
  64. package/dist/cjs/StepFact.d.ts +66 -0
  65. package/dist/cjs/StepFact.d.ts.map +1 -0
  66. package/dist/cjs/StepFact.js +68 -0
  67. package/dist/cjs/StepFact.js.map +7 -0
  68. package/dist/cjs/index.d.ts +95 -0
  69. package/dist/cjs/index.d.ts.map +1 -0
  70. package/dist/cjs/index.js +63 -0
  71. package/dist/cjs/index.js.map +7 -0
  72. package/dist/cjs/internal/JournalInternalFault.d.ts +37 -0
  73. package/dist/cjs/internal/JournalInternalFault.d.ts.map +1 -0
  74. package/dist/cjs/internal/JournalInternalFault.js +43 -0
  75. package/dist/cjs/internal/JournalInternalFault.js.map +7 -0
  76. package/dist/cjs/migrations/0001_initial.d.ts +15 -0
  77. package/dist/cjs/migrations/0001_initial.d.ts.map +1 -0
  78. package/dist/cjs/migrations/0001_initial.js +54 -0
  79. package/dist/cjs/migrations/0001_initial.js.map +7 -0
  80. package/dist/cjs/migrations/0002_checkpoints.d.ts +27 -0
  81. package/dist/cjs/migrations/0002_checkpoints.d.ts.map +1 -0
  82. package/dist/cjs/migrations/0002_checkpoints.js +48 -0
  83. package/dist/cjs/migrations/0002_checkpoints.js.map +7 -0
  84. package/dist/cjs/migrations/0003_startup_index.d.ts +15 -0
  85. package/dist/cjs/migrations/0003_startup_index.d.ts.map +1 -0
  86. package/dist/cjs/migrations/0003_startup_index.js +40 -0
  87. package/dist/cjs/migrations/0003_startup_index.js.map +7 -0
  88. package/dist/cjs/migrations/0004_dedup.d.ts +15 -0
  89. package/dist/cjs/migrations/0004_dedup.d.ts.map +1 -0
  90. package/dist/cjs/migrations/0004_dedup.js +57 -0
  91. package/dist/cjs/migrations/0004_dedup.js.map +7 -0
  92. package/dist/cjs/migrations/0005_run_event_type.d.ts +15 -0
  93. package/dist/cjs/migrations/0005_run_event_type.d.ts.map +1 -0
  94. package/dist/cjs/migrations/0005_run_event_type.js +40 -0
  95. package/dist/cjs/migrations/0005_run_event_type.js.map +7 -0
  96. package/dist/cjs/migrations/0006_consensus.d.ts +22 -0
  97. package/dist/cjs/migrations/0006_consensus.d.ts.map +1 -0
  98. package/dist/cjs/migrations/0006_consensus.js +84 -0
  99. package/dist/cjs/migrations/0006_consensus.js.map +7 -0
  100. package/dist/cjs/package.json +1 -0
  101. package/dist/cjs/test/Notifying.d.ts +65 -0
  102. package/dist/cjs/test/Notifying.d.ts.map +1 -0
  103. package/dist/cjs/test/Notifying.js +62 -0
  104. package/dist/cjs/test/Notifying.js.map +7 -0
  105. package/dist/cjs/test/TestJournal.d.ts +43 -0
  106. package/dist/cjs/test/TestJournal.d.ts.map +1 -0
  107. package/dist/cjs/test/TestJournal.js +43 -0
  108. package/dist/cjs/test/TestJournal.js.map +7 -0
  109. package/dist/esm/CallFact.d.ts +129 -0
  110. package/dist/esm/CallFact.d.ts.map +1 -0
  111. package/dist/esm/CallFact.js +96 -0
  112. package/dist/esm/CallFact.js.map +1 -0
  113. package/dist/esm/Consensus.d.ts +440 -0
  114. package/dist/esm/Consensus.d.ts.map +1 -0
  115. package/dist/esm/Consensus.js +454 -0
  116. package/dist/esm/Consensus.js.map +1 -0
  117. package/dist/esm/EngineEvent.d.ts +890 -0
  118. package/dist/esm/EngineEvent.d.ts.map +1 -0
  119. package/dist/esm/EngineEvent.js +614 -0
  120. package/dist/esm/EngineEvent.js.map +1 -0
  121. package/dist/esm/ExecutionFact.d.ts +216 -0
  122. package/dist/esm/ExecutionFact.d.ts.map +1 -0
  123. package/dist/esm/ExecutionFact.js +374 -0
  124. package/dist/esm/ExecutionFact.js.map +1 -0
  125. package/dist/esm/Journal.d.ts +617 -0
  126. package/dist/esm/Journal.d.ts.map +1 -0
  127. package/dist/esm/Journal.js +323 -0
  128. package/dist/esm/Journal.js.map +1 -0
  129. package/dist/esm/JournalEvent.d.ts +421 -0
  130. package/dist/esm/JournalEvent.d.ts.map +1 -0
  131. package/dist/esm/JournalEvent.js +517 -0
  132. package/dist/esm/JournalEvent.js.map +1 -0
  133. package/dist/esm/JournalGeneration.d.ts +34 -0
  134. package/dist/esm/JournalGeneration.d.ts.map +1 -0
  135. package/dist/esm/JournalGeneration.js +65 -0
  136. package/dist/esm/JournalGeneration.js.map +1 -0
  137. package/dist/esm/JournalMetrics.d.ts +72 -0
  138. package/dist/esm/JournalMetrics.d.ts.map +1 -0
  139. package/dist/esm/JournalMetrics.js +79 -0
  140. package/dist/esm/JournalMetrics.js.map +1 -0
  141. package/dist/esm/Migrations.d.ts +42 -0
  142. package/dist/esm/Migrations.d.ts.map +1 -0
  143. package/dist/esm/Migrations.js +59 -0
  144. package/dist/esm/Migrations.js.map +1 -0
  145. package/dist/esm/OwnerId.d.ts +40 -0
  146. package/dist/esm/OwnerId.d.ts.map +1 -0
  147. package/dist/esm/OwnerId.js +33 -0
  148. package/dist/esm/OwnerId.js.map +1 -0
  149. package/dist/esm/Projection.d.ts +29 -0
  150. package/dist/esm/Projection.d.ts.map +1 -0
  151. package/dist/esm/Projection.js +13 -0
  152. package/dist/esm/Projection.js.map +1 -0
  153. package/dist/esm/RedactedLogger.d.ts +121 -0
  154. package/dist/esm/RedactedLogger.d.ts.map +1 -0
  155. package/dist/esm/RedactedLogger.js +445 -0
  156. package/dist/esm/RedactedLogger.js.map +1 -0
  157. package/dist/esm/Redaction.d.ts +350 -0
  158. package/dist/esm/Redaction.d.ts.map +1 -0
  159. package/dist/esm/Redaction.js +1584 -0
  160. package/dist/esm/Redaction.js.map +1 -0
  161. package/dist/esm/SqlConsensus.d.ts +44 -0
  162. package/dist/esm/SqlConsensus.d.ts.map +1 -0
  163. package/dist/esm/SqlConsensus.js +252 -0
  164. package/dist/esm/SqlConsensus.js.map +1 -0
  165. package/dist/esm/SqlJournal.d.ts +173 -0
  166. package/dist/esm/SqlJournal.d.ts.map +1 -0
  167. package/dist/esm/SqlJournal.js +1858 -0
  168. package/dist/esm/SqlJournal.js.map +1 -0
  169. package/dist/esm/StepFact.d.ts +66 -0
  170. package/dist/esm/StepFact.d.ts.map +1 -0
  171. package/dist/esm/StepFact.js +50 -0
  172. package/dist/esm/StepFact.js.map +1 -0
  173. package/dist/esm/index.d.ts +95 -0
  174. package/dist/esm/index.d.ts.map +1 -0
  175. package/dist/esm/index.js +95 -0
  176. package/dist/esm/index.js.map +1 -0
  177. package/dist/esm/internal/JournalInternalFault.d.ts +37 -0
  178. package/dist/esm/internal/JournalInternalFault.d.ts.map +1 -0
  179. package/dist/esm/internal/JournalInternalFault.js +28 -0
  180. package/dist/esm/internal/JournalInternalFault.js.map +1 -0
  181. package/dist/esm/migrations/0001_initial.d.ts +15 -0
  182. package/dist/esm/migrations/0001_initial.d.ts.map +1 -0
  183. package/dist/esm/migrations/0001_initial.js +32 -0
  184. package/dist/esm/migrations/0001_initial.js.map +1 -0
  185. package/dist/esm/migrations/0002_checkpoints.d.ts +27 -0
  186. package/dist/esm/migrations/0002_checkpoints.d.ts.map +1 -0
  187. package/dist/esm/migrations/0002_checkpoints.js +38 -0
  188. package/dist/esm/migrations/0002_checkpoints.js.map +1 -0
  189. package/dist/esm/migrations/0003_startup_index.d.ts +15 -0
  190. package/dist/esm/migrations/0003_startup_index.d.ts.map +1 -0
  191. package/dist/esm/migrations/0003_startup_index.js +18 -0
  192. package/dist/esm/migrations/0003_startup_index.js.map +1 -0
  193. package/dist/esm/migrations/0004_dedup.d.ts +15 -0
  194. package/dist/esm/migrations/0004_dedup.d.ts.map +1 -0
  195. package/dist/esm/migrations/0004_dedup.js +38 -0
  196. package/dist/esm/migrations/0004_dedup.js.map +1 -0
  197. package/dist/esm/migrations/0005_run_event_type.d.ts +15 -0
  198. package/dist/esm/migrations/0005_run_event_type.d.ts.map +1 -0
  199. package/dist/esm/migrations/0005_run_event_type.js +18 -0
  200. package/dist/esm/migrations/0005_run_event_type.js.map +1 -0
  201. package/dist/esm/migrations/0006_consensus.d.ts +22 -0
  202. package/dist/esm/migrations/0006_consensus.d.ts.map +1 -0
  203. package/dist/esm/migrations/0006_consensus.js +69 -0
  204. package/dist/esm/migrations/0006_consensus.js.map +1 -0
  205. package/dist/esm/test/Notifying.d.ts +65 -0
  206. package/dist/esm/test/Notifying.d.ts.map +1 -0
  207. package/dist/esm/test/Notifying.js +62 -0
  208. package/dist/esm/test/Notifying.js.map +1 -0
  209. package/dist/esm/test/TestJournal.d.ts +43 -0
  210. package/dist/esm/test/TestJournal.d.ts.map +1 -0
  211. package/dist/esm/test/TestJournal.js +27 -0
  212. package/dist/esm/test/TestJournal.js.map +1 -0
  213. package/docs/README.md +164 -0
  214. package/docs/api.md +639 -0
  215. package/docs/concepts/compaction.md +157 -0
  216. package/docs/concepts/idempotency.md +127 -0
  217. package/docs/concepts/owner-fence.md +124 -0
  218. package/docs/concepts/redaction.md +218 -0
  219. package/docs/concepts/state-event-authority.md +159 -0
  220. package/docs/concepts/two-channels.md +167 -0
  221. package/docs/guides/commit-state-and-entry.md +114 -0
  222. package/docs/guides/compact-a-run.md +134 -0
  223. package/docs/guides/fold-a-projection.md +106 -0
  224. package/docs/guides/read-a-run.md +139 -0
  225. package/docs/guides/redact-log-output.md +94 -0
  226. package/docs/guides/testing.md +124 -0
  227. package/docs/guides/write-lifecycle-events.md +110 -0
  228. package/docs/installation.md +133 -0
  229. package/docs/quickstart.md +143 -0
  230. package/docs/troubleshooting.md +214 -0
  231. package/package.json +263 -3
  232. package/src/CallFact.ts +117 -0
  233. package/src/Consensus.ts +683 -0
  234. package/src/EngineEvent.ts +823 -0
  235. package/src/ExecutionFact.ts +433 -0
  236. package/src/Journal.ts +688 -0
  237. package/src/JournalEvent.ts +654 -0
  238. package/src/JournalGeneration.ts +77 -0
  239. package/src/JournalMetrics.ts +89 -0
  240. package/src/Migrations.ts +62 -0
  241. package/src/OwnerId.ts +42 -0
  242. package/src/Projection.ts +31 -0
  243. package/src/RedactedLogger.ts +483 -0
  244. package/src/Redaction.ts +1784 -0
  245. package/src/SqlConsensus.ts +344 -0
  246. package/src/SqlJournal.ts +2732 -0
  247. package/src/StepFact.ts +69 -0
  248. package/src/index.ts +109 -0
  249. package/src/internal/JournalInternalFault.ts +40 -0
  250. package/src/migrations/0001_initial.ts +41 -0
  251. package/src/migrations/0002_checkpoints.ts +46 -0
  252. package/src/migrations/0003_startup_index.ts +19 -0
  253. package/src/migrations/0004_dedup.ts +43 -0
  254. package/src/migrations/0005_run_event_type.ts +19 -0
  255. package/src/migrations/0006_consensus.ts +83 -0
  256. package/src/test/Notifying.ts +101 -0
  257. package/src/test/TestJournal.ts +52 -0
@@ -0,0 +1,440 @@
1
+ /**
2
+ * The injectable consensus strategy arbitrating the journal's ownership rules.
3
+ *
4
+ * The journal owns the consensus rules — single writer per run, fenced and
5
+ * unfenced appends, commit-time admission, the generation fence, and steal
6
+ * only on staleness plus liveness evidence — and this service is how a deployment chooses *how* those rules are
7
+ * arbitrated: where the lease lives, how liveness is probed, and how the
8
+ * fence is checked at commit time. `Consensus` lives here beside `OwnerId`
9
+ * for the same reason `OwnerId` does: the journal is what it fences.
10
+ * `@smthrs/run-store`'s `Ownership` keeps its public API and rules but
11
+ * delegates arbitration to this strategy.
12
+ *
13
+ * Every operation that reasons about staleness takes the caller's clock
14
+ * reading (`nowMs`) rather than reading a clock itself: staleness (R5) and
15
+ * the monotonic lease stamp are defined against the arbitrating caller's
16
+ * reading, exactly as `RunStore`'s compare-and-swap operations always were,
17
+ * so the recorded lease never differs from the outcome the caller observed.
18
+ *
19
+ * Governing design: `packages/smithers/flows/journal/docs/concepts/owner-fence.md`.
20
+ * Rule constants and their provenance:
21
+ * `packages/smithers/flows/run-store/docs/concepts/leases.md`.
22
+ *
23
+ * Prior art: Effect `EventJournal` (`reference/effect` `unstable/eventlog`)
24
+ * resolves multi-writer by merge with conflict surfacing; driving a run is not
25
+ * mergeable, so this surface deviates to exclusive-writer admission. The
26
+ * fencing and generation semantics follow Temporal's shard `rangeID`
27
+ * (`reference/temporal/service/history/shard/context_impl.go`).
28
+ *
29
+ * @since 1.0.0
30
+ */
31
+ import * as Context from "effect/Context";
32
+ import * as Duration from "effect/Duration";
33
+ import * as Effect from "effect/Effect";
34
+ import * as Layer from "effect/Layer";
35
+ import * as Schema from "effect/Schema";
36
+ import { OwnerId } from "./OwnerId.ts";
37
+ /**
38
+ * How often the supervision loop pulses to renew the owner's lease.
39
+ *
40
+ * @since 1.0.0
41
+ * @category constants
42
+ */
43
+ export declare const heartbeatInterval: Duration.Duration;
44
+ /**
45
+ * How old a persisted heartbeat must be before a peer may steal the run.
46
+ * Every strategy judges R5 staleness against this one definition.
47
+ *
48
+ * @since 1.0.0
49
+ * @category constants
50
+ */
51
+ export declare const heartbeatStaleAfter: Duration.Duration;
52
+ /**
53
+ * How far the owner's wall clock may run behind a peer's before the lease
54
+ * reasoning stops holding.
55
+ *
56
+ * The owner stamps its heartbeat from *its* clock and a would-be stealer
57
+ * compares that stamp against *its own*, so the two hosts' clock offset is
58
+ * subtracted directly from the owner's real safety margin. This constant names
59
+ * that allowance instead of leaving it implicit in a "two ticks" arithmetic
60
+ * accident, and it is a budgeted allowance, not a guarantee: see
61
+ * {@link heartbeatWriteTolerance} for what happens once it is exceeded.
62
+ *
63
+ * @since 1.0.0
64
+ * @category constants
65
+ */
66
+ export declare const heartbeatSkewAllowance: Duration.Duration;
67
+ /**
68
+ * How long heartbeat writes may go unconfirmed before ownership must be reconfirmed.
69
+ *
70
+ * A peer judges staleness by the persisted heartbeat and may steal the run the
71
+ * instant it is {@link heartbeatStaleAfter} old, so an owner that tolerated
72
+ * write failures for exactly that long would still be executing side effects
73
+ * when the steal is admitted. The budget is therefore
74
+ * {@link heartbeatStaleAfter} minus {@link heartbeatSkewAllowance} (the peer's
75
+ * clock may already read that much later than the owner's) minus one
76
+ * {@link heartbeatInterval} (reserved for one bounded compare-and-swap
77
+ * reconfirmation before the owner interrupts).
78
+ *
79
+ * This bounds, but does not eliminate, overlap. Beyond
80
+ * {@link heartbeatSkewAllowance} of clock offset a peer can be admitted while
81
+ * the old owner is still running. *Durable* writes stay safe regardless — they
82
+ * are fenced by the strategy's commit-time admission, so the displaced owner's
83
+ * writes fail rather than corrupt. Non-durable external side effects (an HTTP
84
+ * call, a spawned process) can genuinely overlap. That is inherent to any
85
+ * wall-clock lease and is stated here rather than asserted away; a caller that
86
+ * cannot tolerate any overlap needs an external fencing token at the side
87
+ * effect itself, not a larger timeout.
88
+ *
89
+ * @since 1.0.0
90
+ * @category constants
91
+ */
92
+ export declare const heartbeatWriteTolerance: Duration.Duration;
93
+ /**
94
+ * Evidence that the owner in an exact run snapshot is no longer live.
95
+ *
96
+ * Defined here because R5 — steal requires staleness plus liveness evidence —
97
+ * is a consensus rule every strategy validates. `@smthrs/run-store`'s
98
+ * `Ownership` re-exports it alongside the probes that mint it.
99
+ *
100
+ * Two of the three kinds are collected outside the strategy:
101
+ * `same-host-pid-dead` is a local process probe, and
102
+ * `cross-host-unreachable-stale` is a reachability judgement the deployment
103
+ * makes. `lease-expired` is different — it asserts only that the persisted
104
+ * heartbeat is older than the staleness cutoff, which is the one claim a
105
+ * strategy can check for itself, and `steal` checks it: the takeover refuses
106
+ * any lease whose heartbeat is still inside the window. It is therefore
107
+ * accepted from a claimant on any host, while the other two stay bound to the
108
+ * host relation that makes them meaningful. The observation must carry the
109
+ * exact instant supplied to the consuming operation: `checkedAtMs` must equal
110
+ * that operation's `nowMs`. A caller that probes at T and calls at T+1 is
111
+ * refused and must build fresh evidence.
112
+ *
113
+ * @since 1.0.0
114
+ * @category models
115
+ */
116
+ export declare const LivenessEvidence: Schema.Struct<{
117
+ readonly expectedOwner: Schema.Struct<{
118
+ readonly hostId: Schema.String;
119
+ readonly pid: Schema.Int;
120
+ readonly nonce: Schema.String;
121
+ }>;
122
+ readonly checkedAtMs: Schema.Number;
123
+ readonly kind: Schema.Literals<readonly ["same-host-pid-dead", "cross-host-unreachable-stale", "lease-expired"]>;
124
+ }>;
125
+ /**
126
+ * Evidence that the owner in an exact run snapshot is no longer live.
127
+ *
128
+ * @since 1.0.0
129
+ * @category models
130
+ */
131
+ export type LivenessEvidence = typeof LivenessEvidence.Type;
132
+ /**
133
+ * Structural equality on the process identity tuple.
134
+ *
135
+ * @since 1.0.0
136
+ * @category predicates
137
+ */
138
+ export declare const sameOwner: (left: OwnerId, right: OwnerId) => boolean;
139
+ /**
140
+ * Validates liveness evidence against the owner it claims to disprove.
141
+ *
142
+ * The evidence must name the expected owner, carry the observer's current
143
+ * clock reading, and respect the host rule: a `same-host-pid-dead` probe is
144
+ * only meaningful from the same host, a `cross-host-unreachable-stale`
145
+ * observation only from a different one, and `lease-expired` is host-neutral
146
+ * because the strategy verifies the cutoff it names for itself.
147
+ *
148
+ * @since 1.0.0
149
+ * @category predicates
150
+ */
151
+ export declare const matchesEvidence: (expectedOwner: OwnerId, observer: OwnerId, nowMs: number, evidence: LivenessEvidence) => boolean;
152
+ /**
153
+ * Why a strategy refused a claim, steal, or recovery.
154
+ *
155
+ * @since 1.0.0
156
+ * @category models
157
+ */
158
+ export declare const RejectionReason: Schema.Literals<readonly ["already_claimed", "owner_held", "owner_live", "evidence_invalid", "claim_fresh", "claim_changed", "unavailable"]>;
159
+ /**
160
+ * Why a strategy refused a claim, steal, or recovery.
161
+ *
162
+ * @since 1.0.0
163
+ * @category models
164
+ */
165
+ export type RejectionReason = typeof RejectionReason.Type;
166
+ /**
167
+ * A granted claim, carrying the grant timestamp the later activation must
168
+ * present (R4 — the generation fence).
169
+ *
170
+ * @since 1.0.0
171
+ * @category models
172
+ */
173
+ export declare const Claimed: Schema.TaggedStruct<"Claimed", {
174
+ readonly grantedAtMs: Schema.Number;
175
+ }>;
176
+ /**
177
+ * A granted claim.
178
+ *
179
+ * @since 1.0.0
180
+ * @category models
181
+ */
182
+ export type Claimed = typeof Claimed.Type;
183
+ /**
184
+ * A refused claim, steal, or recovery, with the strategy's typed reason.
185
+ *
186
+ * @since 1.0.0
187
+ * @category models
188
+ */
189
+ export declare const Rejected: Schema.TaggedStruct<"Rejected", {
190
+ readonly reason: Schema.Literals<readonly ["already_claimed", "owner_held", "owner_live", "evidence_invalid", "claim_fresh", "claim_changed", "unavailable"]>;
191
+ }>;
192
+ /**
193
+ * A refused claim, steal, or recovery.
194
+ *
195
+ * @since 1.0.0
196
+ * @category models
197
+ */
198
+ export type Rejected = typeof Rejected.Type;
199
+ /**
200
+ * Outcome of `claim` and `steal`.
201
+ *
202
+ * @since 1.0.0
203
+ * @category models
204
+ */
205
+ export declare const ClaimOutcome: Schema.Union<readonly [Schema.TaggedStruct<"Claimed", {
206
+ readonly grantedAtMs: Schema.Number;
207
+ }>, Schema.TaggedStruct<"Rejected", {
208
+ readonly reason: Schema.Literals<readonly ["already_claimed", "owner_held", "owner_live", "evidence_invalid", "claim_fresh", "claim_changed", "unavailable"]>;
209
+ }>]>;
210
+ /**
211
+ * Outcome of `claim` and `steal`.
212
+ *
213
+ * @since 1.0.0
214
+ * @category models
215
+ */
216
+ export type ClaimOutcome = typeof ClaimOutcome.Type;
217
+ /**
218
+ * A claim promoted to ownership.
219
+ *
220
+ * @since 1.0.0
221
+ * @category models
222
+ */
223
+ export declare const Activated: Schema.TaggedStruct<"Activated", {}>;
224
+ /**
225
+ * A claim promoted to ownership.
226
+ *
227
+ * @since 1.0.0
228
+ * @category models
229
+ */
230
+ export type Activated = typeof Activated.Type;
231
+ /**
232
+ * The claim or lease the caller presented no longer exists.
233
+ *
234
+ * @since 1.0.0
235
+ * @category models
236
+ */
237
+ export declare const Lost: Schema.TaggedStruct<"Lost", {}>;
238
+ /**
239
+ * The claim or lease the caller presented no longer exists.
240
+ *
241
+ * @since 1.0.0
242
+ * @category models
243
+ */
244
+ export type Lost = typeof Lost.Type;
245
+ /**
246
+ * Outcome of `activate`.
247
+ *
248
+ * @since 1.0.0
249
+ * @category models
250
+ */
251
+ export declare const ActivateOutcome: Schema.Union<readonly [Schema.TaggedStruct<"Activated", {}>, Schema.TaggedStruct<"Lost", {}>]>;
252
+ /**
253
+ * Outcome of `activate`.
254
+ *
255
+ * @since 1.0.0
256
+ * @category models
257
+ */
258
+ export type ActivateOutcome = typeof ActivateOutcome.Type;
259
+ /**
260
+ * A renewed lease, carrying the monotonic heartbeat stamp the strategy
261
+ * recorded — the maximum of the stored stamp and the caller's reading, so a
262
+ * late pulse never moves the lease backwards.
263
+ *
264
+ * @since 1.0.0
265
+ * @category models
266
+ */
267
+ export declare const Renewed: Schema.TaggedStruct<"Renewed", {
268
+ readonly heartbeatAtMs: Schema.Number;
269
+ }>;
270
+ /**
271
+ * A renewed lease.
272
+ *
273
+ * @since 1.0.0
274
+ * @category models
275
+ */
276
+ export type Renewed = typeof Renewed.Type;
277
+ /**
278
+ * Outcome of `heartbeat` and `reconfirm`.
279
+ *
280
+ * @since 1.0.0
281
+ * @category models
282
+ */
283
+ export declare const HeartbeatOutcome: Schema.Union<readonly [Schema.TaggedStruct<"Renewed", {
284
+ readonly heartbeatAtMs: Schema.Number;
285
+ }>, Schema.TaggedStruct<"Lost", {}>]>;
286
+ /**
287
+ * Outcome of `heartbeat` and `reconfirm`.
288
+ *
289
+ * @since 1.0.0
290
+ * @category models
291
+ */
292
+ export type HeartbeatOutcome = typeof HeartbeatOutcome.Type;
293
+ /**
294
+ * A stale claim cleared after its claimant was proven dead.
295
+ *
296
+ * @since 1.0.0
297
+ * @category models
298
+ */
299
+ export declare const Recovered: Schema.TaggedStruct<"Recovered", {}>;
300
+ /**
301
+ * A stale claim cleared after its claimant was proven dead.
302
+ *
303
+ * @since 1.0.0
304
+ * @category models
305
+ */
306
+ export type Recovered = typeof Recovered.Type;
307
+ /**
308
+ * Outcome of `recover`.
309
+ *
310
+ * @since 1.0.0
311
+ * @category models
312
+ */
313
+ export declare const RecoverOutcome: Schema.Union<readonly [Schema.TaggedStruct<"Recovered", {}>, Schema.TaggedStruct<"Rejected", {
314
+ readonly reason: Schema.Literals<readonly ["already_claimed", "owner_held", "owner_live", "evidence_invalid", "claim_fresh", "claim_changed", "unavailable"]>;
315
+ }>]>;
316
+ /**
317
+ * Outcome of `recover`.
318
+ *
319
+ * @since 1.0.0
320
+ * @category models
321
+ */
322
+ export type RecoverOutcome = typeof RecoverOutcome.Type;
323
+ declare const ConsensusError_base: Schema.Class<ConsensusError, Schema.TaggedStruct<"@smthrs/journal/ConsensusError", {
324
+ readonly code: Schema.Literals<readonly ["fence_lost", "persistence_failed"]>;
325
+ readonly message: Schema.String;
326
+ readonly cause: Schema.optional<Schema.Unknown>;
327
+ }>, import("effect/Cause").YieldableError>;
328
+ /**
329
+ * Failure raised by a consensus strategy.
330
+ *
331
+ * `fence_lost` is `guard`'s refusal: the supplied owner no longer holds the
332
+ * run, so the fenced write it joins must not commit. `persistence_failed`
333
+ * wraps a strategy's storage failure; the original cause is preserved so the
334
+ * durable writer's retry classification still sees a transient conflict
335
+ * through the wrapper.
336
+ *
337
+ * @since 1.0.0
338
+ * @category errors
339
+ */
340
+ export declare class ConsensusError extends ConsensusError_base {
341
+ }
342
+ /**
343
+ * Consensus operations.
344
+ *
345
+ * The rules being arbitrated are strategy-independent; a strategy
346
+ * chooses where the lease lives and how the fence is checked at commit time.
347
+ * The claim lifecycle is two-phase, exactly as `RunStore`'s always was:
348
+ * `claim` (or `steal`, its evidence-gated form) reserves the run and returns
349
+ * the grant timestamp, `activate` presents that grant to take ownership, and
350
+ * `release` clears whichever of the caller's claim or ownership still stands.
351
+ * `recover` clears a *third party's* stale claim after its claimant was proven
352
+ * dead — the relocated `recoverClaim` mechanic. `guard` is the commit-time
353
+ * admission check (R3) `Journal.emitDurable`, `checkpoint`, and `compact`
354
+ * join: it succeeds while the owner holds the run and fails with `fence_lost`
355
+ * otherwise.
356
+ *
357
+ * Heartbeats and lease state are the strategy's private evidence and never
358
+ * enter the journal.
359
+ *
360
+ * @since 1.0.0
361
+ * @category models
362
+ */
363
+ export interface Service {
364
+ readonly claim: (runId: string, claimant: OwnerId, nowMs: number) => Effect.Effect<ClaimOutcome, ConsensusError>;
365
+ readonly activate: (runId: string, owner: OwnerId, grantedAtMs: number, nowMs: number) => Effect.Effect<ActivateOutcome, ConsensusError>;
366
+ readonly heartbeat: (runId: string, owner: OwnerId, nowMs: number) => Effect.Effect<HeartbeatOutcome, ConsensusError>;
367
+ /** Renews only while this owner holds the lease and no takeover claim is pending. */
368
+ readonly reconfirm: (runId: string, owner: OwnerId, nowMs: number) => Effect.Effect<HeartbeatOutcome, ConsensusError>;
369
+ readonly release: (runId: string, owner: OwnerId) => Effect.Effect<void, ConsensusError>;
370
+ readonly steal: (runId: string, claimant: OwnerId, nowMs: number, evidence: LivenessEvidence) => Effect.Effect<ClaimOutcome, ConsensusError>;
371
+ readonly recover: (runId: string, staleClaimant: OwnerId, grantedAtMs: number, observer: OwnerId, nowMs: number, evidence: LivenessEvidence) => Effect.Effect<RecoverOutcome, ConsensusError>;
372
+ readonly guard: (runId: string, owner: OwnerId) => Effect.Effect<void, ConsensusError>;
373
+ }
374
+ declare const Consensus_base: Context.ServiceClass<Consensus, "@smthrs/journal/Consensus", Service>;
375
+ /**
376
+ * Context service for the injected consensus strategy.
377
+ *
378
+ * @since 1.0.0
379
+ * @category services
380
+ */
381
+ export declare class Consensus extends Consensus_base {
382
+ }
383
+ /**
384
+ * Constructs a consensus service from an implementation.
385
+ *
386
+ * @since 1.0.0
387
+ * @category constructors
388
+ */
389
+ export declare const make: (implementation: Service) => Service;
390
+ /**
391
+ * The refusal `guard` raises for an owner that no longer holds the run.
392
+ *
393
+ * @since 1.0.0
394
+ * @category errors
395
+ */
396
+ export declare const fenceLost: (runId: string, owner: OwnerId) => ConsensusError;
397
+ /**
398
+ * Constructs a strategy that arbitrates nothing: claims are refused, leases
399
+ * are never held, and every fenced write is rejected.
400
+ *
401
+ * @since 1.0.0
402
+ * @category constructors
403
+ */
404
+ export declare const makeNoop: (overrides?: Partial<Service>) => Service;
405
+ /**
406
+ * Provides the refusing strategy stub.
407
+ *
408
+ * @since 1.0.0
409
+ * @category layers
410
+ */
411
+ export declare const layerNoop: (overrides?: Partial<Service>) => Layer.Layer<Consensus>;
412
+ /**
413
+ * Constructs the in-memory single-process strategy.
414
+ *
415
+ * @since 1.0.0
416
+ * @category constructors
417
+ */
418
+ export declare const makeLocal: Effect.Effect<Service>;
419
+ /**
420
+ * Provides the in-memory single-process strategy.
421
+ *
422
+ * The lease lives in process memory, so R3 is exact within the process — the
423
+ * strategy's transitions and the serialized append transactions interleave
424
+ * atomically on one event loop — and browser support needs nothing beyond
425
+ * this layer plus the browser-safe journal. State is per layer build: provide
426
+ * one instance to every service that must agree on it, which is what
427
+ * `SqlJournal.layerWith` and `RunStore.layerWith` exist for.
428
+ *
429
+ * The lease is not part of any database transaction: a transition made inside
430
+ * a `Journal.transact` that later rolls back stays applied in memory, so the
431
+ * lease and a rolled-back run row can disagree until the next transition.
432
+ * `SqlConsensus` keeps the two in one transaction; prefer it wherever a
433
+ * database is present.
434
+ *
435
+ * @since 1.0.0
436
+ * @category layers
437
+ */
438
+ export declare const layerLocal: Layer.Layer<Consensus>;
439
+ export {};
440
+ //# sourceMappingURL=Consensus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Consensus.d.ts","sourceRoot":"","sources":["../../src/Consensus.ts"],"names":[],"mappings":"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"}