@reventlessdev/reventless-core 3.0.0-alpha.239 → 3.0.0-alpha.240

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 (170) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/package.json +9 -9
  3. package/src/Message.res +11 -11
  4. package/src/Message.res.mjs +15 -14
  5. package/src/Projection.res +2 -2
  6. package/src/Projection.res.mjs +5 -4
  7. package/src/adapter/Monitoring/Monitoring.res +24 -2
  8. package/src/adapter/Monitoring/Monitoring.res.mjs +3 -3
  9. package/src/admin/Platform_AdminApi.res.mjs +3 -3
  10. package/src/admin/Platform_Admin_Structure.res +33 -113
  11. package/src/admin/Platform_Admin_Structure.res.mjs +8 -139
  12. package/src/admin/UiFragmentRegistry/StateChangeSlice/UiFragmentRegistry.res.mjs +12 -12
  13. package/src/admin/UiFragmentRegistry/StateViewSlice/UiFragments.res.mjs +14 -14
  14. package/src/components/Aggregate/Aggregate_Callback.res +2 -2
  15. package/src/components/Aggregate/Aggregate_Callback.res.mjs +4 -4
  16. package/src/components/Api/ApiAllowedStatesHelpers.res.mjs +3 -3
  17. package/src/components/Api/ApiNoApiHelpers.res.mjs +5 -5
  18. package/src/components/Api/ApiTargetStateHelpers.res.mjs +3 -3
  19. package/src/components/Api/GraphQL_FragmentGenerator.res +18 -12
  20. package/src/components/Api/GraphQL_FragmentGenerator.res.mjs +7 -13
  21. package/src/components/Api/GraphQL_SchemaInspector.res +1 -1
  22. package/src/components/Api/GraphQL_SchemaInspector.res.mjs +1 -1
  23. package/src/components/Api/MCP_SchemaGenerator.res +1 -1
  24. package/src/components/Api/MCP_SchemaGenerator.res.mjs +1 -1
  25. package/src/components/Api/SchemaType.res +6 -10
  26. package/src/components/Api/SchemaType.res.mjs +4 -4
  27. package/src/components/Api/StorageRefFields.res +1 -1
  28. package/src/components/Api/StorageRefFields.res.mjs +1 -1
  29. package/src/components/Api/SuryToJsonSchema.res +11 -0
  30. package/src/components/Api/SuryToJsonSchema.res.mjs +2 -1
  31. package/src/components/AutomationSlice/AutomationSlice_Callback.res +3 -4
  32. package/src/components/AutomationSlice/AutomationSlice_Callback.res.mjs +22 -23
  33. package/src/components/CommandTopic/CommandTopic_Callback.res +1 -2
  34. package/src/components/CommandTopic/CommandTopic_Callback.res.mjs +3 -4
  35. package/src/components/CommandTopic/CommandTopic_Helpers.res +1 -1
  36. package/src/components/CommandTopic/CommandTopic_Helpers.res.mjs +3 -3
  37. package/src/components/Counter/Counter.res.mjs +2 -2
  38. package/src/components/Counter/Counter_Callback.res.mjs +4 -4
  39. package/src/components/Counter/Counter_Operations.res.mjs +4 -4
  40. package/src/components/Dcb/Dcb_Builder.res +1 -1
  41. package/src/components/Dcb/Dcb_Builder.res.mjs +8 -6
  42. package/src/components/DcbEventLog/DcbEventLog_Builder.res.mjs +4 -3
  43. package/src/components/EventCollector/EventCollector_Builder.res +1 -1
  44. package/src/components/InboundTranslationSlice/InboundTranslationSlice_Callback.res +1 -2
  45. package/src/components/InboundTranslationSlice/InboundTranslationSlice_Callback.res.mjs +11 -12
  46. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Callback.res +3 -4
  47. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Callback.res.mjs +24 -25
  48. package/src/components/SideEffectHandler/SideEffectHandler_Callback.res +1 -1
  49. package/src/components/SideEffectHandler/SideEffectHandler_Callback.res.mjs +3 -3
  50. package/src/components/StateChangeSlice/StateChangeSlice_Callback.res +2 -2
  51. package/src/components/StateChangeSlice/StateChangeSlice_Callback.res.mjs +4 -4
  52. package/src/components/StateViewSlice/StateViewSlice_Builder.res +1 -1
  53. package/src/components/StateViewSlice/StateViewSlice_Builder.res.mjs +3 -3
  54. package/src/plugin/api/PluginBaseFragment.res +12 -29
  55. package/src/plugin/api/PluginBaseFragment.res.mjs +3 -22
  56. package/src/plugin/component/Capability_Inference.res +118 -1
  57. package/src/plugin/component/Capability_Inference.res.mjs +128 -1
  58. package/src/plugin/component/Plugin_Builder.res +2 -2
  59. package/src/plugin/component/Plugin_Builder.res.mjs +2 -1
  60. package/src/plugin/component/Plugin_Helpers.res +11 -11
  61. package/src/plugin/component/Plugin_Helpers.res.mjs +11 -10
  62. package/src/plugin/component/Plugin_Structure.res +349 -274
  63. package/src/plugin/component/Plugin_Structure.res.mjs +212 -175
  64. package/src/plugin/component/Plugin_SubscriptionSchema.res +1 -1
  65. package/src/plugin/component/Plugin_SubscriptionSchema.res.mjs +1 -1
  66. package/src/plugin/component/SchemaWalker.res +11 -11
  67. package/src/plugin/component/SchemaWalker.res.mjs +8 -9
  68. package/src/plugin/connect/PluginExtensionPoint_Plugin.res.mjs +15 -15
  69. package/src/plugin/lifecycle/PluginBehavior.res.mjs +55 -55
  70. package/src/plugin/lifecycle/PluginSpec.res +22 -7
  71. package/src/plugin/lifecycle/PluginSpec.res.mjs +91 -36
  72. package/src/plugin/lifecycle/PluginsReadModelSpec.res +36 -9
  73. package/src/plugin/lifecycle/PluginsReadModelSpec.res.mjs +33 -22
  74. package/src/util/Interstack.res +3 -3
  75. package/src/util/LogFormat.res +1 -2
  76. package/src/util/LogFormat.res.mjs +2 -2
  77. package/tests/IdentityTest.res +6 -7
  78. package/tests/IdentityTest.res.mjs +7 -9
  79. package/tests/adapter/MonitoringTest.res +30 -3
  80. package/tests/adapter/MonitoringTest.res.mjs +31 -12
  81. package/tests/adapter/RuntimeExtensionHookReachTest.res +0 -1
  82. package/tests/adapter/RuntimeExtensionHookReachTest.res.mjs +5 -7
  83. package/tests/admin/Platform_Admin_StructureTest.res +254 -0
  84. package/tests/admin/Platform_Admin_StructureTest.res.mjs +219 -0
  85. package/tests/aggregate/AggregateCacheTest.res +0 -1
  86. package/tests/aggregate/AggregateCacheTest.res.mjs +13 -15
  87. package/tests/aggregate/AggregateConflictTest.res +0 -1
  88. package/tests/aggregate/AggregateConflictTest.res.mjs +7 -9
  89. package/tests/aggregate/AggregateFixtures.res +0 -1
  90. package/tests/aggregate/AggregateFixtures.res.mjs +19 -21
  91. package/tests/aggregate/AggregateSnapshotTest.res +1 -2
  92. package/tests/aggregate/AggregateSnapshotTest.res.mjs +15 -16
  93. package/tests/api/ApiNoApiTest.res.mjs +17 -9
  94. package/tests/api/GraphQL_FragmentGeneratorTest.res +62 -1
  95. package/tests/api/GraphQL_FragmentGeneratorTest.res.mjs +102 -58
  96. package/tests/api/PsInternalFieldsReadModel.res +21 -0
  97. package/tests/api/PsInternalFieldsReadModel.res.mjs +74 -0
  98. package/tests/api/StorageRefFieldsTest.res.mjs +13 -13
  99. package/tests/api/SuryToJsonSchemaTest.res +43 -0
  100. package/tests/api/SuryToJsonSchemaTest.res.mjs +352 -849
  101. package/tests/commandgenerator/CommandGeneratorFixtures.res +0 -1
  102. package/tests/commandgenerator/CommandGeneratorFixtures.res.mjs +19 -21
  103. package/tests/commandgenerator/OwnerStampingTest.res +0 -1
  104. package/tests/commandgenerator/OwnerStampingTest.res.mjs +9 -11
  105. package/tests/commandtopic/CommandTopicCallbackFixtures.res +0 -1
  106. package/tests/commandtopic/CommandTopicCallbackFixtures.res.mjs +7 -9
  107. package/tests/counter/CounterFixtures.res +0 -1
  108. package/tests/counter/CounterFixtures.res.mjs +1 -4
  109. package/tests/dcb/DcbDecodeTest.res.mjs +24 -24
  110. package/tests/dcb/DcbEventLogOperationsTest.res +2 -2
  111. package/tests/dcb/DcbEventLogOperationsTest.res.mjs +3 -3
  112. package/tests/dcb/DcbEventLogSchemaTest.res.mjs +7 -7
  113. package/tests/dcb/DcbFixtures.res +0 -1
  114. package/tests/dcb/DcbFixtures.res.mjs +87 -89
  115. package/tests/dcb/DcbTagTest.res.mjs +6 -6
  116. package/tests/dcb/DcbValidationTest.res.mjs +52 -52
  117. package/tests/eventlog/EventLogFixtures.res +0 -1
  118. package/tests/eventlog/EventLogFixtures.res.mjs +7 -9
  119. package/tests/eventmapper/EventMapperFixtures.res +0 -1
  120. package/tests/eventmapper/EventMapperFixtures.res.mjs +24 -26
  121. package/tests/eventtopic/EventTopicFixtures.res +0 -1
  122. package/tests/eventtopic/EventTopicFixtures.res.mjs +7 -9
  123. package/tests/extensionpoint/ExtensionPointFixtures.res +0 -1
  124. package/tests/extensionpoint/ExtensionPointFixtures.res.mjs +10 -12
  125. package/tests/extensionpoint/ExtensionPointOperationsTest.res +1 -2
  126. package/tests/extensionpoint/ExtensionPointOperationsTest.res.mjs +9 -10
  127. package/tests/logger/LogFormatTest.res +3 -2
  128. package/tests/logger/LogFormatTest.res.mjs +7 -9
  129. package/tests/message/MessageTest.res +2 -2
  130. package/tests/message/MessageTest.res.mjs +8 -7
  131. package/tests/message/MetaEnvelopeTest.res +5 -5
  132. package/tests/message/MetaEnvelopeTest.res.mjs +12 -11
  133. package/tests/plugin/ManifestVisibilityTest.res.mjs +7 -7
  134. package/tests/plugin/PluginDefinitionScalars.res +5 -3
  135. package/tests/plugin/PluginDefinitionScalars.res.mjs +2 -2
  136. package/tests/plugin/PluginLifecycleCorpusTest.res +4 -3
  137. package/tests/plugin/PluginLifecycleCorpusTest.res.mjs +3 -6
  138. package/tests/plugin/PluginSpecExperiment.res +0 -1
  139. package/tests/plugin/PluginSpecExperiment.res.mjs +12 -14
  140. package/tests/plugin/PluginStructureTest.res +188 -1
  141. package/tests/plugin/PluginStructureTest.res.mjs +293 -102
  142. package/tests/plugin/Plugin_EventQuerySchemaTest.res.mjs +3 -3
  143. package/tests/plugin/SchemaWalkerTest.res +0 -1
  144. package/tests/plugin/SchemaWalkerTest.res.mjs +17 -19
  145. package/tests/plugin/StateChangeSlice/PsAttachInvoice.res.mjs +5 -5
  146. package/tests/plugin/StateChangeSlice/PsChangePhoto.res.mjs +8 -8
  147. package/tests/plugin/StateChangeSlice/PsDispatchShipment.res.mjs +5 -5
  148. package/tests/plugin/StateChangeSlice/PsGatedCommands.res.mjs +9 -9
  149. package/tests/plugin/StateChangeSlice/PsPlaceOrder.res.mjs +5 -5
  150. package/tests/plugin/StateChangeSlice/PsReserveStock.res.mjs +8 -8
  151. package/tests/plugin/StateChangeSlice/PsShipOrder.res.mjs +15 -15
  152. package/tests/plugin/StateChangeSlice/PsTypoStore.res +31 -0
  153. package/tests/plugin/StateChangeSlice/PsTypoStore.res.mjs +62 -0
  154. package/tests/plugin/StateChangeSlice/PsUploadAvatar.res.mjs +8 -8
  155. package/tests/plugin/StateChangeSlice/PsUploadImages.res +40 -0
  156. package/tests/plugin/StateChangeSlice/PsUploadImages.res.mjs +66 -0
  157. package/tests/plugin/StateViewSlice/PsAnnotatedView.res.mjs +13 -12
  158. package/tests/plugin/StateViewSlice/PsAvailableProductsView.res.mjs +8 -8
  159. package/tests/plugin/StateViewSlice/PsCategoriesView.res.mjs +6 -6
  160. package/tests/plugin/StateViewSlice/PsCustomersView.res.mjs +10 -10
  161. package/tests/plugin/StateViewSlice/PsGatedView.res.mjs +6 -6
  162. package/tests/plugin/StateViewSlice/PsOrdersView.res.mjs +9 -9
  163. package/tests/plugin/StateViewSlice/PsShipmentsView.res.mjs +11 -10
  164. package/tests/plugin/pluginDefinitionRequiredScalars.txt +15 -0
  165. package/tests/querydb/QueryDbFixtures.res +0 -1
  166. package/tests/querydb/QueryDbFixtures.res.mjs +5 -7
  167. package/tests/sideeffecthandler/SideEffectHandlerFixtures.res +0 -1
  168. package/tests/sideeffecthandler/SideEffectHandlerFixtures.res.mjs +4 -6
  169. package/tests/util/CommandPublisherTest.res +0 -1
  170. package/tests/util/CommandPublisherTest.res.mjs +4 -6
