@reventlessdev/reventless-aws 3.0.0-alpha.395 → 3.0.0-alpha.397

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 (42) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/package.json +7 -7
  3. package/scripts/DeployApp.res +7 -1
  4. package/scripts/DeployApp.res.mjs +1 -1
  5. package/scripts/ProvisionAccounts.res +89 -4
  6. package/scripts/ProvisionAccounts.res.mjs +101 -5
  7. package/scripts/ProvisionIdentity.res +42 -18
  8. package/scripts/ProvisionIdentity.res.mjs +40 -26
  9. package/src/Platform.res +47 -10
  10. package/src/Platform.res.mjs +44 -10
  11. package/src/Platform_Stack.res +17 -0
  12. package/src/Platform_Stack.res.mjs +7 -1
  13. package/src/adapter/Auth/Auth_ActiveRoleTrigger.res +25 -9
  14. package/src/adapter/Auth/Auth_ActiveRoleTrigger.res.mjs +17 -4
  15. package/src/adapter/Auth/Auth_ActiveRoleTrigger_Ops.res +59 -9
  16. package/src/adapter/Auth/Auth_ActiveRoleTrigger_Ops.res.mjs +53 -6
  17. package/src/adapter/Auth/Auth_Cognito.res +13 -2
  18. package/src/adapter/Auth/Auth_Cognito.res.mjs +9 -2
  19. package/src/adapter/Auth/Auth_IdentityStore.res +91 -0
  20. package/src/adapter/Auth/Auth_IdentityStore.res.mjs +85 -0
  21. package/src/adapter/Auth/Auth_IdentityStore_Schema.res +39 -0
  22. package/src/adapter/Auth/Auth_IdentityStore_Schema.res.mjs +35 -0
  23. package/src/adapter/Identity/IdentityProvider_Cognito_Backend.res +251 -0
  24. package/src/adapter/Identity/IdentityProvider_Cognito_Backend.res.mjs +300 -0
  25. package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res +7 -4
  26. package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res.mjs +2 -2
  27. package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res +80 -0
  28. package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res.mjs +53 -2
  29. package/src/components/AutomationSlice_Builder.res.mjs +1 -1
  30. package/src/components/OutboundTranslationSlice_Builder.res +2 -0
  31. package/src/components/OutboundTranslationSlice_Builder.res.mjs +1 -1
  32. package/src/plugin/runtime/PluginRuntime_Builder.res +23 -0
  33. package/src/plugin/runtime/PluginRuntime_Builder.res.mjs +29 -0
  34. package/tests/Auth_ActiveRoleTrigger_OpsTest.res +40 -0
  35. package/tests/Auth_ActiveRoleTrigger_OpsTest.res.mjs +59 -8
  36. package/tests/Auth_CognitoTest.res +62 -0
  37. package/tests/Auth_CognitoTest.res.mjs +98 -0
  38. package/tests/Auth_IdentityStore_SchemaTest.res +35 -0
  39. package/tests/Auth_IdentityStore_SchemaTest.res.mjs +43 -0
  40. package/tests/IdentityProvider_Cognito_BackendTest.res +314 -0
  41. package/tests/IdentityProvider_Cognito_BackendTest.res.mjs +442 -0
  42. package/tests/ProvisionAccountsTest.res.mjs +1 -1
@@ -171,3 +171,43 @@ describe("Auth_ActiveRoleTrigger_Ops.respond", () => {
171
171
  )->toEqual(Some(["arn:aws:iam::1:role/Shopper"]))
172
172
  })
173
173
  })
