@reventlessdev/reventless-aws 3.0.0-alpha.344 → 3.0.0-alpha.346

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 (263) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/package.json +15 -12
  3. package/run-provision-accounts.mjs +3 -0
  4. package/run-provision-admin.mjs +3 -0
  5. package/scripts/ProvisionAccounts.res +325 -0
  6. package/scripts/ProvisionAccounts.res.mjs +337 -0
  7. package/scripts/ProvisionAdmin.res +275 -0
  8. package/scripts/ProvisionAdmin.res.mjs +289 -0
  9. package/scripts/ProvisionCognito.res +149 -0
  10. package/scripts/ProvisionCognito.res.mjs +98 -0
  11. package/scripts/ProvisionIdentity.res +84 -14
  12. package/scripts/ProvisionIdentity.res.mjs +72 -7
  13. package/scripts/ProvisionProvider.res +104 -0
  14. package/scripts/ProvisionProvider.res.mjs +123 -0
  15. package/src/Platform.res +358 -329
  16. package/src/Platform.res.mjs +24 -12
  17. package/src/Platform_Casts.res +13 -4
  18. package/src/Platform_Stack.res +119 -9
  19. package/src/Platform_Stack.res.mjs +42 -4
  20. package/src/adapter/Api/AppSyncEventsSigner_Ops.res +8 -4
  21. package/src/adapter/Api/AppSync_EventsApi.res +12 -14
  22. package/src/adapter/Api/AppSync_Resolver_Native.res +3 -4
  23. package/src/adapter/Api/AppSync_Resolver_Retrying.res +78 -70
  24. package/src/adapter/Api/AppSync_SourceApiAssociation_Retrying.res +11 -8
  25. package/src/adapter/Api/Platform_AdminScan_Ops.res +15 -14
  26. package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res +10 -2
  27. package/src/adapter/Api/Platform_ComponentDefinitions_Lambda_Ops.res +40 -50
  28. package/src/adapter/Api/Platform_UIFragments_Lambda.res +39 -32
  29. package/src/adapter/Api/Platform_UIFragments_Lambda_Ops.res +5 -2
  30. package/src/adapter/Auth/Auth_ActiveRolePoolAttachment.res +0 -1
  31. package/src/adapter/Auth/Auth_ActiveRoleStore.res +1 -2
  32. package/src/adapter/Auth/Auth_ActiveRoleStore_Schema.res +1 -4
  33. package/src/adapter/Auth/Auth_ActiveRoleTrigger_Ops.res +5 -2
  34. package/src/adapter/Auth/Auth_Cognito.res +3 -9
  35. package/src/adapter/Auth/Auth_LoginIdentifier.res +66 -0
  36. package/src/adapter/Auth/Auth_LoginIdentifier.res.mjs +70 -0
  37. package/src/adapter/Auth/Auth_SignUpMode.res +78 -0
  38. package/src/adapter/Auth/Auth_SignUpMode.res.mjs +56 -0
  39. package/src/adapter/CommandGenerator/CommandGeneratorResolvers_AppSync.res +1 -4
  40. package/src/adapter/CommandGenerator/CommandGeneratorResolvers_AppSync_NoOp.res +3 -1
  41. package/src/adapter/CommandGenerator/InboundTranslationResolvers_AppSync.res +1 -4
  42. package/src/adapter/CommandTopic/CommandTopicChannel_SQS.res +7 -4
  43. package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Async.res +6 -1
  44. package/src/adapter/CommandTopic/CommandTopicChannel_SQS_FIFO.res +7 -4
  45. package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Runtime.res +24 -18
  46. package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Sync.res +9 -4
  47. package/src/adapter/CommandTopic/CommandTopicRegistry.res +1 -4
  48. package/src/adapter/Counter/CounterHandler_DynamoDbStream.res +15 -15
  49. package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb.res +9 -5
  50. package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res +179 -213
  51. package/src/adapter/EventCollector/EventCollectorChannel_DynamoDbStream.res +5 -5
  52. package/src/adapter/EventCollector/EventCollectorChannel_Helpers.res +6 -2
  53. package/src/adapter/EventCollector/EventCollectorChannel_SQS.res +14 -7
  54. package/src/adapter/EventCollector/EventCollectorChannel_SQS_FIFO.res +14 -7
  55. package/src/adapter/EventCollector/EventCollectorChannel_SQS_Runtime.res +6 -3
  56. package/src/adapter/EventLog/EventLogStorage_DynamoDbStream.res +6 -1
  57. package/src/adapter/EventLog/EventLogStorage_DynamoDb_Runtime.res +13 -17
  58. package/src/adapter/EventLog/EventLogStorage_Postgres.res +7 -4
  59. package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res +12 -7
  60. package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync_Ops.res +4 -2
  61. package/src/adapter/EventTopic/EventTopicPublisher_DynamoDbStream.res +3 -2
  62. package/src/adapter/EventTopic/EventTopicPublisher_SNS.res +20 -12
  63. package/src/adapter/EventTopic/EventTopicPublisher_SNS_FIFO.res +21 -9
  64. package/src/adapter/EventTopic/EventTopicPublisher_SNS_Runtime.res +5 -3
  65. package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver.res +6 -3
  66. package/src/adapter/Mcp/MCP_Lambda.res +31 -46
  67. package/src/adapter/Messaging/Messaging_Ses_Backend.res +11 -7
  68. package/src/adapter/Messaging/Messaging_Ses_Backend.res.mjs +2 -4
  69. package/src/adapter/Monitoring/Monitoring_CloudWatch.res +16 -16
  70. package/src/adapter/Postgres/PgChangeFeedRelay_Builder.res +5 -10
  71. package/src/adapter/Postgres/PgChangeFeedRelay_Runtime.res +4 -2
  72. package/src/adapter/Postgres/PgConnection.res +6 -5
  73. package/src/adapter/Postgres/PgMigration_Builder.res +4 -8
  74. package/src/adapter/Postgres/PgRuntime.res +4 -7
  75. package/src/adapter/QueryDb/PgQueryResolver_Builder.res +9 -11
  76. package/src/adapter/QueryDb/PgQueryResolver_Lambda.res +22 -21
  77. package/src/adapter/QueryDb/QueryDbResolvers_AppSync.res +114 -111
  78. package/src/adapter/QueryDb/QueryDbResolvers_Lambda.res +1 -7
  79. package/src/adapter/QueryDb/QueryDbStorage.res +4 -2
  80. package/src/adapter/QueryDb/QueryDbStorage_DynamoDb.res +23 -24
  81. package/src/adapter/QueryDb/QueryDbStorage_DynamoDbStream.res +8 -2
  82. package/src/adapter/QueryDb/QueryDbStorage_DynamoDb_Runtime.res +71 -73
  83. package/src/adapter/QueryDb/QueryDbStorage_Postgres.res +5 -2
  84. package/src/adapter/QueryDb/QueryInterceptor_Provisioning.res +1 -4
  85. package/src/adapter/QueryEngine/QueryEngine_DynamoDb.res +8 -2
  86. package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res +73 -81
  87. package/src/adapter/Runtime/AggregateRuntime_Builder_Micro_Async.res +72 -78
  88. package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate.res +44 -67
  89. package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate_Async.res +44 -67
  90. package/src/adapter/Runtime/AggregateRuntime_Builder_Single.res +53 -82
  91. package/src/adapter/Runtime/AggregateRuntime_Builder_Single_Async.res +47 -77
  92. package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res +23 -11
  93. package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res.mjs +5 -1
  94. package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res +80 -97
  95. package/src/adapter/Runtime/CounterEntryPoint_Ops.res +2 -7
  96. package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res +16 -10
  97. package/src/adapter/Runtime/EventCollectorEntryPoint_Ops.res +24 -15
  98. package/src/adapter/Runtime/EventCollectorRuntime_Builder_PerEventCollector.res +17 -37
  99. package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res +31 -57
  100. package/src/adapter/Runtime/EventMapperEntryPoint_Ops.res +18 -24
  101. package/src/adapter/Runtime/ExtensionPointEntryPoint_Ops.res +1 -5
  102. package/src/adapter/Runtime/ExtensionPointRuntime_Builder_PerExtensionPoint.res +4 -3
  103. package/src/adapter/Runtime/HeartbeatEntryPoint.res +0 -1
  104. package/src/adapter/Runtime/PgChangeFeedRelayEntryPoint.res +4 -2
  105. package/src/adapter/Runtime/PgMigrationEntryPoint.res +0 -1
  106. package/src/adapter/Runtime/PgQueryResolverEntryPoint_Ops.res +3 -2
  107. package/src/adapter/Runtime/PluginExtensionPointEntryPoint.res +1 -2
  108. package/src/adapter/Runtime/ProjectionEntryPoint_Ops.res +4 -5
  109. package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res +22 -10
  110. package/src/adapter/Runtime/RuntimeExtensionEntryPoint_Ops.res +8 -2
  111. package/src/adapter/Runtime/SideEffectHandlerRuntime_Builder_Single.res +14 -31
  112. package/src/adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res +16 -17
  113. package/src/adapter/Runtime/StateViewSliceEntryPoint_Ops.res +10 -9
  114. package/src/adapter/Runtime/StateViewSliceRuntime_Builder_Single.res +46 -52
  115. package/src/adapter/Runtime/StreamRoutedEntryPoint_Ops.res +36 -41
  116. package/src/adapter/Runtime/TaskBucketEntryPoint_Ops.res +31 -37
  117. package/src/adapter/Runtime/TaskRuntime_Builder_PerBucket.res +6 -7
  118. package/src/adapter/ScheduledPublisher/ScheduledPublisher_CloudWatchEvents.res +4 -6
  119. package/src/adapter/ScheduledPublisher/ScheduledPublisher_CloudWatchEvents_Runtime.res +2 -6
  120. package/src/adapter/StateTopic/StateTopic_AppSync.res +21 -16
  121. package/src/adapter/StateTopic/StateTopic_AppSync_Ops.res +36 -32
  122. package/src/adapter/Task/TaskBucket_S3.res +6 -1
  123. package/src/adapter/Upload/Upload_Claim_S3.res +17 -20
  124. package/src/adapter/Upload/Upload_Claim_S3_Ops.res +5 -2
  125. package/src/adapter/Upload/Upload_Presign_S3.res +51 -49
  126. package/src/capability/Capability_Geocoding_AwsLocation.res +4 -1
  127. package/src/capability/Capability_Messaging.res +4 -5
  128. package/src/capability/Capability_Messaging_Ses.res +3 -1
  129. package/src/capability/Capability_ObjectStore_S3.res +1 -7
  130. package/src/components/Api/AppSync_Adapter.res +80 -109
  131. package/src/components/Api/AppSync_Adapter.res.mjs +26 -60
  132. package/src/components/Api/AppSync_SdlDecorate.res +118 -31
  133. package/src/components/Api/AppSync_SdlDecorate.res.mjs +45 -0
  134. package/src/components/AutomationSlice_Builder.res +6 -4
  135. package/src/components/ExtensionPoint_Builder.res +9 -10
  136. package/src/components/InboundTranslationSlice_Builder.res +7 -8
  137. package/src/components/OutboundTranslationSlice_Builder.res +14 -8
  138. package/src/components/OutboundTranslationSlice_Builder.res.mjs +1 -1
  139. package/src/components/SideEffectHandler_Single.res +4 -4
  140. package/src/components/StateViewSlice_Builder.res +6 -4
  141. package/src/components/StateViewSlice_Builder_Stream.res +6 -4
  142. package/src/components/Task_Builder_PerBucket.res +10 -11
  143. package/src/plugin/cloner/ClonerRunner_Fargate.res +3 -10
  144. package/src/plugin/cloner/ClonerRunner_Fargate_Runtime.res +1 -4
  145. package/src/plugin/heartbeat/HeartbeatRunner_CloudWatchEvents.res +5 -5
  146. package/src/plugin/runtime/PluginExtensionPointRuntime_Builder.res +19 -21
  147. package/src/plugin/runtime/PluginRuntime_Builder.res +167 -188
  148. package/src/plugin/runtime/Util_PluginMessage_Runtime.res +6 -5
  149. package/src/plugin/stack/Plugin_Stack.res +104 -103
  150. package/src/util/Util_AlarmSpec.res +2 -1
  151. package/src/util/Util_AppSync.res +8 -2
  152. package/src/util/Util_AppSync_Caller.res +15 -14
  153. package/src/util/Util_Bundle.res +46 -42
  154. package/src/util/Util_CognitoGroupUser_Runtime.res +32 -34
  155. package/src/util/Util_Cognito_Runtime.res +11 -7
  156. package/src/util/Util_DeadLetterQueue.res +12 -2
  157. package/src/util/Util_DynamoDb.res +5 -3
  158. package/src/util/Util_DynamoDbStream.res +7 -3
  159. package/src/util/Util_DynamoDbStream_Runtime.res +1 -2
  160. package/src/util/Util_DynamoDb_Runtime.res +23 -41
  161. package/src/util/Util_HostUiDomain.res +6 -1
  162. package/src/util/Util_Kinesis_Runtime.res +10 -11
  163. package/src/util/Util_Lambda.res +12 -5
  164. package/src/util/Util_LambdaEnvBudget.res +5 -5
  165. package/src/util/Util_LambdaLogging.res +1 -2
  166. package/src/util/Util_LogGroup_Adopting.res +1 -4
  167. package/src/util/Util_ResourceNaming.res +1 -2
  168. package/src/util/Util_SNS.res +8 -3
  169. package/src/util/Util_SNS_FIFO.res +1 -1
  170. package/src/util/Util_SNS_Runtime.res +11 -10
  171. package/src/util/Util_SQS.res +4 -2
  172. package/src/util/Util_SQS_FIFO.res +5 -2
  173. package/src/util/Util_SQS_Runtime.res +37 -36
  174. package/src/util/Util_ShellConfig.res +3 -2
  175. package/src/util/Util_StaticBundle.res +1 -3
  176. package/src/util/Util_StoreLayout.res +4 -1
  177. package/tests/AWS_TagsTest.res +16 -5
  178. package/tests/AppSyncEventsSigner_OpsTest.res +11 -2
  179. package/tests/AppSync_AdapterTest.res +286 -224
  180. package/tests/AppSync_AdapterTest.res.mjs +69 -0
  181. package/tests/AppSync_Resolver_RetryingTest.res +64 -44
  182. package/tests/AppSync_RetirementNarrowingTest.res +59 -46
  183. package/tests/AppSync_SdlDecorateTest.res +22 -20
  184. package/tests/AppSync_SourceApiAssociation_RetryingTest.res +40 -22
  185. package/tests/Auth_ActiveRolePoolAttachmentTest.res +114 -107
  186. package/tests/Auth_ActiveRoleStoreTest.res +12 -9
  187. package/tests/Auth_ActiveRoleStore_SchemaTest.res +2 -1
  188. package/tests/Auth_ActiveRoleTrigger_OpsTest.res +20 -16
  189. package/tests/Auth_CognitoTest.res +31 -46
  190. package/tests/Auth_LoginIdentifierTest.res +51 -0
  191. package/tests/Auth_LoginIdentifierTest.res.mjs +51 -0
  192. package/tests/Auth_SignUpModeTest.res +56 -0
  193. package/tests/Auth_SignUpModeTest.res.mjs +53 -0
  194. package/tests/AutomationSliceEntryPoint_OpsTest.res +69 -67
  195. package/tests/BakeConvergenceTest.res +22 -25
  196. package/tests/Capability_MessagingTest.res +28 -12
  197. package/tests/CommandTopicQueuePolicyTest.res +1 -2
  198. package/tests/CounterEntryPoint_OpsTest.res +3 -7
  199. package/tests/DcbEventLogStorage_DynamoDb_RuntimeTest.res +306 -210
  200. package/tests/EventCollectorConnectLambdaPreviewTest.res +14 -7
  201. package/tests/EventCollectorEntryPoint_OpsTest.res +12 -4
  202. package/tests/EventCollectorPluginDefinitionAssetTest.res +18 -11
  203. package/tests/EventCollectorReadyGateTest.res +5 -4
  204. package/tests/EventLogStorage_DynamoDb_RuntimeTest.res +1 -2
  205. package/tests/EventMapperEntryPoint_OpsTest.res +1 -3
  206. package/tests/ExtensionPointEntryPoint_OpsTest.res +1 -4
  207. package/tests/HandlerFactoryDispatchTest.res +97 -70
  208. package/tests/MCP_LambdaTest.res +16 -27
  209. package/tests/PgChangeFeedRelay_IntegrationTest.res +123 -93
  210. package/tests/PgChangeFeedRelay_RuntimeTest.res +13 -10
  211. package/tests/PgMigrationEntryPoint_IntegrationTest.res +0 -1
  212. package/tests/PgPipeline_IntegrationTest.res +80 -66
  213. package/tests/PgQueryDbUnion_IntegrationTest.res +1 -2
  214. package/tests/PgQueryResolverEntryPoint_OpsTest.res +2 -6
  215. package/tests/PgQueryResolver_LambdaTest.res +41 -24
  216. package/tests/Platform_AdminScan_OpsTest.res +4 -1
  217. package/tests/Platform_ComponentDefinitions_Lambda_OpsTest.res +137 -129
  218. package/tests/ProjectionEntryPoint_DisplayNameTest.res +7 -3
  219. package/tests/ProjectionEntryPoint_UnionStampTest.res +3 -2
  220. package/tests/ProvisionAccountsTest.res +142 -0
  221. package/tests/ProvisionAccountsTest.res.mjs +153 -0
  222. package/tests/ProvisionAdminTest.res +55 -0
  223. package/tests/ProvisionAdminTest.res.mjs +66 -0
  224. package/tests/ProvisionIdentityTest.res +91 -9
  225. package/tests/ProvisionIdentityTest.res.mjs +66 -1
  226. package/tests/QueryDbOwnerIndexTableTest.res +6 -4
  227. package/tests/QueryDbResolvers_AppSyncTest.res +23 -16
  228. package/tests/QueryInterceptor_LambdaTest.res +11 -13
  229. package/tests/ReadModelEntryPoint_OpsTest.res +43 -41
  230. package/tests/RuntimeExtensionEntryPoint_OpsTest.res +4 -3
  231. package/tests/SideEffectEntryPoint_OpsTest.res +23 -18
  232. package/tests/StateChangeDescriptorParityTest.res +28 -26
  233. package/tests/StateTopicKeySchemaTest.res +18 -15
  234. package/tests/StateViewSliceEntryPoint_OpsTest.res +55 -44
  235. package/tests/TaskBucketEntryPoint_OpsTest.res +13 -13
  236. package/tests/Upload_ClaimTest.res +3 -3
  237. package/tests/Util_AwsErrorTest.res +4 -7
  238. package/tests/Util_BundleDependencyClosureTest.res +15 -3
  239. package/tests/Util_BundleEsmLoaderTest.res +3 -3
  240. package/tests/Util_BundleResolveTest.res +4 -6
  241. package/tests/Util_BundleRuntimeExtensionTest.res +17 -18
  242. package/tests/Util_DcbMetricsTest.res +6 -6
  243. package/tests/Util_DynamoDbStreamTest.res +4 -5
  244. package/tests/Util_DynamoDbTest.res +3 -2
  245. package/tests/Util_LambdaEnvBudgetTest.res +22 -18
  246. package/tests/Util_LambdaLoggingTest.res +9 -8
  247. package/tests/Util_LogGroup_AdoptingTest.res +10 -5
  248. package/tests/Util_LogRetentionTest.res +6 -2
  249. package/tests/Util_OwnerScopeEnvTest.res +35 -8
  250. package/tests/Util_OwnerScopeEnvTest.res.mjs +13 -0
  251. package/tests/Util_SQS_RuntimeTest.res +5 -7
  252. package/tests/Util_ShellConfigTest.res +7 -17
  253. package/tests/Util_StaticBundleTest.res +3 -8
  254. package/tests/Util_StoreLayoutTest.res +17 -12
  255. package/tests/integration/AggregateEntryPoint_IntegrationTest.res +1 -4
  256. package/tests/integration/DcbCommandTopicEntryPoint_IntegrationTest.res +15 -15
  257. package/tests/integration/DcbEventLogStorage_DynamoDb_IntegrationTest.res +296 -232
  258. package/tests/integration/DcbIntegrationHarness.res +8 -8
  259. package/tests/integration/EpCompositeSlice.res +16 -8
  260. package/tests/integration/QueryDbUnion_DynamoDb_IntegrationTest.res +8 -10
  261. package/tests/integration/StateViewSliceEntryPoint_IntegrationTest.res +10 -10
  262. package/tests/integration/SvsTestSlice_Projection.res +1 -3
  263. package/tests/util/Util_AlarmSpecTest.res +62 -49
