@reventlessdev/reventless-aws 3.0.0-alpha.396 → 3.0.0-alpha.398

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 (87) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/package.json +8 -8
  3. package/scripts/BakeManifest.res +15 -15
  4. package/scripts/DeployApp.res +8 -9
  5. package/scripts/DeployApp.res.mjs +4 -13
  6. package/scripts/DeployManifest.res +4 -5
  7. package/scripts/DeployManifest.res.mjs +0 -1
  8. package/scripts/ProvisionAccounts.res +41 -33
  9. package/scripts/ProvisionAccounts.res.mjs +6 -9
  10. package/scripts/ProvisionAdmin.res +10 -10
  11. package/scripts/ProvisionIdentity.res +2 -2
  12. package/scripts/ResolveEnvironment.res +3 -3
  13. package/src/Platform.res +6 -4
  14. package/src/Platform.res.mjs +6 -4
  15. package/src/Platform_ProvidedGroups.res +4 -4
  16. package/src/Platform_Stack.res +2 -3
  17. package/src/Platform_Stack.res.mjs +1 -2
  18. package/src/adapter/Api/AppSyncEventsSigner_Ops.res +2 -2
  19. package/src/adapter/Api/AppSync_EventsApi.res +2 -2
  20. package/src/adapter/Api/Platform_ComponentDefinitions_Lambda_Ops.res +6 -6
  21. package/src/adapter/Auth/Auth_ActiveRoleTrigger.res +15 -8
  22. package/src/adapter/Auth/Auth_ActiveRoleTrigger.res.mjs +7 -7
  23. package/src/adapter/Auth/Auth_IdentityStore.res +41 -2
  24. package/src/adapter/Auth/Auth_IdentityStore.res.mjs +42 -3
  25. package/src/adapter/DcbEventLog/DcbBackend.res +3 -3
  26. package/src/adapter/DcbEventLog/DcbBackend.res.mjs +1 -3
  27. package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res +11 -9
  28. package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res.mjs +4 -6
  29. package/src/adapter/EventLog/EventLogBackend.res +3 -3
  30. package/src/adapter/EventLog/EventLogBackend.res.mjs +1 -3
  31. package/src/adapter/Geocoder/Geocoder_AwsLocation_Backend.res +1 -1
  32. package/src/adapter/QueryDb/PgQueryResolver_Lambda.res +5 -5
  33. package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res +2 -2
  34. package/src/adapter/Runtime/AggregateRuntime_Builder_Micro_Async.res +2 -2
  35. package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res +32 -32
  36. package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res.mjs +4 -3
  37. package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res +6 -6
  38. package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res +16 -5
  39. package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res.mjs +3 -3
  40. package/src/adapter/Runtime/EventCollectorEntryPoint_Ops.res +5 -5
  41. package/src/adapter/Runtime/PgQueryResolverEntryPoint_Ops.res +24 -18
  42. package/src/adapter/Runtime/ReadModelEntryPoint_Ops.res +16 -14
  43. package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res +2 -2
  44. package/src/adapter/Runtime/RuntimeExtensionEntryPoint_Ops.res +4 -4
  45. package/src/adapter/Runtime/SideEffectEntryPoint_Ops.res +4 -4
  46. package/src/adapter/Runtime/StateViewSliceEntryPoint_Ops.res +9 -9
  47. package/src/adapter/Runtime/TaskBucketEntryPoint_Ops.res +11 -9
  48. package/src/components/Api/AppSync_Adapter.res +4 -4
  49. package/src/components/InboundTranslationSlice_Builder.res +19 -0
  50. package/src/components/InboundTranslationSlice_Builder.res.mjs +12 -2
  51. package/src/plugin/runtime/PluginExtensionPointRuntime_Builder.res +4 -7
  52. package/src/plugin/runtime/PluginExtensionPointRuntime_Builder.res.mjs +1 -4
  53. package/src/plugin/runtime/PluginRuntime_Builder.res +17 -26
  54. package/src/plugin/runtime/PluginRuntime_Builder.res.mjs +7 -22
  55. package/tests/AppSyncEventsSigner_OpsTest.res +1 -1
  56. package/tests/AppSync_AdapterTest.res +4 -4
  57. package/tests/AppSync_AdapterTest.res.mjs +4 -8
  58. package/tests/Auth_ActiveRoleStoreTest.res +1 -1
  59. package/tests/Auth_ActiveRoleTrigger_OpsTest.res +1 -1
  60. package/tests/AutomationSliceEntryPoint_OpsTest.res +0 -2
  61. package/tests/AutomationSliceEntryPoint_OpsTest.res.mjs +3 -6
  62. package/tests/BakeConvergenceTest.res +1 -8
  63. package/tests/BakeConvergenceTest.res.mjs +3 -23
  64. package/tests/BakeManifestTest.res +5 -10
  65. package/tests/BakeManifestTest.res.mjs +1 -6
  66. package/tests/CommandLineTest.res +3 -3
  67. package/tests/DeployAppTest.res +3 -4
  68. package/tests/DeployAppTest.res.mjs +6 -15
  69. package/tests/EpInboundTestSlice.res +1 -0
  70. package/tests/EpInboundTestSlice.res.mjs +3 -0
  71. package/tests/EventCollectorPluginDefinitionAssetTest.res +1 -2
  72. package/tests/EventCollectorPluginDefinitionAssetTest.res.mjs +11 -21
  73. package/tests/IdentityProvider_Cognito_BackendTest.res +0 -3
  74. package/tests/IdentityProvider_Cognito_BackendTest.res.mjs +0 -3
  75. package/tests/PgQueryResolver_LambdaTest.res +6 -10
  76. package/tests/PgQueryResolver_LambdaTest.res.mjs +4 -34
  77. package/tests/Platform_ProvidedGroupsTest.res +2 -2
  78. package/tests/Platform_ProvidedGroupsTest.res.mjs +1 -2
  79. package/tests/ProvisionAccountsTest.res +5 -10
  80. package/tests/ProvisionAccountsTest.res.mjs +0 -9
  81. package/tests/ProvisionAdminTest.res +4 -9
  82. package/tests/ProvisionAdminTest.res.mjs +0 -7
  83. package/tests/ProvisionIdentityTest.res +2 -4
  84. package/tests/ProvisionIdentityTest.res.mjs +0 -2
  85. package/tests/SideEffectEntryPoint_OpsTest.res +2 -2
  86. package/tests/Util_ShellConfigTest.res +3 -3
  87. package/tests/Util_ShellConfigTest.res.mjs +1 -2