@@ -1,6 +1,6 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
- import * as S from "sury/src/S.res.mjs";
3
+ import * as Sury from "sury";
4
4
  import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
5
5
  import * as Id$Reventless from "@reventlessdev/reventless-spec/src/types/Id.res.mjs";
6
6
  import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
@@ -79,19 +79,6 @@ function Make(Spec) {
79
79
  };
80
80
  let directiveHandler = async (createSchedule, deleteSchedule, queryEngine, directive) => {
81
81
  switch (directive.TAG) {
82
- case "CreateDisconnectSchedule" :
83
- let id = directive._0;
84
- return await createSchedule({
85
- name: disconnectScheduleName(id),
86
- rate: ScheduleOps$ReventlessCore.minutesFromNow(directive._1),
87
- payload: JSON.stringify(Message$ReventlessCore.encodeCommand$p({
88
- id: id,
89
- meta: Message$ReventlessCore.generateMeta(PluginExtensionPointSpec$ReventlessInfra.name, undefined, "Scheduler", undefined, undefined, undefined, undefined, undefined),
90
- command: "DisconnectPlugin"
91
- }, S.string, PluginExtensionPointSpec$ReventlessInfra.commandSchema))
92
- });
93
- case "DeleteDisconnectSchedule" :
94
- return await deleteSchedule(disconnectScheduleName(directive._0));
95
82
  case "DoConnectPlugin" :
96
83
  let fn = Spec.manageSubscriptions;
97
84
  if (fn !== undefined) {
@@ -117,6 +104,19 @@ function Make(Spec) {
117
104
  case "ForwardCommand" :
118
105
  let match = directive._0;
119
106
  return await forwardCommand(match.id, match.command, match.extensionPointName, queryEngine);
107
+ case "CreateDisconnectSchedule" :
108
+ let id = directive._0;
109
+ return await createSchedule({
110
+ name: disconnectScheduleName(id),
111
+ rate: ScheduleOps$ReventlessCore.minutesFromNow(directive._1),
112
+ payload: JSON.stringify(Message$ReventlessCore.encodeCommand$p({
113
+ id: id,
114
+ meta: Message$ReventlessCore.generateMeta(PluginExtensionPointSpec$ReventlessInfra.name, undefined, "Scheduler", undefined, undefined, undefined, undefined, undefined),
115
+ command: "DisconnectPlugin"
116
+ }, Sury.string, PluginExtensionPointSpec$ReventlessInfra.commandSchema))
117
+ });
118
+ case "DeleteDisconnectSchedule" :
119
+ return await deleteSchedule(disconnectScheduleName(directive._0));
120
120
  }
121
121
  };
122
122
  let mapIncomingCommand = (id, cmd, _meta) => {
@@ -380,4 +380,4 @@ export {
380
380
  Make,
381
381
  moduleUrl,
382
382
  }
383
- /* S Not a pure module */
383
+ /* sury Not a pure module */
@@ -1,26 +1,26 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
- import * as S from "sury/src/S.res.mjs";
3
+ import * as Sury from "sury";
4
4
  import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
5
5
  import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
6
6
  import * as Plugin$Reventless from "@reventlessdev/reventless-spec/src/components/Plugin.res.mjs";
7
7
  import * as Plugin$ReventlessCore from "../component/Plugin.res.mjs";
8
8
 
9
- let versionStatusSchema = S.union([
10
- S.literal("Connected"),
11
- S.literal("Disconnected"),
12
- S.literal("Inactive"),
13
- S.literal("Retired")
9
+ let versionStatusSchema = Sury.union([
10
+ Sury.literal("Connected"),
11
+ Sury.literal("Disconnected"),
12
+ Sury.literal("Inactive"),
13
+ Sury.literal("Retired")
14
14
  ]);
15
15
 
16
- let knownVersionSchema = S.schema(s => ({
16
+ let knownVersionSchema = Sury.$schema(s => ({
17
17
  definition: s.m(Plugin$Reventless.pluginDefinitionSchema),
18
18
  status: s.m(versionStatusSchema)
19
19
  }));
20
20
 
21
- let stateSchema = S.schema(s => ({
22
- current: s.m(S.option(Plugin$Reventless.versionSchema)),
23
- known: s.m(S.dict(knownVersionSchema))
21
+ let stateSchema = Sury.$schema(s => ({
22
+ current: s.m(Sury.$option(Plugin$Reventless.versionSchema)),
23
+ known: s.m(Sury.dict(knownVersionSchema))
24
24
  }));
25
25
 
26
26
  let initialState_known = {};
@@ -119,23 +119,56 @@ function promoteEvents(state, v) {
119
119
 
120
120
  function decide(state, command) {
121
121
  switch (command.TAG) {
122
- case "Heartbeat" :
123
- let v = command._0;
122
+ case "Connect" :
123
+ let def = command._0;
124
+ let v = def.version;
124
125
  let match = state.known[v];
125
- if (match === undefined) {
126
+ if (match !== undefined && match.status === "Connected") {
127
+ if (Primitive_object.equal(match.definition, def)) {
128
+ return {
129
+ TAG: "Ok",
130
+ _0: []
131
+ };
132
+ } else {
133
+ return {
134
+ TAG: "Ok",
135
+ _0: [{
136
+ TAG: "VersionConnected",
137
+ _0: def
138
+ }]
139
+ };
140
+ }
141
+ } else {
142
+ return {
143
+ TAG: "Ok",
144
+ _0: connectEvents(state, v, def)
145
+ };
146
+ }
147
+ case "ReportIncompatibility" :
148
+ return {
149
+ TAG: "Ok",
150
+ _0: [{
151
+ TAG: "IncompatiblePluginDetected",
152
+ _0: command._0
153
+ }]
154
+ };
155
+ case "Heartbeat" :
156
+ let v$1 = command._0;
157
+ let match$1 = state.known[v$1];
158
+ if (match$1 === undefined) {
126
159
  return {
127
160
  TAG: "Ok",
128
161
  _0: [{
129
162
  TAG: "VersionDetected",
130
- _0: v
163
+ _0: v$1
131
164
  }]
132
165
  };
133
166
  }
134
- switch (match.status) {
167
+ switch (match$1.status) {
135
168
  case "Disconnected" :
136
169
  return {
137
170
  TAG: "Ok",
138
- _0: connectEvents(state, v, match.definition)
171
+ _0: connectEvents(state, v$1, match$1.definition)
139
172
  };
140
173
  case "Connected" :
141
174
  case "Inactive" :
@@ -146,25 +179,25 @@ function decide(state, command) {
146
179
  };
147
180
  }
148
181
  case "Redetect" :
149
- let v$1 = command._0;
150
- let match$1 = state.known[v$1];
151
- if (match$1 === undefined) {
182
+ let v$2 = command._0;
183
+ let match$2 = state.known[v$2];
184
+ if (match$2 === undefined) {
152
185
  return {
153
186
  TAG: "Ok",
154
187
  _0: [{
155
188
  TAG: "VersionDetected",
156
- _0: v$1
189
+ _0: v$2
157
190
  }]
158
191
  };
159
192
  }
160
- switch (match$1.status) {
193
+ switch (match$2.status) {
161
194
  case "Connected" :
162
195
  case "Disconnected" :
163
196
  return {
164
197
  TAG: "Ok",
165
198
  _0: [{
166
199
  TAG: "VersionDetected",
167
- _0: v$1
200
+ _0: v$2
168
201
  }]
169
202
  };
170
203
  case "Inactive" :
@@ -174,31 +207,6 @@ function decide(state, command) {
174
207
  _0: []
175
208
  };
176
209
  }
177
- case "Connect" :
178
- let def = command._0;
179
- let v$2 = def.version;
180
- let match$2 = state.known[v$2];
181
- if (match$2 !== undefined && match$2.status === "Connected") {
182
- if (Primitive_object.equal(match$2.definition, def)) {
183
- return {
184
- TAG: "Ok",
185
- _0: []
186
- };
187
- } else {
188
- return {
189
- TAG: "Ok",
190
- _0: [{
191
- TAG: "VersionConnected",
192
- _0: def
193
- }]
194
- };
195
- }
196
- } else {
197
- return {
198
- TAG: "Ok",
199
- _0: connectEvents(state, v$2, def)
200
- };
201
- }
202
210
  case "Disconnect" :
203
211
  let v$3 = command._0;
204
212
  let match$3 = state.known[v$3];
@@ -309,14 +317,6 @@ function decide(state, command) {
309
317
  }].concat(promoteEvents(state, v$5))
310
318
  };
311
319
  break;
312
- case "ReportIncompatibility" :
313
- return {
314
- TAG: "Ok",
315
- _0: [{
316
- TAG: "IncompatiblePluginDetected",
317
- _0: command._0
318
- }]
319
- };
320
320
  case "Retire" :
321
321
  let v$6 = command._0;
322
322
  let match$7 = state.known[v$6];
@@ -2,29 +2,44 @@
2
2
 
3
3
  open Reventless.Plugin
4
4
 
5
+ // Alias, not `open`: the PPX strips `@transition` before the typechecker, so the
6
+ // state constructors never reach it and an `open` would warn as unused.
7
+ module Plugins = PluginsReadModelSpec
8
+
5
9
  // The Plugin aggregate is keyed by plugin **name** (not name@version). One
6
10
  // instance owns the whole lifecycle of every version of that name, deciding
7
11
  // supersession synchronously. Version-scoped commands carry the `version`
8
12
  // the transition targets; the ExtensionPoint→Plugin mapping supplies it
9
13
  // (translated from the transport-level `name@version` id — Approach 1).
14
+ // Order is load-bearing: sury strands constructors declared after a run of two or
15
+ // more same-shaped ones, so the `pluginDefinition` pair must lead (DZakh/sury#392).
10
16
  @schema
11
17
  type command =
18
+ // The handshake brings the version's row into being, so it runs from no state
19
+ // — `decide` accepts it against an unknown version and against every status
20
+ // but `Connected`, where it is a definition refresh rather than a move.
21
+ | @noApi @transition(() => Plugins.Connected) Connect(pluginDefinition)
22
+ // Records a protocol-version incompatibility without changing connection state.
23
+ | @noApi ReportIncompatibility(pluginDefinition)
12
24
  | @noApi Heartbeat(version)
13
25
  // Deploy-time re-detect (from RedetectPlugin). Forces the connect handshake to
14
26
  // re-run for an already-connected version so its definition is refreshed on the
15
27
  // row — unlike Heartbeat, which no-ops a connected keep-alive.
16
28
  | @noApi Redetect(version)
17
- | @noApi Connect(pluginDefinition)
18
- | @noApi Disconnect(version)
29
+ // A heartbeat timing out is the only way a row reaches `Disconnected`, and
30
+ // `decide` moves the row for exactly one status — anything else is a stray
31
+ // disconnect it tolerates without emitting.
32
+ | @noApi @transition(([Plugins.Connected]) => Plugins.Disconnected) Disconnect(version)
19
33
  // Admin lifecycle commands — API-exposed (auto-derived admin mutations,
20
34
  // Cognito group-gated). `version` selects which known version to act on.
21
- | Activate(version)
22
- | Deactivate(version)
23
- // Records a protocol-version incompatibility without changing connection state.
24
- | @noApi ReportIncompatibility(pluginDefinition)
35
+ // The `@transition` edges must agree with `decide` below; `Platform_Admin_Structure`
36
+ // reads them off this schema rather than restating them.
37
+ | @transition(([Plugins.Inactive, Plugins.Retired]) => Plugins.Connected) Activate(version)
38
+ | @transition(([Plugins.Connected, Plugins.Disconnected]) => Plugins.Inactive) Deactivate(version)
25
39
  // Manual admin retirement of a specific version (archive). Distinct from the
26
40
  // automatic `Superseded` transition (which is decided, not commanded).
27
- | Retire(version)
41
+ | @transition(([Plugins.Connected, Plugins.Disconnected, Plugins.Inactive]) => Plugins.Retired)
42
+ Retire(version)
28
43
 
29
44
  // Carries both the superseded and the superseding version's full definition —
30
45
  // a deterministic trigger for version-to-version schema/data migrations
@@ -1,103 +1,155 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
- import * as S from "sury/src/S.res.mjs";
3
+ import * as Sury from "sury";
4
4
  import * as Plugin$Reventless from "@reventlessdev/reventless-spec/src/components/Plugin.res.mjs";
5
5
  import * as Api$ReventlessInfra from "@reventlessdev/reventless-infra/src/components/Api.res.mjs";
6
6
 
7
- let commandSchema = S.union([
8
- S.schema(s => ({
7
+ let commandSchema = Sury.union([
8
+ Sury.$schema(s => ({
9
+ TAG: "Connect",
10
+ _0: s.m(Plugin$Reventless.pluginDefinitionSchema)
11
+ })),
12
+ Sury.$schema(s => ({
13
+ TAG: "ReportIncompatibility",
14
+ _0: s.m(Plugin$Reventless.pluginDefinitionSchema)
15
+ })),
16
+ Sury.$schema(s => ({
9
17
  TAG: "Heartbeat",
10
18
  _0: s.m(Plugin$Reventless.versionSchema)
11
19
  })),
12
- S.schema(s => ({
20
+ Sury.$schema(s => ({
13
21
  TAG: "Redetect",
14
22
  _0: s.m(Plugin$Reventless.versionSchema)
15
23
  })),
16
- S.schema(s => ({
17
- TAG: "Connect",
18
- _0: s.m(Plugin$Reventless.pluginDefinitionSchema)
19
- })),
20
- S.schema(s => ({
24
+ Sury.$schema(s => ({
21
25
  TAG: "Disconnect",
22
26
  _0: s.m(Plugin$Reventless.versionSchema)
23
27
  })),
24
- S.schema(s => ({
28
+ Sury.$schema(s => ({
25
29
  TAG: "Activate",
26
30
  _0: s.m(Plugin$Reventless.versionSchema)
27
31
  })),
28
- S.schema(s => ({
32
+ Sury.$schema(s => ({
29
33
  TAG: "Deactivate",
30
34
  _0: s.m(Plugin$Reventless.versionSchema)
31
35
  })),
32
- S.schema(s => ({
33
- TAG: "ReportIncompatibility",
34
- _0: s.m(Plugin$Reventless.pluginDefinitionSchema)
35
- })),
36
- S.schema(s => ({
36
+ Sury.$schema(s => ({
37
37
  TAG: "Retire",
38
38
  _0: s.m(Plugin$Reventless.versionSchema)
39
39
  }))
40
40
  ]);
41
41
 
42
- let versionSupersededDataSchema = S.schema(s => ({
42
+ let versionSupersededDataSchema = Sury.$schema(s => ({
43
43
  supersededVersion: s.m(Plugin$Reventless.versionSchema),
44
44
  supersededDefinition: s.m(Plugin$Reventless.pluginDefinitionSchema),
45
45
  newVersion: s.m(Plugin$Reventless.versionSchema),
46
46
  newDefinition: s.m(Plugin$Reventless.pluginDefinitionSchema)
47
47
  }));
48
48
 
49
- let eventSchema = S.union([
50
- S.schema(s => ({
49
+ let eventSchema = Sury.union([
50
+ Sury.$schema(s => ({
51
51
  TAG: "VersionDetected",
52
52
  _0: s.m(Plugin$Reventless.versionSchema)
53
53
  })),
54
- S.schema(s => ({
54
+ Sury.$schema(s => ({
55
55
  TAG: "VersionConnected",
56
56
  _0: s.m(Plugin$Reventless.pluginDefinitionSchema)
57
57
  })),
58
- S.schema(s => ({
58
+ Sury.$schema(s => ({
59
59
  TAG: "VersionSuperseded",
60
60
  _0: s.m(versionSupersededDataSchema)
61
61
  })),
62
- S.schema(s => ({
62
+ Sury.$schema(s => ({
63
63
  TAG: "VersionPromoted",
64
64
  _0: s.m(Plugin$Reventless.pluginDefinitionSchema)
65
65
  })),
66
- S.schema(s => ({
66
+ Sury.$schema(s => ({
67
67
  TAG: "VersionDisconnected",
68
68
  _0: s.m(Plugin$Reventless.pluginDefinitionSchema)
69
69
  })),
70
- S.schema(s => ({
70
+ Sury.$schema(s => ({
71
71
  TAG: "VersionActivated",
72
72
  _0: s.m(Plugin$Reventless.pluginDefinitionSchema)
73
73
  })),
74
- S.schema(s => ({
74
+ Sury.$schema(s => ({
75
75
  TAG: "VersionDeactivated",
76
76
  _0: s.m(Plugin$Reventless.pluginDefinitionSchema)
77
77
  })),
78
- S.schema(s => ({
78
+ Sury.$schema(s => ({
79
79
  TAG: "VersionRetired",
80
80
  _0: s.m(Plugin$Reventless.pluginDefinitionSchema)
81
81
  })),
82
- S.schema(s => ({
82
+ Sury.$schema(s => ({
83
83
  TAG: "IncompatiblePluginDetected",
84
84
  _0: s.m(Plugin$Reventless.pluginDefinitionSchema)
85
85
  }))
86
86
  ]);
87
87
 
88
- let errorSchema = S.union([
89
- S.literal("UnknownVersion"),
90
- S.literal("AlreadyConnected"),
91
- S.literal("IsDisconnected"),
92
- S.literal("IsInactive")
88
+ let errorSchema = Sury.union([
89
+ Sury.literal("UnknownVersion"),
90
+ Sury.literal("AlreadyConnected"),
91
+ Sury.literal("IsDisconnected"),
92
+ Sury.literal("IsInactive")
93
93
  ]);
94
94
 
95
95
  let commandSchema$1 = Api$ReventlessInfra.markNoApiVariants(commandSchema, [
96
+ "Connect",
97
+ "ReportIncompatibility",
96
98
  "Heartbeat",
97
99
  "Redetect",
98
- "Connect",
99
- "Disconnect",
100
- "ReportIncompatibility"
100
+ "Disconnect"
101
+ ]);
102
+
103
+ let commandSchema$2 = Api$ReventlessInfra.markAllowedStates(commandSchema$1, [
104
+ [
105
+ "Disconnect",
106
+ ["Connected"]
107
+ ],
108
+ [
109
+ "Activate",
110
+ [
111
+ "Inactive",
112
+ "Retired"
113
+ ]
114
+ ],
115
+ [
116
+ "Deactivate",
117
+ [
118
+ "Connected",
119
+ "Disconnected"
120
+ ]
121
+ ],
122
+ [
123
+ "Retire",
124
+ [
125
+ "Connected",
126
+ "Disconnected",
127
+ "Inactive"
128
+ ]
129
+ ]
130
+ ]);
131
+
132
+ let commandSchema$3 = Api$ReventlessInfra.markTargetState(commandSchema$2, [
133
+ [
134
+ "Connect",
135
+ "Connected"
136
+ ],
137
+ [
138
+ "Disconnect",
139
+ "Disconnected"
140
+ ],
141
+ [
142
+ "Activate",
143
+ "Connected"
144
+ ],
145
+ [
146
+ "Deactivate",
147
+ "Inactive"
148
+ ],
149
+ [
150
+ "Retire",
151
+ "Retired"
152
+ ]
101
153
  ]);
102
154
 
103
155
  function commandAuthorization(param) {
@@ -108,15 +160,18 @@ let name = "Plugin";
108
160
 
109
161
  let Id;
110
162
 
163
+ let Plugins;
164
+
111
165
  let moduleUrl = "@reventlessdev/reventless-core/src/plugin/lifecycle/PluginSpec.res.mjs";
112
166
 
113
167
  export {
114
168
  name,
115
169
  Id,
170
+ Plugins,
116
171
  versionSupersededDataSchema,
117
172
  eventSchema,
118
173
  errorSchema,
119
- commandSchema$1 as commandSchema,
174
+ commandSchema$3 as commandSchema,
120
175
  moduleUrl,
121
176
  commandAuthorization,
122
177
  }
@@ -1,5 +1,17 @@
1
1
  @@reventless.spec("Plugins")
2
2
 
3
+ // Who may read this view. Declared rather than left to default, because the
4
+ // default was `AllowAuthenticated` and it was not true: `PluginBaseFragment`
5
+ // hand-wrote an `Admin` Cognito gate beside it, and the local platform serves
6
+ // every `Platform_*` field behind an `Admin` wrapper. Three statements of one
7
+ // rule, one of which disagreed with the other two.
8
+ //
9
+ // Stating it here makes the spec the source. The AppSync directive comes from
10
+ // this (spec-level `permission` outranks the legacy `{tableName, group}` pair),
11
+ // and so does the `requiredAccess` the platform publishes — so a shell can gate
12
+ // the Plugins view up front instead of offering it and meeting a refusal.
13
+ @@reventless.authorize(Reventless.Authorization.AllowGroups(["Admin"]))
14
+
3
15
  // Current view — one row per plugin **name**, holding the currently-active
4
16
  // version's definition. Keyed by the aggregate id (= plugin name). The status
5
17
  // here is the *current* version's status; "Superseded" is not represented (a
@@ -17,21 +29,33 @@ type status =
17
29
  type state = {
18
30
  name: Reventless.Plugin.name,
19
31
  version: Reventless.Plugin.version,
20
- eventCollector: string,
32
+ // Projection/storage only — never on the GraphQL surface. `@internal` says so
33
+ // on the field, where the next person to edit the record will see it; the same
34
+ // three names used to live in a hand-written exclude list in `PluginBaseFragment`
35
+ // that nothing kept in step with this declaration.
36
+ @internal eventCollector: string,
21
37
  extensionPoints: array<Reventless.Plugin.extensionPointDefinition>,
22
- extensionPointNames: array<string>,
23
- extensionNames: array<string>,
38
+ @internal extensionPointNames: array<string>,
39
+ @internal extensionNames: array<string>,
24
40
  extensions: array<Reventless.Plugin.extensionDefinition>,
25
- status: status,
41
+ // Annotated rather than renamed to `lifecycle` to meet the convention: `status`
42
+ // is published in the SDL, in stored rows and in the UI's hand-written plugin
43
+ // views. Without this the transition check has no states to compare and passes
44
+ // while verifying nothing.
45
+ @lifecycle status: status,
26
46
  statusChange: Message.statusChange,
27
47
  // Stored as the **untagged** offload wire JSON (a bare fragment, or an
28
48
  // `{$offload: {...}}` reference) — NOT the `Offload.payload` variant. The QueryDb
29
49
  // write path marshals the raw ReScript value straight to DynamoDB without
30
50
  // sury-encoding through this field's schema, so a variant would persist as its
31
- // runtime `{TAG, _0}` shape and no reader could parse it. UI-excluded
32
- // (PluginBaseFragment.pluginUIOnlyExcludeFields), so JSON.t typing costs no
33
- // GraphQL consumer. PluginsProjection.displayState writes it via Offload.toJson.
34
- apiSchemaFragment: option<JSON.t>,
51
+ // runtime `{TAG, _0}` shape and no reader could parse it.
52
+ // PluginsProjection.displayState writes it via Offload.toJson.
53
+ //
54
+ // `@hidden`, not `@internal`: the field IS on the API and the host shell fetches
55
+ // it through a dedicated resolver path. What it must not be is a column in a
56
+ // generated list view — it is a multi-kilobyte JSON blob, and a query that names
57
+ // it drags one per row over the wire to render a cell nobody reads.
58
+ @hidden apiSchemaFragment: option<JSON.t>,
35
59
  // API target for split-API schema routing. Absent/None means "Domain" (backward compat).
36
60
  // "Platform" → excluded from DomainApi runtime schema stitching in updateApiSchema.
37
61
  apiTarget?: string,
@@ -39,7 +63,10 @@ type state = {
39
63
  // None for older plugins whose protocol version did not carry the field. Same
40
64
  // untagged-JSON storage as apiSchemaFragment above; the ComponentDefinitions
41
65
  // Lambda detects the `$offload` sentinel and resolves it from S3.
42
- structure: option<JSON.t>,
66
+ //
67
+ // `@hidden` for the same reason, and more so: this is the larger of the two
68
+ // blobs.
69
+ @hidden structure: option<JSON.t>,
43
70
  // DCB EventLog definition for plugins that bundle a DcbEventLog component.
44
71
  // Admin's manageSubscriptions uses this to wire cross-plugin SNS subscriptions
45
72
  // from this plugin's DCB topic → peer EventCollectors (and vice-versa). None
@@ -1,46 +1,54 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
- import * as S from "sury/src/S.res.mjs";
3
+ import * as Sury from "sury";
4
4
  import * as Plugin$Reventless from "@reventlessdev/reventless-spec/src/components/Plugin.res.mjs";
5
5
  import * as ReadModel$Reventless from "@reventlessdev/reventless-spec/src/components/ReadModel.res.mjs";
6
6
  import * as Message$ReventlessCore from "../../Message.res.mjs";
7
7
  import * as StateAnnotations$Reventless from "@reventlessdev/reventless-spec/src/components/StateAnnotations.res.mjs";
8
8
 
9
- let statusSchema = S.union([
10
- S.literal("Connected"),
11
- S.literal("Disconnected"),
12
- S.literal("Inactive"),
13
- S.literal("Retired")
9
+ let statusSchema = Sury.union([
10
+ Sury.literal("Connected"),
11
+ Sury.literal("Disconnected"),
12
+ Sury.literal("Inactive"),
13
+ Sury.literal("Retired")
14
14
  ]);
15
15
 
16
- let stateSchema = S.schema(s => ({
16
+ let stateSchema = Sury.$schema(s => ({
17
17
  name: s.m(Plugin$Reventless.nameSchema),
18
18
  version: s.m(Plugin$Reventless.versionSchema),
19
- eventCollector: s.m(S.string),
20
- extensionPoints: s.m(S.array(Plugin$Reventless.extensionPointDefinitionSchema)),
21
- extensionPointNames: s.m(S.array(S.string)),
22
- extensionNames: s.m(S.array(S.string)),
23
- extensions: s.m(S.array(Plugin$Reventless.extensionDefinitionSchema)),
19
+ eventCollector: s.m(Sury.string),
20
+ extensionPoints: s.m(Sury.array(Plugin$Reventless.extensionPointDefinitionSchema)),
21
+ extensionPointNames: s.m(Sury.array(Sury.string)),
22
+ extensionNames: s.m(Sury.array(Sury.string)),
23
+ extensions: s.m(Sury.array(Plugin$Reventless.extensionDefinitionSchema)),
24
24
  status: s.m(statusSchema),
25
25
  statusChange: s.m(Message$ReventlessCore.statusChangeSchema),
26
- apiSchemaFragment: s.m(S.option(S.json)),
27
- apiTarget: s.m(S.option(S.string)),
28
- structure: s.m(S.option(S.json)),
26
+ apiSchemaFragment: s.m(Sury.$option(Sury.json)),
27
+ apiTarget: s.m(Sury.$option(Sury.string)),
28
+ structure: s.m(Sury.$option(Sury.json)),
29
29
  dcbEventLog: s.m(Plugin$Reventless.dcbEventLogOptionSchema),
30
- kind: s.m(S.option(Plugin$Reventless.pluginKindSchema)),
31
- otherConnectedVersions: s.m(S.array(Plugin$Reventless.versionSchema))
30
+ kind: s.m(Sury.$option(Plugin$Reventless.pluginKindSchema)),
31
+ otherConnectedVersions: s.m(Sury.array(Plugin$Reventless.versionSchema))
32
32
  }));
33
33
 
34
34
  let config = ReadModel$Reventless.config(undefined, undefined, undefined);
35
35
 
36
- let stateSchema$1 = S.Metadata.set(stateSchema, StateAnnotations$Reventless.stateAnnotationsId, {
36
+ let stateSchema$1 = Sury.$Metadata_set(stateSchema, StateAnnotations$Reventless.stateAnnotationsId, {
37
37
  ids: [],
38
38
  compositeIds: [],
39
39
  subIds: [],
40
40
  compositeSubIds: [],
41
41
  indexes: [],
42
- hidden: [],
42
+ hidden: [
43
+ "apiSchemaFragment",
44
+ "structure"
45
+ ],
43
46
  summary: [],
47
+ internal: [
48
+ "eventCollector",
49
+ "extensionPointNames",
50
+ "extensionNames"
51
+ ],
44
52
  drillTargets: [],
45
53
  drillTargetKeys: [],
46
54
  collapsed: [],
@@ -48,13 +56,18 @@ let stateSchema$1 = S.Metadata.set(stateSchema, StateAnnotations$Reventless.stat
48
56
  scanSort: [],
49
57
  semantic: [],
50
58
  metric: [],
51
- lifecycle: undefined,
59
+ lifecycle: "status",
52
60
  groupBy: "kind",
53
61
  visibility: undefined,
54
62
  live: undefined,
55
63
  retired: undefined
56
64
  });
57
65
 
66
+ let authorization = {
67
+ TAG: "AllowGroups",
68
+ _0: ["Admin"]
69
+ };
70
+
58
71
  let name = "Plugins";
59
72
 
60
73
  let Id;
@@ -63,8 +76,6 @@ let subIdConfig;
63
76
 
64
77
  let moduleUrl = "@reventlessdev/reventless-core/src/plugin/lifecycle/PluginsReadModelSpec.res.mjs";
65
78
 
66
- let authorization = "AllowAuthenticated";
67
-
68
79
  let visibility = "Public";
69
80
 
70
81
  export {