174
+
175
+ // ── The domain id claim ─────────────────────────────────────────────────────
176
+ //
177
+ // Rides on whatever else the mint adds. The regression line above still holds
178
+ // for every account created before the identity store existed, because such an
179
+ // account has no row and so no `userId` arrives here.
180
+
181
+ describe("Auth_ActiveRoleTrigger_Ops.respond with a domain id", () => {
182
+ testSync("no stored role and a domain id adds the claim and nothing else", () => {
183
+ let input = eventFor(~membership=["Admin", "Shopper"])
184
+ let event = Trigger.respond(~event=input, ~decision=Unchanged, ~userId="u_abc")
185
+ expect(claimOf(event, ReventlessCore.Auth_UserId.claim))->toEqual(Some("u_abc"))
186
+ expect(groupsOf(event))->toEqual(None)
187
+ })
188
+
189
+ testSync("narrowing and a domain id carry both", () => {
190
+ let event = Trigger.respond(
191
+ ~event=eventFor(~membership=["Admin", "Shopper"]),
192
+ ~decision=Narrow({role: "Shopper", membership: ["Admin", "Shopper"]}),
193
+ ~userId="u_abc",
194
+ )
195
+ expect(groupsOf(event))->toEqual(Some(["Shopper"]))
196
+ expect((
197
+ claimOf(event, Contract.activeRoleClaim),
198
+ claimOf(event, ReventlessCore.Auth_UserId.claim),
199
+ ))->toEqual((Some("Shopper"), Some("u_abc")))
200
+ })
201
+
202
+ testSync("no domain id leaves a narrowed token without the claim", () => {
203
+ let event = Trigger.respond(
204
+ ~event=eventFor(~membership=["Admin", "Shopper"]),
205
+ ~decision=Narrow({role: "Shopper", membership: ["Admin", "Shopper"]}),
206
+ )
207
+ expect(claimOf(event, ReventlessCore.Auth_UserId.claim))->toEqual(None)
208
+ })
209
+
210
+ testPromise("no identity store configured reads as no row", async () =>
211
+ expect(await Trigger.userIdFor(~sub="u-carol", ~table=None))->toEqual(None)
212
+ )
213
+ })
@@ -1,6 +1,7 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
3
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
4
+ import * as Auth_UserId$ReventlessCore from "@reventlessdev/reventless-core/src/adapter/Auth/Auth_UserId.res.mjs";
4
5
  import * as Auth_ActiveRole$ReventlessCore from "@reventlessdev/reventless-core/src/adapter/Auth/Auth_ActiveRole.res.mjs";
5
6
  import * as Auth_ActiveRoleTrigger_Ops$ReventlessAws from "../src/adapter/Auth/Auth_ActiveRoleTrigger_Ops.res.mjs";
6
7
 
@@ -43,7 +44,7 @@ globalThis.describe("the conformance table, minted by the trigger", () => {
43
44
  let requested = param.requested;
44
45
  let membership = param.membership;
45
46
  globalThis.test(param.label, () => {
46
- let event = Auth_ActiveRoleTrigger_Ops$ReventlessAws.respond(eventFor(membership, undefined, undefined), Auth_ActiveRoleTrigger_Ops$ReventlessAws.decide(membership, requested));
47
+ let event = Auth_ActiveRoleTrigger_Ops$ReventlessAws.respond(eventFor(membership, undefined, undefined), Auth_ActiveRoleTrigger_Ops$ReventlessAws.decide(membership, requested), undefined);
47
48
  globalThis.expect(Stdlib_Option.getOr(groupsOf(event), membership)).toEqual(Stdlib_Option.getOr(expected, membership));
48
49
  });
49
50
  });
@@ -84,7 +85,7 @@ globalThis.describe("Auth_ActiveRoleTrigger_Ops.respond", () => {
84
85
  "Admin",
85
86
  "Shopper"
86
87
  ], undefined, undefined);
87
- globalThis.expect(Auth_ActiveRoleTrigger_Ops$ReventlessAws.respond(input, "Unchanged")).toEqual(input);
88
+ globalThis.expect(Auth_ActiveRoleTrigger_Ops$ReventlessAws.respond(input, "Unchanged", undefined)).toEqual(input);
88
89
  });
89
90
  globalThis.test("narrowing puts the chosen role alone in the group claim", () => {
90
91
  let event = Auth_ActiveRoleTrigger_Ops$ReventlessAws.respond(eventFor([
@@ -97,7 +98,7 @@ globalThis.describe("Auth_ActiveRoleTrigger_Ops.respond", () => {
97
98
  "Admin",
98
99
  "Shopper"
99
100
  ]
100
- });
101
+ }, undefined);
101
102
  globalThis.expect(groupsOf(event)).toEqual(["Shopper"]);
102
103
  });