@@ -7,16 +7,35 @@ module Make = (
7
7
  let apiRole: unit => Types.AppSync.role
8
8
  },
9
9
  ) => {
10
+ // The deployed slice runs in the shared DCB command Lambda, which builds its
11
+ // own callback and is handed no capabilities; this in-process path answers the
12
+ // same, so the two cannot differ. A spec that declares a need is refused below.
10
13
  module Inner = ReventlessCore.InboundTranslationSlice_Builder.Make(
11
14
  QueryDbStorage.DynamoDb,
12
15
  QueryDbResolvers.AppSync,
13
16
  Api,
17
+ {
18
+ let capabilities = () => Reventless.Capabilities.none
19
+ },
14
20
  )
15
21
 
16
22
  module Make = (
17
23
  Spec: Reventless.InboundTranslationSlice.Spec,
18
24
  Translation: Reventless.InboundTranslationSlice.Translation with module Spec := Spec,
19
25
  ): (ReventlessCore.InboundTranslationSlice.T with module Spec = Spec) => {
26
+ // Refused rather than deployed to fail quietly: the DCB command Lambda this
27
+ // slice runs in has neither the capability settings nor the grants the
28
+ // automation Lambda gets, so every call would answer `Unavailable` at run
29
+ // time with nothing at deploy time to say why.
30
+ if Spec.capabilityNeeds != [] {
31
+ JsError.throwWithMessage(
32
+ `${Spec.name}: an inbound translation slice that declares capability needs (${Spec.capabilityNeeds
33
+ ->Array.map(Reventless.CapabilityNeed.toString)
34
+ ->Array.join(
35
+ ", ",
36
+ )}) cannot be deployed to AWS yet — the DCB command Lambda it runs in is handed no capabilities. Host it on the local platform.`,
37
+ )
38
+ }
20
39
  // Register spec + translation module paths so the shared DCB command Lambda's
21
40
  // entry point can import them and route `__inboundTranslation` payloads to this
22
41
  // slice's `receive` (mirrors StateChangeSlice_Builder's path registration).
@@ -1,6 +1,10 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
+ import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
4
+ import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
5
+ import * as Capabilities$Reventless from "@reventlessdev/reventless-spec/src/semantic/Capabilities.res.mjs";
3
6
  import * as Component$ReventlessCore from "@reventlessdev/reventless-core/src/components/Component.res.mjs";
7
+ import * as CapabilityNeed$Reventless from "@reventlessdev/reventless-spec/src/semantic/CapabilityNeed.res.mjs";
4
8
  import * as Util_Bundle$ReventlessAws from "../util/Util_Bundle.res.mjs";
5
9
  import * as PluginRuntime_Builder$ReventlessAws from "../plugin/runtime/PluginRuntime_Builder.res.mjs";
6
10
  import * as QueryDbStorage_DynamoDb$ReventlessAws from "../adapter/QueryDb/QueryDbStorage_DynamoDb.res.mjs";
@@ -8,12 +12,18 @@ import * as QueryDbResolvers_AppSync$ReventlessAws from "../adapter/QueryDb/Quer
8
12
  import * as InboundTranslationSlice_Builder$ReventlessCore from "@reventlessdev/reventless-core/src/components/InboundTranslationSlice/InboundTranslationSlice_Builder.res.mjs";
9
13
 
10
14
  function Make(Api) {
15
+ let capabilities = () => Capabilities$Reventless.none;
11
16
  let Inner = InboundTranslationSlice_Builder$ReventlessCore.Make({
12
17
  make: QueryDbStorage_DynamoDb$ReventlessAws.make
13
18
  })({
14
19
  make: QueryDbResolvers_AppSync$ReventlessAws.make
15
- })(Api);
20
+ })(Api)({
21
+ capabilities: capabilities
22
+ });
16
23
  let Make$1 = Spec => (Translation => {
24
+ if (Primitive_object.notequal(Spec.capabilityNeeds, [])) {
25
+ Stdlib_JsError.throwWithMessage(Spec.name + `: an inbound translation slice that declares capability needs (` + Spec.capabilityNeeds.map(CapabilityNeed$Reventless.toString).join(", ") + `) cannot be deployed to AWS yet — the DCB command Lambda it runs in is handed no capabilities. Host it on the local platform.`);
26
+ }
17
27
  PluginRuntime_Builder$ReventlessAws.registerInboundTranslationSliceSpec(Spec.name, Util_Bundle$ReventlessAws.getModuleSpecifier(Spec.moduleUrl), Util_Bundle$ReventlessAws.getModuleSpecifier(Translation.moduleUrl));
18
28
  let match = Spec.endpoint;
19
29
  if (match !== undefined) {
@@ -50,4 +60,4 @@ function Make(Api) {
50
60
  export {
51
61
  Make,
52
62
  }
53
- /* Component-ReventlessCore Not a pure module */
63
+ /* Capabilities-Reventless Not a pure module */
@@ -10,17 +10,14 @@ type runtimeParts = Util.Lambda.runtimeParts
10
10
  // scheduler resources; consumed lazily at deploy-resolve time when
11
11
  // `forCommandTopic` runs inside its `Pulumi.Output.apply`.
12
12
  type adminExtras = {
13
- pluginReadModelTableName: option<Pulumi.Output.t<string>>,
14
- schedulerRoleArn: option<Pulumi.Output.t<string>>,
13
+ pluginReadModelTableName?: Pulumi.Output.t<string>,
14
+ schedulerRoleArn?: Pulumi.Output.t<string>,
15
15
  }
16
16
 
17
- let adminExtras: ref<adminExtras> = ref({
18
- pluginReadModelTableName: None,
19
- schedulerRoleArn: None,
20
- })
17
+ let adminExtras: ref<adminExtras> = ref(({}: adminExtras))
21
18
 
22
19
  let registerPluginExtensionPoint = (~pluginReadModelTableName=?, ~schedulerRoleArn=?, ()) =>
23
- adminExtras := {pluginReadModelTableName, schedulerRoleArn}
20
+ adminExtras := {?pluginReadModelTableName, ?schedulerRoleArn}
24
21
 
25
22
  let forCommandTopic = (
26
23
  ~handler as _,
@@ -8,10 +8,7 @@ import * as Util_Bundle$ReventlessAws from "../../util/Util_Bundle.res.mjs";
8
8
  import * as RuntimeEnvironment_Lambda$ReventlessAws from "../../adapter/Runtime/RuntimeEnvironment_Lambda.res.mjs";
9
9
 
10
10
  let adminExtras = {
11
- contents: {
12
- pluginReadModelTableName: undefined,
13
- schedulerRoleArn: undefined
14
- }
11
+ contents: {}
15
12
  };
16
13
 
17
14
  function registerPluginExtensionPoint(pluginReadModelTableName, schedulerRoleArn, param) {
@@ -1,22 +1,16 @@
1
1
  let log = ReventlessCore.Logger.fromEnv()
2
2
 
3
3
  type adminConfig = {
4
- eventTopicArn: option<Pulumi.Output.t<string>>,
5
- pluginReadModelTableName: option<Pulumi.Output.t<string>>,
6
- schedulerRoleArn: option<Pulumi.Output.t<string>>,
7
- schedulerQueueArn: option<Pulumi.Output.t<string>>,
8
- schedulerQueueName: option<Pulumi.Output.t<string>>,
9
- appSyncApiId: option<Pulumi.Output.t<string>>,
4
+ eventTopicArn?: Pulumi.Output.t<string>,
5
+ pluginReadModelTableName?: Pulumi.Output.t<string>,
6
+ schedulerRoleArn?: Pulumi.Output.t<string>,
7
+ schedulerQueueArn?: Pulumi.Output.t<string>,
8
+ schedulerQueueName?: Pulumi.Output.t<string>,
9
+ appSyncApiId?: Pulumi.Output.t<string>,
10
10
  clonerEnabled: bool,
11
11
  }
12
12
 
13
13
  let configRef: ref<adminConfig> = ref({
14
- eventTopicArn: None,
15
- pluginReadModelTableName: None,
16
- schedulerRoleArn: None,
17
- schedulerQueueArn: None,
18
- schedulerQueueName: None,
19
- appSyncApiId: None,
20
14
  clonerEnabled: false,
21
15
  })
22
16
 
@@ -121,13 +115,12 @@ type sliceModulePaths = {
121
115
 
122
116
  type dcbConfig = {
123
117
  pluginName: string,
124
- dcbTableName: option<Pulumi.Output.t<string>>,
118
+ dcbTableName?: Pulumi.Output.t<string>,
125
119
  stateChangeSliceModulePaths: array<sliceModulePaths>,
126
120
  }
127
121
 
128
122
  let dcbConfigRef: ref<dcbConfig> = ref({
129
123
  pluginName: "",
130
- dcbTableName: None,
131
124
  stateChangeSliceModulePaths: [],
132
125
  })
133
126
 
@@ -219,23 +212,22 @@ compiles; slated for removal.
219
212
  "pluginName is auto-registered by Plugin_Builder.make; use registerDcbTableName / registerStateChangeSliceSpec for the other fields. This call is unnecessary and will be removed."
220
213
  )
221
214
  let registerDcbConfig = (~pluginName, ~dcbTableName=?, ~stateChangeSliceModulePaths=[], ()) => {
222
- dcbConfigRef := {pluginName, dcbTableName, stateChangeSliceModulePaths}
215
+ dcbConfigRef := {pluginName, ?dcbTableName, stateChangeSliceModulePaths}
223
216
  stateChangeSliceModulePaths->Array.length
224
217
  }
225
218
 
226
219
  let registerDcbTableName = (dcbTableName: Pulumi.Output.t<string>) =>
227
- dcbConfigRef := {...dcbConfigRef.contents, dcbTableName: Some(dcbTableName)}
220
+ dcbConfigRef := {...dcbConfigRef.contents, dcbTableName}
228
221
 
229
222
  type heartbeatConfig = {
230
223
  pluginId: string,
231
224
  heartbeatTimeout: int,
232
- epQueueUrl: option<Pulumi.Output.t<string>>,
225
+ epQueueUrl?: Pulumi.Output.t<string>,
233
226
  }
234
227
 
235
228
  let heartbeatConfigRef: ref<heartbeatConfig> = ref({
236
229
  pluginId: "",
237
230
  heartbeatTimeout: 10,
238
- epQueueUrl: None,
239
231
  })
240
232
 
241
233
  // heartbeatTimeout is mandatory: it drives the HEARTBEAT_TIMEOUT env var (and thus
@@ -244,7 +236,7 @@ let heartbeatConfigRef: ref<heartbeatConfig> = ref({
244
236
  // silently decoupled the two (schedule every 60min, Heartbeat(10) → 12min grace →
245
237
  // flapping); make callers supply it so the values can't diverge.
246
238
  let registerHeartbeatConfig = (~pluginId, ~heartbeatTimeout, ~epQueueUrl=?, ()) =>
247
- heartbeatConfigRef := {pluginId, heartbeatTimeout, epQueueUrl}
239
+ heartbeatConfigRef := {pluginId, heartbeatTimeout, ?epQueueUrl}
248
240
 
249
241
  // Resolves once this plugin's EventCollector Lambda exists at its new code.
250
242
  // `Platform.deployPlugin` gates the deploy-time re-detect on it: the re-detect
@@ -285,12 +277,12 @@ let registerConfig = (
285
277
  (),
286
278
  ) =>
287
279
  configRef := {
288
- eventTopicArn,
289
- pluginReadModelTableName,
290
- schedulerRoleArn,
291
- schedulerQueueArn,
292
- schedulerQueueName,
293
- appSyncApiId,
280
+ ?eventTopicArn,
281
+ ?pluginReadModelTableName,
282
+ ?schedulerRoleArn,
283
+ ?schedulerQueueArn,
284
+ ?schedulerQueueName,
285
+ ?appSyncApiId,
294
286
  clonerEnabled,
295
287
  }
296
288
 
@@ -351,7 +343,6 @@ module Make = (
351
343
  aggregateNames: [ReventlessCore.PluginSpec.name],
352
344
  },
353
345
  ],
354
- connectExtension: None,
355
346
  extensions: [],
356
347
  pluginExtensionPointCmdTopicUrl: Pulumi.Output.make(""),
357
348
  publishToAggregates: Dict.make(),
@@ -29,12 +29,6 @@ let log = Logger$ReventlessCore.fromEnv();
29
29
 
30
30
  let configRef = {
31
31
  contents: {
32
- eventTopicArn: undefined,
33
- pluginReadModelTableName: undefined,
34
- schedulerRoleArn: undefined,
35
- schedulerQueueArn: undefined,
36
- schedulerQueueName: undefined,
37
- appSyncApiId: undefined,
38
32
  clonerEnabled: false
39
33
  }
40
34
  };
@@ -118,7 +112,6 @@ function identityProviderProvisioned() {
118
112
  let dcbConfigRef = {
119
113
  contents: {
120
114
  pluginName: "",
121
- dcbTableName: undefined,
122
115
  stateChangeSliceModulePaths: []
123
116
  }
124
117
  };
@@ -192,19 +185,15 @@ function registerDcbConfig(pluginName, dcbTableName, stateChangeSliceModulePaths
192
185
  }
193
186
 
194
187
  function registerDcbTableName(dcbTableName) {
195
- let init = dcbConfigRef.contents;
196
- dcbConfigRef.contents = {
197
- pluginName: init.pluginName,
198
- dcbTableName: dcbTableName,
199
- stateChangeSliceModulePaths: init.stateChangeSliceModulePaths
200
- };
188
+ let newrecord = {...dcbConfigRef.contents};
189
+ newrecord.dcbTableName = dcbTableName;
190
+ dcbConfigRef.contents = newrecord;
201
191
  }
202
192
 
203
193
  let heartbeatConfigRef = {
204
194
  contents: {
205
195
  pluginId: "",
206
- heartbeatTimeout: 10,
207
- epQueueUrl: undefined
196
+ heartbeatTimeout: 10
208
197
  }
209
198
  };
210
199
 
@@ -252,12 +241,9 @@ function registerConfig(eventTopicArn, pluginReadModelTableName, schedulerRoleAr
252
241
 
253
242
  function Make(EventCollectorChannel) {
254
243
  let registerPluginName = pluginName => {
255
- let init = dcbConfigRef.contents;
256
- dcbConfigRef.contents = {
257
- pluginName: pluginName,
258
- dcbTableName: init.dcbTableName,
259
- stateChangeSliceModulePaths: init.stateChangeSliceModulePaths
260
- };
244
+ let newrecord = {...dcbConfigRef.contents};
245
+ newrecord.pluginName = pluginName;
246
+ dcbConfigRef.contents = newrecord;
261
247
  };
262
248
  let outputOrPlaceholder = opt => {
263
249
  if (opt !== undefined) {
@@ -280,7 +266,6 @@ function Make(EventCollectorChannel) {
280
266
  eventTopicArn: adminEpEventTopicArn,
281
267
  aggregateNames: [PluginSpec$ReventlessCore.name]
282
268
  }],
283
- connectExtension: undefined,
284
269
  extensions: [],
285
270
  pluginExtensionPointCmdTopicUrl: Pulumi.output(""),
286
271
  publishToAggregates: {},
@@ -33,7 +33,7 @@ let assertParity = (
33
33
  ~secretAccessKey,
34
34
  ~sessionToken,
35
35
  ) => {
36
- let creds: AppSyncEventsSigner_Ops.creds = {accessKeyId, secretAccessKey, sessionToken}
36
+ let creds: AppSyncEventsSigner_Ops.creds = {accessKeyId, secretAccessKey, ?sessionToken}
37
37
  let mine = AppSyncEventsSigner_Ops.signedHeaders(~host, ~path, ~body, ~region, ~isoNow, ~creds)
38
38
  let jsCreds: jsCreds = {accessKeyId, secretAccessKey, ?sessionToken}
39
39
  let ref = signedHeadersJs(~host, ~path, ~body, ~region, ~isoNow, ~creds=jsCreds)
@@ -961,10 +961,10 @@ describe("AppSync_Adapter.waitForMergeSuccess", () => {
961
961
  }
962
962
 
963
963
  let response = (~status, ~detail=?): AppSync_Adapter.getSourceApiAssociationResult => {
964
- sourceApiAssociation: Some({
965
- sourceApiAssociationStatus: Some(status),
966
- sourceApiAssociationStatusDetail: detail,
967
- }),
964
+ sourceApiAssociation: {
965
+ sourceApiAssociationStatus: status,
966
+ sourceApiAssociationStatusDetail: ?detail,
967
+ },
968
968
  }
969
969
 
970
970
  test("resolves once the association reports MERGE_SUCCESS", async () => {
@@ -853,20 +853,17 @@ globalThis.describe("AppSync_Adapter.waitForMergeSuccess", () => {
853
853
  let client = makeFakeClient([
854
854
  {
855
855
  sourceApiAssociation: {
856
- sourceApiAssociationStatus: "MERGE_SCHEDULED",
857
- sourceApiAssociationStatusDetail: undefined
856
+ sourceApiAssociationStatus: "MERGE_SCHEDULED"
858
857
  }
859
858
  },
860
859
  {
861
860
  sourceApiAssociation: {
862
- sourceApiAssociationStatus: "MERGE_IN_PROGRESS",
863
- sourceApiAssociationStatusDetail: undefined
861
+ sourceApiAssociationStatus: "MERGE_IN_PROGRESS"
864
862
  }
865
863
  },
866
864
  {
867
865
  sourceApiAssociation: {
868
- sourceApiAssociationStatus: "MERGE_SUCCESS",
869
- sourceApiAssociationStatusDetail: undefined
866
+ sourceApiAssociationStatus: "MERGE_SUCCESS"
870
867
  }
871
868
  }
872
869
  ]);
@@ -892,8 +889,7 @@ globalThis.describe("AppSync_Adapter.waitForMergeSuccess", () => {
892
889
  globalThis.test("times out after maxAttempts on a status that never settles", async () => {
893
890
  let client = makeFakeClient([{
894
891
  sourceApiAssociation: {
895
- sourceApiAssociationStatus: "MERGE_IN_PROGRESS",
896
- sourceApiAssociationStatusDetail: undefined
892
+ sourceApiAssociationStatus: "MERGE_IN_PROGRESS"
897
893
  }
898
894
  }]);
899
895
  let message = "";
@@ -12,7 +12,7 @@ module Ops = Auth_ActiveRoleStore_Ops
12
12
  module Contract = ReventlessCore.Auth_ActiveRole
13
13
 
14
14
  describe("Auth_ActiveRoleStore_Ops.mayActAs — the conformance table", () => {
15
- Contract.conformanceCases->Array.forEach(({label, membership, requested, expected}) =>
15
+ Contract.conformanceCases->Array.forEach(({label, membership, ?requested, ?expected}) =>
16
16
  switch requested {
17
17
  // "no role requested" has no subset decision to make — it is the clearing
18
18
  // path, exercised against the handler rather than the predicate.
@@ -53,7 +53,7 @@ let claimOf = (e: Trigger.event, key) =>
53
53
  let effectiveGroups = (e: Trigger.event, ~membership) => groupsOf(e)->Option.getOr(membership)
54
54
 
55
55
  describe("the conformance table, minted by the trigger", () => {
56
- Contract.conformanceCases->Array.forEach(({label, membership, requested, expected}) =>
56
+ Contract.conformanceCases->Array.forEach(({label, membership, ?requested, ?expected}) =>
57
57
  testSync(
58
58
  label,
59
59
  () => {
@@ -309,7 +309,6 @@ describe("AutomationSliceEntryPoint_Ops.runSweeps", () => {
309
309
  comp,
310
310
  name: comp,
311
311
  tick: None,
312
- reconcile: None,
313
312
  }
314
313
 
315
314
  test("sweeps every slice", async () => {
@@ -346,7 +345,6 @@ describe("AutomationSliceEntryPoint_Ops.runTick", () => {
346
345
  comp: name,
347
346
  name,
348
347
  tick,
349
- reconcile: None,
350
348
  }
351
349
  let slices = [
352
350
  slice(~name="Outbound", ~tick=None),
@@ -465,8 +465,7 @@ globalThis.describe("AutomationSliceEntryPoint_Ops.runSweeps", () => {
465
465
  sweep: run,
466
466
  comp: comp,
467
467
  name: comp,
468
- tick: undefined,
469
- reconcile: undefined
468
+ tick: undefined
470
469
  });
471
470
  globalThis.test("sweeps every slice", async () => {
472
471
  let swept = [];
@@ -512,8 +511,7 @@ globalThis.describe("AutomationSliceEntryPoint_Ops.runTick", () => {
512
511
  sweep: async () => {},
513
512
  comp: name,
514
513
  name: name,
515
- tick: tick,
516
- reconcile: undefined
514
+ tick: tick
517
515
  });
518
516
  let slices = [
519
517
  {
@@ -521,8 +519,7 @@ globalThis.describe("AutomationSliceEntryPoint_Ops.runTick", () => {
521
519
  sweep: async () => {},
522
520
  comp: "Outbound",
523
521
  name: "Outbound",
524
- tick: undefined,
525
- reconcile: undefined
522
+ tick: undefined
526
523
  },
527
524
  slice("DemandReport", async (key, at) => {
528
525
  ticks.push([
@@ -48,11 +48,6 @@ let emptyStructure: Reventless.Plugin.pluginStructure = {
48
48
  outboundTranslationSlices: [],
49
49
  inboundTranslationSlices: [],
50
50
  extensions: [],
51
- extensionPoints: None,
52
- requiredStores: None,
53
- requiredStoreDeclarations: None,
54
- requiredCapabilities: None,
55
- traitDeclarations: None,
56
51
  }
57
52
 
58
53
  let definition = (~structure): Reventless.Plugin.pluginDefinition => {
@@ -64,9 +59,7 @@ let definition = (~structure): Reventless.Plugin.pluginDefinition => {
64
59
  eventCollector: "arn:aws:sqs:eu-west-1:0:Ordering",
65
60
  extensionProtocols: [],
66
61
  apiSchemaFragment: None,
67
- apiTarget: None,
68
62
  structure: Some(structure),
69
- dcbEventLog: None,
70
63
  kind: Domain,
71
64
  }
72
65
 
@@ -119,7 +112,7 @@ describe("the bake converges when a plugin's structure changes", () => {
119
112
  let (keyA, structureA) = deployStructure(emptyStructure)
120
113
  let (keyB, structureB) = deployStructure({
121
114
  ...emptyStructure,
122
- requiredStores: Some(["Ordering.receipts"]),
115
+ requiredStores: ["Ordering.receipts"],
123
116
  })
124
117
  let defA = definition(~structure=structureA)
125
118
  let defB = definition(~structure=structureB)
@@ -60,12 +60,7 @@ let emptyStructure = {
60
60
  automationSlices: emptyStructure_automationSlices,
61
61
  outboundTranslationSlices: emptyStructure_outboundTranslationSlices,
62
62
  inboundTranslationSlices: emptyStructure_inboundTranslationSlices,
63
- extensions: emptyStructure_extensions,
64
- extensionPoints: undefined,
65
- requiredStores: undefined,
66
- requiredStoreDeclarations: undefined,
67
- requiredCapabilities: undefined,
68
- traitDeclarations: undefined
63
+ extensions: emptyStructure_extensions
69
64
  };
70
65
 
71
66
  function definition(structure) {
@@ -78,9 +73,7 @@ function definition(structure) {
78
73
  eventCollector: "arn:aws:sqs:eu-west-1:0:Ordering",
79
74
  extensionProtocols: [],
80
75
  apiSchemaFragment: undefined,
81
- apiTarget: undefined,
82
76
  structure: structure,
83
- dcbEventLog: undefined,
84
77
  kind: "Domain"
85
78
  };
86
79
  }
@@ -125,21 +118,8 @@ let afterDeploy = "2026-08-27T10:05:00Z";
125
118
  globalThis.describe("the bake converges when a plugin's structure changes", () => {
126
119
  let match = deployStructure(emptyStructure);
127
120
  let keyA = match[0];
128
- let match$1 = deployStructure({
129
- readModels: emptyStructure_readModels,
130
- stateViewSlices: emptyStructure_stateViewSlices,
131
- stateChangeSlices: emptyStructure_stateChangeSlices,
132
- aggregates: emptyStructure_aggregates,
133
- automationSlices: emptyStructure_automationSlices,
134
- outboundTranslationSlices: emptyStructure_outboundTranslationSlices,
135
- inboundTranslationSlices: emptyStructure_inboundTranslationSlices,
136
- extensions: emptyStructure_extensions,
137
- extensionPoints: undefined,
138
- requiredStores: ["Ordering.receipts"],
139
- requiredStoreDeclarations: undefined,
140
- requiredCapabilities: undefined,
141
- traitDeclarations: undefined
142
- });
121
+ let newrecord = {...emptyStructure};
122
+ let match$1 = deployStructure((newrecord.requiredStores = ["Ordering.receipts"], newrecord));
143
123
  let keyB = match$1[0];
144
124
  let defA = definition(match[1]);
145
125
  let defB = definition(match$1[1]);
@@ -33,12 +33,11 @@ plugins:
33
33
  expect(resolved)->toEqual(
34
34
  Ok({
35
35
  DeployManifest.file: "/repo/shop/deploy-manifest.yaml",
36
- region: Some("eu-west-1"),
36
+ region: "eu-west-1",
37
37
  platform: {
38
38
  name: "shop-platform",
39
39
  dir: "/repo/shop/platform-aws",
40
40
  stackDefaults: Dict.fromArray([("platform:messagingEmailProvider", "log")]),
41
- region: None,
42
41
  review: true,
43
42
  },
44
43
  plugins: [
@@ -46,14 +45,13 @@ plugins:
46
45
  name: "catalog",
47
46
  dir: "/repo/shop/catalog-aws",
48
47
  stackDefaults: Dict.make(),
49
- region: None,
50
48
  review: true,
51
49
  },
52
50
  {
53
51
  name: "ordering",
54
52
  dir: "/repo/shop/ordering-aws",
55
53
  stackDefaults: Dict.make(),
56
- region: Some("eu-central-1"),
54
+ region: "eu-central-1",
57
55
  review: false,
58
56
  },
59
57
  ],
@@ -79,9 +77,9 @@ describe("BakeManifest.parseArgs", () => {
79
77
  ]),
80
78
  )->toEqual(
81
79
  Ok({
82
- Bake.manifest: Some("m.yaml"),
83
- stack: Some("alpha"),
84
- since: Some("2026-09-16T10:00:00Z"),
80
+ Bake.manifest: "m.yaml",
81
+ stack: "alpha",
82
+ since: "2026-09-16T10:00:00Z",
85
83
  review: false,
86
84
  help: false,
87
85
  }),
@@ -109,7 +107,6 @@ describe("BakeManifest.pluginsToRead", () => {
109
107
  DeployManifest.name,
110
108
  dir: `/repo/shop/${name}-aws`,
111
109
  stackDefaults: Dict.make(),
112
- region: None,
113
110
  review,
114
111
  }
115
112
  let plugins = [plugin("catalog", ~review=true), plugin("ingest", ~review=false)]
@@ -213,8 +210,6 @@ describe("BakeManifest.readAnswer", () => {
213
210
  plugin: "Catalog",
214
211
  state: "missing",
215
212
  expected: "sha256/new",
216
- found: None,
217
- writtenAt: None,
218
213
  }),
219
214
  )->toBe(" Catalog: missing — expected sha256/new, row holds no row (written never)")
220
215
  )
@@ -40,7 +40,6 @@ plugins:
40
40
  "platform:messagingEmailProvider",
41
41
  "log"
42
42
  ]]),
43
- region: undefined,
44
43
  review: true
45
44
  },
46
45
  plugins: [
@@ -48,7 +47,6 @@ plugins:
48
47
  name: "catalog",
49
48
  dir: "/repo/shop/catalog-aws",
50
49
  stackDefaults: {},
51
- region: undefined,
52
50
  review: true
53
51
  },
54
52
  {
@@ -122,7 +120,6 @@ globalThis.describe("BakeManifest.pluginsToRead", () => {
122
120
  name: name,
123
121
  dir: `/repo/shop/` + name + `-aws`,
124
122
  stackDefaults: {},
125
- region: undefined,
126
123
  review: review
127
124
  });
128
125
  let plugins = [
@@ -229,9 +226,7 @@ globalThis.describe("BakeManifest.readAnswer", () => {
229
226
  globalThis.expect(BakeManifest$ReventlessAws.registrationLine({
230
227
  plugin: "Catalog",
231
228
  state: "missing",
232
- expected: "sha256/new",
233
- found: undefined,
234
- writtenAt: undefined
229
+ expected: "sha256/new"
235
230
  })).toBe(" Catalog: missing — expected sha256/new, row holds no row (written never)");
236
231
  });
237
232
  });
@@ -11,14 +11,14 @@ let answersLikeEveryTool = (cli: CliArgs.cli<'args>, ~mistake, ~message) =>
11
11
  test(`${cli.bin}: --help and a usage mistake`, async () => {
12
12
  let usage = cli.usage->String.trim
13
13
  expect(usage->String.startsWith(`Usage: ${cli.bin} `))->toBe(true)
14
- let help = {CliArgs.stdout: [usage], stderr: [], exitCode: Some(0), reachedMain: false}
14
+ let help = {CliArgs.stdout: [usage], stderr: [], exitCode: 0, reachedMain: false}
15
15
  expect(await CliArgs.observe(cli, ["-h"]))->toEqual(help)
16
16
  // Help wins: whoever asks what a tool takes is least sure of their arguments.
17
17
  expect(await CliArgs.observe(cli, mistake->Array.concat(["--help"])))->toEqual(help)
18
18
  expect(await CliArgs.observe(cli, mistake))->toEqual({
19
19
  CliArgs.stdout: [],
20
20
  stderr: [`${cli.bin}: ${message}\n\n${usage}`],
21
- exitCode: Some(2),
21
+ exitCode: 2,
22
22
  reachedMain: false,
23
23
  })
24
24
  })
@@ -62,7 +62,7 @@ describe("a string flag's value", () => {
62
62
 
63
63
  testSync("may be given inline", () =>
64
64
  expect(DeployApp.parseArgs(["down", "--manifest=../m.yaml", "--stack=try"]))->toEqual(
65
- Ok({DeployApp.command: Some(Down), manifest: Some("../m.yaml"), stack: "try", help: false}),
65
+ Ok({DeployApp.command: Down, manifest: "../m.yaml", stack: "try", help: false}),
66
66
  )
67
67
  )
68
68
 
@@ -6,13 +6,13 @@ open JestGlobals
6
6
  describe("DeployApp.parseArgs", () => {
7
7
  testSync("up with the defaults", () =>
8
8
  expect(DeployApp.parseArgs(["up"]))->toEqual(
9
- Ok({DeployApp.command: Some(Up), manifest: None, stack: "dev", help: false}),
9
+ Ok({DeployApp.command: Up, stack: "dev", help: false}),
10
10
  )
11
11
  )
12
12
 
13
13
  testSync("down with a manifest and a stack", () =>
14
14
  expect(DeployApp.parseArgs(["down", "--manifest", "../m.yaml", "--stack", "try"]))->toEqual(
15
- Ok({DeployApp.command: Some(Down), manifest: Some("../m.yaml"), stack: "try", help: false}),
15
+ Ok({DeployApp.command: Down, manifest: "../m.yaml", stack: "try", help: false}),
16
16
  )
17
17
  )
18
18
 
@@ -55,11 +55,10 @@ describe("DeployApp stacks and layer", () => {
55
55
  projectName: "shop-platform-aws",
56
56
  program: "/app/platform-aws/src/Main.res.mjs",
57
57
  stackDefaults: Dict.fromArray([("aws:region", "us-east-1"), ("platform:x", "y")]),
58
- region: None,
59
58
  }
60
59
 
61
60
  testSync("a stack the manifest puts in another region is refused", () => {
62
- let ingest = {...project, label: "ingest", region: Some("eu-central-1")}
61
+ let ingest = {...project, label: "ingest", region: "eu-central-1"}
63
62
  expect(
64
63
  DeployApp.regionProblems(~projects=[project, ingest], ~region="eu-west-1")->Array.length,
65
64
  )->toBe(1)