@reventlessdev/reventless-aws 3.0.0-alpha.397 → 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.
- package/CHANGELOG.md +33 -0
- package/package.json +9 -9
- package/scripts/BakeManifest.res +15 -15
- package/scripts/DeployApp.res +8 -9
- package/scripts/DeployApp.res.mjs +4 -13
- package/scripts/DeployManifest.res +4 -5
- package/scripts/DeployManifest.res.mjs +0 -1
- package/scripts/ProvisionAccounts.res +41 -33
- package/scripts/ProvisionAccounts.res.mjs +6 -9
- package/scripts/ProvisionAdmin.res +10 -10
- package/scripts/ProvisionIdentity.res +2 -2
- package/scripts/ResolveEnvironment.res +3 -3
- package/src/Platform.res +6 -4
- package/src/Platform.res.mjs +6 -4
- package/src/Platform_ProvidedGroups.res +4 -4
- package/src/Platform_Stack.res +2 -3
- package/src/Platform_Stack.res.mjs +1 -2
- package/src/adapter/Api/AppSyncEventsSigner_Ops.res +2 -2
- package/src/adapter/Api/AppSync_EventsApi.res +2 -2
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda_Ops.res +6 -6
- package/src/adapter/DcbEventLog/DcbBackend.res +3 -3
- package/src/adapter/DcbEventLog/DcbBackend.res.mjs +1 -3
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res +11 -9
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res.mjs +4 -6
- package/src/adapter/EventLog/EventLogBackend.res +3 -3
- package/src/adapter/EventLog/EventLogBackend.res.mjs +1 -3
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Backend.res +1 -1
- package/src/adapter/QueryDb/PgQueryResolver_Lambda.res +5 -5
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res +2 -2
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro_Async.res +2 -2
- package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res +32 -32
- package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res.mjs +4 -3
- package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res +6 -6
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res +16 -5
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res.mjs +3 -3
- package/src/adapter/Runtime/EventCollectorEntryPoint_Ops.res +5 -5
- package/src/adapter/Runtime/PgQueryResolverEntryPoint_Ops.res +24 -18
- package/src/adapter/Runtime/ReadModelEntryPoint_Ops.res +16 -14
- package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res +2 -2
- package/src/adapter/Runtime/RuntimeExtensionEntryPoint_Ops.res +4 -4
- package/src/adapter/Runtime/SideEffectEntryPoint_Ops.res +4 -4
- package/src/adapter/Runtime/StateViewSliceEntryPoint_Ops.res +9 -9
- package/src/adapter/Runtime/TaskBucketEntryPoint_Ops.res +11 -9
- package/src/components/Api/AppSync_Adapter.res +4 -4
- package/src/components/InboundTranslationSlice_Builder.res +19 -0
- package/src/components/InboundTranslationSlice_Builder.res.mjs +12 -2
- package/src/plugin/runtime/PluginExtensionPointRuntime_Builder.res +4 -7
- package/src/plugin/runtime/PluginExtensionPointRuntime_Builder.res.mjs +1 -4
- package/src/plugin/runtime/PluginRuntime_Builder.res +17 -26
- package/src/plugin/runtime/PluginRuntime_Builder.res.mjs +7 -22
- package/tests/AppSyncEventsSigner_OpsTest.res +1 -1
- package/tests/AppSync_AdapterTest.res +4 -4
- package/tests/AppSync_AdapterTest.res.mjs +4 -8
- package/tests/Auth_ActiveRoleStoreTest.res +1 -1
- package/tests/Auth_ActiveRoleTrigger_OpsTest.res +1 -1
- package/tests/AutomationSliceEntryPoint_OpsTest.res +0 -2
- package/tests/AutomationSliceEntryPoint_OpsTest.res.mjs +3 -6
- package/tests/BakeConvergenceTest.res +1 -8
- package/tests/BakeConvergenceTest.res.mjs +3 -23
- package/tests/BakeManifestTest.res +5 -10
- package/tests/BakeManifestTest.res.mjs +1 -6
- package/tests/CommandLineTest.res +3 -3
- package/tests/DeployAppTest.res +3 -4
- package/tests/DeployAppTest.res.mjs +6 -15
- package/tests/EpInboundTestSlice.res +1 -0
- package/tests/EpInboundTestSlice.res.mjs +3 -0
- package/tests/EventCollectorPluginDefinitionAssetTest.res +1 -2
- package/tests/EventCollectorPluginDefinitionAssetTest.res.mjs +11 -21
- package/tests/IdentityProvider_Cognito_BackendTest.res +0 -3
- package/tests/IdentityProvider_Cognito_BackendTest.res.mjs +0 -3
- package/tests/PgQueryResolver_LambdaTest.res +6 -10
- package/tests/PgQueryResolver_LambdaTest.res.mjs +4 -34
- package/tests/Platform_ProvidedGroupsTest.res +2 -2
- package/tests/Platform_ProvidedGroupsTest.res.mjs +1 -2
- package/tests/ProvisionAccountsTest.res +5 -10
- package/tests/ProvisionAccountsTest.res.mjs +0 -9
- package/tests/ProvisionAdminTest.res +4 -9
- package/tests/ProvisionAdminTest.res.mjs +0 -7
- package/tests/ProvisionIdentityTest.res +2 -4
- package/tests/ProvisionIdentityTest.res.mjs +0 -2
- package/tests/SideEffectEntryPoint_OpsTest.res +2 -2
- package/tests/Util_ShellConfigTest.res +3 -3
- package/tests/Util_ShellConfigTest.res.mjs +1 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,39 @@
|
|
|
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.398 (2026-10-25)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **aws:** provision-accounts mints a domain id only when the deployed trigger reads the store ([2c4b172](https://github.com/ReventlessDev/reventless-core/commit/2c4b172338c2dff8add8121517f2d7caf17fe42b))
|
|
11
|
+
* refactor!: internal results and tool records whose parts may be absent are optional fields ([7009ddf](https://github.com/ReventlessDev/reventless-core/commit/7009ddf5d522f39ec9946a3b5cd062ceae889bbf))
|
|
12
|
+
* refactor(aws)!: deploy and runtime configuration a function may lack are optional fields ([de80a54](https://github.com/ReventlessDev/reventless-core/commit/de80a546501a97b39cbe71200120f062bb260da4))
|
|
13
|
+
* refactor(aws)!: command-line arguments a tool may not be given are optional fields ([82d5880](https://github.com/ReventlessDev/reventless-core/commit/82d5880e9aeda73fe9625dee73a1ca633b20a59a))
|
|
14
|
+
* refactor(spec)!: the plugin structure's optional parts are optional fields ([130bad5](https://github.com/ReventlessDev/reventless-core/commit/130bad581caf725a9d61b5a3df3d012e4f8ba402))
|
|
15
|
+
* feat!: an inbound translation is async and handed the platform's capabilities, and its audit row withholds sensitive fields ([dae6049](https://github.com/ReventlessDev/reventless-core/commit/dae6049e084f81408a494a2cd2011ec564dda65c))
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
* a plugin declares per role how a person is admitted, and the local platform honors the self-service and provisioned halves ([9c37bf5](https://github.com/ReventlessDev/reventless-core/commit/9c37bf50f15cac1703bf2c351713518121a56211))
|
|
19
|
+
* a stash capability holds a value for minutes outside the log and hands it over once ([627f285](https://github.com/ReventlessDev/reventless-core/commit/627f28529ead2d2d31bdd091c9f42e7faca40f6f))
|
|
20
|
+
|
|
21
|
+
### BREAKING CHANGES
|
|
22
|
+
|
|
23
|
+
* code that builds these records drops `name: None` and
|
|
24
|
+
writes `name: x` for `name: Some(x)`; a destructure of one of them binds a
|
|
25
|
+
field that may be absent with `?name`.
|
|
26
|
+
* code that builds these records drops `name: None` and
|
|
27
|
+
writes `name: x` for `name: Some(x)`.
|
|
28
|
+
* code that builds these records drops `name: None` and
|
|
29
|
+
writes `name: x` for `name: Some(x)`.
|
|
30
|
+
* code that builds these records drops `name: None`, writes
|
|
31
|
+
`name: x` for `name: Some(x)`, and `name: ?x` for a value already of type
|
|
32
|
+
option.
|
|
33
|
+
* an inbound translation's translate takes ~capabilities and
|
|
34
|
+
returns a promise, and its spec must declare capabilityNeeds ([] for one that
|
|
35
|
+
only maps input). FromSlice steps return promises.
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
6
39
|
# 3.0.0-alpha.397 (2026-10-23)
|
|
7
40
|
|
|
8
41
|
### Bug Fixes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reventlessdev/reventless-aws",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.398",
|
|
4
4
|
"description": "AWS adapters for Reventless",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"bin": {
|
|
@@ -22,19 +22,19 @@
|
|
|
22
22
|
"sury": "11.0.0",
|
|
23
23
|
"uuid": "^13.0.0",
|
|
24
24
|
"yaml": "^2.8.3",
|
|
25
|
-
"@reventlessdev/rescript-aws-sdk": "3.0.0-alpha.35",
|
|
26
|
-
"@reventlessdev/rescript-jest": "1.0.0-alpha.13",
|
|
27
|
-
"@reventlessdev/rescript-pulumi-aws": "3.0.0-alpha.33",
|
|
28
25
|
"@reventlessdev/rescript-effect": "1.0.0-alpha.1",
|
|
26
|
+
"@reventlessdev/rescript-jest": "1.0.0-alpha.13",
|
|
27
|
+
"@reventlessdev/rescript-aws-sdk": "3.0.0-alpha.36",
|
|
29
28
|
"@reventlessdev/rescript-node": "2.0.0-alpha.23",
|
|
29
|
+
"@reventlessdev/rescript-pulumi-aws": "3.0.0-alpha.34",
|
|
30
30
|
"@reventlessdev/rescript-pulumi-pulumi": "3.0.0-alpha.0",
|
|
31
31
|
"@reventlessdev/rescript-uuid": "2.0.0-alpha.1",
|
|
32
|
-
"@reventlessdev/
|
|
32
|
+
"@reventlessdev/reventless-core": "3.0.0-alpha.308",
|
|
33
33
|
"@reventlessdev/reventless-interop": "3.0.0-alpha.42",
|
|
34
|
-
"@reventlessdev/
|
|
35
|
-
"@reventlessdev/reventless-postgres": "3.0.0-alpha.
|
|
36
|
-
"@reventlessdev/reventless-
|
|
37
|
-
"@reventlessdev/reventless-
|
|
34
|
+
"@reventlessdev/rescript-web": "1.0.0-alpha.8",
|
|
35
|
+
"@reventlessdev/reventless-postgres": "3.0.0-alpha.172",
|
|
36
|
+
"@reventlessdev/reventless-infra": "3.0.0-alpha.205",
|
|
37
|
+
"@reventlessdev/reventless-spec": "3.0.0-alpha.176"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"rescript": "12.3.1",
|
package/scripts/BakeManifest.res
CHANGED
|
@@ -24,9 +24,9 @@ module Lambda = AwsSdk.Lambda
|
|
|
24
24
|
// ── Arguments ────────────────────────────────────────────────────────────────
|
|
25
25
|
|
|
26
26
|
type args = {
|
|
27
|
-
manifest
|
|
28
|
-
stack
|
|
29
|
-
since
|
|
27
|
+
manifest?: string,
|
|
28
|
+
stack?: string,
|
|
29
|
+
since?: string,
|
|
30
30
|
review: bool,
|
|
31
31
|
help: bool,
|
|
32
32
|
}
|
|
@@ -35,9 +35,9 @@ let parseArgs = (argv: array<string>): result<args, string> =>
|
|
|
35
35
|
Reventless.CliArgs.parse(~strings=["manifest", "stack", "since"], ~bools=["review"], argv)
|
|
36
36
|
->Result.flatMap(Reventless.CliArgs.noPositionals)
|
|
37
37
|
->Result.map(a => {
|
|
38
|
-
manifest: a->Reventless.CliArgs.string("manifest"),
|
|
39
|
-
stack: a->Reventless.CliArgs.string("stack"),
|
|
40
|
-
since: a->Reventless.CliArgs.string("since")->Option.flatMap(v => v == "" ? None : Some(v)),
|
|
38
|
+
manifest: ?(a->Reventless.CliArgs.string("manifest")),
|
|
39
|
+
stack: ?(a->Reventless.CliArgs.string("stack")),
|
|
40
|
+
since: ?(a->Reventless.CliArgs.string("since")->Option.flatMap(v => v == "" ? None : Some(v))),
|
|
41
41
|
review: a->Reventless.CliArgs.bool("review"),
|
|
42
42
|
help: a->Reventless.CliArgs.help,
|
|
43
43
|
})
|
|
@@ -129,13 +129,13 @@ type registration = {
|
|
|
129
129
|
plugin: string,
|
|
130
130
|
state: string,
|
|
131
131
|
expected: string,
|
|
132
|
-
found
|
|
133
|
-
writtenAt
|
|
132
|
+
found?: string,
|
|
133
|
+
writtenAt?: string,
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
type summary = {plugins: int, registered: int, unchanged: int, matched: int}
|
|
137
137
|
|
|
138
|
-
type written = {bucket: string, key: string, bytes: int, group
|
|
138
|
+
type written = {bucket: string, key: string, bytes: int, group?: string}
|
|
139
139
|
|
|
140
140
|
type answer =
|
|
141
141
|
| Baked({written: array<written>, summary: option<summary>, registrations: array<registration>})
|
|
@@ -155,8 +155,8 @@ let _registrations = (o: dict<JSON.t>): array<registration> =>
|
|
|
155
155
|
plugin: r->_string("plugin")->Option.getOr("?"),
|
|
156
156
|
state: r->_string("state")->Option.getOr("?"),
|
|
157
157
|
expected: r->_string("expected")->Option.getOr("?"),
|
|
158
|
-
found: r->_string("found"),
|
|
159
|
-
writtenAt: r->_string("writtenAt"),
|
|
158
|
+
found: ?(r->_string("found")),
|
|
159
|
+
writtenAt: ?(r->_string("writtenAt")),
|
|
160
160
|
})
|
|
161
161
|
|
|
162
162
|
let readAnswer = (json: JSON.t): result<answer, string> => {
|
|
@@ -184,7 +184,7 @@ let readAnswer = (json: JSON.t): result<answer, string> => {
|
|
|
184
184
|
bucket: e->_string("bucket")->Option.getOr("?"),
|
|
185
185
|
key: e->_string("key")->Option.getOr("?"),
|
|
186
186
|
bytes: e->_int("bytes"),
|
|
187
|
-
group: e->_string("group"),
|
|
187
|
+
group: ?(e->_string("group")),
|
|
188
188
|
}),
|
|
189
189
|
summary: summaryEntry->Option.map(s => {
|
|
190
190
|
plugins: s->_int("plugins"),
|
|
@@ -215,7 +215,7 @@ let unreachable = (registrations: array<registration>): array<registration> =>
|
|
|
215
215
|
|
|
216
216
|
type settled = {
|
|
217
217
|
written: array<written>,
|
|
218
|
-
summary
|
|
218
|
+
summary?: summary,
|
|
219
219
|
registrations: array<registration>,
|
|
220
220
|
}
|
|
221
221
|
|
|
@@ -233,7 +233,7 @@ let converge = async (
|
|
|
233
233
|
| Ok(json) =>
|
|
234
234
|
switch readAnswer(json) {
|
|
235
235
|
| Error(_) as e => e
|
|
236
|
-
| Ok(Baked({written, summary, registrations})) => Ok({written, summary, registrations})
|
|
236
|
+
| Ok(Baked({written, summary, registrations})) => Ok({written, ?summary, registrations})
|
|
237
237
|
| Ok(Pending({pending, registrations})) =>
|
|
238
238
|
registrations->Array.forEach(r => log(registrationLine(r)))
|
|
239
239
|
switch unreachable(registrations) {
|
|
@@ -340,7 +340,7 @@ let bake = async (
|
|
|
340
340
|
~attempts,
|
|
341
341
|
) {
|
|
342
342
|
| Error(_) as e => e
|
|
343
|
-
| Ok({written, summary, registrations}) =>
|
|
343
|
+
| Ok({written, ?summary, registrations}) =>
|
|
344
344
|
written->Array.forEach(w =>
|
|
345
345
|
Console.log(
|
|
346
346
|
`Wrote ${w.bucket}/${w.key} (${w.bytes->Int.toString} bytes${w.group->Option.mapOr(
|
package/scripts/DeployApp.res
CHANGED
|
@@ -29,8 +29,8 @@ module Manifest = Reventless.AccountsManifest
|
|
|
29
29
|
type command = Up | Down
|
|
30
30
|
|
|
31
31
|
type args = {
|
|
32
|
-
command
|
|
33
|
-
manifest
|
|
32
|
+
command?: command,
|
|
33
|
+
manifest?: string,
|
|
34
34
|
stack: string,
|
|
35
35
|
help: bool,
|
|
36
36
|
}
|
|
@@ -41,16 +41,15 @@ let parseArgs = (argv: array<string>): result<args, string> =>
|
|
|
41
41
|
Reventless.CliArgs.parse(~strings=["manifest", "stack"], argv)->Result.flatMap(a => {
|
|
42
42
|
let help = a->Reventless.CliArgs.help
|
|
43
43
|
let args = {
|
|
44
|
-
|
|
45
|
-
manifest: a->Reventless.CliArgs.string("manifest"),
|
|
44
|
+
manifest: ?(a->Reventless.CliArgs.string("manifest")),
|
|
46
45
|
stack: a->Reventless.CliArgs.string("stack")->Option.getOr(defaultStack),
|
|
47
46
|
help,
|
|
48
47
|
}
|
|
49
48
|
let positionals = a->Reventless.CliArgs.positionals
|
|
50
49
|
switch (positionals->Array.get(0), positionals->Array.get(1)) {
|
|
51
50
|
| (_, Some(surplus)) => Reventless.CliArgs.extra(surplus)
|
|
52
|
-
| (Some("up"), None) => Ok({...args, command:
|
|
53
|
-
| (Some("down"), None) => Ok({...args, command:
|
|
51
|
+
| (Some("up"), None) => Ok({...args, command: Up})
|
|
52
|
+
| (Some("down"), None) => Ok({...args, command: Down})
|
|
54
53
|
| (Some(other), None) => Reventless.CliArgs.extra(other)
|
|
55
54
|
| (None, None) => help ? Ok(args) : Error("say `up` or `down`")
|
|
56
55
|
}
|
|
@@ -86,7 +85,7 @@ type project = {
|
|
|
86
85
|
projectName: string,
|
|
87
86
|
program: string,
|
|
88
87
|
stackDefaults: dict<string>,
|
|
89
|
-
region
|
|
88
|
+
region?: string,
|
|
90
89
|
}
|
|
91
90
|
|
|
92
91
|
@module("yaml") external parseYaml: string => JSON.t = "parse"
|
|
@@ -112,7 +111,7 @@ let projectOf = (p: DeployManifest.project): result<project, string> => {
|
|
|
112
111
|
projectName,
|
|
113
112
|
program: NodePath.join([p.dir, field("main")->Option.getOr("index.js")]),
|
|
114
113
|
stackDefaults: p.stackDefaults,
|
|
115
|
-
region: p.region,
|
|
114
|
+
region: ?p.region,
|
|
116
115
|
})
|
|
117
116
|
}
|
|
118
117
|
}
|
|
@@ -693,7 +692,7 @@ let down = async (~manifest: DeployManifest.resolved, ~stack: string): result<un
|
|
|
693
692
|
}
|
|
694
693
|
}
|
|
695
694
|
|
|
696
|
-
let run = async ({command, manifest, stack}: args): result<unit, string> =>
|
|
695
|
+
let run = async ({?command, ?manifest, stack}: args): result<unit, string> =>
|
|
697
696
|
switch DeployManifest.load(manifest->Option.getOr(DeployManifest.defaultFile)) {
|
|
698
697
|
| Error(_) as e => e
|
|
699
698
|
| Ok(manifest) =>
|
|
@@ -39,7 +39,6 @@ function parseArgs(argv) {
|
|
|
39
39
|
let args_manifest = CliArgs$Reventless.string(a, "manifest");
|
|
40
40
|
let args_stack = Stdlib_Option.getOr(CliArgs$Reventless.string(a, "stack"), defaultStack);
|
|
41
41
|
let args = {
|
|
42
|
-
command: undefined,
|
|
43
42
|
manifest: args_manifest,
|
|
44
43
|
stack: args_stack,
|
|
45
44
|
help: help
|
|
@@ -65,24 +64,16 @@ function parseArgs(argv) {
|
|
|
65
64
|
}
|
|
66
65
|
switch (match) {
|
|
67
66
|
case "down" :
|
|
67
|
+
let newrecord = {...args};
|
|
68
68
|
return {
|
|
69
69
|
TAG: "Ok",
|
|
70
|
-
_0:
|
|
71
|
-
command: "Down",
|
|
72
|
-
manifest: args_manifest,
|
|
73
|
-
stack: args_stack,
|
|
74
|
-
help: help
|
|
75
|
-
}
|
|
70
|
+
_0: (newrecord.command = "Down", newrecord)
|
|
76
71
|
};
|
|
77
72
|
case "up" :
|
|
73
|
+
let newrecord$1 = {...args};
|
|
78
74
|
return {
|
|
79
75
|
TAG: "Ok",
|
|
80
|
-
_0:
|
|
81
|
-
command: "Up",
|
|
82
|
-
manifest: args_manifest,
|
|
83
|
-
stack: args_stack,
|
|
84
|
-
help: help
|
|
85
|
-
}
|
|
76
|
+
_0: (newrecord$1.command = "Up", newrecord$1)
|
|
86
77
|
};
|
|
87
78
|
default:
|
|
88
79
|
return CliArgs$Reventless.extra(match);
|
|
@@ -42,14 +42,14 @@ type project = {
|
|
|
42
42
|
name: string,
|
|
43
43
|
dir: string,
|
|
44
44
|
stackDefaults: dict<string>,
|
|
45
|
-
region
|
|
45
|
+
region?: string,
|
|
46
46
|
/** Whether a review environment deploys it: false only on a plugin marked so. */
|
|
47
47
|
review: bool,
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
type resolved = {
|
|
51
51
|
file: string,
|
|
52
|
-
region
|
|
52
|
+
region?: string,
|
|
53
53
|
platform: project,
|
|
54
54
|
plugins: array<project>,
|
|
55
55
|
}
|
|
@@ -66,12 +66,11 @@ let resolve = (manifest: t, ~file: string): resolved => {
|
|
|
66
66
|
let base = NodePath.dirname(NodePath.resolve([file]))
|
|
67
67
|
{
|
|
68
68
|
file,
|
|
69
|
-
region: manifest.region,
|
|
69
|
+
region: ?manifest.region,
|
|
70
70
|
platform: {
|
|
71
71
|
name: manifest.platform.name->Option.getOr("platform"),
|
|
72
72
|
dir: NodePath.resolve([base, manifest.platform.path]),
|
|
73
73
|
stackDefaults: manifest.platform.stackDefaults->Option.getOr(Dict.make()),
|
|
74
|
-
region: None,
|
|
75
74
|
review: true,
|
|
76
75
|
},
|
|
77
76
|
plugins: manifest.plugins
|
|
@@ -80,7 +79,7 @@ let resolve = (manifest: t, ~file: string): resolved => {
|
|
|
80
79
|
name: p.name,
|
|
81
80
|
dir: NodePath.resolve([base, p.path]),
|
|
82
81
|
stackDefaults: p.stackDefaults->Option.getOr(Dict.make()),
|
|
83
|
-
region: p.region,
|
|
82
|
+
region: ?p.region,
|
|
84
83
|
review: p.review->Option.getOr(true),
|
|
85
84
|
}),
|
|
86
85
|
}
|
|
@@ -60,7 +60,6 @@ function resolve(manifest, file) {
|
|
|
60
60
|
name: Stdlib_Option.getOr(manifest.platform.name, "platform"),
|
|
61
61
|
dir: Nodepath.resolve(base, manifest.platform.path),
|
|
62
62
|
stackDefaults: Stdlib_Option.getOr(manifest.platform["stack-defaults"], {}),
|
|
63
|
-
region: undefined,
|
|
64
63
|
review: true
|
|
65
64
|
},
|
|
66
65
|
plugins: Stdlib_Option.getOr(manifest.plugins, []).map(p => ({
|
|
@@ -44,9 +44,9 @@ module Manifest = Reventless.AccountsManifest
|
|
|
44
44
|
// ── Arguments ────────────────────────────────────────────────────────────────
|
|
45
45
|
|
|
46
46
|
type args = {
|
|
47
|
-
providerId
|
|
48
|
-
stack
|
|
49
|
-
file
|
|
47
|
+
providerId?: string,
|
|
48
|
+
stack?: string,
|
|
49
|
+
file?: string,
|
|
50
50
|
help: bool,
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -58,9 +58,9 @@ let parseArgs = (argv: array<string>): result<args, string> =>
|
|
|
58
58
|
Reventless.CliArgs.parse(~strings=["provider-id", "stack", "file"], argv)
|
|
59
59
|
->Result.flatMap(Reventless.CliArgs.noPositionals)
|
|
60
60
|
->Result.map(a => {
|
|
61
|
-
providerId: a->Reventless.CliArgs.string("provider-id"),
|
|
62
|
-
stack: a->Reventless.CliArgs.string("stack"),
|
|
63
|
-
file: a->Reventless.CliArgs.string("file"),
|
|
61
|
+
providerId: ?(a->Reventless.CliArgs.string("provider-id")),
|
|
62
|
+
stack: ?(a->Reventless.CliArgs.string("stack")),
|
|
63
|
+
file: ?(a->Reventless.CliArgs.string("file")),
|
|
64
64
|
help: a->Reventless.CliArgs.help,
|
|
65
65
|
})
|
|
66
66
|
|
|
@@ -167,38 +167,30 @@ let ensureGroups = async (~providerId: string, ~entries: array<Manifest.entry>):
|
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
|
|
171
|
-
One account: the entry, applied.
|
|
172
|
-
|
|
173
|
-
The password is set unconditionally rather than only for an account this run
|
|
174
|
-
created — the same reason `provision-admin` does it, arriving at a manifest: the
|
|
175
|
-
file is the record of what the credential *is*, so an account whose password
|
|
176
|
-
drifted from the file is exactly the case a re-run is expected to fix.
|
|
170
|
+
// ── The domain id ────────────────────────────────────────────────────────────
|
|
177
171
|
|
|
178
|
-
Returns the id the pool minted, which is the value the manifest cannot know until
|
|
179
|
-
the account exists and which nobody should be pasting by hand.
|
|
180
|
-
*/
|
|
181
172
|
/**
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
173
|
+
The identity store the pool's trigger reads, or `None` when it reads none.
|
|
174
|
+
|
|
175
|
+
Only a deployed stack can say, through its `identityStore` output, because the
|
|
176
|
+
store matters only if the trigger was deployed knowing it. An empty output is a
|
|
177
|
+
supplied pool whose store did not exist at the last deploy; a missing one is a
|
|
178
|
+
stack deployed before the store existed; no stack is a pool nothing here can
|
|
179
|
+
vouch for. In each of those the trigger adds no claim, so an id minted now would
|
|
180
|
+
be one the account's own token never carries — every row it wrote would be keyed
|
|
181
|
+
by its `sub` while the manifest named another id. The account keeps its `sub`
|
|
182
|
+
instead, as every account before the store did, and the next deploy that wires
|
|
183
|
+
the store lets the following run mint.
|
|
189
184
|
*/
|
|
190
|
-
let
|
|
191
|
-
|
|
192
|
-
identityStoreFor = (~providerId: string, ~stack: option<string>): option<string> =>
|
|
185
|
+
let identityStoreFor = (~stack: option<string>): option<string> =>
|
|
193
186
|
switch stack->Option.orElse(ProvisionProvider.selectedStack()) {
|
|
187
|
+
| None => None
|
|
194
188
|
| Some(stack) =>
|
|
195
189
|
switch ProvisionProvider.pulumi(["stack", "output", "identityStore", "--stack", stack]) {
|
|
196
|
-
| "" =>
|
|
190
|
+
| "" => None
|
|
197
191
|
| name => Some(name)
|
|
198
|
-
| exception _ =>
|
|
199
|
-
Some(Auth_IdentityStore_Schema.derivedStoreName(~identityProviderId=providerId))
|
|
192
|
+
| exception _ => None
|
|
200
193
|
}
|
|
201
|
-
| None => Some(Auth_IdentityStore_Schema.derivedStoreName(~identityProviderId=providerId))
|
|
202
194
|
}
|
|
203
195
|
|
|
204
196
|
/** The domain id recorded for a subject, if the store has one. */
|
|
@@ -253,6 +245,17 @@ let domainIdFor = async (~store: option<string>, ~sub: string, ~created: bool):
|
|
|
253
245
|
}
|
|
254
246
|
}
|
|
255
247
|
|
|
248
|
+
/**
|
|
249
|
+
One account: the entry, applied.
|
|
250
|
+
|
|
251
|
+
The password is set unconditionally rather than only for an account this run
|
|
252
|
+
created — the same reason `provision-admin` does it, arriving at a manifest: the
|
|
253
|
+
file is the record of what the credential *is*, so an account whose password
|
|
254
|
+
drifted from the file is exactly the case a re-run is expected to fix.
|
|
255
|
+
|
|
256
|
+
Returns the id the pool minted, which is the value the manifest cannot know until
|
|
257
|
+
the account exists and which nobody should be pasting by hand.
|
|
258
|
+
*/
|
|
256
259
|
let applyEntry = async (
|
|
257
260
|
~providerId: string,
|
|
258
261
|
~entry: Manifest.entry,
|
|
@@ -340,7 +343,7 @@ let provision = async (
|
|
|
340
343
|
for index in 0 to entries->Array.length - 1 {
|
|
341
344
|
let entry = entries->Array.getUnsafe(index)
|
|
342
345
|
let userId = await applyEntry(~providerId, ~entry, ~identityStore)
|
|
343
|
-
fills->Array.push({Manifest.index,
|
|
346
|
+
fills->Array.push({Manifest.index, ?userId})
|
|
344
347
|
}
|
|
345
348
|
switch Manifest.fillFile(~path=file, ~fills) {
|
|
346
349
|
| Error(message) => Error(`${file}: ${message}`)
|
|
@@ -371,8 +374,13 @@ let run = async (args: args): result<unit, string> =>
|
|
|
371
374
|
Error(`${message}. To fill in the manifest without creating anything, run prepare-accounts`)
|
|
372
375
|
| Ok((providerId, source)) =>
|
|
373
376
|
Console.log(`provider ${providerId} (from ${source->ProvisionProvider.describe})`)
|
|
374
|
-
let identityStore = identityStoreFor(~
|
|
375
|
-
|
|
377
|
+
let identityStore = identityStoreFor(~stack=args.stack)
|
|
378
|
+
Console.log(
|
|
379
|
+
switch identityStore {
|
|
380
|
+
| Some(store) => `store ${store}`
|
|
381
|
+
| None => `store none the deployed trigger reads — new accounts keep their pool id`
|
|
382
|
+
},
|
|
383
|
+
)
|
|
376
384
|
await provision(~file, ~providerId, ~identityStore?)
|
|
377
385
|
}
|
|
378
386
|
}
|
|
@@ -109,10 +109,10 @@ async function ensureGroups(providerId, entries) {
|
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
function identityStoreFor(
|
|
112
|
+
function identityStoreFor(stack) {
|
|
113
113
|
let stack$1 = Stdlib_Option.orElse(stack, ProvisionProvider$ReventlessAws.selectedStack());
|
|
114
114
|
if (stack$1 === undefined) {
|
|
115
|
-
return
|
|
115
|
+
return;
|
|
116
116
|
}
|
|
117
117
|
let name;
|
|
118
118
|
try {
|
|
@@ -124,10 +124,10 @@ function identityStoreFor(providerId, stack) {
|
|
|
124
124
|
stack$1
|
|
125
125
|
]);
|
|
126
126
|
} catch (exn) {
|
|
127
|
-
return
|
|
127
|
+
return;
|
|
128
128
|
}
|
|
129
129
|
if (name === "") {
|
|
130
|
-
return
|
|
130
|
+
return;
|
|
131
131
|
} else {
|
|
132
132
|
return name;
|
|
133
133
|
}
|
|
@@ -260,7 +260,6 @@ async function provision(file, providerId, identityStore, checkPoolOpt) {
|
|
|
260
260
|
let userId = await applyEntry(providerId, entry, identityStore);
|
|
261
261
|
fills.push({
|
|
262
262
|
index: index,
|
|
263
|
-
password: undefined,
|
|
264
263
|
userId: userId
|
|
265
264
|
});
|
|
266
265
|
}
|
|
@@ -299,10 +298,8 @@ async function run(args) {
|
|
|
299
298
|
let match = message._0;
|
|
300
299
|
let providerId = match[0];
|
|
301
300
|
console.log(`provider ` + providerId + ` (from ` + ProvisionProvider$ReventlessAws.describe(match[1]) + `)`);
|
|
302
|
-
let identityStore = identityStoreFor(
|
|
303
|
-
|
|
304
|
-
console.log(`store ` + store);
|
|
305
|
-
});
|
|
301
|
+
let identityStore = identityStoreFor(args.stack);
|
|
302
|
+
console.log(identityStore !== undefined ? `store ` + identityStore : `store none the deployed trigger reads — new accounts keep their pool id`);
|
|
306
303
|
return await provision(file, providerId, identityStore, undefined);
|
|
307
304
|
}
|
|
308
305
|
|
|
@@ -41,9 +41,9 @@ module Cognito = CognitoIdentityServiceProvider
|
|
|
41
41
|
// ── Arguments ────────────────────────────────────────────────────────────────
|
|
42
42
|
|
|
43
43
|
type args = {
|
|
44
|
-
providerId
|
|
45
|
-
stack
|
|
46
|
-
email
|
|
44
|
+
providerId?: string,
|
|
45
|
+
stack?: string,
|
|
46
|
+
email?: string,
|
|
47
47
|
help: bool,
|
|
48
48
|
}
|
|
49
49
|
|
|
@@ -56,9 +56,9 @@ let parseArgs = (argv: array<string>): result<args, string> =>
|
|
|
56
56
|
Reventless.CliArgs.parse(~strings=["provider-id", "stack", "email"], argv)
|
|
57
57
|
->Result.flatMap(Reventless.CliArgs.noPositionals)
|
|
58
58
|
->Result.map(a => {
|
|
59
|
-
providerId: a->Reventless.CliArgs.string("provider-id"),
|
|
60
|
-
stack: a->Reventless.CliArgs.string("stack"),
|
|
61
|
-
email: a->Reventless.CliArgs.string("email"),
|
|
59
|
+
providerId: ?(a->Reventless.CliArgs.string("provider-id")),
|
|
60
|
+
stack: ?(a->Reventless.CliArgs.string("stack")),
|
|
61
|
+
email: ?(a->Reventless.CliArgs.string("email")),
|
|
62
62
|
help: a->Reventless.CliArgs.help,
|
|
63
63
|
})
|
|
64
64
|
|
|
@@ -200,21 +200,21 @@ made through a signed-in session because there is no signed-in session yet. The
|
|
|
200
200
|
rest of the cast is a list rather than a command: declare it in
|
|
201
201
|
.reventless/users.yaml and run \`pnpm exec provision-accounts\`.`
|
|
202
202
|
|
|
203
|
-
type request = {email: string, providerId
|
|
203
|
+
type request = {email: string, providerId?: string, stack?: string}
|
|
204
204
|
|
|
205
205
|
/** The address is required before anything else is looked at: it costs nothing,
|
|
206
206
|
while resolving the provider may shell out to Pulumi, and a run missing both
|
|
207
207
|
arguments should say the cheap thing rather than fail on a stack lookup it
|
|
208
208
|
never needed. */
|
|
209
209
|
let parseRequest = (argv: array<string>): result<request, string> =>
|
|
210
|
-
parseArgs(argv)->Result.flatMap(({email, providerId, stack}) =>
|
|
210
|
+
parseArgs(argv)->Result.flatMap(({?email, ?providerId, ?stack}) =>
|
|
211
211
|
switch email {
|
|
212
212
|
| None => Error("--email is required — it is the address the administrator signs in with")
|
|
213
|
-
| Some(email) => Ok({email, providerId, stack})
|
|
213
|
+
| Some(email) => Ok({email, ?providerId, ?stack})
|
|
214
214
|
}
|
|
215
215
|
)
|
|
216
216
|
|
|
217
|
-
let run = async ({email, providerId, stack}: request): result<unit, string> =>
|
|
217
|
+
let run = async ({email, ?providerId, ?stack}: request): result<unit, string> =>
|
|
218
218
|
switch ProvisionProvider.resolve(~given=providerId, ~stack) {
|
|
219
219
|
| Error(_) as e => e
|
|
220
220
|
| Ok((providerId, source)) =>
|
|
@@ -37,7 +37,7 @@ module Schema = Auth_ActiveRoleStore_Schema
|
|
|
37
37
|
|
|
38
38
|
type args = {
|
|
39
39
|
poolName: string,
|
|
40
|
-
providerId
|
|
40
|
+
providerId?: string,
|
|
41
41
|
loginIdentifier: Auth_LoginIdentifier.t,
|
|
42
42
|
signUpMode: Auth_SignUpMode.t,
|
|
43
43
|
help: bool,
|
|
@@ -69,7 +69,7 @@ let parseArgs = (argv: array<string>): result<args, string> =>
|
|
|
69
69
|
| (Ok(loginIdentifier), Ok(signUpMode)) =>
|
|
70
70
|
Ok({
|
|
71
71
|
poolName: given("name")->Option.getOr(defaultPoolName),
|
|
72
|
-
providerId: given("provider-id"),
|
|
72
|
+
providerId: ?given("provider-id"),
|
|
73
73
|
loginIdentifier,
|
|
74
74
|
signUpMode,
|
|
75
75
|
help: a->Reventless.CliArgs.help,
|
|
@@ -27,8 +27,8 @@ type request =
|
|
|
27
27
|
| PullRequest({number: int, base: string, draft: bool})
|
|
28
28
|
|
|
29
29
|
type args = {
|
|
30
|
-
file
|
|
31
|
-
manifest
|
|
30
|
+
file?: string,
|
|
31
|
+
manifest?: string,
|
|
32
32
|
request: request,
|
|
33
33
|
}
|
|
34
34
|
|
|
@@ -52,7 +52,7 @@ let parseArgs = (argv: array<string>): result<args, string> =>
|
|
|
52
52
|
| (None, None, None) => Error("say what deploys: --ref, or --pull-request with --base")
|
|
53
53
|
| _ => Error("--ref and --pull-request are two different questions; ask one")
|
|
54
54
|
}
|
|
55
|
-
request->Result.map(request => {file: string("file"), manifest: string("manifest"), request})
|
|
55
|
+
request->Result.map(request => {file: ?string("file"), manifest: ?string("manifest"), request})
|
|
56
56
|
})
|
|
57
57
|
|
|
58
58
|
let usage = `
|
package/src/Platform.res
CHANGED
|
@@ -71,7 +71,7 @@ type objectStoreEndpoint = {
|
|
|
71
71
|
// itself. `None` when a host-UI bundle is deployed — there the shell's own
|
|
72
72
|
// origin serves the store same-origin and a relative `/{prefix}/…` resolves
|
|
73
73
|
// without a base.
|
|
74
|
-
baseUrl
|
|
74
|
+
baseUrl?: Pulumi.Output.t<string>,
|
|
75
75
|
}
|
|
76
76
|
let objectStoreEndpointsRef: ref<array<objectStoreEndpoint>> = ref([])
|
|
77
77
|
|
|
@@ -534,7 +534,6 @@ module MakeWithConfig = (
|
|
|
534
534
|
let eventsApi: AppSync_EventsApi.t = {
|
|
535
535
|
name: "DomainEventsApi",
|
|
536
536
|
api,
|
|
537
|
-
defaultNamespace: None,
|
|
538
537
|
}
|
|
539
538
|
Some(eventsApi)
|
|
540
539
|
}
|
|
@@ -1858,7 +1857,8 @@ module MakeWithConfig = (
|
|
|
1858
1857
|
| ObjectStore({plugin, store}) => Some((plugin, store))
|
|
1859
1858
|
| Geocoding
|
|
1860
1859
|
| Messaging
|
|
1861
|
-
| IdentityProvider
|
|
1860
|
+
| IdentityProvider
|
|
1861
|
+
| Stash =>
|
|
1862
1862
|
None
|
|
1863
1863
|
}
|
|
1864
1864
|
)
|
|
@@ -2047,7 +2047,7 @@ module MakeWithConfig = (
|
|
|
2047
2047
|
store,
|
|
2048
2048
|
keyPrefix,
|
|
2049
2049
|
bucketName: physicalBucketName->Pulumi.Output.fromInput,
|
|
2050
|
-
baseUrl: storeServingBaseUrl,
|
|
2050
|
+
baseUrl: ?storeServingBaseUrl,
|
|
2051
2051
|
})
|
|
2052
2052
|
objectStoreEndpointsRef := declaredStoreEndpoints
|
|
2053
2053
|
|
|
@@ -2982,6 +2982,8 @@ module MakeWithConfig = (
|
|
|
2982
2982
|
`REVENTLESS_MESSAGING_EMAIL_SENDER), then verify the address with SES — or ` ++ `\`platform:messagingEmailProvider: log\` to log every message and send none.`
|
|
2983
2983
|
| IdentityProvider =>
|
|
2984
2984
|
`\n IdentityProvider is the platform's Cognito pool, exported as ` ++ `\`identityProviderId\`. This platform stack exports none — deploy it first.`
|
|
2985
|
+
| Stash =>
|
|
2986
|
+
`\n Stash has no deployed backend yet; the local platform keeps one in ` ++ `memory. Host a plugin that needs it on the local platform.`
|
|
2985
2987
|
}
|
|
2986
2988
|
)
|
|
2987
2989
|
// One line per capability, not per declaring component: two slices
|
package/src/Platform.res.mjs
CHANGED
|
@@ -334,8 +334,7 @@ function MakeWithConfig(Config) {
|
|
|
334
334
|
};
|
|
335
335
|
domainEventsApiOpt = {
|
|
336
336
|
name: "DomainEventsApi",
|
|
337
|
-
api: api$2
|
|
338
|
-
defaultNamespace: undefined
|
|
337
|
+
api: api$2
|
|
339
338
|
};
|
|
340
339
|
} else {
|
|
341
340
|
let cognitoPool = Platform_Stack$ReventlessAws.resolveCognitoUserPool();
|
|
@@ -1505,6 +1504,8 @@ function MakeWithConfig(Config) {
|
|
|
1505
1504
|
return `\n Messaging is \`Capability_Messaging.make\`, passed to the platform as \`~messagingSender\`. The sender itself is configuration and has no default: set \`platform:messagingEmailSender\` in Pulumi.<stack>.yaml (or REVENTLESS_MESSAGING_EMAIL_SENDER), then verify the address with SES — or \`platform:messagingEmailProvider: log\` to log every message and send none.`;
|
|
1506
1505
|
case "IdentityProvider" :
|
|
1507
1506
|
return `\n IdentityProvider is the platform's Cognito pool, exported as \`identityProviderId\`. This platform stack exports none — deploy it first.`;
|
|
1507
|
+
case "Stash" :
|
|
1508
|
+
return `\n Stash has no deployed backend yet; the local platform keeps one in memory. Host a plugin that needs it on the local platform.`;
|
|
1508
1509
|
}
|
|
1509
1510
|
}))).join(""));
|
|
1510
1511
|
}
|
|
@@ -1768,8 +1769,7 @@ function Make($star) {
|
|
|
1768
1769
|
};
|
|
1769
1770
|
domainEventsApiOpt = {
|
|
1770
1771
|
name: "DomainEventsApi",
|
|
1771
|
-
api: api$2
|
|
1772
|
-
defaultNamespace: undefined
|
|
1772
|
+
api: api$2
|
|
1773
1773
|
};
|
|
1774
1774
|
} else {
|
|
1775
1775
|
let cognitoPool = Platform_Stack$ReventlessAws.resolveCognitoUserPool();
|
|
@@ -2914,6 +2914,8 @@ function Make($star) {
|
|
|
2914
2914
|
return `\n Messaging is \`Capability_Messaging.make\`, passed to the platform as \`~messagingSender\`. The sender itself is configuration and has no default: set \`platform:messagingEmailSender\` in Pulumi.<stack>.yaml (or REVENTLESS_MESSAGING_EMAIL_SENDER), then verify the address with SES — or \`platform:messagingEmailProvider: log\` to log every message and send none.`;
|
|
2915
2915
|
case "IdentityProvider" :
|
|
2916
2916
|
return `\n IdentityProvider is the platform's Cognito pool, exported as \`identityProviderId\`. This platform stack exports none — deploy it first.`;
|
|
2917
|
+
case "Stash" :
|
|
2918
|
+
return `\n Stash has no deployed backend yet; the local platform keeps one in memory. Host a plugin that needs it on the local platform.`;
|
|
2917
2919
|
}
|
|
2918
2920
|
}))).join(""));
|
|
2919
2921
|
}
|