103
104
  globalThis.test("a narrowed token records the choice and what it gave up", () => {
@@ -111,7 +112,7 @@ globalThis.describe("Auth_ActiveRoleTrigger_Ops.respond", () => {
111
112
  "Admin",
112
113
  "Shopper"
113
114
  ]
114
- });
115
+ }, undefined);
115
116
  globalThis.expect([
116
117
  claimOf(event, Auth_ActiveRole$ReventlessCore.activeRoleClaim),
117
118
  claimOf(event, Auth_ActiveRole$ReventlessCore.availableRolesClaim)
@@ -125,7 +126,7 @@ globalThis.describe("Auth_ActiveRoleTrigger_Ops.respond", () => {
125
126
  TAG: "Stale",
126
127
  role: "Admin",
127
128
  membership: ["Shopper"]
128
- });
129
+ }, undefined);
129
130
  globalThis.expect([
130
131
  groupsOf(event),
131
132
  claimOf(event, Auth_ActiveRole$ReventlessCore.staleRoleClaim)
@@ -139,7 +140,7 @@ globalThis.describe("Auth_ActiveRoleTrigger_Ops.respond", () => {
139
140
  TAG: "Stale",
140
141
  role: "Admin",
141
142
  membership: ["Shopper"]
142
- });
143
+ }, undefined);
143
144
  globalThis.expect(claimOf(event, Auth_ActiveRole$ReventlessCore.activeRoleClaim)).toEqual(undefined);
144
145
  });
145
146
  globalThis.test("narrowing carries the caller's IAM roles through untouched", () => {
@@ -153,7 +154,7 @@ globalThis.describe("Auth_ActiveRoleTrigger_Ops.respond", () => {
153
154
  "Admin",
154
155
  "Shopper"
155
156
  ]
156
- });
157
+ }, undefined);
157
158
  let details = Stdlib_Option.flatMap(overrideOf(event), c => c.groupOverrideDetails);
158
159
  globalThis.expect([
159
160
  Stdlib_Option.map(details, d => d.iamRolesToOverride),
@@ -168,11 +169,61 @@ globalThis.describe("Auth_ActiveRoleTrigger_Ops.respond", () => {
168
169
  TAG: "Stale",
169
170
  role: "Admin",
170
171
  membership: ["Shopper"]
171
- });
172
+ }, undefined);
172
173
  globalThis.expect(Stdlib_Option.map(Stdlib_Option.flatMap(overrideOf(event), c => c.groupOverrideDetails), d => d.iamRolesToOverride)).toEqual(["arn:aws:iam::1:role/Shopper"]);
173
174
  });
174
175
  });
175
176
 
177
+ globalThis.describe("Auth_ActiveRoleTrigger_Ops.respond with a domain id", () => {
178
+ globalThis.test("no stored role and a domain id adds the claim and nothing else", () => {
179
+ let input = eventFor([
180
+ "Admin",
181
+ "Shopper"
182
+ ], undefined, undefined);
183
+ let event = Auth_ActiveRoleTrigger_Ops$ReventlessAws.respond(input, "Unchanged", "u_abc");
184
+ globalThis.expect(claimOf(event, Auth_UserId$ReventlessCore.claim)).toEqual("u_abc");
185
+ globalThis.expect(groupsOf(event)).toEqual(undefined);
186
+ });
187
+ globalThis.test("narrowing and a domain id carry both", () => {
188
+ let event = Auth_ActiveRoleTrigger_Ops$ReventlessAws.respond(eventFor([
189
+ "Admin",
190
+ "Shopper"
191
+ ], undefined, undefined), {
192
+ TAG: "Narrow",
193
+ role: "Shopper",
194
+ membership: [
195
+ "Admin",
196
+ "Shopper"
197
+ ]
198
+ }, "u_abc");
199
+ globalThis.expect(groupsOf(event)).toEqual(["Shopper"]);
200
+ globalThis.expect([
201
+ claimOf(event, Auth_ActiveRole$ReventlessCore.activeRoleClaim),
202
+ claimOf(event, Auth_UserId$ReventlessCore.claim)
203
+ ]).toEqual([
204
+ "Shopper",
205
+ "u_abc"
206
+ ]);
207
+ });
208
+ globalThis.test("no domain id leaves a narrowed token without the claim", () => {
209
+ let event = Auth_ActiveRoleTrigger_Ops$ReventlessAws.respond(eventFor([
210
+ "Admin",
211
+ "Shopper"
212
+ ], undefined, undefined), {
213
+ TAG: "Narrow",
214
+ role: "Shopper",
215
+ membership: [
216
+ "Admin",
217
+ "Shopper"
218
+ ]
219
+ }, undefined);
220
+ globalThis.expect(claimOf(event, Auth_UserId$ReventlessCore.claim)).toEqual(undefined);
221
+ });
222
+ globalThis.test("no identity store configured reads as no row", async () => {
223
+ globalThis.expect(await Auth_ActiveRoleTrigger_Ops$ReventlessAws.userIdFor("u-carol", undefined)).toEqual(undefined);
224
+ });
225
+ });
226
+
176
227
  let Trigger;
