@smthrs/notifications 0.0.0-stage → 1.0.0-rc.13

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 (146) hide show
  1. package/CHANGELOG.md +127 -0
  2. package/LICENSE +21 -0
  3. package/README.md +93 -2
  4. package/dist/cjs/AlertPolicy.d.ts +284 -0
  5. package/dist/cjs/AlertPolicy.d.ts.map +1 -0
  6. package/dist/cjs/AlertPolicy.js +124 -0
  7. package/dist/cjs/AlertPolicy.js.map +7 -0
  8. package/dist/cjs/AlertRuntime.d.ts +90 -0
  9. package/dist/cjs/AlertRuntime.d.ts.map +1 -0
  10. package/dist/cjs/AlertRuntime.js +166 -0
  11. package/dist/cjs/AlertRuntime.js.map +7 -0
  12. package/dist/cjs/AlertSink.d.ts +101 -0
  13. package/dist/cjs/AlertSink.d.ts.map +1 -0
  14. package/dist/cjs/AlertSink.js +44 -0
  15. package/dist/cjs/AlertSink.js.map +7 -0
  16. package/dist/cjs/Alerts.d.ts +57 -0
  17. package/dist/cjs/Alerts.d.ts.map +1 -0
  18. package/dist/cjs/Alerts.js +46 -0
  19. package/dist/cjs/Alerts.js.map +7 -0
  20. package/dist/cjs/Notification.d.ts +214 -0
  21. package/dist/cjs/Notification.d.ts.map +1 -0
  22. package/dist/cjs/Notification.js +62 -0
  23. package/dist/cjs/Notification.js.map +7 -0
  24. package/dist/cjs/NotificationEvent.d.ts +214 -0
  25. package/dist/cjs/NotificationEvent.d.ts.map +1 -0
  26. package/dist/cjs/NotificationEvent.js +84 -0
  27. package/dist/cjs/NotificationEvent.js.map +7 -0
  28. package/dist/cjs/NotificationQueue.d.ts +194 -0
  29. package/dist/cjs/NotificationQueue.d.ts.map +1 -0
  30. package/dist/cjs/NotificationQueue.js +477 -0
  31. package/dist/cjs/NotificationQueue.js.map +7 -0
  32. package/dist/cjs/NotificationState.d.ts +169 -0
  33. package/dist/cjs/NotificationState.d.ts.map +1 -0
  34. package/dist/cjs/NotificationState.js +110 -0
  35. package/dist/cjs/NotificationState.js.map +7 -0
  36. package/dist/cjs/Projection.d.ts +30 -0
  37. package/dist/cjs/Projection.d.ts.map +1 -0
  38. package/dist/cjs/Projection.js +53 -0
  39. package/dist/cjs/Projection.js.map +7 -0
  40. package/dist/cjs/SteerPayload.d.ts +177 -0
  41. package/dist/cjs/SteerPayload.d.ts.map +1 -0
  42. package/dist/cjs/SteerPayload.js +61 -0
  43. package/dist/cjs/SteerPayload.js.map +7 -0
  44. package/dist/cjs/index.d.ts +41 -0
  45. package/dist/cjs/index.d.ts.map +1 -0
  46. package/dist/cjs/index.js +47 -0
  47. package/dist/cjs/index.js.map +7 -0
  48. package/dist/cjs/internal/foldCache.d.ts +36 -0
  49. package/dist/cjs/internal/foldCache.d.ts.map +1 -0
  50. package/dist/cjs/internal/foldCache.js +54 -0
  51. package/dist/cjs/internal/foldCache.js.map +7 -0
  52. package/dist/cjs/internal/replay.d.ts +22 -0
  53. package/dist/cjs/internal/replay.d.ts.map +1 -0
  54. package/dist/cjs/internal/replay.js +46 -0
  55. package/dist/cjs/internal/replay.js.map +7 -0
  56. package/dist/cjs/layerWebhook.d.ts +60 -0
  57. package/dist/cjs/layerWebhook.d.ts.map +1 -0
  58. package/dist/cjs/layerWebhook.js +145 -0
  59. package/dist/cjs/layerWebhook.js.map +7 -0
  60. package/dist/cjs/package.json +1 -0
  61. package/dist/esm/AlertPolicy.d.ts +284 -0
  62. package/dist/esm/AlertPolicy.d.ts.map +1 -0
  63. package/dist/esm/AlertPolicy.js +284 -0
  64. package/dist/esm/AlertPolicy.js.map +1 -0
  65. package/dist/esm/AlertRuntime.d.ts +90 -0
  66. package/dist/esm/AlertRuntime.d.ts.map +1 -0
  67. package/dist/esm/AlertRuntime.js +191 -0
  68. package/dist/esm/AlertRuntime.js.map +1 -0
  69. package/dist/esm/AlertSink.d.ts +101 -0
  70. package/dist/esm/AlertSink.d.ts.map +1 -0
  71. package/dist/esm/AlertSink.js +63 -0
  72. package/dist/esm/AlertSink.js.map +1 -0
  73. package/dist/esm/Alerts.d.ts +57 -0
  74. package/dist/esm/Alerts.d.ts.map +1 -0
  75. package/dist/esm/Alerts.js +57 -0
  76. package/dist/esm/Alerts.js.map +1 -0
  77. package/dist/esm/Notification.d.ts +214 -0
  78. package/dist/esm/Notification.d.ts.map +1 -0
  79. package/dist/esm/Notification.js +121 -0
  80. package/dist/esm/Notification.js.map +1 -0
  81. package/dist/esm/NotificationEvent.d.ts +214 -0
  82. package/dist/esm/NotificationEvent.d.ts.map +1 -0
  83. package/dist/esm/NotificationEvent.js +158 -0
  84. package/dist/esm/NotificationEvent.js.map +1 -0
  85. package/dist/esm/NotificationQueue.d.ts +194 -0
  86. package/dist/esm/NotificationQueue.d.ts.map +1 -0
  87. package/dist/esm/NotificationQueue.js +625 -0
  88. package/dist/esm/NotificationQueue.js.map +1 -0
  89. package/dist/esm/NotificationState.d.ts +169 -0
  90. package/dist/esm/NotificationState.d.ts.map +1 -0
  91. package/dist/esm/NotificationState.js +191 -0
  92. package/dist/esm/NotificationState.js.map +1 -0
  93. package/dist/esm/Projection.d.ts +30 -0
  94. package/dist/esm/Projection.d.ts.map +1 -0
  95. package/dist/esm/Projection.js +47 -0
  96. package/dist/esm/Projection.js.map +1 -0
  97. package/dist/esm/SteerPayload.d.ts +177 -0
  98. package/dist/esm/SteerPayload.d.ts.map +1 -0
  99. package/dist/esm/SteerPayload.js +139 -0
  100. package/dist/esm/SteerPayload.js.map +1 -0
  101. package/dist/esm/index.d.ts +41 -0
  102. package/dist/esm/index.d.ts.map +1 -0
  103. package/dist/esm/index.js +41 -0
  104. package/dist/esm/index.js.map +1 -0
  105. package/dist/esm/internal/foldCache.d.ts +36 -0
  106. package/dist/esm/internal/foldCache.d.ts.map +1 -0
  107. package/dist/esm/internal/foldCache.js +58 -0
  108. package/dist/esm/internal/foldCache.js.map +1 -0
  109. package/dist/esm/internal/replay.d.ts +22 -0
  110. package/dist/esm/internal/replay.d.ts.map +1 -0
  111. package/dist/esm/internal/replay.js +31 -0
  112. package/dist/esm/internal/replay.js.map +1 -0
  113. package/dist/esm/layerWebhook.d.ts +60 -0
  114. package/dist/esm/layerWebhook.d.ts.map +1 -0
  115. package/dist/esm/layerWebhook.js +186 -0
  116. package/dist/esm/layerWebhook.js.map +1 -0
  117. package/docs/README.md +146 -0
  118. package/docs/api.md +443 -0
  119. package/docs/concepts/admission-and-promotion.md +144 -0
  120. package/docs/concepts/alerting.md +138 -0
  121. package/docs/concepts/journal-records.md +132 -0
  122. package/docs/guides/alert-on-a-stuck-run.md +140 -0
  123. package/docs/guides/drain-at-a-turn-boundary.md +95 -0
  124. package/docs/guides/handle-a-full-queue.md +102 -0
  125. package/docs/guides/report-pending-notifications.md +92 -0
  126. package/docs/guides/send-alerts-to-a-webhook.md +155 -0
  127. package/docs/guides/steer-a-run.md +127 -0
  128. package/docs/guides/testing.md +161 -0
  129. package/docs/installation.md +123 -0
  130. package/docs/quickstart.md +159 -0
  131. package/docs/troubleshooting.md +254 -0
  132. package/package.json +182 -3
  133. package/src/AlertPolicy.ts +377 -0
  134. package/src/AlertRuntime.ts +280 -0
  135. package/src/AlertSink.ts +105 -0
  136. package/src/Alerts.ts +71 -0
  137. package/src/Notification.ts +171 -0
  138. package/src/NotificationEvent.ts +213 -0
  139. package/src/NotificationQueue.ts +856 -0
  140. package/src/NotificationState.ts +295 -0
  141. package/src/Projection.ts +48 -0
  142. package/src/SteerPayload.ts +198 -0
  143. package/src/index.ts +47 -0
  144. package/src/internal/foldCache.ts +72 -0
  145. package/src/internal/replay.ts +39 -0
  146. package/src/layerWebhook.ts +239 -0
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Journal event types owned by the notification queue.
3
+ *
4
+ * @since 0.1.0
5
+ */
6
+ import { JournalEvent } from "@smthrs/journal";
7
+ import * as Option from "effect/Option";
8
+ import * as Schema from "effect/Schema";
9
+ /**
10
+ * The journal `eventType` recorded for one admission decision.
11
+ *
12
+ * The spelling is slashes and a PascalCase leaf, where every other event type
13
+ * in this repository is dot-separated and lowercase (`control.run.parked`,
14
+ * `flows.alerts.delivered`). The value is already durable in every engine
15
+ * database, and a rename would silently stop matching the projections that
16
+ * consumers key on, so it stays as written. A foreign projection must match
17
+ * this literal rather than the repository convention, which is why the two
18
+ * spellings are frozen by `test/WireFormat.test.ts`.
19
+ *
20
+ * @category constants
21
+ * @since 0.1.0
22
+ */
23
+ export declare const AdmittedEventType = "flows/notifications/Admitted";
24
+ /**
25
+ * The journal `eventType` recorded when pending notifications are promoted.
26
+ *
27
+ * Spelled like {@link AdmittedEventType}, and frozen for the same reason.
28
+ *
29
+ * @category constants
30
+ * @since 0.1.0
31
+ */
32
+ export declare const PromotedEventType = "flows/notifications/Promoted";
33
+ /**
34
+ * What a durable admission record says was decided.
35
+ *
36
+ * This is the one declaration of the admission vocabulary: it validates every
37
+ * journal entry through {@link fromEntry}, and `NotificationState` types its
38
+ * public signatures against it, so a fourth decision cannot be added to one
39
+ * half and forgotten in the other.
40
+ *
41
+ * @category models
42
+ * @since 1.0.0
43
+ */
44
+ export declare const AdmissionDecision: Schema.Literals<readonly ["admitted", "coalesced", "rejected-full"]>;
45
+ /**
46
+ * The decoded form of {@link AdmissionDecision}.
47
+ *
48
+ * @category models
49
+ * @since 1.0.0
50
+ */
51
+ export type AdmissionDecision = typeof AdmissionDecision.Type;
52
+ /**
53
+ * A durable admission record: the notification a run was told about, and what
54
+ * the queue decided to do with it.
55
+ *
56
+ * A `rejected-full` decision is never written. The queue refuses a full queue
57
+ * in the receipt alone, so the notification id stays admissible once a
58
+ * boundary drains. The literal remains in {@link AdmissionDecision} because a
59
+ * reader must stay total over a record any writer could have produced.
60
+ *
61
+ * @category models
62
+ * @since 0.1.0
63
+ */
64
+ export declare const Admitted: Schema.Struct<{
65
+ readonly notification: Schema.Union<readonly [Schema.TaggedStruct<"human-steer", {
66
+ readonly delivery: Schema.Literal<"steer">;
67
+ readonly id: Schema.NonEmptyString;
68
+ readonly targetLineageId: Schema.NonEmptyString;
69
+ readonly provenance: Schema.Struct<{
70
+ readonly sourceRunId: Schema.String;
71
+ readonly sourceLineageId: Schema.String;
72
+ readonly sourceTurn: Schema.Int;
73
+ readonly sourceActor: Schema.String;
74
+ readonly attribution: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
75
+ }>;
76
+ readonly payload: Schema.Codec<Schema.Json, Schema.Json, never, never>;
77
+ }>, Schema.TaggedStruct<"human-followup", {
78
+ readonly delivery: Schema.Literal<"queue">;
79
+ readonly id: Schema.NonEmptyString;
80
+ readonly targetLineageId: Schema.NonEmptyString;
81
+ readonly provenance: Schema.Struct<{
82
+ readonly sourceRunId: Schema.String;
83
+ readonly sourceLineageId: Schema.String;
84
+ readonly sourceTurn: Schema.Int;
85
+ readonly sourceActor: Schema.String;
86
+ readonly attribution: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
87
+ }>;
88
+ readonly payload: Schema.Codec<Schema.Json, Schema.Json, never, never>;
89
+ }>, Schema.TaggedStruct<"system-event", {
90
+ readonly delivery: Schema.Literal<"queue">;
91
+ readonly coalescingKey: Schema.optional<Schema.String>;
92
+ readonly id: Schema.NonEmptyString;
93
+ readonly targetLineageId: Schema.NonEmptyString;
94
+ readonly provenance: Schema.Struct<{
95
+ readonly sourceRunId: Schema.String;
96
+ readonly sourceLineageId: Schema.String;
97
+ readonly sourceTurn: Schema.Int;
98
+ readonly sourceActor: Schema.String;
99
+ readonly attribution: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
100
+ }>;
101
+ readonly payload: Schema.Codec<Schema.Json, Schema.Json, never, never>;
102
+ }>]>;
103
+ readonly decision: Schema.Literals<readonly ["admitted", "coalesced", "rejected-full"]>;
104
+ /** SHA-256 of canonical validated input, absent in legacy admission rows. */
105
+ readonly fingerprint: Schema.optional<Schema.String>;
106
+ readonly version: Schema.optional<Schema.Number>;
107
+ }>;
108
+ /**
109
+ * The decoded form of {@link Admitted}.
110
+ *
111
+ * @category models
112
+ * @since 0.1.0
113
+ */
114
+ export type Admitted = typeof Admitted.Type;
115
+ /**
116
+ * A durable promotion record: which notifications one boundary of one lineage
117
+ * delivered.
118
+ *
119
+ * The triple `(runId, targetLineageId, boundary)` is the unit of promotion, so
120
+ * a second lineage draining the same boundary name is a separate record rather
121
+ * than a repeat of the first.
122
+ *
123
+ * @category models
124
+ * @since 0.1.0
125
+ */
126
+ export declare const Promoted: Schema.Struct<{
127
+ readonly boundary: Schema.String;
128
+ readonly targetLineageId: Schema.String;
129
+ readonly ids: Schema.$Array<Schema.String>;
130
+ }>;
131
+ /**
132
+ * The decoded form of {@link Promoted}.
133
+ *
134
+ * @category models
135
+ * @since 0.1.0
136
+ */
137
+ export type Promoted = typeof Promoted.Type;
138
+ /**
139
+ * Any journal event owned by this package.
140
+ *
141
+ * The two members are told apart with {@link isAdmitted} and
142
+ * {@link isPromoted} rather than a stored discriminant, because the discriminant
143
+ * would be a durable field this vocabulary does not have.
144
+ *
145
+ * @category models
146
+ * @since 0.1.0
147
+ */
148
+ export type Event = Admitted | Promoted;
149
+ /**
150
+ * Whether an owned event is an admission record.
151
+ *
152
+ * @param event an owned event
153
+ * @category refinements
154
+ * @since 1.0.0
155
+ */
156
+ export declare const isAdmitted: (event: Event) => event is Admitted;
157
+ /**
158
+ * Whether an owned event is a promotion record.
159
+ *
160
+ * @param event an owned event
161
+ * @category refinements
162
+ * @since 1.0.0
163
+ */
164
+ export declare const isPromoted: (event: Event) => event is Promoted;
165
+ /**
166
+ * The journal source every admission of one notification is written under.
167
+ *
168
+ * @param notificationId the admitted notification's id
169
+ * @category constructors
170
+ * @since 1.0.0
171
+ */
172
+ export declare const admissionSourceId: (notificationId: string) => JournalEvent.SourceId;
173
+ /**
174
+ * The identity of one drain: the lineage and the boundary, each encoded so a
175
+ * value containing a slash cannot forge another pair's identity.
176
+ *
177
+ * @param targetLineageId the lineage the boundary closed on
178
+ * @param boundary the boundary name
179
+ * @category constructors
180
+ * @since 1.0.0
181
+ */
182
+ export declare const drainKey: (targetLineageId: string, boundary: string) => string;
183
+ /**
184
+ * The journal source one drain's promotion record is written under.
185
+ *
186
+ * @param targetLineageId the lineage the boundary closed on
187
+ * @param boundary the boundary name
188
+ * @category constructors
189
+ * @since 1.0.0
190
+ */
191
+ export declare const drainSourceId: (targetLineageId: string, boundary: string) => JournalEvent.SourceId;
192
+ /**
193
+ * Decodes an owned notification event from a journal entry.
194
+ *
195
+ * Foreign entries and structurally invalid payloads decode to `None` so a
196
+ * projection over a shared journal stays total.
197
+ *
198
+ * The event type alone does not make an entry owned: any producer on a shared
199
+ * journal can choose one. An admission counts only under
200
+ * {@link admissionSourceId} for the notification it carries, and a promotion
201
+ * only under the `/notifications/drain/` source family the queue writes, so
202
+ * another producer's record with the same event type stays out of the
203
+ * projection. This scopes records; it does not authenticate the writer. The
204
+ * journal fences writes on run ownership, not on source, so a writer that
205
+ * sets this package's source id is read as this package. The drain check is
206
+ * a prefix because records written before the lineage joined the identity
207
+ * carry the boundary alone.
208
+ *
209
+ * @param entry one journal entry, owned or foreign
210
+ * @category constructors
211
+ * @since 0.1.0
212
+ */
213
+ export declare const fromEntry: (entry: JournalEvent.Entry) => Option.Option<Event>;
214
+ //# sourceMappingURL=NotificationEvent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NotificationEvent.d.ts","sourceRoot":"","sources":["../../src/NotificationEvent.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAGvC;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,iCAAiC,CAAA;AAE/D;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,iCAAiC,CAAA;AAE/D;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iBAAiB,sEAA8D,CAAA;AAE5F;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,iBAAiB,CAAC,IAAI,CAAA;AAE7D;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAGnB,6EAA6E;;;EAG7E,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAE3C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,QAAQ;;;;EAInB,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAE3C;;;;;;;;;GASG;AACH,MAAM,MAAM,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAEvC;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,KAAK,KAAG,KAAK,IAAI,QAAmC,CAAA;AAEtF;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,KAAK,KAAG,KAAK,IAAI,QAA8B,CAAA;AAEjF;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAAI,gBAAgB,MAAM,KAAG,YAAY,CAAC,QACC,CAAA;AAEzE;;;;;;;;GAQG;AACH,eAAO,MAAM,QAAQ,GAAI,iBAAiB,MAAM,EAAE,UAAU,MAAM,KAAG,MACK,CAAA;AAE1E;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GAAI,iBAAiB,MAAM,EAAE,UAAU,MAAM,KAAG,YAAY,CAAC,QACG,CAAA;AAQ1F;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,SAAS,GAAI,OAAO,YAAY,CAAC,KAAK,KAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAWxE,CAAA"}
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Journal event types owned by the notification queue.
3
+ *
4
+ * @since 0.1.0
5
+ */
6
+ import { JournalEvent } from "@smthrs/journal";
7
+ import * as Option from "effect/Option";
8
+ import * as Schema from "effect/Schema";
9
+ import * as Notification from "./Notification.js";
10
+ /**
11
+ * The journal `eventType` recorded for one admission decision.
12
+ *
13
+ * The spelling is slashes and a PascalCase leaf, where every other event type
14
+ * in this repository is dot-separated and lowercase (`control.run.parked`,
15
+ * `flows.alerts.delivered`). The value is already durable in every engine
16
+ * database, and a rename would silently stop matching the projections that
17
+ * consumers key on, so it stays as written. A foreign projection must match
18
+ * this literal rather than the repository convention, which is why the two
19
+ * spellings are frozen by `test/WireFormat.test.ts`.
20
+ *
21
+ * @category constants
22
+ * @since 0.1.0
23
+ */
24
+ export const AdmittedEventType = "flows/notifications/Admitted";
25
+ /**
26
+ * The journal `eventType` recorded when pending notifications are promoted.
27
+ *
28
+ * Spelled like {@link AdmittedEventType}, and frozen for the same reason.
29
+ *
30
+ * @category constants
31
+ * @since 0.1.0
32
+ */
33
+ export const PromotedEventType = "flows/notifications/Promoted";
34
+ /**
35
+ * What a durable admission record says was decided.
36
+ *
37
+ * This is the one declaration of the admission vocabulary: it validates every
38
+ * journal entry through {@link fromEntry}, and `NotificationState` types its
39
+ * public signatures against it, so a fourth decision cannot be added to one
40
+ * half and forgotten in the other.
41
+ *
42
+ * @category models
43
+ * @since 1.0.0
44
+ */
45
+ export const AdmissionDecision = Schema.Literals(["admitted", "coalesced", "rejected-full"]);
46
+ /**
47
+ * A durable admission record: the notification a run was told about, and what
48
+ * the queue decided to do with it.
49
+ *
50
+ * A `rejected-full` decision is never written. The queue refuses a full queue
51
+ * in the receipt alone, so the notification id stays admissible once a
52
+ * boundary drains. The literal remains in {@link AdmissionDecision} because a
53
+ * reader must stay total over a record any writer could have produced.
54
+ *
55
+ * @category models
56
+ * @since 0.1.0
57
+ */
58
+ export const Admitted = Schema.Struct({
59
+ notification: Notification.Notification,
60
+ decision: AdmissionDecision,
61
+ /** SHA-256 of canonical validated input, absent in legacy admission rows. */
62
+ fingerprint: Schema.optional(Schema.String),
63
+ version: Schema.optional(Schema.Number)
64
+ });
65
+ /**
66
+ * A durable promotion record: which notifications one boundary of one lineage
67
+ * delivered.
68
+ *
69
+ * The triple `(runId, targetLineageId, boundary)` is the unit of promotion, so
70
+ * a second lineage draining the same boundary name is a separate record rather
71
+ * than a repeat of the first.
72
+ *
73
+ * @category models
74
+ * @since 0.1.0
75
+ */
76
+ export const Promoted = Schema.Struct({
77
+ boundary: Schema.String,
78
+ targetLineageId: Schema.String,
79
+ ids: Schema.Array(Schema.String)
80
+ });
81
+ /**
82
+ * Whether an owned event is an admission record.
83
+ *
84
+ * @param event an owned event
85
+ * @category refinements
86
+ * @since 1.0.0
87
+ */
88
+ export const isAdmitted = (event) => "notification" in event;
89
+ /**
90
+ * Whether an owned event is a promotion record.
91
+ *
92
+ * @param event an owned event
93
+ * @category refinements
94
+ * @since 1.0.0
95
+ */
96
+ export const isPromoted = (event) => !isAdmitted(event);
97
+ /**
98
+ * The journal source every admission of one notification is written under.
99
+ *
100
+ * @param notificationId the admitted notification's id
101
+ * @category constructors
102
+ * @since 1.0.0
103
+ */
104
+ export const admissionSourceId = (notificationId) => JournalEvent.SourceId.make(`${admissionSourcePrefix}${notificationId}`);
105
+ /**
106
+ * The identity of one drain: the lineage and the boundary, each encoded so a
107
+ * value containing a slash cannot forge another pair's identity.
108
+ *
109
+ * @param targetLineageId the lineage the boundary closed on
110
+ * @param boundary the boundary name
111
+ * @category constructors
112
+ * @since 1.0.0
113
+ */
114
+ export const drainKey = (targetLineageId, boundary) => `${encodeURIComponent(targetLineageId)}/${encodeURIComponent(boundary)}`;
115
+ /**
116
+ * The journal source one drain's promotion record is written under.
117
+ *
118
+ * @param targetLineageId the lineage the boundary closed on
119
+ * @param boundary the boundary name
120
+ * @category constructors
121
+ * @since 1.0.0
122
+ */
123
+ export const drainSourceId = (targetLineageId, boundary) => JournalEvent.SourceId.make(`${drainSourcePrefix}${drainKey(targetLineageId, boundary)}`);
124
+ const admissionSourcePrefix = "/notifications/admission/";
125
+ const drainSourcePrefix = "/notifications/drain/";
126
+ const decodeAdmitted = Schema.decodeUnknownOption(Admitted);
127
+ const decodePromoted = Schema.decodeUnknownOption(Promoted);
128
+ /**
129
+ * Decodes an owned notification event from a journal entry.
130
+ *
131
+ * Foreign entries and structurally invalid payloads decode to `None` so a
132
+ * projection over a shared journal stays total.
133
+ *
134
+ * The event type alone does not make an entry owned: any producer on a shared
135
+ * journal can choose one. An admission counts only under
136
+ * {@link admissionSourceId} for the notification it carries, and a promotion
137
+ * only under the `/notifications/drain/` source family the queue writes, so
138
+ * another producer's record with the same event type stays out of the
139
+ * projection. This scopes records; it does not authenticate the writer. The
140
+ * journal fences writes on run ownership, not on source, so a writer that
141
+ * sets this package's source id is read as this package. The drain check is
142
+ * a prefix because records written before the lineage joined the identity
143
+ * carry the boundary alone.
144
+ *
145
+ * @param entry one journal entry, owned or foreign
146
+ * @category constructors
147
+ * @since 0.1.0
148
+ */
149
+ export const fromEntry = (entry) => {
150
+ if (entry.eventType === AdmittedEventType) {
151
+ return Option.filter(decodeAdmitted(entry.payload), (event) => entry.sourceId === admissionSourceId(event.notification.id));
152
+ }
153
+ if (entry.eventType === PromotedEventType && entry.sourceId.startsWith(drainSourcePrefix)) {
154
+ return decodePromoted(entry.payload);
155
+ }
156
+ return Option.none();
157
+ };
158
+ //# sourceMappingURL=NotificationEvent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NotificationEvent.js","sourceRoot":"","sources":["../../src/NotificationEvent.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Journal event types owned by the notification queue.\n *\n * @since 0.1.0\n */\n\nimport { JournalEvent } from \"@smthrs/journal\"\nimport * as Option from \"effect/Option\"\nimport * as Schema from \"effect/Schema\"\nimport * as Notification from \"./Notification.ts\"\n\n/**\n * The journal `eventType` recorded for one admission decision.\n *\n * The spelling is slashes and a PascalCase leaf, where every other event type\n * in this repository is dot-separated and lowercase (`control.run.parked`,\n * `flows.alerts.delivered`). The value is already durable in every engine\n * database, and a rename would silently stop matching the projections that\n * consumers key on, so it stays as written. A foreign projection must match\n * this literal rather than the repository convention, which is why the two\n * spellings are frozen by `test/WireFormat.test.ts`.\n *\n * @category constants\n * @since 0.1.0\n */\nexport const AdmittedEventType = \"flows/notifications/Admitted\"\n\n/**\n * The journal `eventType` recorded when pending notifications are promoted.\n *\n * Spelled like {@link AdmittedEventType}, and frozen for the same reason.\n *\n * @category constants\n * @since 0.1.0\n */\nexport const PromotedEventType = \"flows/notifications/Promoted\"\n\n/**\n * What a durable admission record says was decided.\n *\n * This is the one declaration of the admission vocabulary: it validates every\n * journal entry through {@link fromEntry}, and `NotificationState` types its\n * public signatures against it, so a fourth decision cannot be added to one\n * half and forgotten in the other.\n *\n * @category models\n * @since 1.0.0\n */\nexport const AdmissionDecision = Schema.Literals([\"admitted\", \"coalesced\", \"rejected-full\"])\n\n/**\n * The decoded form of {@link AdmissionDecision}.\n *\n * @category models\n * @since 1.0.0\n */\nexport type AdmissionDecision = typeof AdmissionDecision.Type\n\n/**\n * A durable admission record: the notification a run was told about, and what\n * the queue decided to do with it.\n *\n * A `rejected-full` decision is never written. The queue refuses a full queue\n * in the receipt alone, so the notification id stays admissible once a\n * boundary drains. The literal remains in {@link AdmissionDecision} because a\n * reader must stay total over a record any writer could have produced.\n *\n * @category models\n * @since 0.1.0\n */\nexport const Admitted = Schema.Struct({\n notification: Notification.Notification,\n decision: AdmissionDecision,\n /** SHA-256 of canonical validated input, absent in legacy admission rows. */\n fingerprint: Schema.optional(Schema.String),\n version: Schema.optional(Schema.Number)\n})\n\n/**\n * The decoded form of {@link Admitted}.\n *\n * @category models\n * @since 0.1.0\n */\nexport type Admitted = typeof Admitted.Type\n\n/**\n * A durable promotion record: which notifications one boundary of one lineage\n * delivered.\n *\n * The triple `(runId, targetLineageId, boundary)` is the unit of promotion, so\n * a second lineage draining the same boundary name is a separate record rather\n * than a repeat of the first.\n *\n * @category models\n * @since 0.1.0\n */\nexport const Promoted = Schema.Struct({\n boundary: Schema.String,\n targetLineageId: Schema.String,\n ids: Schema.Array(Schema.String)\n})\n\n/**\n * The decoded form of {@link Promoted}.\n *\n * @category models\n * @since 0.1.0\n */\nexport type Promoted = typeof Promoted.Type\n\n/**\n * Any journal event owned by this package.\n *\n * The two members are told apart with {@link isAdmitted} and\n * {@link isPromoted} rather than a stored discriminant, because the discriminant\n * would be a durable field this vocabulary does not have.\n *\n * @category models\n * @since 0.1.0\n */\nexport type Event = Admitted | Promoted\n\n/**\n * Whether an owned event is an admission record.\n *\n * @param event an owned event\n * @category refinements\n * @since 1.0.0\n */\nexport const isAdmitted = (event: Event): event is Admitted => \"notification\" in event\n\n/**\n * Whether an owned event is a promotion record.\n *\n * @param event an owned event\n * @category refinements\n * @since 1.0.0\n */\nexport const isPromoted = (event: Event): event is Promoted => !isAdmitted(event)\n\n/**\n * The journal source every admission of one notification is written under.\n *\n * @param notificationId the admitted notification's id\n * @category constructors\n * @since 1.0.0\n */\nexport const admissionSourceId = (notificationId: string): JournalEvent.SourceId =>\n JournalEvent.SourceId.make(`${admissionSourcePrefix}${notificationId}`)\n\n/**\n * The identity of one drain: the lineage and the boundary, each encoded so a\n * value containing a slash cannot forge another pair's identity.\n *\n * @param targetLineageId the lineage the boundary closed on\n * @param boundary the boundary name\n * @category constructors\n * @since 1.0.0\n */\nexport const drainKey = (targetLineageId: string, boundary: string): string =>\n `${encodeURIComponent(targetLineageId)}/${encodeURIComponent(boundary)}`\n\n/**\n * The journal source one drain's promotion record is written under.\n *\n * @param targetLineageId the lineage the boundary closed on\n * @param boundary the boundary name\n * @category constructors\n * @since 1.0.0\n */\nexport const drainSourceId = (targetLineageId: string, boundary: string): JournalEvent.SourceId =>\n JournalEvent.SourceId.make(`${drainSourcePrefix}${drainKey(targetLineageId, boundary)}`)\n\nconst admissionSourcePrefix = \"/notifications/admission/\"\nconst drainSourcePrefix = \"/notifications/drain/\"\n\nconst decodeAdmitted = Schema.decodeUnknownOption(Admitted)\nconst decodePromoted = Schema.decodeUnknownOption(Promoted)\n\n/**\n * Decodes an owned notification event from a journal entry.\n *\n * Foreign entries and structurally invalid payloads decode to `None` so a\n * projection over a shared journal stays total.\n *\n * The event type alone does not make an entry owned: any producer on a shared\n * journal can choose one. An admission counts only under\n * {@link admissionSourceId} for the notification it carries, and a promotion\n * only under the `/notifications/drain/` source family the queue writes, so\n * another producer's record with the same event type stays out of the\n * projection. This scopes records; it does not authenticate the writer. The\n * journal fences writes on run ownership, not on source, so a writer that\n * sets this package's source id is read as this package. The drain check is\n * a prefix because records written before the lineage joined the identity\n * carry the boundary alone.\n *\n * @param entry one journal entry, owned or foreign\n * @category constructors\n * @since 0.1.0\n */\nexport const fromEntry = (entry: JournalEvent.Entry): Option.Option<Event> => {\n if (entry.eventType === AdmittedEventType) {\n return Option.filter(\n decodeAdmitted(entry.payload),\n (event) => entry.sourceId === admissionSourceId(event.notification.id)\n )\n }\n if (entry.eventType === PromotedEventType && entry.sourceId.startsWith(drainSourcePrefix)) {\n return decodePromoted(entry.payload)\n }\n return Option.none()\n}\n"]}
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Journal-backed durable notification admission and turn-boundary drain.
3
+ *
4
+ * Governing contract: `packages/smithers/notifications/docs/api.md`, published as
5
+ * `/api/notifications`.
6
+ *
7
+ * @since 0.1.0
8
+ */
9
+ import { Journal } from "@smthrs/journal";
10
+ import { Context, Effect, Layer, Schema } from "effect";
11
+ import * as NotificationModel from "./Notification.ts";
12
+ import * as NotificationState from "./NotificationState.ts";
13
+ declare const NotificationError_base: Schema.Class<NotificationError, Schema.TaggedStruct<"/notifications/NotificationError", {
14
+ readonly code: Schema.withConstructorDefault<Schema.Literals<readonly ["notification_unavailable", "notification_closed", "notification_full", "notification_id_reused", "notification_invalid", "notification_refused"]>>;
15
+ readonly message: Schema.String;
16
+ /** The notification the failure is about, when one was readable. */
17
+ readonly notificationId: Schema.optional<Schema.String>;
18
+ /** Dotted path of the offending field, for `notification_invalid`. */
19
+ readonly path: Schema.optional<Schema.String>;
20
+ }>, import("effect/Cause").YieldableError>;
21
+ /**
22
+ * The queue could not be reached, or it refused what a caller handed it.
23
+ *
24
+ * `code` is the stable half and the one to branch on. `notification_unavailable`
25
+ * is the seam reporting that it serves nothing; `notification_id_reused` says a
26
+ * stable id was admitted once already with different content, which is a
27
+ * producer bug rather than a storage failure; `notification_invalid` says the
28
+ * value is not a notification, and `path` names the field inside it that failed.
29
+ * `notification_closed` means the receiver has finished and the caller must
30
+ * start a new request; `notification_full` means nothing was retained and the
31
+ * same notification may be retried after pending work drains. Neither the
32
+ * message nor `path` ever carries the offending value.
33
+ * `notification_refused` rejects reserved outside-change payloads before admission.
34
+ *
35
+ * @category errors
36
+ * @since 0.1.0
37
+ */
38
+ export declare class NotificationError extends NotificationError_base {
39
+ }
40
+ /**
41
+ * What admitting one notification decided.
42
+ *
43
+ * `seq` is the journal sequence the admission committed at, and it is absent
44
+ * exactly when nothing was written, which today means a `rejected-full`
45
+ * refusal. `duplicate` says the id was already admitted, in which case
46
+ * `decision` and `seq` are read back from the committed record rather than
47
+ * recomputed here.
48
+ *
49
+ * A caller MUST inspect `decision`: `rejected-full` means the queue was at
50
+ * capacity and retained nothing, so the notification never reaches the model
51
+ * unless the caller admits it again once a boundary has drained.
52
+ *
53
+ * @category models
54
+ * @since 0.1.0
55
+ */
56
+ export interface AdmissionReceipt {
57
+ readonly notificationId: string;
58
+ readonly decision: NotificationState.AdmissionDecision;
59
+ readonly seq: number | undefined;
60
+ readonly duplicate: boolean;
61
+ readonly consumed?: boolean;
62
+ readonly consumedNotification?: NotificationModel.Notification;
63
+ }
64
+ /**
65
+ * The boundary a drain is attempted at, and whether the run would go idle
66
+ * if nothing were delivered.
67
+ *
68
+ * `(runId, targetLineageId, boundary)` is the unit of drain: two lineages
69
+ * closing a turn under the same boundary name are two drains, and each is
70
+ * recorded separately.
71
+ *
72
+ * @category models
73
+ * @since 0.1.0
74
+ */
75
+ export interface DrainInput {
76
+ readonly runId: string;
77
+ readonly targetLineageId: string;
78
+ readonly boundary: string;
79
+ readonly wouldIdle: boolean;
80
+ /**
81
+ * The journal sequence that opened this turn. A steer admitted after it is
82
+ * held for the next boundary, which is what keeps a message that arrived
83
+ * mid-turn out of the turn already in flight. Omitting it delivers
84
+ * everything pending for the lineage. A value that is not a non-negative
85
+ * integer fails the drain with `notification_invalid` and records nothing.
86
+ */
87
+ readonly cutoffSeq?: number | undefined;
88
+ }
89
+ /**
90
+ * The notifications this boundary delivers, and whether the boundary had
91
+ * already drained.
92
+ *
93
+ * The notifications are the ones the committed promotion record names, so two
94
+ * processes draining one boundary report the same delivery rather than two
95
+ * divergent guesses.
96
+ *
97
+ * @category models
98
+ * @since 0.1.0
99
+ */
100
+ export interface DrainReceipt {
101
+ readonly notifications: ReadonlyArray<NotificationModel.Notification>;
102
+ readonly boundary: string;
103
+ readonly duplicate: boolean;
104
+ }
105
+ /**
106
+ * The durable pending queue: admit a notification exactly once, and drain
107
+ * what a boundary is allowed to deliver.
108
+ *
109
+ * @category services
110
+ * @since 0.1.0
111
+ */
112
+ export interface Service {
113
+ readonly admit: (runId: string, notification: NotificationModel.Notification, version?: number) => Effect.Effect<AdmissionReceipt, Journal.JournalError | NotificationError>;
114
+ readonly drain: (input: DrainInput) => Effect.Effect<DrainReceipt, Journal.JournalError | NotificationError>;
115
+ /**
116
+ * What this run has been told that no boundary has delivered yet, in
117
+ * admission order.
118
+ *
119
+ * The queue is the owner of that fact: pending is admitted minus promoted,
120
+ * and both halves are its own journal records. A supervisor that counted
121
+ * admissions alone would report a steer as waiting forever.
122
+ */
123
+ readonly pending: (runId: string) => Effect.Effect<ReadonlyArray<NotificationModel.Notification>, Journal.JournalError | NotificationError>;
124
+ }
125
+ declare const NotificationQueue_base: Context.ServiceClass<NotificationQueue, "/notifications/NotificationQueue", Service>;
126
+ /**
127
+ * The {@link Service} tag.
128
+ *
129
+ * @category services
130
+ * @since 0.1.0
131
+ */
132
+ export declare class NotificationQueue extends NotificationQueue_base {
133
+ }
134
+ /**
135
+ * Builds a {@link Service} from an implementation of its methods.
136
+ *
137
+ * @param implementation the methods to serve
138
+ * @category constructors
139
+ * @since 0.1.0
140
+ */
141
+ export declare const make: (implementation: Service) => Service;
142
+ /**
143
+ * A {@link Service} that fails every method as unavailable. Overrides
144
+ * replace individual methods.
145
+ *
146
+ * @param overrides methods to serve instead of failing
147
+ * @category constructors
148
+ * @since 0.1.0
149
+ */
150
+ export declare const makeNoop: (overrides?: Partial<Service>) => Service;
151
+ /**
152
+ * Provides {@link makeNoop}.
153
+ *
154
+ * @param overrides methods to serve instead of failing
155
+ * @category layers
156
+ * @since 0.1.0
157
+ */
158
+ export declare const layerNoop: (overrides?: Partial<Service>) => Layer.Layer<NotificationQueue>;
159
+ /**
160
+ * Journal-backed production layer, with the pending capacity a composition
161
+ * chooses.
162
+ *
163
+ * Admission and drain evidence is written through `emitDurableUnfenced`, so
164
+ * both return only after the corresponding entry is durably committed and a
165
+ * dropped lifecycle event is unrepresentable. The channel is the unfenced one
166
+ * on purpose: the notifying process owns no run, so there is no ownership
167
+ * fence to hand over, and both records are first-writer-wins on their own
168
+ * identity instead.
169
+ *
170
+ * The capacity guard is a conditional write at the storage layer, not a check
171
+ * against a fold one process happened to load: the fold, the guard, and the
172
+ * admission record are decided and written inside ONE `journal.transact`
173
+ * write transaction, which the durable writer serializes against every other
174
+ * writer of the database and replays when a concurrent writer commits between
175
+ * the guard's reads and the insert. Two processes admitting to one full queue
176
+ * therefore produce one admission and one `rejected-full`, never two
177
+ * admissions.
178
+ *
179
+ * @param options the pending capacity, defaulting to `NotificationState.defaultCapacity`
180
+ * @category layers
181
+ * @since 1.0.0
182
+ */
183
+ export declare const layerWith: (options?: {
184
+ readonly capacity?: number | undefined;
185
+ }) => Layer.Layer<NotificationQueue, never, Journal.Journal>;
186
+ /**
187
+ * Journal-backed production layer at the default capacity.
188
+ *
189
+ * @category layers
190
+ * @since 0.1.0
191
+ */
192
+ export declare const layer: Layer.Layer<NotificationQueue, never, Journal.Journal>;
193
+ export {};
194
+ //# sourceMappingURL=NotificationQueue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NotificationQueue.d.ts","sourceRoot":"","sources":["../../src/NotificationQueue.ts"],"names":[],"mappings":"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"}