package/CHANGELOG.md CHANGED
@@ -3,6 +3,42 @@
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.346 (2026-09-11)
7
+
8
+ ### Bug Fixes
9
+
10
+ * **aws:** the schema refuses a rule it cannot enforce, instead of inverting it ([47da2ff](https://github.com/ReventlessDev/reventless-core/commit/47da2ffeff34498a5589d6df347de400f7360f63))
11
+ * feat(spec)!: a secret is a capability, so a test can know it in advance ([71507c6](https://github.com/ReventlessDev/reventless-core/commit/71507c6459b49178746f00c5040cb479d7fdade8))
12
+ * feat(spec)!: making a principal is a capability, so the provider is replaceable ([3e59b9b](https://github.com/ReventlessDev/reventless-core/commit/3e59b9b665cc7e4b6b6f156b63b1b6bd0c6181ca))
13
+ ### Features
14
+
15
+ * **aws:** the first administrator is one command, not the console ([5f1a846](https://github.com/ReventlessDev/reventless-core/commit/5f1a84603b21a9feb691a08a148751c6c6e8eca8))
16
+ * **aws:** the rest of the cast is a file, not a comment ([aa23581](https://github.com/ReventlessDev/reventless-core/commit/aa23581f09948a47fb451ec2ecf2fc2bdd8e6ee6))
17
+ * **aws:** the sign-in attribute is chosen at first deploy, not hard-coded ([21ff246](https://github.com/ReventlessDev/reventless-core/commit/21ff24693fb8ddf8d50abeb5197d4b0d1ad54f83))
18
+ * **aws:** who may create an account is a setting, not a hard-coded field ([a89e13f](https://github.com/ReventlessDev/reventless-core/commit/a89e13f0b3929898ae604a101d0b338755008bfb))
19
+ * **spec:** preparing a manifest is not an AWS errand ([bd7f8e2](https://github.com/ReventlessDev/reventless-core/commit/bd7f8e2f6132c0cacac2ab839165f21fe91eaf6c))
20
+
21
+ ### BREAKING CHANGES
22
+
23
+ * Capabilities.t gains a secrets member. A platform that builds
24
+ the record literally no longer compiles until it supplies one;
25
+ Capabilities.none.secrets is the refusing value. Code that spreads
26
+ Capabilities.none is unaffected.
27
+ * Capabilities.t gains an identityProvider member. A platform
28
+ that builds the record literally no longer compiles until it supplies one;
29
+ Capabilities.none.identityProvider is the refusing value to pass while no
30
+ backend exists. Code that spreads Capabilities.none is unaffected.
31
+
32
+
33
+
34
+ # 3.0.0-alpha.345 (2026-09-09)
35
+
36
+ **Note:** Version bump only for package @reventlessdev/reventless-aws
37
+
38
+
39
+
40
+
41
+
6
42
  # 3.0.0-alpha.344 (2026-09-09)
7
43
 
8
44
  ### Bug Fixes
package/package.json CHANGED
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "name": "@reventlessdev/reventless-aws",
3
- "version": "3.0.0-alpha.344",
3
+ "version": "3.0.0-alpha.346",
4
4
  "description": "AWS adapters for Reventless",
5
5
  "license": "Apache-2.0",
6
6
  "bin": {
7
- "provision-identity": "./run-provision-identity.mjs"
7
+ "provision-identity": "./run-provision-identity.mjs",
8
+ "provision-admin": "./run-provision-admin.mjs",
9
+ "provision-accounts": "./run-provision-accounts.mjs"
8
10
  },
9
11
  "dependencies": {
10
12
  "@aws-sdk/client-appsync": "3.970.0",
@@ -15,18 +17,19 @@
15
17
  "@aws-sdk/s3-request-presigner": "3.970.0",
16
18
  "sury": "11.0.0-rc.2",
17
19
  "uuid": "^13.0.0",
18
- "@reventlessdev/rescript-effect": "0.1.0-alpha.32",
20
+ "yaml": "^2.8.3",
21
+ "@reventlessdev/rescript-aws-sdk": "3.0.0-alpha.18",
19
22
  "@reventlessdev/rescript-jest": "1.0.0-alpha.10",
20
- "@reventlessdev/rescript-pulumi-aws": "3.0.0-alpha.11",
21
- "@reventlessdev/rescript-aws-sdk": "3.0.0-alpha.16",
22
- "@reventlessdev/rescript-node": "2.0.0-alpha.10",
23
+ "@reventlessdev/rescript-node": "2.0.0-alpha.11",
24
+ "@reventlessdev/rescript-pulumi-aws": "3.0.0-alpha.13",
25
+ "@reventlessdev/rescript-effect": "0.1.0-alpha.33",
26
+ "@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.20",
23
27
  "@reventlessdev/rescript-uuid": "2.0.0-alpha.0",
24
- "@reventlessdev/reventless-core": "3.0.0-alpha.260",
25
- "@reventlessdev/reventless-interop": "3.0.0-alpha.35",
26
- "@reventlessdev/reventless-postgres": "3.0.0-alpha.124",
27
- "@reventlessdev/reventless-infra": "3.0.0-alpha.161",
28
- "@reventlessdev/reventless-spec": "3.0.0-alpha.133",
29
- "@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.19"
28
+ "@reventlessdev/reventless-core": "3.0.0-alpha.262",
29
+ "@reventlessdev/reventless-interop": "3.0.0-alpha.36",
30
+ "@reventlessdev/reventless-postgres": "3.0.0-alpha.126",
31
+ "@reventlessdev/reventless-spec": "3.0.0-alpha.135",
32
+ "@reventlessdev/reventless-infra": "3.0.0-alpha.163"
30
33
  },
31
34
  "devDependencies": {
32
35
  "rescript": "12.3.0",
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { main } from "./scripts/ProvisionAccounts.res.mjs"
3
+ await main()
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { main } from "./scripts/ProvisionAdmin.res.mjs"
3
+ await main()
@@ -0,0 +1,325 @@
1
+ /***
2
+ Turn a declared cast of accounts into working sign-ins.
3
+
4
+ `provision-admin` makes the *first* administrator, which is the account that
5
+ cannot be made from a signed-in session because there is no signed-in session yet.
6
+ This one makes a declared list of accounts instead.
7
+
8
+ 🚨 **Neither needs the other to have run.** Both authenticate as the AWS caller,
9
+ not as a Cognito principal, so there is no bootstrap ordering between them: a
10
+ manifest declaring an entry in the administrator group stands a deployment up on
11
+ its own. The difference is where the credential ends up — `provision-admin` prints
12
+ one and keeps no copy, while this writes into the manifest, which is what
13
+ `pnpm run seed` reads. For a demo whose cast already names an administrator, this
14
+ one alone is enough.
15
+
16
+ ```
17
+ pnpm exec provision-accounts
18
+ ```
19
+
20
+ It reads `.reventless/users.yaml`, and knows nothing about any particular
21
+ application's cast: the manifest belongs to whoever is deploying. A demo's four
22
+ roles and a company's twelve staff are the same run. Which pool it writes to is
23
+ [ProvisionProvider]'s question, and usually needs no argument either.
24
+
25
+ 🚨 **Two halves, and only the second is AWS's.** [Reventless.AccountsManifest.prepare]
26
+ validates the manifest and mints a password into every empty field, on any
27
+ platform and with no credentials — locally that is the whole of provisioning,
28
+ because there the manifest *is* the user store. This script then applies the
29
+ prepared manifest to a Cognito pool. That first half is its own bin,
30
+ `prepare-accounts`, so a platform that never deploys to AWS can reach it without
31
+ depending on this package.
32
+
33
+ Re-running is safe and is the normal case — an operator adding one account to
34
+ four. A password already in the file is never replaced; see
35
+ [Reventless.AccountsManifest.applyFills] for why that rule is the whole of the
36
+ write-back's safety.
37
+ */
38
+
39
+ open AwsSdk
40
+
41
+ module Cognito = CognitoIdentityServiceProvider
42
+ module Manifest = Reventless.AccountsManifest
43
+
44
+ // ── Arguments ────────────────────────────────────────────────────────────────
45
+
46
+ type args = {
47
+ providerId: option<string>,
48
+ stack: option<string>,
49
+ file: option<string>,
50
+ help: bool,
51
+ }
52
+
53
+ /** Parsed rather than positional, and unknown flags are an error — the reason
54
+ [ProvisionAdmin.parseArgs] gives, which lands harder here: a typo'd
55
+ `--provider-id` would fall through to the environment and create the whole cast
56
+ in a *different pool* than the operator named. */
57
+ let parseArgs = (argv: array<string>): result<args, string> => {
58
+ let acc = ref(Ok({providerId: None, stack: None, file: None, help: false}))
59
+ let i = ref(0)
60
+ let count = argv->Array.length
61
+ while i.contents < count {
62
+ let flag = argv->Array.getUnsafe(i.contents)
63
+ let value = argv->Array.get(i.contents + 1)
64
+ switch (acc.contents, flag, value) {
65
+ | (Error(_), _, _) => i := count
66
+ | (Ok(a), "--provider-id", Some(v)) =>
67
+ acc := Ok({...a, providerId: Some(v)})
68
+ i := i.contents + 2
69
+ | (Ok(a), "--stack", Some(v)) =>
70
+ acc := Ok({...a, stack: Some(v)})
71
+ i := i.contents + 2
72
+ | (Ok(a), "--file", Some(v)) =>
73
+ acc := Ok({...a, file: Some(v)})
74
+ i := i.contents + 2
75
+ | (Ok(a), "--help", _) | (Ok(a), "-h", _) =>
76
+ acc := Ok({...a, help: true})
77
+ i := i.contents + 1
78
+ | (Ok(_), "--provider-id", None) | (Ok(_), "--file", None) | (Ok(_), "--stack", None) =>
79
+ acc := Error(`${flag} needs a value`)
80
+ | (Ok(_), unknown, _) => acc := Error(`unknown argument "${unknown}"`)
81
+ }
82
+ }
83
+ acc.contents
84
+ }
85
+
86
+ let usage = `
87
+ Turn a declared cast of accounts into working sign-ins.
88
+
89
+ --provider-id <id> The identity provider to create the accounts in. Usually
90
+ omitted: it falls back to ${ProvisionProvider.envKey},
91
+ then to the identityProviderId exported by the selected
92
+ Pulumi stack — which every deployment exports, whether it
93
+ created the pool or was handed one.
94
+ --stack <name> Read that output from this stack instead of the selected
95
+ one. The run always names the stack it used.
96
+ --file <path> The manifest. Defaults to .reventless/users.yaml relative
97
+ to the working directory, which is where both platforms
98
+ keep it.
99
+
100
+ For every entry: ensures the groups it names, ensures the account, sets a
101
+ permanent password, and applies the memberships. Generated passwords and the ids
102
+ the pool mints are written back into the manifest, so the seed client can read
103
+ them without anyone retyping a UUID.
104
+
105
+ A password already in the manifest is never replaced. Region and credentials come
106
+ from the environment, as for any AWS SDK call.
107
+ `
108
+
109
+ // ── Preflight ────────────────────────────────────────────────────────────────
110
+
111
+ let looksLikeEmail = (username: string): bool =>
112
+ username->String.includes("@") && username->String.includes(".")
113
+
114
+ /**
115
+ Refuse a pool this cast could never sign in to.
116
+
117
+ The mirror of [ProvisionAdmin.checkPoolAcceptsEmail], and it has to run the other
118
+ way round: that script is handed an address and asks whether the pool takes one,
119
+ while a manifest usually names plain usernames — `shopper`, `merch` — and the
120
+ question is whether the pool will accept *those*. A pool created with
121
+ `UsernameAttributes: [email]` will not, and the accounts it makes instead are
122
+ correctly created and unable to authenticate.
123
+
124
+ Checked for every entry before anything is created, so a manifest that cannot work
125
+ costs nothing rather than half a cast.
126
+ */
127
+ let checkPoolAcceptsUsernames = async (~providerId: string, ~usernames: array<string>): result<
128
+ unit,
129
+ string,
130
+ > =>
131
+ switch await ProvisionCognito.usernameAttributes(~providerId) {
132
+ | Error(_) as e => e
133
+ | Ok(attributes) =>
134
+ let signsInOnEmail = attributes->Array.includes("email")
135
+ let unusable = signsInOnEmail ? usernames->Array.filter(u => !looksLikeEmail(u)) : []
136
+ if unusable->Array.length == 0 {
137
+ Console.log(
138
+ `pool signs in on ${attributes->Array.length == 0
139
+ ? "username"
140
+ : attributes->Array.join(", ")}`,
141
+ )
142
+ Ok()
143
+ } else {
144
+ Error(
145
+ `pool "${providerId}" signs in on ${attributes->Array.join(
146
+ ", ",
147
+ )}, so ${unusable->Array.join(
148
+ ", ",
149
+ )} could never authenticate. The sign-in attribute is fixed at pool creation and no update can change it — either name these accounts by address in the manifest, or provision them in a pool that signs in on a username.`,
150
+ )
151
+ }
152
+ }
153
+
154
+ // ── Applying ─────────────────────────────────────────────────────────────────
155
+
156
+ let describe = (outcome: ProvisionCognito.outcome) =>
157
+ switch outcome {
158
+ | Created => "created"
159
+ | AlreadyPresent => "already present"
160
+ }
161
+
162
+ /** Every group the manifest names, made once rather than once per member.
163
+
164
+ The description says where the group came from because a pool outlives the
165
+ deployment that seeded it, and an operator meeting an undocumented group in the
166
+ console has no other way to find out. */
167
+ let ensureGroups = async (~providerId: string, ~entries: array<Manifest.entry>): unit => {
168
+ let named = []
169
+ entries->Array.forEach(entry =>
170
+ entry.groups->Array.forEach(group =>
171
+ if !(named->Array.includes(group)) {
172
+ named->Array.push(group)
173
+ }
174
+ )
175
+ )
176
+ for index in 0 to named->Array.length - 1 {
177
+ let group = named->Array.getUnsafe(index)
178
+ let outcome = await ProvisionCognito.ensureGroup(
179
+ ~providerId,
180
+ ~group,
181
+ ~description="Declared in a Reventless accounts manifest",
182
+ )
183
+ Console.log(`group ${group} (${outcome->describe})`)
184
+ }
185
+ }
186
+
187
+ /**
188
+ One account: the entry, applied.
189
+
190
+ The password is set unconditionally rather than only for an account this run
191
+ created — the same reason `provision-admin` does it, arriving at a manifest: the
192
+ file is the record of what the credential *is*, so an account whose password
193
+ drifted from the file is exactly the case a re-run is expected to fix.
194
+
195
+ Returns the id the pool minted, which is the value the manifest cannot know until
196
+ the account exists and which nobody should be pasting by hand.
197
+ */
198
+ let applyEntry = async (~providerId: string, ~entry: Manifest.entry): option<string> => {
199
+ let attributes: array<Cognito.AdminCreateUserCommand.attributeType> = looksLikeEmail(
200
+ entry.username,
201
+ )
202
+ ? [{name: "email", value: entry.username}, {name: "email_verified", value: "true"}]
203
+ : []
204
+ let outcome = await ProvisionCognito.ensureUser(
205
+ ~providerId,
206
+ ~username=entry.username,
207
+ ~attributes,
208
+ )
209
+ Console.log(`user ${entry.username} (${outcome->describe})`)
210
+ await ProvisionCognito.setPassword(
211
+ ~providerId,
212
+ ~username=entry.username,
213
+ ~password=entry.password,
214
+ )
215
+ for index in 0 to entry.groups->Array.length - 1 {
216
+ let group = entry.groups->Array.getUnsafe(index)
217
+ await ProvisionCognito.addToGroup(~providerId, ~username=entry.username, ~group)
218
+ Console.log(`member ${entry.username} in ${group}`)
219
+ }
220
+ await ProvisionCognito.subOf(~providerId, ~username=entry.username)
221
+ }
222
+
223
+ // ── Main ─────────────────────────────────────────────────────────────────────
224
+
225
+ /**
226
+ 🚨 **The passwords are in the manifest, not in this output, and that is the whole
227
+ point of the write-back.**
228
+
229
+ `provision-admin` prints its one credential because there is nowhere else for it
230
+ to live. A cast of four has somewhere: the file the seed client already reads to
231
+ sign in. Printing them here would put every account's password in scrollback and
232
+ in any build log, and buy nothing — whoever needs them can read the file they
233
+ already have.
234
+ */
235
+ let manifestNote = (~file: string) =>
236
+ `
237
+ 🚨 Generated passwords were written into ${file}. They are not printed here
238
+ because that file is where they are read from — by you and by \`pnpm run seed\`.
239
+ It is gitignored on every platform; keep it that way. These are bootstrap
240
+ credentials for a deployment, not secrets to reuse anywhere real.`
241
+
242
+ let run = async (): result<unit, string> =>
243
+ // argv[0] is node, argv[1] this script.
244
+ switch parseArgs(NodeProcess.argv->Array.slice(~start=2, ~end=NodeProcess.argv->Array.length)) {
245
+ | Error(_) as e => e
246
+ | Ok(args) if args.help =>
247
+ Console.log(usage)
248
+ Ok()
249
+ | Ok(args) =>
250
+ switch Manifest.locate(~given=?args.file, ()) {
251
+ | Error(_) as e => e
252
+ | Ok(located) =>
253
+ let file = located->Manifest.pathOf
254
+ switch located {
255
+ | SeededFrom(_, template) => Console.log(`manifest ${file} (new, copied from ${template})`)
256
+ | Declared(_) => ()
257
+ }
258
+ switch Manifest.prepare(~path=file) {
259
+ | Error(message) => Error(`${file}: ${message}`)
260
+ | Ok([]) => Error(`${file} declares no accounts`)
261
+ | Ok(prepared) =>
262
+ let generated = prepared->Array.filter(p => p.passwordGenerated)->Array.length
263
+ Console.log(
264
+ `manifest ${file} (${prepared
265
+ ->Array.length
266
+ ->Int.toString} accounts, ${generated->Int.toString} password(s) generated)`,
267
+ )
268
+ let entries = prepared->Array.map(p => p.entry)
269
+ switch ProvisionProvider.resolve(~given=args.providerId, ~stack=args.stack) {
270
+ | Error(message) =>
271
+ Error(
272
+ `${message}. To fill in the manifest without creating anything, run prepare-accounts`,
273
+ )
274
+ | Ok((providerId, source)) =>
275
+ Console.log(`provider ${providerId} (from ${source->ProvisionProvider.describe})`)
276
+ switch await checkPoolAcceptsUsernames(
277
+ ~providerId,
278
+ ~usernames=entries->Array.map(e => e.username),
279
+ ) {
280
+ | Error(_) as e => e
281
+ | Ok() =>
282
+ await ensureGroups(~providerId, ~entries)
283
+ let fills = []
284
+ for index in 0 to entries->Array.length - 1 {
285
+ let entry = entries->Array.getUnsafe(index)
286
+ let userId = await applyEntry(~providerId, ~entry)
287
+ fills->Array.push({Manifest.index, password: None, userId})
288
+ }
289
+ switch Manifest.fillFile(~path=file, ~fills) {
290
+ | Error(message) => Error(`${file}: ${message}`)
291
+ | Ok(report) =>
292
+ let corrected = report->Array.filter(r => r.userIdWritten)->Array.length
293
+ Console.log(
294
+ `manifest ${file} (${corrected->Int.toString} id(s) written back)${manifestNote(
295
+ ~file,
296
+ )}`,
297
+ )
298
+ Ok()
299
+ }
300
+ }
301
+ }
302
+ }
303
+ }
304
+ }
305
+
306
+ /**
307
+ 🚨 **Catches thrown exceptions, not only `Error` results** — the reason
308
+ [ProvisionAdmin.main] gives. Without it an SDK failure escapes an async function
309
+ nothing awaits and Node reports `UnhandledPromiseRejection ... "#<Object>"`,
310
+ naming neither the call that failed nor why.
311
+ */
312
+ let main = async () =>
313
+ switch await run() {
314
+ | Ok() => ()
315
+ | Error(message) =>
316
+ Console.error(`provision-accounts: ${message}`)
317
+ NodeProcess.exit(1)
318
+ | exception exn =>
319
+ Console.error(`provision-accounts: ${Util_AwsError.describe(exn)}`)
320
+ NodeProcess.exit(1)
321
+ }
322
+
323
+ // 🚨 **No top-level call.** `../run-provision-accounts.mjs` invokes [main]; this
324
+ // module only defines it. A module that ran itself on import could not be
325
+ // imported by a test.