177
228
 
178
229
  let Contract;
@@ -186,3 +186,65 @@ describe("Auth_Cognito.fromAppSyncIdentity", () => {
186
186
  }
187
187
  })
188
188
  })
189
+
190
+ // ── The domain id claim ─────────────────────────────────────────────────────
191
+ //
192
+ // Both arms, on both entry points. The second arm is the one that will look
193
+ // redundant to a later reader and is not: every `@owner` field written before
194
+ // the identity store existed holds a `sub`, and it keeps matching only while a
195
+ // token without the claim produces exactly that `sub`.
196
+
197
+ describe("Auth_Cognito and the domain id claim", () => {
198
+ let claimName = ReventlessCore.Auth_UserId.claim
199
+
200
+ testAsync("authenticate: a token carrying the claim yields it, not the sub", async () => {
201
+ let token = buildJwt(
202
+ Dict.fromArray([
203
+ ("sub", JSON.Encode.string("c3741234-aaaa")),
204
+ (claimName, JSON.Encode.string("u_0123")),
205
+ ]),
206
+ )
207
+ switch await Auth_Cognito.authenticate(buildContext([("authorization", "Bearer " ++ token)])) {
208
+ | Authenticated(identity) => expect(identity.userId)->toBe("u_0123")
209
+ | _ => JsError.throwWithMessage("expected Authenticated")
210
+ }
211
+ })
212
+
213
+ testAsync("authenticate: a token without the claim yields exactly the sub", async () => {
214
+ let token = buildJwt(Dict.fromArray([("sub", JSON.Encode.string("c3741234-aaaa"))]))
215
+ switch await Auth_Cognito.authenticate(buildContext([("authorization", "Bearer " ++ token)])) {
216
+ | Authenticated(identity) => expect(identity.userId)->toBe("c3741234-aaaa")
217
+ | _ => JsError.throwWithMessage("expected Authenticated")
218
+ }
219
+ })
220
+
221
+ testSync("fromAppSyncIdentity: the claim wins over the sub", () => {
222
+ let id: Auth_Cognito.appSyncIdentity = {
223
+ sub: "c3741234-aaaa",
224
+ claims: Dict.fromArray([(claimName, JSON.Encode.string("u_0123"))]),
225
+ }
226
+ switch Auth_Cognito.fromAppSyncIdentity(Some(id)) {
227
+ | Authenticated(identity) => expect(identity.userId)->toBe("u_0123")
228
+ | _ => JsError.throwWithMessage("expected Authenticated")
229
+ }
230
+ })
231
+
232
+ testSync("fromAppSyncIdentity: no claim is exactly the sub", () => {
233
+ let id: Auth_Cognito.appSyncIdentity = {sub: "c3741234-aaaa", claims: Dict.make()}
234
+ switch Auth_Cognito.fromAppSyncIdentity(Some(id)) {
235
+ | Authenticated(identity) => expect(identity.userId)->toBe("c3741234-aaaa")
236
+ | _ => JsError.throwWithMessage("expected Authenticated")
237
+ }
238
+ })
239
+
240
+ testSync("an empty claim is treated as absent", () => {
241
+ let id: Auth_Cognito.appSyncIdentity = {
242
+ sub: "c3741234-aaaa",
243
+ claims: Dict.fromArray([(claimName, JSON.Encode.string(""))]),
244
+ }
245
+ switch Auth_Cognito.fromAppSyncIdentity(Some(id)) {
246
+ | Authenticated(identity) => expect(identity.userId)->toBe("c3741234-aaaa")
247
+ | _ => JsError.throwWithMessage("expected Authenticated")
248
+ }
249
+ })
250
+ })
@@ -2,6 +2,7 @@
2
2
 
3
3
  import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
4
4
  import * as Auth_Cognito$ReventlessAws from "../src/adapter/Auth/Auth_Cognito.res.mjs";
5
+ import * as Auth_UserId$ReventlessCore from "@reventlessdev/reventless-core/src/adapter/Auth/Auth_UserId.res.mjs";
5
6
 
6
7
  function buildContext(headers) {
7
8
  return {
@@ -240,6 +241,103 @@ globalThis.describe("Auth_Cognito.fromAppSyncIdentity", () => {
240
241
  });
241
242
  });
