@reventlessdev/reventless-core 3.0.0-alpha.146 → 3.0.0-alpha.147

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,13 @@
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.147 (2026-07-08)
7
+
8
+ ### Bug Fixes
9
+
10
+ * **reventless-core:** composite DCB slices can read back their own events ([4604a91](https://github.com/ReventlessDev/reventless-core/commit/4604a9159fb8bf59b2191ad69fee6613c7f75cd9))
11
+
12
+
6
13
  # 3.0.0-alpha.146 (2026-07-08)
7
14
 
8
15
  ### Features
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reventlessdev/reventless-core",
3
- "version": "3.0.0-alpha.146",
3
+ "version": "3.0.0-alpha.147",
4
4
  "description": "Core package for Reventless framework",
5
5
  "license": "Apache-2.0",
6
6
  "jest": {
@@ -28,17 +28,17 @@
28
28
  "dependencies": {
29
29
  "sury": "11.0.0-alpha.4",
30
30
  "uuid": "^13.0.0",
31
- "@reventlessdev/rescript-hash-object": "1.2.0-alpha.10",
32
- "@reventlessdev/rescript-fast-csv": "1.2.0-alpha.11",
33
31
  "@reventlessdev/rescript-effect": "0.1.0-alpha.25",
32
+ "@reventlessdev/rescript-hash-object": "1.2.0-alpha.10",
34
33
  "@reventlessdev/rescript-jest": "1.0.0-alpha.6",
35
34
  "@reventlessdev/rescript-node-streams": "1.1.0-alpha.10",
35
+ "@reventlessdev/rescript-fast-csv": "1.2.0-alpha.11",
36
36
  "@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.14",
37
- "@reventlessdev/rescript-uuid": "1.1.0-alpha.14",
37
+ "@reventlessdev/rescript-ssh2": "1.1.0-alpha.11",
38
38
  "@reventlessdev/reventless-infra": "3.0.0-alpha.91",
39
39
  "@reventlessdev/reventless-interop": "3.0.0-alpha.24",
40
- "@reventlessdev/reventless-spec": "3.0.0-alpha.69",
41
- "@reventlessdev/rescript-ssh2": "1.1.0-alpha.11"
40
+ "@reventlessdev/rescript-uuid": "1.1.0-alpha.14",
41
+ "@reventlessdev/reventless-spec": "3.0.0-alpha.69"
42
42
  },
43
43
  "devDependencies": {
44
44
  "rescript": "^12.3.0",
@@ -61,8 +61,7 @@ module Make = (
61
61
  | Some(keys) => baseTags->Array.filter(t => keys->Array.includes(t.key))
62
62
  | None => baseTags
63
63
  }
64
- let tags =
65
- indexedTags->Array.concat([{Reventless.DcbTag.key: "originatorSlice", value: Spec.name}])
64
+ let tags = indexedTags
66
65
  // Inherit service from the triggering command — the DcbEventLog publish path
67
66
  // overrides service to `<name>DcbEventLog` for routing so EventCollector
68
67
  // subscriptions still match.
@@ -83,12 +82,8 @@ module Make = (
83
82
  // tag value(s) instead of logging no id.
84
83
  let readEventId = (tags: array<Reventless.DcbTag.tag>): option<string> => {
85
84
  let ownTagValues = () => {
86
- // Skip the `originatorSlice` metadata tag that `encodeEvent` appends to
87
- // every stored event — it's the producing slice's name, not an entity id.
88
85
  let vals =
89
- tags
90
- ->Array.filter((t: Reventless.DcbTag.tag) => t.key != "originatorSlice")
91
- ->Array.reduce([], (acc, t: Reventless.DcbTag.tag) =>
86
+ tags->Array.reduce([], (acc, t: Reventless.DcbTag.tag) =>
92
87
  acc->Array.includes(t.value) ? acc : acc->Array.concat([t.value])
93
88
  )
94
89
  vals->Array.length == 0 ? None : Some(vals->Array.join(","))
@@ -29,7 +29,7 @@ function Make(Spec) {
29
29
  ]]);
30
30
  let readEventId = tags => {
31
31
  let ownTagValues = () => {
32
- let vals = Stdlib_Array.reduce(tags.filter(t => t.key !== "originatorSlice"), [], (acc, t) => {
32
+ let vals = Stdlib_Array.reduce(tags, [], (acc, t) => {
33
33
  if (acc.includes(t.value)) {
34
34
  return acc;
35
35
  } else {
@@ -188,15 +188,11 @@ function Make(Spec) {
188
188
  let baseTags = DcbTag$Reventless.extractTagsExpanded(Spec.eventSchema, e);
189
189
  let keys = tagKeysByEventType[eventType];
190
190
  let indexedTags = keys !== undefined ? baseTags.filter(t => keys.includes(t.key)) : baseTags;
191
- let tags = indexedTags.concat([{
192
- key: "originatorSlice",
193
- value: Spec.name
194
- }]);
195
191
  let meta = Message$ReventlessCore.deriveMeta(parentMeta, undefined);
196
192
  return {
197
193
  eventType: eventType,
198
194
  data: match[1],
199
- tags: tags,
195
+ tags: indexedTags,
200
196
  meta: meta
201
197
  };
202
198
  });
@@ -61,8 +61,7 @@ let sourceCFields = (
61
61
  // Pushed via AppSync Events API. Admin / observability only.
62
62
  //
63
63
  // Returns (subscriptionFields, supportingTypes) — the supporting type is the
64
- // {DisplayName}EventLogEvent type that carries position, eventType, payload, and
65
- // the optional originatorSlice tag injected by StateChangeSlice_Callback.
64
+ // {DisplayName}EventLogEvent type that carries position, eventType, and payload.
66
65
 
67
66
  let sourceAFieldsAndTypes = (
68
67
  ~eventLogEntries: array<eventLogSchemaEntry>,
@@ -76,7 +75,7 @@ let sourceAFieldsAndTypes = (
76
75
  seen->Set.add(n)
77
76
  fields->Array.push(` on${n}EventLog_eventAppended: ${n}EventLogEvent`)
78
77
  types->Array.push(
79
- `type ${n}EventLogEvent {\n position: String!\n eventType: String!\n payload: AWSJSON!\n originatorSlice: String\n}`,
78
+ `type ${n}EventLogEvent {\n position: String!\n eventType: String!\n payload: AWSJSON!\n}`,
80
79
  )
81
80
  }
82
81
  })
@@ -41,7 +41,7 @@ function sourceAFieldsAndTypes(eventLogEntries) {
41
41
  if (!seen.has(n)) {
42
42
  seen.add(n);
43
43
  fields.push(` on` + n + `EventLog_eventAppended: ` + n + `EventLogEvent`);
44
- types.push(`type ` + n + `EventLogEvent {\n position: String!\n eventType: String!\n payload: AWSJSON!\n originatorSlice: String\n}`);
44
+ types.push(`type ` + n + `EventLogEvent {\n position: String!\n eventType: String!\n payload: AWSJSON!\n}`);
45
45
  return;
46
46
  }
47
47
  });
@@ -81,7 +81,7 @@ describe("StateChangeSlice_Callback:", () => {
81
81
  ))->toEqual(([Ok("ref-1")], 1, 1))
82
82
  })
83
83
 
84
- testPromise("stored event has correct tags", async () => {
84
+ testPromise("stored event carries only its entity tags (no framework provenance tag)", async () => {
85
85
  let _ = await TestHandler.handleCommands(
86
86
  testDcbEventLog,
87
87
  Stream.fromIterable([
@@ -90,10 +90,11 @@ describe("StateChangeSlice_Callback:", () => {
90
90
  )->Effect.runPromise
91
91
  let storedEvent = mock.getEvents()->Array.getUnsafe(0)
92
92
 
93
- expect(storedEvent.tags)->toEqual([
94
- {Reventless.DcbTag.key: "itemId", value: "item-1"},
95
- {Reventless.DcbTag.key: "originatorSlice", value: "TestStateChangeSlice"},
96
- ])
93
+ // No `originatorSlice` (or any other) metadata tag is smuggled into the tag
94
+ // set — a stored event's tags are exactly its DCB entity tags, so the
95
+ // composite read/write keys stay aligned. See
96
+ // docs/analysis/dcb-event-provenance-and-metadata.md.
97
+ expect(storedEvent.tags)->toEqual([{Reventless.DcbTag.key: "itemId", value: "item-1"}])
97
98
  })
98
99
  })
99
100
 
@@ -201,23 +201,17 @@ globalThis.describe("StateChangeSlice_Callback:", () => {
201
201
  1
202
202
  ]);
203
203
  });
204
- globalThis.test("stored event has correct tags", async () => {
204
+ globalThis.test("stored event carries only its entity tags (no framework provenance tag)", async () => {
205
205
  await Effect.runPromise(TestHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([makeTopicItem("ref-1", {
206
206
  TAG: "CreateItem",
207
207
  itemId: "item-1",
208
208
  name: "Test"
209
209
  })])));
210
210
  let storedEvent = mock.getEvents()[0];
211
- globalThis.expect(storedEvent.tags).toEqual([
212
- {
211
+ globalThis.expect(storedEvent.tags).toEqual([{
213
212
  key: "itemId",
214
213
  value: "item-1"
215
- },
216
- {
217
- key: "originatorSlice",
218
- value: "TestStateChangeSlice"
219
- }
220
- ]);
214
+ }]);
221
215
  });
222
216
  });
223
217
  globalThis.describe("handleCommands - decide returns Ok([])", () => {