@reventlessdev/reventless-spec 3.0.0-alpha.121 → 3.0.0-alpha.123

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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,28 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # 3.0.0-alpha.123 (2026-08-23)
7
+
8
+ ### Features
9
+
10
+ * **querydb:** serve owner-scoped lists from an index instead of a filtered Scan ([ad26c28](https://github.com/ReventlessDev/reventless-core/commit/ad26c284b4b0650fa3f3b6109ed33bbfe8608f6d))
11
+
12
+
13
+ # 3.0.0-alpha.122 (2026-08-22)
14
+
15
+ * feat(core)!: a slice that has given up says so ([f5559ab](https://github.com/ReventlessDev/reventless-core/commit/f5559abede3a9cf2c9a48aadc69a666c46cc75bf))
16
+
17
+ ### BREAKING CHANGES
18
+
19
+ * `onExhausted` is required on the Translation and Automation
20
+ module types. ReScript has no optional module-type fields, so the alternative
21
+ was a PPX-injected default — and defaulting this one to silence is the bug.
22
+ A slice now states what abandonment means for its domain, `None` included.
23
+ GeocodeCustomerAddress answers with MarkAddressUnresolvable; the others say
24
+ nothing, on purpose.
25
+
26
+
27
+
6
28
  # 3.0.0-alpha.121 (2026-08-21)
7
29
 
8
30
  ### Bug Fixes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reventlessdev/reventless-spec",
3
- "version": "3.0.0-alpha.121",
3
+ "version": "3.0.0-alpha.123",
4
4
  "description": "Specifications for Reventless",
5
5
  "license": "Apache-2.0",
6
6
  "bin": {
@@ -153,6 +153,22 @@ module type Automation = {
153
153
  */
154
154
  let process: (string, Spec.todoItem) => option<(string, Spec.command)>
155
155
 
156
+ /**
157
+ The retry budget is spent: this item will never be processed again.
158
+
159
+ Return `Some((targetId, command))` to tell the domain, or `None` to say nothing.
160
+
161
+ Abandonment is an outcome, not the absence of one, and the framework cannot
162
+ publish it on a slice's behalf: the command would have to name a target, and
163
+ which target is exactly what this module knows and the framework does not. So
164
+ the choice is declared here even when the answer is `None` — a slice that stays
165
+ silent says so on purpose.
166
+
167
+ The row is marked `Abandoned` either way; this decides only whether anything
168
+ downstream hears about it.
169
+ */
170
+ let onExhausted: (string, Spec.todoItem) => option<(string, Spec.command)>
171
+
156
172
  /** File URL of this Automation module (`import.meta.url`). */
157
173
  let moduleUrl: string
158
174
 
@@ -147,6 +147,25 @@ module type Translation = {
147
147
  result<option<(string, Spec.inboundCommand)>, string>,
148
148
  >
149
149
 
150
+ /**
151
+ The retry budget is spent: this item will never be attempted again.
152
+
153
+ Return `Some((targetId, cmd))` to tell the domain, or `None` to say nothing.
154
+ `~lastError` is the failure that ended it.
155
+
156
+ Abandonment is an outcome, not the absence of one, and the framework cannot
157
+ publish it on a slice's behalf: the event would need a home in some aggregate's
158
+ log, and which aggregate is exactly what this module knows and the framework
159
+ does not. So the choice is declared here even when the answer is `None` —
160
+ a slice that stays silent says so on purpose.
161
+
162
+ The row is marked `Abandoned` either way; this decides only whether anything
163
+ downstream hears about it.
164
+ */
165
+ let onExhausted: (string, Spec.outboundItem, ~lastError: option<string>) => option<
166
+ (string, Spec.inboundCommand),
167
+ >
168
+
150
169
  /** File URL of this Translation module (`import.meta.url`). */
151
170
  let moduleUrl: string
152
171
  }
@@ -90,6 +90,10 @@ Configuration for a DynamoDB Global Secondary Index on a read model table.
90
90
  - `pkSep` / `skSep` — separator for composite pk/sk concatenation (default `"/"`)
91
91
  - `projectionType` — which attributes are projected into the index
92
92
  - `authorization` — optional AppSync authorization rule
93
+ - `derived` — the framework wrote this index, not the author. It keys a read the
94
+ generated resolvers already make (`@owner` scoping); no `<single>By<Index>`
95
+ door is emitted for it, since a door named after a key the author never
96
+ declared is noise on every published schema.
93
97
  */
94
98
  type indexConfig = {
95
99
  index: string,
@@ -102,8 +106,13 @@ type indexConfig = {
102
106
  skSep?: string,
103
107
  projectionType: projectionType,
104
108
  authorization?: authorization,
109
+ derived?: bool,
105
110
  }
106
111
 
112
+ /** Does this index carry an SDL door? Derived indexes serve a read the resolvers
113
+ already make and are provisioned without one. */
114
+ let isDerivedIndex = (ic: indexConfig) => ic.derived->Option.getOr(false)
115
+
107
116
  /**
108
117
  Composite-key configuration for a read model that has both a primary ID and a sub-ID.
109
118
 
@@ -1,5 +1,10 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
4
+
5
+ function isDerivedIndex(ic) {
6
+ return Stdlib_Option.getOr(ic.derived, false);
7
+ }
3
8
 
4
9
  function config(idResolversOpt, idsResolversOpt, indexesOpt) {
5
10
  let idResolvers = idResolversOpt !== undefined ? idResolversOpt : [];
@@ -13,6 +18,7 @@ function config(idResolversOpt, idsResolversOpt, indexesOpt) {
13
18
  }
14
19
 
15
20
  export {
21
+ isDerivedIndex,
16
22
  config,
17
23
  }
18
24
  /* No side effect */