242
243
 
244
+ globalThis.describe("Auth_Cognito and the domain id claim", () => {
245
+ globalThis.test("authenticate: a token carrying the claim yields it, not the sub", async () => {
246
+ let token = buildJwt(Object.fromEntries([
247
+ [
248
+ "sub",
249
+ "c3741234-aaaa"
250
+ ],
251
+ [
252
+ Auth_UserId$ReventlessCore.claim,
253
+ "u_0123"
254
+ ]
255
+ ]));
256
+ let identity = await Auth_Cognito$ReventlessAws.authenticate(buildContext([[
257
+ "authorization",
258
+ "Bearer " + token
259
+ ]]));
260
+ if (typeof identity !== "object") {
261
+ return Stdlib_JsError.throwWithMessage("expected Authenticated");
262
+ }
263
+ if (identity.TAG !== "Authenticated") {
264
+ return Stdlib_JsError.throwWithMessage("expected Authenticated");
265
+ }
266
+ globalThis.expect(identity._0.userId).toBe("u_0123");
267
+ });
268
+ globalThis.test("authenticate: a token without the claim yields exactly the sub", async () => {
269
+ let token = buildJwt(Object.fromEntries([[
270
+ "sub",
271
+ "c3741234-aaaa"
272
+ ]]));
273
+ let identity = await Auth_Cognito$ReventlessAws.authenticate(buildContext([[
274
+ "authorization",
275
+ "Bearer " + token
276
+ ]]));
277
+ if (typeof identity !== "object") {
278
+ return Stdlib_JsError.throwWithMessage("expected Authenticated");
279
+ }
280
+ if (identity.TAG !== "Authenticated") {
281
+ return Stdlib_JsError.throwWithMessage("expected Authenticated");
282
+ }
283
+ globalThis.expect(identity._0.userId).toBe("c3741234-aaaa");
284
+ });
285
+ globalThis.test("fromAppSyncIdentity: the claim wins over the sub", () => {
286
+ let id_sub = "c3741234-aaaa";
287
+ let id_claims = Object.fromEntries([[
288
+ Auth_UserId$ReventlessCore.claim,
289
+ "u_0123"
290
+ ]]);
291
+ let id = {
292
+ sub: id_sub,
293
+ claims: id_claims
294
+ };
295
+ let identity = Auth_Cognito$ReventlessAws.fromAppSyncIdentity(id);
296
+ if (typeof identity !== "object") {
297
+ return Stdlib_JsError.throwWithMessage("expected Authenticated");
298
+ }
299
+ if (identity.TAG !== "Authenticated") {
300
+ return Stdlib_JsError.throwWithMessage("expected Authenticated");
301
+ }
302
+ globalThis.expect(identity._0.userId).toBe("u_0123");
303
+ });
304
+ globalThis.test("fromAppSyncIdentity: no claim is exactly the sub", () => {
305
+ let id_sub = "c3741234-aaaa";
306
+ let id_claims = {};
307
+ let id = {
308
+ sub: id_sub,
309
+ claims: id_claims
310
+ };
311
+ let identity = Auth_Cognito$ReventlessAws.fromAppSyncIdentity(id);
312
+ if (typeof identity !== "object") {
313
+ return Stdlib_JsError.throwWithMessage("expected Authenticated");
314
+ }
315
+ if (identity.TAG !== "Authenticated") {
316
+ return Stdlib_JsError.throwWithMessage("expected Authenticated");
317
+ }
318
+ globalThis.expect(identity._0.userId).toBe("c3741234-aaaa");
319
+ });
320
+ globalThis.test("an empty claim is treated as absent", () => {
321
+ let id_sub = "c3741234-aaaa";
322
+ let id_claims = Object.fromEntries([[
323
+ Auth_UserId$ReventlessCore.claim,
324
+ ""
325
+ ]]);
326
+ let id = {
327
+ sub: id_sub,
328
+ claims: id_claims
329
+ };
330
+ let identity = Auth_Cognito$ReventlessAws.fromAppSyncIdentity(id);
331
+ if (typeof identity !== "object") {
332
+ return Stdlib_JsError.throwWithMessage("expected Authenticated");
333
+ }
334
+ if (identity.TAG !== "Authenticated") {
335
+ return Stdlib_JsError.throwWithMessage("expected Authenticated");
336
+ }
337
+ globalThis.expect(identity._0.userId).toBe("c3741234-aaaa");
338
+ });
339
+ });
340
+
243
341
  export {
244
342
  buildContext,
245
343
  b64urlEncode,
@@ -0,0 +1,35 @@
1
+ open JestGlobals
2
+
3
+ // The identity store's name and key, shared by the deploy, the trigger and the
4
+ // provisioning scripts. The symptom of any two disagreeing is quiet: the claim
5
+ // is never added, and every new account silently keeps its `sub`.
6
+
7
+ module Schema = Auth_IdentityStore_Schema
8
+
9
+ describe("Auth_IdentityStore_Schema", () => {
10
+ testSync("names the store after the provider whose trigger reads it", () =>
11
+ expect(Schema.derivedStoreName(~identityProviderId="eu-west-1_CQTwafSeX"))->toBe(
12
+ "ReventlessIdentityStore-eu-west-1_CQTwafSeX",
13
+ )
14
+ )
15
+
16
+ testSync("does not collide with the active-role store on the same provider", () =>
17
+ expect(
18
+ Schema.derivedStoreName(~identityProviderId="eu-west-1_A") ==
19
+ Auth_ActiveRoleStore_Schema.derivedStoreName(~identityProviderId="eu-west-1_A"),
20
+ )->toBe(false)
21
+ )
22
+
23
+ testSync("is keyed on the subject alone", () =>
24
+ expect(Schema.expectedKeySchema)->toEqual([("id", "HASH")])
25
+ )
26
+
27
+ testSync("adopts a table with the right key and refuses one with another", () => {
28
+ expect(Schema.keySchemaRefusal(~tableName="t", ~actual=[("id", "HASH")]))->toEqual(None)
29
+ expect(
30
+ Schema.keySchemaRefusal(~tableName="t", ~actual=[("id", "HASH"), ("clientId", "RANGE")])
31
+ ->Option.map(m => m->String.includes("identity store needs [id:HASH]"))
32
+ ->Option.getOr(false),
33
+ )->toBe(true)
34
+ })
35
+ })
@@ -0,0 +1,43 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
4
+ import * as Auth_IdentityStore_Schema$ReventlessAws from "../src/adapter/Auth/Auth_IdentityStore_Schema.res.mjs";
5
+ import * as Auth_ActiveRoleStore_Schema$ReventlessAws from "../src/adapter/Auth/Auth_ActiveRoleStore_Schema.res.mjs";
6
+
7
+ globalThis.describe("Auth_IdentityStore_Schema", () => {
8
+ globalThis.test("names the store after the provider whose trigger reads it", () => {
9
+ globalThis.expect(Auth_IdentityStore_Schema$ReventlessAws.derivedStoreName("eu-west-1_CQTwafSeX")).toBe("ReventlessIdentityStore-eu-west-1_CQTwafSeX");
10
+ });
11
+ globalThis.test("does not collide with the active-role store on the same provider", () => {
12
+ globalThis.expect(Auth_IdentityStore_Schema$ReventlessAws.derivedStoreName("eu-west-1_A") === Auth_ActiveRoleStore_Schema$ReventlessAws.derivedStoreName("eu-west-1_A")).toBe(false);
13
+ });
14
+ globalThis.test("is keyed on the subject alone", () => {
15
+ globalThis.expect(Auth_IdentityStore_Schema$ReventlessAws.expectedKeySchema).toEqual([[
16
+ "id",
17
+ "HASH"
18
+ ]]);
19
+ });
20
+ globalThis.test("adopts a table with the right key and refuses one with another", () => {
21
+ globalThis.expect(Auth_IdentityStore_Schema$ReventlessAws.keySchemaRefusal("t", [[
22
+ "id",
23
+ "HASH"
24
+ ]])).toEqual(undefined);
25
+ globalThis.expect(Stdlib_Option.getOr(Stdlib_Option.map(Auth_IdentityStore_Schema$ReventlessAws.keySchemaRefusal("t", [
26
+ [
27
+ "id",
28
+ "HASH"
29
+ ],
30
+ [
31
+ "clientId",
32
+ "RANGE"
33
+ ]
34
+ ]), m => m.includes("identity store needs [id:HASH]")), false)).toBe(true);
35
+ });
36
+ });
37
+
38
+ let Schema;
39
+
40
+ export {
41
+ Schema,
42
+ }
43
+ /* Not a pure module */