@reventlessdev/online-shop-hybrid-ordering 1.0.0-alpha.304 → 1.0.0-alpha.306

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 CHANGED
@@ -3,6 +3,21 @@
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
+ # 1.0.0-alpha.306 (2026-10-31)
7
+
8
+ **Note:** Version bump only for package @reventlessdev/online-shop-hybrid-ordering
9
+
10
+
11
+
12
+
13
+
14
+ # 1.0.0-alpha.305 (2026-10-30)
15
+
16
+ ### Features
17
+
18
+ * **spec:** an aggregate keyed by its owner's id refuses other callers ([e05f287](https://github.com/ReventlessDev/reventless-core/commit/e05f287eee959d26190af494691c4fa472797cad))
19
+
20
+
6
21
  # 1.0.0-alpha.304 (2026-10-30)
7
22
 
8
23
  **Note:** Version bump only for package @reventlessdev/online-shop-hybrid-ordering
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reventlessdev/online-shop-hybrid-ordering",
3
- "version": "1.0.0-alpha.304",
3
+ "version": "1.0.0-alpha.306",
4
4
  "description": "Online Shop Hybrid example — Ordering plugin (Customer aggregate + Order/CatalogProduct DCB)",
5
5
  "license": "Apache-2.0",
6
6
  "jest": {
@@ -21,15 +21,15 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "sury": "11.0.0",
24
- "@reventlessdev/online-shop-hybrid-catalog-spec": "1.0.0-alpha.187",
25
- "@reventlessdev/online-shop-hybrid-ordering-spec": "1.0.0-alpha.186",
24
+ "@reventlessdev/online-shop-hybrid-catalog-spec": "1.0.0-alpha.188",
25
+ "@reventlessdev/reventless-gwt": "1.0.0-alpha.274",
26
26
  "@reventlessdev/rescript-pulumi-pulumi": "3.0.0-alpha.0",
27
- "@reventlessdev/reventless-infra": "3.0.0-alpha.219",
28
- "@reventlessdev/reventless-gwt": "1.0.0-alpha.272",
29
- "@reventlessdev/reventless-local": "3.0.0-alpha.315",
30
- "@reventlessdev/trait-address-geocoding": "1.0.0-alpha.74",
31
- "@reventlessdev/trait-notification": "1.0.0-alpha.74",
32
- "@reventlessdev/reventless-spec": "3.0.0-alpha.190"
27
+ "@reventlessdev/reventless-infra": "3.0.0-alpha.220",
28
+ "@reventlessdev/online-shop-hybrid-ordering-spec": "1.0.0-alpha.187",
29
+ "@reventlessdev/reventless-spec": "3.0.0-alpha.191",
30
+ "@reventlessdev/trait-notification": "1.0.0-alpha.76",
31
+ "@reventlessdev/trait-address-geocoding": "1.0.0-alpha.76",
32
+ "@reventlessdev/reventless-local": "3.0.0-alpha.317"
33
33
  },
