@thomasfosterau/pulpit 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 (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1271 -1
  3. package/dist/blobs.d.ts +249 -0
  4. package/dist/blobs.d.ts.map +1 -0
  5. package/dist/blobs.js +193 -0
  6. package/dist/blobs.js.map +1 -0
  7. package/dist/budgets.d.ts +255 -0
  8. package/dist/budgets.d.ts.map +1 -0
  9. package/dist/budgets.js +211 -0
  10. package/dist/budgets.js.map +1 -0
  11. package/dist/cache.d.ts +154 -0
  12. package/dist/cache.d.ts.map +1 -0
  13. package/dist/cache.js +118 -0
  14. package/dist/cache.js.map +1 -0
  15. package/dist/collections.d.ts +242 -0
  16. package/dist/collections.d.ts.map +1 -0
  17. package/dist/collections.js +215 -0
  18. package/dist/collections.js.map +1 -0
  19. package/dist/comments.d.ts +212 -0
  20. package/dist/comments.d.ts.map +1 -0
  21. package/dist/comments.js +192 -0
  22. package/dist/comments.js.map +1 -0
  23. package/dist/content.d.ts +231 -0
  24. package/dist/content.d.ts.map +1 -0
  25. package/dist/content.js +204 -0
  26. package/dist/content.js.map +1 -0
  27. package/dist/documents.d.ts +184 -0
  28. package/dist/documents.d.ts.map +1 -0
  29. package/dist/documents.js +190 -0
  30. package/dist/documents.js.map +1 -0
  31. package/dist/edges.d.ts +645 -0
  32. package/dist/edges.d.ts.map +1 -0
  33. package/dist/edges.js +558 -0
  34. package/dist/edges.js.map +1 -0
  35. package/dist/filter.d.ts +461 -0
  36. package/dist/filter.d.ts.map +1 -0
  37. package/dist/filter.js +387 -0
  38. package/dist/filter.js.map +1 -0
  39. package/dist/index.d.ts +133 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +133 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/internal/filter-columns.d.ts +8 -0
  44. package/dist/internal/filter-columns.d.ts.map +1 -0
  45. package/dist/internal/filter-columns.js +43 -0
  46. package/dist/internal/filter-columns.js.map +1 -0
  47. package/dist/internal/list-order.d.ts +26 -0
  48. package/dist/internal/list-order.d.ts.map +1 -0
  49. package/dist/internal/list-order.js +92 -0
  50. package/dist/internal/list-order.js.map +1 -0
  51. package/dist/internal/owned-columns.d.ts +93 -0
  52. package/dist/internal/owned-columns.d.ts.map +1 -0
  53. package/dist/internal/owned-columns.js +98 -0
  54. package/dist/internal/owned-columns.js.map +1 -0
  55. package/dist/internal/plain-rows.d.ts +32 -0
  56. package/dist/internal/plain-rows.d.ts.map +1 -0
  57. package/dist/internal/plain-rows.js +32 -0
  58. package/dist/internal/plain-rows.js.map +1 -0
  59. package/dist/internal/reference-columns.d.ts +80 -0
  60. package/dist/internal/reference-columns.d.ts.map +1 -0
  61. package/dist/internal/reference-columns.js +102 -0
  62. package/dist/internal/reference-columns.js.map +1 -0
  63. package/dist/moderation.d.ts +392 -0
  64. package/dist/moderation.d.ts.map +1 -0
  65. package/dist/moderation.js +375 -0
  66. package/dist/moderation.js.map +1 -0
  67. package/dist/paths.d.ts +204 -0
  68. package/dist/paths.d.ts.map +1 -0
  69. package/dist/paths.js +165 -0
  70. package/dist/paths.js.map +1 -0
  71. package/dist/proposals.d.ts +523 -0
  72. package/dist/proposals.d.ts.map +1 -0
  73. package/dist/proposals.js +505 -0
  74. package/dist/proposals.js.map +1 -0
  75. package/dist/publication.d.ts +148 -0
  76. package/dist/publication.d.ts.map +1 -0
  77. package/dist/publication.js +183 -0
  78. package/dist/publication.js.map +1 -0
  79. package/dist/purge.d.ts +224 -0
  80. package/dist/purge.d.ts.map +1 -0
  81. package/dist/purge.js +151 -0
  82. package/dist/purge.js.map +1 -0
  83. package/dist/reactions.d.ts +246 -0
  84. package/dist/reactions.d.ts.map +1 -0
  85. package/dist/reactions.js +183 -0
  86. package/dist/reactions.js.map +1 -0
  87. package/dist/registry.d.ts +316 -0
  88. package/dist/registry.d.ts.map +1 -0
  89. package/dist/registry.js +305 -0
  90. package/dist/registry.js.map +1 -0
  91. package/dist/search.d.ts +366 -0
  92. package/dist/search.d.ts.map +1 -0
  93. package/dist/search.js +273 -0
  94. package/dist/search.js.map +1 -0
  95. package/dist/social.d.ts +311 -0
  96. package/dist/social.d.ts.map +1 -0
  97. package/dist/social.js +205 -0
  98. package/dist/social.js.map +1 -0
  99. package/dist/subtype.d.ts +1613 -0
  100. package/dist/subtype.d.ts.map +1 -0
  101. package/dist/subtype.js +1300 -0
  102. package/dist/subtype.js.map +1 -0
  103. package/dist/testing.d.ts +675 -0
  104. package/dist/testing.d.ts.map +1 -0
  105. package/dist/testing.js +1022 -0
  106. package/dist/testing.js.map +1 -0
  107. package/dist/version-chain.d.ts +702 -0
  108. package/dist/version-chain.d.ts.map +1 -0
  109. package/dist/version-chain.js +489 -0
  110. package/dist/version-chain.js.map +1 -0
  111. package/dist/working-copy.d.ts +116 -0
  112. package/dist/working-copy.d.ts.map +1 -0
  113. package/dist/working-copy.js +95 -0
  114. package/dist/working-copy.js.map +1 -0
  115. package/package.json +138 -4
  116. package/src/blobs.ts +384 -0
  117. package/src/budgets.ts +338 -0
  118. package/src/cache.ts +218 -0
  119. package/src/collections.ts +427 -0
  120. package/src/comments.ts +392 -0
  121. package/src/content.ts +238 -0
  122. package/src/documents.ts +284 -0
  123. package/src/edges.ts +1185 -0
  124. package/src/filter.ts +523 -0
  125. package/src/index.ts +153 -0
  126. package/src/internal/filter-columns.ts +50 -0
  127. package/src/internal/list-order.ts +117 -0
  128. package/src/internal/owned-columns.ts +140 -0
  129. package/src/internal/plain-rows.ts +54 -0
  130. package/src/internal/reference-columns.ts +156 -0
  131. package/src/moderation.ts +728 -0
  132. package/src/paths.ts +267 -0
  133. package/src/proposals.ts +1014 -0
  134. package/src/publication.ts +225 -0
  135. package/src/purge.ts +313 -0
  136. package/src/reactions.ts +347 -0
  137. package/src/registry.ts +524 -0
  138. package/src/search.ts +540 -0
  139. package/src/social.ts +469 -0
  140. package/src/subtype.ts +3095 -0
  141. package/src/testing.ts +1873 -0
  142. package/src/version-chain.ts +1093 -0
  143. package/src/working-copy.ts +192 -0
@@ -0,0 +1,523 @@
1
+ /**
2
+ * **Suggested edits (proposals)** — a contributor's patch against a node
3
+ * they can read, stamped with the version it was written against, which
4
+ * the node's writer accepts (appending it) or rejects.
5
+ *
6
+ * The behavioural spec is gardeneria's `apps/api/src/operations/proposals.ts`,
7
+ * `proposal-patch.ts` and `proposal-conflict.ts` (#565), with their tests; a
8
+ * `#NNN` here names a gardeneria issue.
9
+ *
10
+ * ## The model (owner decisions on pulpit#49)
11
+ *
12
+ * - **A proposal is a plain row, not a node.** It carries the target, the
13
+ * patch as submitted, the `baseVersion` it was written against (stamped
14
+ * from the target's head, never client-supplied), its status (`pending |
15
+ * accepted | rejected | withdrawn`), the reviewer and the timestamps.
16
+ * Rejecting or withdrawing changes its status; only accepting writes to
17
+ * the target.
18
+ * - **Accepting appends through the target's own `update`** (`PUB-003`), as
19
+ * the account that accepted, so it runs the target's gate, its precondition
20
+ * and its before hooks, and lands as an ordinary `update` version
21
+ * (`VERSION-CHAIN-001/002`). The version records the proposer as its
22
+ * `proposedBy` fact beside that actor, so history shows both.
23
+ *
24
+ * ## Classification, in two tiers (#565, decision 2)
25
+ *
26
+ * - {@link classifyProposalBase} — `clean` or `moved`, from two version
27
+ * numbers in hand: no read, safe for every row of a list page.
28
+ * - {@link classifyProposalConflict} — `clean`, `stale` or `conflicting`,
29
+ * from the target's states at the base version and at the head
30
+ * (`diffStates`): two version reads, so only {@link ProposalOps.review}
31
+ * and {@link ProposalOps.accept} run it (`PERF-DB-003`).
32
+ *
33
+ * A touched attribute either state lacks (one kept in a side table, outside
34
+ * the chain) cannot be compared, so on a moved target it counts as
35
+ * conflicting: fail closed, since `stale` would let an accept overwrite a
36
+ * change nobody looked at.
37
+ *
38
+ * ## The gates
39
+ *
40
+ * - **Submit:** a signed-in account at the application's propose rung
41
+ * ({@link ProposalsDefinition.canPropose}) that can `get` the target; a
42
+ * target it can't read fails `NodeNotFound`, never `Forbidden`
43
+ * (`SEC-AUTH-ENUM-001`).
44
+ * - **Accept / reject / review:** the target's write gate (`requireWriter`:
45
+ * owner-or-moderator on an owned leaf, the corpus-write rung on a reference
46
+ * one), before the proposal's status is disclosed. Accept and review then
47
+ * read the two versions through the target's gated `compare` (`READ-009`).
48
+ * - **Withdraw:** the proposal's own author, while it is pending.
49
+ * - **Reads:** the moderate rung reads every proposal; any other signed-in
50
+ * account reads its own and those on targets it owns; the anonymous read
51
+ * none. A proposal is never public.
52
+ *
53
+ * ## A localised leaf (pulpit#184)
54
+ *
55
+ * On a leaf with a locale level (pulpit#56) a proposal may also carry a
56
+ * per-locale patch over the leaf's translated columns
57
+ * ({@link ProposalsDefinition.localeAttributes}), stored beside its shared
58
+ * patch and accepted through the same `update` as one version. Its conflict
59
+ * check reads each touched locale at the base and at the head: a touched
60
+ * translated column conflicts when it changed, when either version lacks it,
61
+ * or when the locale was added or dropped in between. A proposal may add a
62
+ * translation but never drop one (a `null` locale is refused): removing a
63
+ * locale is the owner's.
64
+ *
65
+ * A write budget (pulpit#199) is an opt-in: `budget` throttles `submit`.
66
+ * Notifications and the wire shape are the application's.
67
+ *
68
+ * @copyright Thomas Foster
69
+ * @module pulpit/proposals
70
+ * @since 0.1.0
71
+ */
72
+ import * as Effect from "effect/Effect";
73
+ import * as Option from "effect/Option";
74
+ import * as Schema from "effect/Schema";
75
+ import type { BoundBudget } from "./budgets.ts";
76
+ import { type ListFilter } from "./filter.ts";
77
+ import { Forbidden, Unauthorized, type AccessPolicy, type Page, type SubtypeOps, type Viewer, type ViewerAccount, type WriteRejected } from "./subtype.ts";
78
+ import { NodeNotFound, type ChainPatch, type LocalePatch, type ChainWrite, type StaleVersion, type VersionChainStore, type VersionConflict, type VersionNotFound, type VersionSnapshot } from "./version-chain.ts";
79
+ /**
80
+ * A proposal's status. `pending` is the only open one; the other three are
81
+ * terminal, and a withdrawn proposal is recorded, not deleted.
82
+ *
83
+ * @since 0.1.0
84
+ */
85
+ export declare const ProposalStatus: Schema.Literals<readonly ["pending", "accepted", "rejected", "withdrawn"]>;
86
+ /**
87
+ * The {@link ProposalStatus} literal union.
88
+ *
89
+ * @since 0.1.0
90
+ */
91
+ export type ProposalStatus = typeof ProposalStatus.Type;
92
+ /**
93
+ * The cheap verdict: `moved` means "stale or conflicting, not yet told
94
+ * apart", never a claim that the patch still applies.
95
+ *
96
+ * @since 0.1.0
97
+ */
98
+ export type ProposalBaseState = "clean" | "moved";
99
+ /**
100
+ * The full verdict: `clean` (the target has not moved), `stale` (it moved,
101
+ * but no touched attribute changed) or `conflicting`.
102
+ *
103
+ * @since 0.1.0
104
+ */
105
+ export type ProposalConflictState = "clean" | "stale" | "conflicting";
106
+ /**
107
+ * One proposal row, as the {@link ProposalStore} keeps it.
108
+ *
109
+ * @since 0.1.0
110
+ */
111
+ export interface ProposalRow {
112
+ readonly id: string;
113
+ /** The target node and its leaf type. */
114
+ readonly targetId: string;
115
+ readonly targetType: string;
116
+ /** The proposer. */
117
+ readonly authorId: string;
118
+ /** The patch as submitted (what the reviewer reads), decoded again at accept. */
119
+ readonly patch: Schema.Json;
120
+ /**
121
+ * A localised leaf's per-locale patch as submitted (pulpit#184), decoded
122
+ * again at accept; none for a proposal that touches no translation.
123
+ */
124
+ readonly locales: Option.Option<Schema.Json>;
125
+ readonly rationale: Option.Option<string>;
126
+ /** The target's head when the proposal was submitted. */
127
+ readonly baseVersion: bigint;
128
+ readonly status: ProposalStatus;
129
+ readonly submittedAt: Date;
130
+ /** When, and by whom, it left `pending` (the author, for a withdrawal). */
131
+ readonly decidedAt: Option.Option<Date>;
132
+ readonly decidedBy: Option.Option<string>;
133
+ readonly decisionNote: Option.Option<string>;
134
+ /** The version an accepted proposal produced: its provenance pointer. */
135
+ readonly appliedVersion: Option.Option<bigint>;
136
+ }
137
+ /**
138
+ * A proposal row as a read returns it, with the target's head version (none
139
+ * when the target has no versions), read in the same query.
140
+ *
141
+ * @since 0.1.0
142
+ */
143
+ export interface ProposalListing {
144
+ readonly row: ProposalRow;
145
+ readonly targetVersion: Option.Option<bigint>;
146
+ }
147
+ /**
148
+ * The write that closes a pending proposal.
149
+ *
150
+ * @since 0.1.0
151
+ */
152
+ export interface ProposalDecision {
153
+ readonly status: Exclude<ProposalStatus, "pending">;
154
+ readonly decidedAt: Date;
155
+ readonly decidedBy: string;
156
+ readonly decisionNote: Option.Option<string>;
157
+ readonly appliedVersion: Option.Option<bigint>;
158
+ }
159
+ declare const ProposalNotFound_base: Schema.Class<ProposalNotFound, Schema.TaggedStruct<"ProposalNotFound", {
160
+ readonly id: Schema.String;
161
+ }>, import("effect/Cause").YieldableError & {
162
+ readonly brand: unique symbol;
163
+ }>;
164
+ /**
165
+ * No proposal at that id that the viewer may read: the wire's 404.
166
+ *
167
+ * @since 0.1.0
168
+ */
169
+ export declare class ProposalNotFound extends ProposalNotFound_base {
170
+ }
171
+ declare const ProposalClosed_base: Schema.Class<ProposalClosed, Schema.TaggedStruct<"ProposalClosed", {
172
+ readonly id: Schema.String;
173
+ readonly status: Schema.Literals<readonly ["pending", "accepted", "rejected", "withdrawn"]>;
174
+ }>, import("effect/Cause").YieldableError & {
175
+ readonly brand: unique symbol;
176
+ }>;
177
+ /**
178
+ * The proposal is no longer pending, so it can't be decided or withdrawn
179
+ * again: the wire's 409.
180
+ *
181
+ * @since 0.1.0
182
+ */
183
+ export declare class ProposalClosed extends ProposalClosed_base {
184
+ }
185
+ declare const ProposalConflict_base: Schema.Class<ProposalConflict, Schema.TaggedStruct<"ProposalConflict", {
186
+ readonly id: Schema.String;
187
+ readonly attributes: Schema.$Array<Schema.String>;
188
+ /** The conflicting translated columns, by locale (pulpit#184); `{}` when none. */
189
+ readonly locales: Schema.$Record<Schema.String, Schema.$Array<Schema.String>>;
190
+ }>, import("effect/Cause").YieldableError & {
191
+ readonly brand: unique symbol;
192
+ }>;
193
+ /**
194
+ * The target changed underneath a touched attribute since the proposal was
195
+ * written (or one can't be compared), so accepting would overwrite an edit
196
+ * the reviewer never saw: the wire's 409. Reject it and resubmit against
197
+ * the new head.
198
+ *
199
+ * @since 0.1.0
200
+ */
201
+ export declare class ProposalConflict extends ProposalConflict_base {
202
+ }
203
+ declare const InvalidProposalPatch_base: Schema.Class<InvalidProposalPatch, Schema.TaggedStruct<"InvalidProposalPatch", {
204
+ readonly type: Schema.String;
205
+ readonly reason: Schema.String;
206
+ }>, import("effect/Cause").YieldableError & {
207
+ readonly brand: unique symbol;
208
+ }>;
209
+ /**
210
+ * A patch that can't be proposed: not an object, empty, touching a
211
+ * forbidden or unknown attribute, or refused by the leaf's decoder. The
212
+ * wire's 422.
213
+ *
214
+ * @since 0.1.0
215
+ */
216
+ export declare class InvalidProposalPatch extends InvalidProposalPatch_base {
217
+ }
218
+ /**
219
+ * The cheap verdict, from the base version and the target's head: `clean`
220
+ * only when they are equal.
221
+ *
222
+ * @example
223
+ * ```ts
224
+ * import { strictEqual } from "node:assert";
225
+ * import { classifyProposalBase } from "@thomasfosterau/pulpit/proposals";
226
+ *
227
+ * strictEqual(classifyProposalBase(4n, 4n), "clean");
228
+ * strictEqual(classifyProposalBase(4n, 5n), "moved");
229
+ * ```
230
+ *
231
+ * @since 0.1.0
232
+ */
233
+ export declare const classifyProposalBase: (baseVersion: bigint, currentVersion: bigint) => ProposalBaseState;
234
+ /**
235
+ * The full verdict, and the attributes responsible for it.
236
+ *
237
+ * @since 0.1.0
238
+ */
239
+ export interface ProposalConflictVerdict {
240
+ readonly state: ProposalConflictState;
241
+ /** The touched attributes that changed or can't be compared; empty unless `conflicting`. */
242
+ readonly conflictingAttributes: ReadonlyArray<string>;
243
+ /**
244
+ * The touched translated columns that changed or can't be compared, by
245
+ * locale (pulpit#184); a locale with none is omitted, so it is `{}` unless
246
+ * `conflicting`.
247
+ */
248
+ readonly conflictingLocales: TouchedLocales;
249
+ }
250
+ /**
251
+ * The translated columns a proposal touches, by locale (pulpit#184).
252
+ *
253
+ * @since 0.1.0
254
+ */
255
+ export type TouchedLocales = {
256
+ readonly [locale: string]: ReadonlyArray<string>;
257
+ };
258
+ /**
259
+ * The full verdict from the target's states at the base version and at the
260
+ * head, over the attributes the patch touches. Equal versions are `clean`
261
+ * without comparing anything. Otherwise a touched attribute conflicts when
262
+ * `diffStates` reports it changed (values compare structurally: a document
263
+ * by content, `null` against a value is a change, two `null`s are not) or
264
+ * when either state lacks it (fail closed).
265
+ *
266
+ * On a localised leaf, `touchedLocales` names the translated columns the
267
+ * proposal touches, by locale (pulpit#184), and each is read from the two
268
+ * versions' locale levels the same way. A locale neither version carries
269
+ * cannot conflict (a new translation); a locale only one carries (added or
270
+ * dropped in between) conflicts on every touched column. Pure.
271
+ *
272
+ * @example
273
+ * ```ts
274
+ * import { deepStrictEqual } from "node:assert";
275
+ * import { classifyProposalConflict } from "@thomasfosterau/pulpit/proposals";
276
+ *
277
+ * const at = (version: bigint, state: { readonly [column: string]: string }) => ({
278
+ * version,
279
+ * action: "update" as const,
280
+ * timestamp: new Date(0),
281
+ * state,
282
+ * });
283
+ * deepStrictEqual(
284
+ * classifyProposalConflict(at(4n, { name: "a", note: "x" }), at(5n, { name: "b", note: "x" }), [
285
+ * "name",
286
+ * "note",
287
+ * ]),
288
+ * { state: "conflicting", conflictingAttributes: ["name"], conflictingLocales: {} },
289
+ * );
290
+ * ```
291
+ *
292
+ * @since 0.1.0
293
+ */
294
+ export declare const classifyProposalConflict: (base: VersionSnapshot, current: VersionSnapshot, touchedKeys: ReadonlyArray<string>, touchedLocales?: TouchedLocales) => ProposalConflictVerdict;
295
+ /**
296
+ * The attributes no proposal may carry, whatever the leaf declares:
297
+ * identity (`id`, `type`) and the publication axes (`visibility`, `draft`,
298
+ * `publishedAt`), which are the owner's to set (`PUB-005`). An application
299
+ * adds its own through {@link ProposalsDefinition.forbidden} (gardeneria
300
+ * adds `slug`, a node's public URL).
301
+ *
302
+ * @since 0.1.0
303
+ */
304
+ export declare const PROPOSAL_FORBIDDEN_KEYS: ReadonlyArray<string>;
305
+ /**
306
+ * A patch that passed validation.
307
+ *
308
+ * @since 0.1.0
309
+ */
310
+ export interface ValidatedPatch {
311
+ /** The decoded patch, ready for the target's `update`. */
312
+ readonly patch: ChainPatch;
313
+ /** The attribute names it touches, in the leaf's declaration order. */
314
+ readonly touchedKeys: ReadonlyArray<string>;
315
+ /** The decoded per-locale patch (pulpit#184), ready for the target's `update`; `{}` for none. */
316
+ readonly locales: LocalePatch;
317
+ /** The translated columns it touches, by locale, each in the declaration order. */
318
+ readonly touchedLocales: TouchedLocales;
319
+ }
320
+ /**
321
+ * Check a submitted patch's shape and keys against the leaf's proposable
322
+ * `attributes` (its update fields, in declaration order) and the
323
+ * `forbidden` keys, then decode it with the leaf's own decoder. Unknown keys
324
+ * are refused loudly rather than dropped (a misspelt attribute would
325
+ * otherwise accept and change nothing). Run at submit and again at accept,
326
+ * since the leaf's schema may have moved in between. Fails
327
+ * {@link InvalidProposalPatch}.
328
+ *
329
+ * On a localised leaf, `options.locales` is the per-locale patch as
330
+ * submitted (pulpit#184): an object from a non-empty locale tag to an object
331
+ * of changes to `options.localeAttributes` (the translated columns), each
332
+ * checked and decoded as the shared patch is. A `null` locale (dropping a
333
+ * translation) is refused, as is any locale on a leaf with no
334
+ * `localeAttributes`. The shared patch may then be `{}`, so long as some
335
+ * locale changes something.
336
+ *
337
+ * @since 0.1.0
338
+ */
339
+ export declare const validateProposalPatch: <R>(type: string, patch: Schema.Json, options: {
340
+ readonly attributes: ReadonlyArray<string>;
341
+ readonly forbidden: ReadonlyArray<string>;
342
+ readonly decode: (patch: Schema.Json) => Effect.Effect<ChainPatch, InvalidProposalPatch, R>;
343
+ /** The per-locale patch as submitted (pulpit#184); absent, none. */
344
+ readonly locales?: Schema.Json | undefined;
345
+ /** The translated columns a proposal may touch, in declaration order; absent, none. */
346
+ readonly localeAttributes?: ReadonlyArray<string> | undefined;
347
+ }) => Effect.Effect<ValidatedPatch, InvalidProposalPatch, R>;
348
+ /**
349
+ * The proposal table an application supplies (gardeneria's
350
+ * `participation.proposal`). It applies no policy, never opens a
351
+ * transaction, and fails only with its `E`. See the package README → Seams
352
+ * for the expected schema.
353
+ *
354
+ * @since 0.1.0
355
+ */
356
+ export interface ProposalStore<E, R> {
357
+ /** Mint a fresh proposal id (a UUID). */
358
+ readonly mintId: Effect.Effect<string, E, R>;
359
+ /** Insert a new (pending) row. */
360
+ readonly insert: (row: ProposalRow) => Effect.Effect<void, E, R>;
361
+ /** One row with its target's head version, or none. */
362
+ readonly get: (id: string) => Effect.Effect<Option.Option<ProposalListing>, E, R>;
363
+ /**
364
+ * One row, locked for the rest of the transaction (`SELECT … FOR
365
+ * UPDATE`), so two decisions on one proposal serialise and the second
366
+ * sees it closed.
367
+ */
368
+ readonly lock: (id: string) => Effect.Effect<Option.Option<ProposalRow>, E, R>;
369
+ /** Close a pending row: write its terminal status, decider and provenance. */
370
+ readonly close: (id: string, decision: ProposalDecision) => Effect.Effect<void, E, R>;
371
+ /**
372
+ * The page under `where`, newest first (`submitted_at DESC, id DESC`,
373
+ * a total order), with the unpaged total. `where` reads the columns
374
+ * `authorId`, `targetId`, `targetType`, `status` and `targetOwnerId`
375
+ * (the target's owner, `core.node_owner`, or `NULL`).
376
+ */
377
+ readonly list: (query: {
378
+ readonly where: ListFilter<never>;
379
+ readonly limit: number;
380
+ readonly offset: number;
381
+ }) => Effect.Effect<Page<ProposalListing>, E, R>;
382
+ }
383
+ /**
384
+ * One leaf's proposal surface: its target operations, the stores, and the
385
+ * patch rules.
386
+ *
387
+ * @since 0.1.0
388
+ */
389
+ export interface ProposalsDefinition<Resource, E, R> {
390
+ /** The target leaf's wire type: the proposals' `targetType`. */
391
+ readonly type: string;
392
+ /** The target leaf's operations: `get` gates a submission, `compare` and `update` an acceptance. */
393
+ readonly target: SubtypeOps<Resource, E, R>;
394
+ /** The target leaf's chain store, for the head a proposal is stamped with. */
395
+ readonly chain: VersionChainStore<E, R>;
396
+ /** The target's owner (its `LeafStore.ownerOf`), for the write gate and the reads. */
397
+ readonly ownerOf: (id: string) => Effect.Effect<Option.Option<string>, E, R>;
398
+ readonly proposals: ProposalStore<E, R>;
399
+ /** The request's viewer. */
400
+ readonly viewer: Effect.Effect<Viewer, never, R>;
401
+ readonly policy: AccessPolicy;
402
+ /** The rung that may propose (gardeneria: any signed-in account; website: contributor+). */
403
+ readonly canPropose: (account: ViewerAccount) => boolean;
404
+ /** The attributes a proposal may touch: the leaf's update fields, in declaration order. */
405
+ readonly attributes: ReadonlyArray<string>;
406
+ /** The keys no proposal may carry; {@link PROPOSAL_FORBIDDEN_KEYS} when omitted. */
407
+ readonly forbidden?: ReadonlyArray<string> | undefined;
408
+ /** The leaf's update decoder over a patch's values (`SEC-INPUT-001`), shared or one locale's. */
409
+ readonly decode: (patch: Schema.Json) => Effect.Effect<ChainPatch, InvalidProposalPatch, R>;
410
+ /**
411
+ * The translated columns a proposal may touch on a localised leaf
412
+ * (pulpit#184), in declaration order: the leaf's locale level's columns,
413
+ * or fewer. Omitted, a proposal carries no per-locale patch.
414
+ */
415
+ readonly localeAttributes?: ReadonlyArray<string> | undefined;
416
+ /**
417
+ * A write budget on `submit` (pulpit#199, `./budgets`' `bindBudget`),
418
+ * spent as the `submit` action once the submission validates and before
419
+ * it is stored. Omitted, submissions are unthrottled.
420
+ */
421
+ readonly budget?: BoundBudget<E, R> | undefined;
422
+ }
423
+ /**
424
+ * A proposal as a read returns it: the row, and the cheap verdict while it
425
+ * is pending.
426
+ *
427
+ * @since 0.1.0
428
+ */
429
+ export interface ProposalView {
430
+ readonly proposal: ProposalRow;
431
+ readonly baseState: Option.Option<ProposalBaseState>;
432
+ }
433
+ /**
434
+ * A pending proposal as the review screen reads it: the full verdict too.
435
+ *
436
+ * @since 0.1.0
437
+ */
438
+ export interface ProposalReview extends ProposalView {
439
+ readonly conflict: ProposalConflictVerdict;
440
+ }
441
+ type WriteGate = Unauthorized | Forbidden | NodeNotFound;
442
+ /**
443
+ * The operations {@link defineProposals} produces.
444
+ *
445
+ * @since 0.1.0
446
+ */
447
+ export interface ProposalOps<E, R> {
448
+ /**
449
+ * Submit a pending proposal against `targetId`, stamped with its head.
450
+ * Fails `Unauthorized` when anonymous, `Forbidden` below the propose rung,
451
+ * `NodeNotFound` when the viewer can't `get` the target,
452
+ * {@link InvalidProposalPatch}, and `WriteRejected` (`RATE_LIMITED`) when
453
+ * the declared budget is spent.
454
+ */
455
+ readonly submit: (input: {
456
+ readonly targetId: string;
457
+ readonly patch: Schema.Json;
458
+ /** A localised leaf's per-locale patch (pulpit#184); absent, none. */
459
+ readonly locales?: Schema.Json | undefined;
460
+ readonly rationale: Option.Option<string>;
461
+ }) => Effect.Effect<{
462
+ readonly id: string;
463
+ }, Unauthorized | Forbidden | NodeNotFound | InvalidProposalPatch | WriteRejected | E, R>;
464
+ /**
465
+ * One proposal the viewer may read (the moderate rung, its author, or the
466
+ * target's owner), with its cheap verdict while pending. Fails
467
+ * {@link ProposalNotFound} for a missing or unreadable one.
468
+ */
469
+ readonly get: (id: string) => Effect.Effect<ProposalView, ProposalNotFound | E, R>;
470
+ /** One page of the proposals the viewer may read, newest first, optionally narrowed. */
471
+ readonly list: (request: {
472
+ readonly targetId: Option.Option<string>;
473
+ readonly status: Option.Option<ProposalStatus>;
474
+ readonly limit: number;
475
+ readonly offset: number;
476
+ }) => Effect.Effect<Page<ProposalView>, E, R>;
477
+ /**
478
+ * A pending proposal with the full verdict, behind the target's write
479
+ * gate and its gated `compare`. Fails `ProposalNotFound`, the gate's
480
+ * failures, `ProposalClosed`, `VersionNotFound`, or
481
+ * `InvalidProposalPatch` when the stored patch no longer validates.
482
+ */
483
+ readonly review: (id: string) => Effect.Effect<ProposalReview, ProposalNotFound | WriteGate | ProposalClosed | VersionNotFound | InvalidProposalPatch | E, R>;
484
+ /**
485
+ * Accept a pending proposal: re-validate its patch, classify it against
486
+ * the head (failing {@link ProposalConflict} when conflicting), append it
487
+ * through the target's `update` with the head as its expected version and
488
+ * the author as `proposedBy`, and close it with the version it produced.
489
+ * Fails as `review` does, and as the target's `update` does
490
+ * (`StaleVersion` when the head moved after the classification;
491
+ * `WriteRejected` when one of its before hooks refuses the write).
492
+ */
493
+ readonly accept: (id: string, options?: {
494
+ readonly note: Option.Option<string>;
495
+ }) => Effect.Effect<ChainWrite, ProposalNotFound | WriteGate | ProposalClosed | ProposalConflict | VersionNotFound | InvalidProposalPatch | StaleVersion | VersionConflict | WriteRejected | E, R>;
496
+ /**
497
+ * Reject a pending proposal, writing nothing to the target, behind its
498
+ * write gate (a proposal whose target was deleted can still be rejected).
499
+ * Fails `ProposalNotFound`, the gate's failures, `ProposalClosed`.
500
+ */
501
+ readonly reject: (id: string, options?: {
502
+ readonly note: Option.Option<string>;
503
+ }) => Effect.Effect<void, ProposalNotFound | WriteGate | ProposalClosed | E, R>;
504
+ /**
505
+ * Withdraw the caller's own pending proposal. Fails `Unauthorized` when
506
+ * anonymous, `ProposalNotFound`, `Forbidden` for someone else's, and
507
+ * `ProposalClosed`.
508
+ */
509
+ readonly withdraw: (id: string) => Effect.Effect<void, Unauthorized | ProposalNotFound | Forbidden | ProposalClosed | E, R>;
510
+ }
511
+ /**
512
+ * Bind one leaf's proposal operations. Every operation is traced as
513
+ * `${type}.proposals.<operation>`, and the writes run in the caller's
514
+ * transaction: an accept's append and its close commit or roll back
515
+ * together. An accept runs the target's `update`, so its before hooks, but
516
+ * not `subtypeHandlers`' write-through: an application that caches the
517
+ * target writes the accepted version through itself.
518
+ *
519
+ * @since 0.1.0
520
+ */
521
+ export declare const defineProposals: <Resource, E, R>(definition: ProposalsDefinition<Resource, E, R>) => ProposalOps<E, R>;
522
+ export {};
523
+ //# sourceMappingURL=proposals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proposals.d.ts","sourceRoot":"","sources":["../src/proposals.ts"],"names":[],"mappings":"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"}