34
34
  "devDependencies": {
35
35
  "rescript": "12.3.1",
@@ -3,7 +3,9 @@
3
3
 
4
4
  @@reventless.spec
5
5
 
6
- module Id = CustomerId
6
+ // The customer is the shopper whose account id keys them: only they, or an
7
+ // elevated caller, may act on this aggregate.
8
+ module Id = Reventless.Id.Owned(CustomerId)
7
9
 
8
10
  // A map coordinate carried by location commands/events. `GeoPoint.t` rather than
9
11
  // a local `{lat, lng}` record: the wire shape is identical — so every event
@@ -55,12 +57,12 @@ type command =
55
57
  // Carries the address it is a verdict about, so a verdict for an address the
56
58
  // customer has since changed can be dropped rather than applied.
57
59
  | @noApi MarkEmailVerified({@pii email: string})
58
- | Deactivate
60
+ | @authorize(AllowRoles([Admin])) Deactivate
59
61
  // The way back. Deactivation withdraws a customer from ordinary use; it does
60
62
  // not erase them, so restoring one needs no payload — the profile is still in
61
63
  // the state, and asking a caller to re-supply an email they never changed
62
64
  // would be a second chance to get it wrong.
63
- | Reactivate
65
+ | @authorize(AllowRoles([Admin])) Reactivate
64
66
 
65
67
  @schema
66
68
  type event =
@@ -1,10 +1,14 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
3
  import * as Sury from "sury";
4
+ import * as Id$Reventless from "@reventlessdev/reventless-spec/src/types/Id.res.mjs";
4
5
  import * as Pii$Reventless from "@reventlessdev/reventless-spec/src/components/Pii.res.mjs";
5
6
  import * as Api$ReventlessInfra from "@reventlessdev/reventless-infra/src/components/Api.res.mjs";
7
+ import * as CustomerId$OrderingPlugin from "../CustomerId.res.mjs";
6
8
  import * as AddressGeocoding$TraitAddressGeocoding from "@reventlessdev/trait-address-geocoding/src/AddressGeocoding.res.mjs";
7
9
 
10
+ let Id = Id$Reventless.Owned(CustomerId$OrderingPlugin);
11
+
8
12
  let commandSchema = Sury.union([
9
13
  Sury.$schema(s => ({
10
14
  TAG: "Register",
@@ -85,14 +89,21 @@ let traits = [AddressGeocoding$TraitAddressGeocoding.declaration];
85
89
 
86
90
  let commandSchema$1 = Api$ReventlessInfra.markNoApiVariants(commandSchema, ["MarkEmailVerified"]);
87
91
 
88
- function authorizationOf(param) {
89
- return "AllowAuthenticated";
92
+ function authorizationOf(name) {
93
+ switch (name) {
94
+ case "Deactivate" :
95
+ case "Reactivate" :
96
+ return {
97
+ TAG: "AllowRoles",
98
+ _0: ["Admin"]
99
+ };
100
+ default:
101
+ return "AllowAuthenticated";
102
+ }
90
103
  }
91
104
 
92
105
  let name = "Customer";
93
106
 
94
- let Id;
95
-
96
107
  let moduleUrl = "@reventlessdev/online-shop-hybrid-ordering/src/Customer/Aggregate/Customer.res.mjs";
97
108
 
98
109
  export {
@@ -106,4 +117,4 @@ export {
106
117
  moduleUrl,
107
118
  authorizationOf,
108
119
  }
109
- /* commandSchema Not a pure module */
120
+ /* Id Not a pure module */
@@ -169,7 +169,7 @@ function project(param) {
169
169
  }
170
170
 
171
171
  let CustomerMapping = Projection$Reventless.Mapping.Make({
172
- Id: CustomerId$OrderingPlugin,
172
+ Id: Customer$OrderingPlugin.Id,
173
173
  name: Customer$OrderingPlugin.name,
174
174
  eventSchema: Customer$OrderingPlugin.eventSchema
175
175
  })({
@@ -423,7 +423,7 @@ function Make(Platform) {
423
423
  moduleUrl: VerifyCustomerEmail_Translation$OrderingPlugin.moduleUrl
424
424
  });
425
425
  let CustomerAggregate = Platform.Aggregate.Make({
426
- Id: CustomerId$OrderingPlugin,
426
+ Id: Customer$OrderingPlugin.Id,
427
427
  name: Customer$OrderingPlugin.name,
428
428
  eventSchema: Customer$OrderingPlugin.eventSchema,
429
429
  errorSchema: Customer$OrderingPlugin.errorSchema,
@@ -440,7 +440,7 @@ function Make(Platform) {
440
440
  moduleUrl: Customer_Decision$OrderingPlugin.moduleUrl
441
441
  })(NoEventMappings$ReventlessInfra.Make({
442
442
  name: Customer$OrderingPlugin.name,
443
- Id: CustomerId$OrderingPlugin,
443
+ Id: Customer$OrderingPlugin.Id,
444
444
  commandSchema: Customer$OrderingPlugin.commandSchema
445
445
  }));
446
446
  let CustomersReadModel = Platform.ReadModelStream.Make({
@@ -36,6 +36,9 @@
36
36
  "declaredBy": [
37
37
  {
38
38
  "component": "SendNotification"
39
+ },
40
+ {
41
+ "component": "VerifyCustomerEmail"
39
42
  }
40
43
  ]
41
44
  }
@@ -170,6 +170,7 @@ let Conformance = AddressGeocoding_Conformance$TraitAddressGeocoding.Make({
170
170
  subjectB: subjectB,
171
171
  posture: "WritesBack",
172
172
  Spec: {
173
+ Id: Customer$OrderingPlugin.Id,
173
174
  name: Customer$OrderingPlugin.name,
174
175
  commandSchema: Customer$OrderingPlugin.commandSchema,
175
176
  eventSchema: Customer$OrderingPlugin.eventSchema,
@@ -178,6 +179,7 @@ let Conformance = AddressGeocoding_Conformance$TraitAddressGeocoding.Make({
178
179
  },
179
180
  Decision: {
180
181
  Spec: {
182
+ Id: Customer$OrderingPlugin.Id,
181
183
  name: Customer$OrderingPlugin.name,
182
184
  commandSchema: Customer$OrderingPlugin.commandSchema,
183
185
  eventSchema: Customer$OrderingPlugin.eventSchema,
@@ -194,3 +194,115 @@ describe("Customer email verification", () => {
194
194
  ->thenError(CustomerNotFound)
195
195
  )
196
196
  })
197
+
198
+ // A customer is the shopper their id names: they, or an administrator, change
199
+ // their profile. Taking a customer out of use, or back, is an administrator's.
200
+ describe("Who may act on a Customer", () => {
201
+ // scenario-id: 6dc19620-bd20-4e98-a67b-a78aa39083ca
202
+ test("a customer may register themself", () =>
203
+ givenEvents([])
204
+ ->onId(c1)
205
+ ->asCaller(Caller.owner(c1))
206
+ ->whenCmd(Register({email: aliceEmail, address: mainStreet}))
207
+ ->thenEvent(Registered({email: Value(aliceEmail), address: Value(mainStreet)}))
208
+ )
209
+
210
+ // scenario-id: ded81926-2cd1-4b9b-8fbf-2683e23e8114
211
+ test("a customer may not register someone else", () =>
212
+ givenEvents([])
213
+ ->onId(c1)
214
+ ->asCaller(Caller.owner(c2))
215
+ ->whenCmd(Register({email: aliceEmail, address: mainStreet}))
216
+ ->thenForbidden
217
+ )
218
+
219
+ // scenario-id: f9cd0f95-17f7-477b-be54-8a60c3010bbd
220
+ test("a customer may change their own email", () =>
221
+ givenEvents([Registered({email: Value(aliceEmail), address: Value(mainStreet)})])
222
+ ->onId(c1)
223
+ ->asCaller(Caller.owner(c1))
224
+ ->whenCmd(UpdateEmail({email: aliceNewEmail}))
225
+ ->thenEvent(EmailUpdated({email: Value(aliceNewEmail)}))
226
+ )
227
+
228
+ // scenario-id: 786b0aa7-aef7-4e2a-8889-f603c78098ca
229
+ test("another customer may not change the email", () =>
230
+ givenEvents([Registered({email: Value(aliceEmail), address: Value(mainStreet)})])
231
+ ->onId(c1)
232
+ ->asCaller(Caller.owner(c2))
233
+ ->whenCmd(UpdateEmail({email: aliceNewEmail}))
234
+ ->thenForbidden
235
+ )
236
+
237
+ // scenario-id: 5e8240aa-2a3c-49c1-ae4a-ffb29a97d138
238
+ test("another customer may not change the address", () =>
239
+ givenEvents([Registered({email: Value(aliceEmail), address: Value(mainStreet)})])
240
+ ->onId(c1)
241
+ ->asCaller(Caller.owner(c2))
242
+ ->whenCmd(UpdateAddress({address: "789 Pine"}))
243
+ ->thenForbidden
244
+ )
245
+
246
+ // scenario-id: 46bfc29e-4cfc-42d8-b2f6-296b28609001
247
+ test("an administrator may change any customer's email", () =>
248
+ givenEvents([Registered({email: Value(aliceEmail), address: Value(mainStreet)})])
249
+ ->onId(c1)
250
+ ->asCaller(Caller.operatorIn([Admin]))
251
+ ->whenCmd(UpdateEmail({email: aliceNewEmail}))
252
+ ->thenEvent(EmailUpdated({email: Value(aliceNewEmail)}))
253
+ )
254
+
255
+ // scenario-id: 019e2283-a3b3-4972-8fdf-b470320b5ce3
256
+ test("a caller who is not signed in may not change the email", () =>
257
+ givenEvents([Registered({email: Value(aliceEmail), address: Value(mainStreet)})])
258
+ ->onId(c1)
259
+ ->asCaller(Caller.anonymous)
260
+ ->whenCmd(UpdateEmail({email: aliceNewEmail}))
261
+ ->thenForbidden
262
+ )
263
+
264
+ // scenario-id: 69dbc4f8-4009-4caa-9e14-f1dd248d7a2a
265
+ test("a customer may not deactivate themself", () =>
266
+ givenEvents([Registered({email: Value(aliceEmail), address: Value(mainStreet)})])
267
+ ->onId(c1)
268
+ ->asCaller(Caller.owner(c1))
269
+ ->whenCmd(Deactivate)
270
+ ->thenForbidden
271
+ )
272
+
273
+ // scenario-id: 7d4c5293-934e-4fb5-81d2-b3b8f96c3e5e
274
+ test("an operator who is not an administrator may not deactivate a customer", () =>
275
+ givenEvents([Registered({email: Value(aliceEmail), address: Value(mainStreet)})])
276
+ ->onId(c1)
277
+ ->asCaller(Caller.operatorIn([Fulfilment]))
278
+ ->whenCmd(Deactivate)
279
+ ->thenForbidden
280
+ )
281
+
282
+ // scenario-id: 13f06620-a184-4099-be1c-fc727e74788b
283
+ test("an administrator may deactivate a customer", () =>
284
+ givenEvents([Registered({email: Value(aliceEmail), address: Value(mainStreet)})])
285
+ ->onId(c1)
286
+ ->asCaller(Caller.operatorIn([Admin]))
287
+ ->whenCmd(Deactivate)
288
+ ->thenEvent(Deactivated)
289
+ )
290
+
291
+ // scenario-id: c5375866-bf51-47fe-8633-b1b2887e2ab2
292
+ test("a customer may not reactivate themself", () =>
293
+ givenEvents([Registered({email: Value(aliceEmail), address: Value(mainStreet)}), Deactivated])
294
+ ->onId(c1)
295
+ ->asCaller(Caller.owner(c1))
296
+ ->whenCmd(Reactivate)
297
+ ->thenForbidden
298
+ )
299
+
300
+ // scenario-id: f2696c97-6582-4ee7-a403-ee5aed6d8c19
301
+ test("an administrator may reactivate a customer", () =>
302
+ givenEvents([Registered({email: Value(aliceEmail), address: Value(mainStreet)}), Deactivated])
303
+ ->onId(c1)
304
+ ->asCaller(Caller.operatorIn([Admin]))
305
+ ->whenCmd(Reactivate)
306
+ ->thenEvent(Reactivated)
307
+ )
308
+ })
@@ -6,6 +6,7 @@ import * as Customer_Decision$OrderingPlugin from "../../../src/Customer/Aggrega
6
6
  import * as Ordering_Examples$OrderingPlugin from "../../Ordering_Examples.res.mjs";
7
7
 
8
8
  let include = Decision_GWT$ReventlessGwt.MakeFromAggregate({
9
+ Id: Customer$OrderingPlugin.Id,
9
10
  name: Customer$OrderingPlugin.name,
10
11
  commandSchema: Customer$OrderingPlugin.commandSchema,
11
12
  eventSchema: Customer$OrderingPlugin.eventSchema,
@@ -13,6 +14,7 @@ let include = Decision_GWT$ReventlessGwt.MakeFromAggregate({
13
14
  authorizationOf: Customer$OrderingPlugin.authorizationOf
14
15
  })({
15
16
  Spec: {
17
+ Id: Customer$OrderingPlugin.Id,
16
18
  name: Customer$OrderingPlugin.name,
17
19
  commandSchema: Customer$OrderingPlugin.commandSchema,
18
20
  eventSchema: Customer$OrderingPlugin.eventSchema,
@@ -32,6 +34,12 @@ let test = include.test;
32
34
 
33
35
  let givenEvents = include.givenEvents;
34
36
 
37
+ let Caller = include.Caller;
38
+
39
+ let asCaller = include.asCaller;
40
+
41
+ let onId = include.onId;
42
+
35
43
  let whenCmd = include.whenCmd;
36
44
 
37
45
  let thenEvent = include.thenEvent;
@@ -40,6 +48,8 @@ let thenNoEvent = include.thenNoEvent;
40
48
 
41
49
  let thenError = include.thenError;
42
50
 
51
+ let thenForbidden = include.thenForbidden;
52
+
43
53
  describe("Customer Decision", () => {
44
54
  test("Register on new aggregate produces Registered", () => thenEvent(whenCmd(givenEvents([]), {
45
55
  TAG: "Register",
@@ -419,11 +429,175 @@ describe("Customer email verification", () => {
419
429
  }), "CustomerNotFound"));
420
430
  });
421
431
 
422
- let Spec = include.Spec;
432
+ describe("Who may act on a Customer", () => {
433
+ test("a customer may register themself", () => thenEvent(whenCmd(asCaller(onId(givenEvents([]), Ordering_Examples$OrderingPlugin.c1), Caller.owner(Ordering_Examples$OrderingPlugin.c1, undefined)), {
434
+ TAG: "Register",
435
+ email: Ordering_Examples$OrderingPlugin.aliceEmail,
436
+ address: Ordering_Examples$OrderingPlugin.mainStreet
437
+ }), {
438
+ TAG: "Registered",
439
+ email: {
440
+ TAG: "Value",
441
+ _0: Ordering_Examples$OrderingPlugin.aliceEmail
442
+ },
443
+ address: {
444
+ TAG: "Value",
445
+ _0: Ordering_Examples$OrderingPlugin.mainStreet
446
+ }
447
+ }));
448
+ test("a customer may not register someone else", () => thenForbidden(whenCmd(asCaller(onId(givenEvents([]), Ordering_Examples$OrderingPlugin.c1), Caller.owner(Ordering_Examples$OrderingPlugin.c2, undefined)), {
449
+ TAG: "Register",
450
+ email: Ordering_Examples$OrderingPlugin.aliceEmail,
451
+ address: Ordering_Examples$OrderingPlugin.mainStreet
452
+ })));
453
+ test("a customer may change their own email", () => thenEvent(whenCmd(asCaller(onId(givenEvents([{
454
+ TAG: "Registered",
455
+ email: {
456
+ TAG: "Value",
457
+ _0: Ordering_Examples$OrderingPlugin.aliceEmail
458
+ },
459
+ address: {
460
+ TAG: "Value",
461
+ _0: Ordering_Examples$OrderingPlugin.mainStreet
462
+ }
463
+ }]), Ordering_Examples$OrderingPlugin.c1), Caller.owner(Ordering_Examples$OrderingPlugin.c1, undefined)), {
464
+ TAG: "UpdateEmail",
465
+ email: Ordering_Examples$OrderingPlugin.aliceNewEmail
466
+ }), {
467
+ TAG: "EmailUpdated",
468
+ email: {
469
+ TAG: "Value",
470
+ _0: Ordering_Examples$OrderingPlugin.aliceNewEmail
471
+ }
472
+ }));
473
+ test("another customer may not change the email", () => thenForbidden(whenCmd(asCaller(onId(givenEvents([{
474
+ TAG: "Registered",
475
+ email: {
476
+ TAG: "Value",
477
+ _0: Ordering_Examples$OrderingPlugin.aliceEmail
478
+ },
479
+ address: {
480
+ TAG: "Value",
481
+ _0: Ordering_Examples$OrderingPlugin.mainStreet
482
+ }
483
+ }]), Ordering_Examples$OrderingPlugin.c1), Caller.owner(Ordering_Examples$OrderingPlugin.c2, undefined)), {
484
+ TAG: "UpdateEmail",
485
+ email: Ordering_Examples$OrderingPlugin.aliceNewEmail
486
+ })));
487
+ test("another customer may not change the address", () => thenForbidden(whenCmd(asCaller(onId(givenEvents([{
488
+ TAG: "Registered",
489
+ email: {
490
+ TAG: "Value",
491
+ _0: Ordering_Examples$OrderingPlugin.aliceEmail
492
+ },
493
+ address: {
494
+ TAG: "Value",
495
+ _0: Ordering_Examples$OrderingPlugin.mainStreet
496
+ }
497
+ }]), Ordering_Examples$OrderingPlugin.c1), Caller.owner(Ordering_Examples$OrderingPlugin.c2, undefined)), {
498
+ TAG: "UpdateAddress",
499
+ address: "789 Pine"
500
+ })));
501
+ test("an administrator may change any customer's email", () => thenEvent(whenCmd(asCaller(onId(givenEvents([{
502
+ TAG: "Registered",
503
+ email: {
504
+ TAG: "Value",
505
+ _0: Ordering_Examples$OrderingPlugin.aliceEmail
506
+ },
507
+ address: {
508
+ TAG: "Value",
509
+ _0: Ordering_Examples$OrderingPlugin.mainStreet
510
+ }
511
+ }]), Ordering_Examples$OrderingPlugin.c1), Caller.operatorIn(["Admin"])), {
512
+ TAG: "UpdateEmail",
513
+ email: Ordering_Examples$OrderingPlugin.aliceNewEmail
514
+ }), {
515
+ TAG: "EmailUpdated",
516
+ email: {
517
+ TAG: "Value",
518
+ _0: Ordering_Examples$OrderingPlugin.aliceNewEmail
519
+ }
520
+ }));
521
+ test("a caller who is not signed in may not change the email", () => thenForbidden(whenCmd(asCaller(onId(givenEvents([{
522
+ TAG: "Registered",
523
+ email: {
524
+ TAG: "Value",
525
+ _0: Ordering_Examples$OrderingPlugin.aliceEmail
526
+ },
527
+ address: {
528
+ TAG: "Value",
529
+ _0: Ordering_Examples$OrderingPlugin.mainStreet
530
+ }
531
+ }]), Ordering_Examples$OrderingPlugin.c1), Caller.anonymous), {
532
+ TAG: "UpdateEmail",
533
+ email: Ordering_Examples$OrderingPlugin.aliceNewEmail
534
+ })));
535
+ test("a customer may not deactivate themself", () => thenForbidden(whenCmd(asCaller(onId(givenEvents([{
536
+ TAG: "Registered",
537
+ email: {
538
+ TAG: "Value",
539
+ _0: Ordering_Examples$OrderingPlugin.aliceEmail
540
+ },
541
+ address: {
542
+ TAG: "Value",
543
+ _0: Ordering_Examples$OrderingPlugin.mainStreet
544
+ }
545
+ }]), Ordering_Examples$OrderingPlugin.c1), Caller.owner(Ordering_Examples$OrderingPlugin.c1, undefined)), "Deactivate")));
546
+ test("an operator who is not an administrator may not deactivate a customer", () => thenForbidden(whenCmd(asCaller(onId(givenEvents([{
547
+ TAG: "Registered",
548
+ email: {
549
+ TAG: "Value",
550
+ _0: Ordering_Examples$OrderingPlugin.aliceEmail
551
+ },
552
+ address: {
553
+ TAG: "Value",
554
+ _0: Ordering_Examples$OrderingPlugin.mainStreet
555
+ }
556
+ }]), Ordering_Examples$OrderingPlugin.c1), Caller.operatorIn(["Fulfilment"])), "Deactivate")));
557
+ test("an administrator may deactivate a customer", () => thenEvent(whenCmd(asCaller(onId(givenEvents([{
558
+ TAG: "Registered",
559
+ email: {
560
+ TAG: "Value",
561
+ _0: Ordering_Examples$OrderingPlugin.aliceEmail
562
+ },
563
+ address: {
564
+ TAG: "Value",
565
+ _0: Ordering_Examples$OrderingPlugin.mainStreet
566
+ }
567
+ }]), Ordering_Examples$OrderingPlugin.c1), Caller.operatorIn(["Admin"])), "Deactivate"), "Deactivated"));
568
+ test("a customer may not reactivate themself", () => thenForbidden(whenCmd(asCaller(onId(givenEvents([
569
+ {
570
+ TAG: "Registered",
571
+ email: {
572
+ TAG: "Value",
573
+ _0: Ordering_Examples$OrderingPlugin.aliceEmail
574
+ },
575
+ address: {
576
+ TAG: "Value",
577
+ _0: Ordering_Examples$OrderingPlugin.mainStreet
578
+ }
579
+ },
580
+ "Deactivated"
581
+ ]), Ordering_Examples$OrderingPlugin.c1), Caller.owner(Ordering_Examples$OrderingPlugin.c1, undefined)), "Reactivate")));
582
+ test("an administrator may reactivate a customer", () => thenEvent(whenCmd(asCaller(onId(givenEvents([
583
+ {
584
+ TAG: "Registered",
585
+ email: {
586
+ TAG: "Value",
587
+ _0: Ordering_Examples$OrderingPlugin.aliceEmail
588
+ },
589
+ address: {
590
+ TAG: "Value",
591
+ _0: Ordering_Examples$OrderingPlugin.mainStreet
592
+ }
593
+ },
594
+ "Deactivated"
595
+ ]), Ordering_Examples$OrderingPlugin.c1), Caller.operatorIn(["Admin"])), "Reactivate"), "Reactivated"));
596
+ });
423
597
 
424
- let Caller = include.Caller;
598
+ let Spec = include.Spec;
425
599
 
426
- let asCaller = include.asCaller;
600
+ let todo = include.todo;
427
601
 
428
602
  let thenCompareEvent = include.thenCompareEvent;
429
603
 
@@ -435,15 +609,15 @@ let thenCompareEvents = include.thenCompareEvents;
435
609
 
436
610
  let thenEventsWithError = include.thenEventsWithError;
437
611
 
438
- let thenForbidden = include.thenForbidden;
439
-
440
612
  export {
441
613
  Spec,
442
614
  describe,
615
+ todo,
443
616
  test,
444
617
  givenEvents,
445
618
  Caller,
446
619
  asCaller,
620
+ onId,
447
621
  whenCmd,
448
622
  thenEvent,
449
623
  thenCompareEvent,