@reventlessdev/online-shop-hybrid-ordering 1.0.0-alpha.299 → 1.0.0-alpha.301

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 (54) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/package.json +9 -9
  3. package/src/Customer/Aggregate/Customer.res +6 -6
  4. package/src/Customer/Aggregate/Customer.res.mjs +9 -8
  5. package/src/Customer/Aggregate/Customer_Decision.res +40 -14
  6. package/src/Customer/Aggregate/Customer_Decision.res.mjs +43 -18
  7. package/src/Customer/OutboundTranslation/GeocodeCustomerAddress.res +3 -3
  8. package/src/Customer/OutboundTranslation/GeocodeCustomerAddress.res.mjs +5 -4
  9. package/src/Customer/OutboundTranslation/GeocodeCustomerAddress_Translation.res +9 -2
  10. package/src/Customer/OutboundTranslation/GeocodeCustomerAddress_Translation.res.mjs +21 -5
  11. package/src/Customer/OutboundTranslation/VerifyCustomerEmail.res +4 -4
  12. package/src/Customer/OutboundTranslation/VerifyCustomerEmail.res.mjs +6 -5
  13. package/src/Customer/OutboundTranslation/VerifyCustomerEmail_Translation.res +4 -2
  14. package/src/Customer/OutboundTranslation/VerifyCustomerEmail_Translation.res.mjs +21 -5
  15. package/src/Customer/ReadModelStream/Customers_Projections.res +11 -1
  16. package/src/Customer/ReadModelStream/Customers_Projections.res.mjs +6 -5
  17. package/src/Customer/StateChange/EmailVerificationChallenges.res +8 -8
  18. package/src/Customer/StateChange/EmailVerificationChallenges.res.mjs +9 -8
  19. package/src/Customer/StateChange/EmailVerificationChallenges_Decision.res +6 -4
  20. package/src/Customer/StateChange/EmailVerificationChallenges_Decision.res.mjs +15 -5
  21. package/src/Notification/OutboundTranslation/AnnounceRecipientContact.res +4 -4
  22. package/src/Notification/OutboundTranslation/AnnounceRecipientContact.res.mjs +5 -4
  23. package/src/Notification/OutboundTranslation/AnnounceRecipientContact_Translation.res +6 -2
  24. package/src/Notification/OutboundTranslation/AnnounceRecipientContact_Translation.res.mjs +21 -5
  25. package/src/Notification/OutboundTranslation/SendNotification.res +4 -4
  26. package/src/Notification/OutboundTranslation/SendNotification.res.mjs +5 -4
  27. package/src/Notification/OutboundTranslation/SendNotification_Translation.res +10 -3
  28. package/src/Notification/OutboundTranslation/SendNotification_Translation.res.mjs +28 -11
  29. package/src/Notification/StateChange/NotificationPreferences.res +6 -6
  30. package/src/Notification/StateChange/NotificationPreferences.res.mjs +7 -6
  31. package/src/Notification/StateChange/NotificationPreferences_Decision.res +15 -5
  32. package/src/Notification/StateChange/NotificationPreferences_Decision.res.mjs +26 -9
  33. package/src/Notification/StateViewStream/NotificationSubscriptions.res +1 -1
  34. package/src/Notification/StateViewStream/NotificationSubscriptions.res.mjs +2 -1
  35. package/src/Notification/StateViewStream/NotificationSubscriptions_Projection.res +4 -1
  36. package/src/Notification/StateViewStream/NotificationSubscriptions_Projection.res.mjs +11 -3
  37. package/tests/Customer/AddressGeocodingConformance_GWT.res +17 -7
  38. package/tests/Customer/AddressGeocodingConformance_GWT.res.mjs +36 -9
  39. package/tests/Customer/Aggregate/Customer_GWT.res +29 -29
  40. package/tests/Customer/Aggregate/Customer_GWT.res.mjs +188 -47
  41. package/tests/Customer/OutboundTranslation/VerifyCustomerEmail_GWT.res +2 -2
  42. package/tests/Customer/OutboundTranslation/VerifyCustomerEmail_GWT.res.mjs +12 -3
  43. package/tests/Customer/ReadModelStream/Customers_GWT.res +29 -14
  44. package/tests/Customer/ReadModelStream/Customers_GWT.res.mjs +88 -22
  45. package/tests/Customer/StateChange/EmailVerificationChallenges_GWT.res +17 -9
  46. package/tests/Customer/StateChange/EmailVerificationChallenges_GWT.res.mjs +38 -9
  47. package/tests/Notification/NotificationConformance_GWT.res +9 -6
  48. package/tests/Notification/NotificationConformance_GWT.res.mjs +24 -6
  49. package/tests/Notification/OutboundTranslation/AnnounceRecipientContact_GWT.res +2 -2
  50. package/tests/Notification/OutboundTranslation/AnnounceRecipientContact_GWT.res.mjs +8 -2
  51. package/tests/Notification/OutboundTranslation/SendNotification_GWT.res +2 -2
  52. package/tests/Notification/OutboundTranslation/SendNotification_GWT.res.mjs +8 -2
  53. package/tests/Notification/StateChange/NotificationPreferences_GWT.res +3 -3
  54. package/tests/Notification/StateChange/NotificationPreferences_GWT.res.mjs +12 -3
package/CHANGELOG.md CHANGED
@@ -3,6 +3,22 @@
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.301 (2026-10-30)
7
+
8
+ ### Features
9
+
10
+ * **examples:** the customer's email and address are marked personal data ([768e985](https://github.com/ReventlessDev/reventless-core/commit/768e9853c4943eaad8926b9cb4df55e2a54f4fa8))
11
+ * **trait-address-geocoding:** the address is personal data ([865d811](https://github.com/ReventlessDev/reventless-core/commit/865d811b0dc801a32d7f9de3a50e7a5089a13b48))
12
+
13
+
14
+ # 1.0.0-alpha.300 (2026-10-30)
15
+
16
+ **Note:** Version bump only for package @reventlessdev/online-shop-hybrid-ordering
17
+
18
+
19
+
20
+
21
+
6
22
  # 1.0.0-alpha.299 (2026-10-30)
7
23
 
8
24
  **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.299",
3
+ "version": "1.0.0-alpha.301",
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.184",
25
- "@reventlessdev/online-shop-hybrid-ordering-spec": "1.0.0-alpha.183",
24
+ "@reventlessdev/online-shop-hybrid-ordering-spec": "1.0.0-alpha.185",
25
+ "@reventlessdev/reventless-gwt": "1.0.0-alpha.269",
26
+ "@reventlessdev/online-shop-hybrid-catalog-spec": "1.0.0-alpha.186",
26
27
  "@reventlessdev/rescript-pulumi-pulumi": "3.0.0-alpha.0",
27
- "@reventlessdev/reventless-gwt": "1.0.0-alpha.267",
28
- "@reventlessdev/reventless-infra": "3.0.0-alpha.216",
29
- "@reventlessdev/reventless-local": "3.0.0-alpha.310",
30
- "@reventlessdev/reventless-spec": "3.0.0-alpha.187",
31
- "@reventlessdev/trait-address-geocoding": "1.0.0-alpha.69",
32
- "@reventlessdev/trait-notification": "1.0.0-alpha.69"
28
+ "@reventlessdev/reventless-infra": "3.0.0-alpha.218",
29
+ "@reventlessdev/reventless-spec": "3.0.0-alpha.189",
30
+ "@reventlessdev/reventless-local": "3.0.0-alpha.312",
31
+ "@reventlessdev/trait-notification": "1.0.0-alpha.71",
32
+ "@reventlessdev/trait-address-geocoding": "1.0.0-alpha.71"
33
33
  },
34
34
  "devDependencies": {
35
35
  "rescript": "12.3.1",
@@ -27,8 +27,8 @@ module Id = CustomerId
27
27
  // wins. That is the whole reason `resolvedFrom` exists.
28
28
  @schema
29
29
  type command =
30
- | Register({email: string, address: string})
31
- | UpdateEmail({email: string})
30
+ | Register({@pii email: string, @pii address: string})
31
+ | UpdateEmail({@pii email: string})
32
32
  // The two public address commands, spliced from the trait: `UpdateAddress` and
33
33
  // `SetAddressLocation`. They stayed hand-written here for as long as their
34
34
  // lifecycle guard had to live on the constructor; `commandTransition` below
@@ -54,7 +54,7 @@ type command =
54
54
  //
55
55
  // Carries the address it is a verdict about, so a verdict for an address the
56
56
  // customer has since changed can be dropped rather than applied.
57
- | @noApi MarkEmailVerified({email: string})
57
+ | @noApi MarkEmailVerified({@pii email: string})
58
58
  | Deactivate
59
59
  // The way back. Deactivation withdraws a customer from ordinary use; it does
60
60
  // not erase them, so restoring one needs no payload — the profile is still in
@@ -64,8 +64,8 @@ type command =
64
64
 
65
65
  @schema
66
66
  type event =
67
- | Registered({email: string, address: string})
68
- | EmailUpdated({email: string})
67
+ | Registered({@pii email: string, @pii address: string})
68
+ | EmailUpdated({@pii email: string})
69
69
  // The geocoding graft's four facts, spliced from the trait rather than copied:
70
70
  // `AddressUpdated`, `LocationSet`, `AddressLocated`, `AddressUnresolvable`.
71
71
  // They are matched unqualified below and in the projections, and sury splices
@@ -74,7 +74,7 @@ type event =
74
74
  // Names the address that was proven, not just that one was. `EmailUpdated`
75
75
  // drops it again, which is what keeps "is this address proven?" decidable
76
76
  // instead of assumed.
77
- | EmailVerified({email: string})
77
+ | EmailVerified({@pii email: string})
78
78
  | Deactivated
79
79
  | Reactivated
80
80
 
@@ -1,22 +1,23 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
3
  import * as Sury from "sury";
4
+ import * as Pii$Reventless from "@reventlessdev/reventless-spec/src/components/Pii.res.mjs";
4
5
  import * as Api$ReventlessInfra from "@reventlessdev/reventless-infra/src/components/Api.res.mjs";
5
6
  import * as AddressGeocoding$TraitAddressGeocoding from "@reventlessdev/trait-address-geocoding/src/AddressGeocoding.res.mjs";
6
7
 
7
8
  let commandSchema = Sury.union([
8
9
  Sury.$schema(s => ({
9
10
  TAG: "Register",
10
- email: s.m(Sury.string),
11
- address: s.m(Sury.string)
11
+ email: s.m(Pii$Reventless.mark("$stream", undefined, Sury.string)),
12
+ address: s.m(Pii$Reventless.mark("$stream", undefined, Sury.string))
12
13
  })),
13
14
  Sury.$schema(s => ({
14
15
  TAG: "UpdateEmail",
15
- email: s.m(Sury.string)
16
+ email: s.m(Pii$Reventless.mark("$stream", undefined, Sury.string))
16
17
  })),
17
18
  Sury.$schema(s => ({
18
19
  TAG: "MarkEmailVerified",
19
- email: s.m(Sury.string)
20
+ email: s.m(Pii$Reventless.mark("$stream", undefined, Sury.string))
20
21
  })),
21
22
  Sury.literal("Deactivate"),
22
23
  Sury.literal("Reactivate")
@@ -25,16 +26,16 @@ let commandSchema = Sury.union([
25
26
  let eventSchema = Sury.union([
26
27
  Sury.$schema(s => ({
27
28
  TAG: "Registered",
28
- email: s.m(Sury.string),
29
- address: s.m(Sury.string)
29
+ email: s.m(Pii$Reventless.marked("$stream", undefined, Sury.string)),
30
+ address: s.m(Pii$Reventless.marked("$stream", undefined, Sury.string))
30
31
  })),
31
32
  Sury.$schema(s => ({
32
33
  TAG: "EmailUpdated",
33
- email: s.m(Sury.string)
34
+ email: s.m(Pii$Reventless.marked("$stream", undefined, Sury.string))
34
35
  })),
35
36
  Sury.$schema(s => ({
36
37
  TAG: "EmailVerified",
37
- email: s.m(Sury.string)
38
+ email: s.m(Pii$Reventless.marked("$stream", undefined, Sury.string))
38
39
  })),
39
40
  Sury.literal("Deactivated"),
40
41
  Sury.literal("Reactivated")
@@ -48,29 +48,54 @@ let initialState = NotCreated
48
48
 
49
49
  let evolve = (state, event) =>
50
50
  switch (state, event) {
51
+ // A personal field reads `Erased` once its customer is erased; the state then
52
+ // holds nothing in its place, as a profile never written would.
51
53
  | (NotCreated, Registered({email, address})) =>
52
- Active({email, address, location: None, locationResolvedFrom: None, verifiedEmail: None})
53
- | (Active(s), Registered({email, address})) => Active({...s, email, address})
54
+ Active({
55
+ email: email->Reventless.Pii.getOr(""),
56
+ address: address->Reventless.Pii.getOr(""),
57
+ location: None,
58
+ locationResolvedFrom: None,
59
+ verifiedEmail: None,
60
+ })
61
+ | (Active(s), Registered({email, address})) =>
62
+ Active({
63
+ ...s,
64
+ email: email->Reventless.Pii.getOr(""),
65
+ address: address->Reventless.Pii.getOr(""),
66
+ })
54
67
  // 🚨 A new address is unproven, whatever was proven before. Dropping the token
55
68
  // here is the host half of the staleness guard: without it a proof issued for
56
69
  // the old address would settle against the new one, which is exactly the
57
70
  // "change the address, then present the old link" takeover.
58
- | (Active(s), EmailUpdated({email})) => Active({...s, email, verifiedEmail: None})
59
- | (Active(s), EmailVerified({email})) => Active({...s, verifiedEmail: Some(email)})
71
+ | (Active(s), EmailUpdated({email})) =>
72
+ Active({...s, email: email->Reventless.Pii.getOr(""), verifiedEmail: None})
73
+ | (Active(s), EmailVerified({email})) =>
74
+ Active({...s, verifiedEmail: email->Reventless.Pii.toOption})
60
75
  // A new address invalidates whatever was known about the old one — dropping
61
76
  // both is what puts the row back in front of the geocoding slice.
62
77
  | (Active(s), AddressUpdated({address})) =>
63
- Active({...s, address, location: None, locationResolvedFrom: None})
78
+ Active({
79
+ ...s,
80
+ address: address->Reventless.Pii.getOr(""),
81
+ location: None,
82
+ locationResolvedFrom: None,
83
+ })
64
84
  | (Active(s), LocationSet({location, resolvedFrom})) =>
65
- Active({...s, location: Some(location), locationResolvedFrom: Some(resolvedFrom)})
85
+ Active({
86
+ ...s,
87
+ location: Some(location),
88
+ locationResolvedFrom: resolvedFrom->Reventless.Pii.toOption,
89
+ })
66
90
  // Both halves at once, from a client. `locationResolvedFrom` is the address
67
91
  // itself: the caller supplied the pair, so there is nothing left to resolve.
68
92
  | (Active(s), AddressLocated({address, location})) =>
93
+ let address = address->Reventless.Pii.getOr("")
69
94
  Active({...s, address, location: Some(location), locationResolvedFrom: Some(address)})
70
95
  // Tried, and no usable answer. Recording the address keeps the slice from
71
96
  // handing it back for another round.
72
97
  | (Active(s), AddressUnresolvable({address})) =>
73
- Active({...s, location: None, locationResolvedFrom: Some(address)})
98
+ Active({...s, location: None, locationResolvedFrom: address->Reventless.Pii.toOption})
74
99
  | (
75
100
  Active({email, address, location, locationResolvedFrom, verifiedEmail}),
76
101
  Customer.Deactivated,
@@ -116,7 +141,8 @@ let verified = (verdict, event) =>
116
141
 
117
142
  let decide = (state, command) =>
118
143
  switch (state, command) {
119
- | (NotCreated, Register({email, address})) => Ok([Registered({email, address})])
144
+ | (NotCreated, Register({email, address})) =>
145
+ Ok([Registered({email: Value(email), address: Value(address)})])
120
146
  | (NotCreated, UpdateEmail(_)) => Error(CustomerNotFound)
121
147
  | (NotCreated, UpdateAddress(_)) => Error(CustomerNotFound)
122
148
  | (NotCreated, SetAddressLocation(_)) => Error(CustomerNotFound)
@@ -128,32 +154,32 @@ let decide = (state, command) =>
128
154
 
129
155
  | (Active(_), Register(_)) => Error(CustomerAlreadyRegistered)
130
156
  | (Active(s), UpdateEmail({email})) if email == s.email => Ok([])
131
- | (Active(_), UpdateEmail({email})) => Ok([EmailUpdated({email: email})])
157
+ | (Active(_), UpdateEmail({email})) => Ok([EmailUpdated({email: Value(email)})])
132
158
  | (Active(s), UpdateAddress({address})) =>
133
159
  Guards.onSubjectUpdate(
134
160
  resolution(s.address, s.location, s.locationResolvedFrom),
135
161
  ~subject=address,
136
- )->appended(AddressUpdated({address: address}))
162
+ )->appended(AddressUpdated({address: Value(address)}))
137
163
 
138
164
  | (Active(s), SetAddressLocation({address, location})) =>
139
165
  Guards.onSuppliedPair(
140
166
  resolution(s.address, s.location, s.locationResolvedFrom),
141
167
  ~subject=address,
142
168
  ~location,
143
- )->appended(AddressLocated({address, location}))
169
+ )->appended(AddressLocated({address: Value(address), location}))
144
170
 
145
171
  | (Active(s), SetLocation({location, resolvedFrom})) =>
146
172
  Guards.onLocationReport(
147
173
  resolution(s.address, s.location, s.locationResolvedFrom),
148
174
  ~location,
149
175
  ~resolvedFrom,
150
- )->appended(LocationSet({location, resolvedFrom}))
176
+ )->appended(LocationSet({location, resolvedFrom: Value(resolvedFrom)}))
151
177
 
152
178
  | (Active(s), MarkAddressUnresolvable({address, reason})) =>
153
179
  Guards.onUnresolvableReport(
154
180
  resolution(s.address, s.location, s.locationResolvedFrom),
155
181
  ~subject=address,
156
- )->appended(AddressUnresolvable({address, reason}))
182
+ )->appended(AddressUnresolvable({address: Value(address), reason}))
157
183
 
158
184
  // 🚨 The security control at the host boundary. A verdict naming an address
159
185
  // the customer has since changed is dropped rather than applied — and it is
@@ -164,7 +190,7 @@ let decide = (state, command) =>
164
190
  Verification.onVerifiedReport(
165
191
  verification(s.email, s.verifiedEmail),
166
192
  ~contact=ByEmail(email),
167
- )->verified(EmailVerified({email: email}))
193
+ )->verified(EmailVerified({email: Value(email)}))
168
194
 
169
195
  | (Active(_), Deactivate) => Ok([Customer.Deactivated])
170
196
  // Already where the caller is asking it to be.
@@ -2,6 +2,7 @@
2
2
 
3
3
  import * as Sury from "sury";
4
4
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
5
+ import * as Pii$Reventless from "@reventlessdev/reventless-spec/src/components/Pii.res.mjs";
5
6
  import * as GeoPoint$Reventless from "@reventlessdev/reventless-spec/src/semantic/GeoPoint.res.mjs";
6
7
  import * as ContactVerification_Guards$OrderingPlugin from "../../ContactVerification_Guards.res.mjs";
7
8
  import * as AddressGeocoding_Guards$TraitAddressGeocoding from "@reventlessdev/trait-address-geocoding/src/AddressGeocoding_Guards.res.mjs";
@@ -33,8 +34,8 @@ function evolve(state, event) {
33
34
  } else {
34
35
  return {
35
36
  TAG: "Active",
36
- email: event.email,
37
- address: event.address,
37
+ email: Pii$Reventless.getOr(event.email, ""),
38
+ address: Pii$Reventless.getOr(event.address, ""),
38
39
  location: undefined,
39
40
  locationResolvedFrom: undefined,
40
41
  verifiedEmail: undefined
@@ -73,8 +74,8 @@ function evolve(state, event) {
73
74
  case "Registered" :
74
75
  return {
75
76
  TAG: "Active",
76
- email: event.email,
77
- address: event.address,
77
+ email: Pii$Reventless.getOr(event.email, ""),
78
+ address: Pii$Reventless.getOr(event.address, ""),
78
79
  location: state.location,
79
80
  locationResolvedFrom: state.locationResolvedFrom,
80
81
  verifiedEmail: state.verifiedEmail
@@ -82,7 +83,7 @@ function evolve(state, event) {
82
83
  case "EmailUpdated" :
83
84
  return {
84
85
  TAG: "Active",
85
- email: event.email,
86
+ email: Pii$Reventless.getOr(event.email, ""),
86
87
  address: state.address,
87
88
  location: state.location,
88
89
  locationResolvedFrom: state.locationResolvedFrom,
@@ -92,7 +93,7 @@ function evolve(state, event) {
92
93
  return {
93
94
  TAG: "Active",
94
95
  email: state.email,
95
- address: event.address,
96
+ address: Pii$Reventless.getOr(event.address, ""),
96
97
  location: undefined,
97
98
  locationResolvedFrom: undefined,
98
99
  verifiedEmail: state.verifiedEmail
@@ -103,11 +104,11 @@ function evolve(state, event) {
103
104
  email: state.email,
104
105
  address: state.address,
105
106
  location: event.location,
106
- locationResolvedFrom: event.resolvedFrom,
107
+ locationResolvedFrom: Pii$Reventless.toOption(event.resolvedFrom),
107
108
  verifiedEmail: state.verifiedEmail
108
109
  };
109
110
  case "AddressLocated" :
110
- let address = event.address;
111
+ let address = Pii$Reventless.getOr(event.address, "");
111
112
  return {
112
113
  TAG: "Active",
113
114
  email: state.email,
@@ -122,7 +123,7 @@ function evolve(state, event) {
122
123
  email: state.email,
123
124
  address: state.address,
124
125
  location: undefined,
125
- locationResolvedFrom: event.address,
126
+ locationResolvedFrom: Pii$Reventless.toOption(event.address),
126
127
  verifiedEmail: state.verifiedEmail
127
128
  };
128
129
  case "EmailVerified" :
@@ -132,7 +133,7 @@ function evolve(state, event) {
132
133
  address: state.address,
133
134
  location: state.location,
134
135
  locationResolvedFrom: state.locationResolvedFrom,
135
- verifiedEmail: event.email
136
+ verifiedEmail: Pii$Reventless.toOption(event.email)
136
137
  };
137
138
  }
138
139
  }
@@ -198,8 +199,14 @@ function decide(state, command) {
198
199
  TAG: "Ok",
199
200
  _0: [{
200
201
  TAG: "Registered",
201
- email: command.email,
202
- address: command.address
202
+ email: {
203
+ TAG: "Value",
204
+ _0: command.email
205
+ },
206
+ address: {
207
+ TAG: "Value",
208
+ _0: command.address
209
+ }
203
210
  }]
204
211
  };
205
212
  }
@@ -236,7 +243,10 @@ function decide(state, command) {
236
243
  TAG: "Ok",
237
244
  _0: [{
238
245
  TAG: "EmailUpdated",
239
- email: email
246
+ email: {
247
+ TAG: "Value",
248
+ _0: email
249
+ }
240
250
  }]
241
251
  };
242
252
  }
@@ -248,7 +258,10 @@ function decide(state, command) {
248
258
  resolvedFrom: state.locationResolvedFrom
249
259
  }, address), {
250
260
  TAG: "AddressUpdated",
251
- address: address
261
+ address: {
262
+ TAG: "Value",
263
+ _0: address
264
+ }
252
265
  });
253
266
  case "SetAddressLocation" :
254
267
  let location = command.location;
@@ -259,7 +272,10 @@ function decide(state, command) {
259
272
  resolvedFrom: state.locationResolvedFrom
260
273
  }, address$1, location), {
261
274
  TAG: "AddressLocated",
262
- address: address$1,
275
+ address: {
276
+ TAG: "Value",
277
+ _0: address$1
278
+ },
263
279
  location: location
264
280
  });
265
281
  case "SetLocation" :
@@ -272,7 +288,10 @@ function decide(state, command) {
272
288
  }, location$1, resolvedFrom), {
273
289
  TAG: "LocationSet",
274
290
  location: location$1,
275
- resolvedFrom: resolvedFrom
291
+ resolvedFrom: {
292
+ TAG: "Value",
293
+ _0: resolvedFrom
294
+ }
276
295
  });
277
296
  case "MarkAddressUnresolvable" :
278
297
  let address$2 = command.address;
@@ -282,7 +301,10 @@ function decide(state, command) {
282
301
  resolvedFrom: state.locationResolvedFrom
283
302
  }, address$2), {
284
303
  TAG: "AddressUnresolvable",
285
- address: address$2,
304
+ address: {
305
+ TAG: "Value",
306
+ _0: address$2
307
+ },
286
308
  reason: command.reason
287
309
  });
288
310
  case "MarkEmailVerified" :
@@ -292,7 +314,10 @@ function decide(state, command) {
292
314
  _0: email$1
293
315
  }), {
294
316
  TAG: "EmailVerified",
295
- email: email$1
317
+ email: {
318
+ TAG: "Value",
319
+ _0: email$1
320
+ }
296
321
  });
297
322
  }
298
323
  } else {
@@ -12,11 +12,11 @@
12
12
  // and the conformance suite asserts that this set is no wider than `collect`.
13
13
  @schema
14
14
  type consumedEvent =
15
- | Registered({email: string, address: string})
16
- | AddressUpdated({address: string})
15
+ | Registered({@pii email: string, @pii address: string})
16
+ | AddressUpdated({@pii address: string})
17
17
 
18
18
  @schema
19
- type outboundItem = {customerId: string, address: string}
19
+ type outboundItem = {customerId: string, @pii("customerId") address: string}
20
20
 
21
21
  @schema
22
22
  type inboundCommand =
@@ -1,24 +1,25 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
3
  import * as Sury from "sury";
4
+ import * as Pii$Reventless from "@reventlessdev/reventless-spec/src/components/Pii.res.mjs";
4
5
  import * as GeoPoint$Reventless from "@reventlessdev/reventless-spec/src/semantic/GeoPoint.res.mjs";
5
6
  import * as AddressGeocoding$TraitAddressGeocoding from "@reventlessdev/trait-address-geocoding/src/AddressGeocoding.res.mjs";
6
7
 
7
8
  let consumedEventSchema = Sury.union([
8
9
  Sury.$schema(s => ({
9
10
  TAG: "Registered",
10
- email: s.m(Sury.string),
11
- address: s.m(Sury.string)
11
+ email: s.m(Pii$Reventless.marked("$stream", undefined, Sury.string)),
12
+ address: s.m(Pii$Reventless.marked("$stream", undefined, Sury.string))
12
13
  })),
13
14
  Sury.$schema(s => ({
14
15
  TAG: "AddressUpdated",
15
- address: s.m(Sury.string)
16
+ address: s.m(Pii$Reventless.marked("$stream", undefined, Sury.string))
16
17
  }))
17
18
  ]);
18
19
 
19
20
  let outboundItemSchema = Sury.$schema(s => ({
20
21
  customerId: s.m(Sury.string),
21
- address: s.m(Sury.string)
22
+ address: s.m(Pii$Reventless.mark("customerId", undefined, Sury.string))
22
23
  }));
23
24
 
24
25
  let inboundCommandSchema = Sury.union([
@@ -5,8 +5,15 @@
5
5
  // which an aggregate's event payload does not repeat.
6
6
  let collect = (event, ~sourceId) =>
7
7
  switch event {
8
- | Registered({address}) => [(`${sourceId}:${address}`, {customerId: sourceId, address})]
9
- | AddressUpdated({address}) => [(`${sourceId}:${address}`, {customerId: sourceId, address})]
8
+ | Registered({address: Value(address)}) => [
9
+ (`${sourceId}:${address}`, {customerId: sourceId, address}),
10
+ ]
11
+ // An erased customer is owed nothing.
12
+ | Registered(_) => []
13
+ | AddressUpdated({address: Value(address)}) => [
14
+ (`${sourceId}:${address}`, {customerId: sourceId, address}),
15
+ ]
16
+ | AddressUpdated(_) => []
10
17
  }
11
18
 
12
19
  // Asking the geocoder and reading its answer are the trait's — including the
@@ -6,20 +6,36 @@ import * as AddressGeocoding_Translate$TraitAddressGeocoding from "@reventlessde
6
6
  function collect(event, sourceId) {
7
7
  if (event.TAG === "Registered") {
8
8
  let address = event.address;
9
+ if (typeof address !== "object") {
10
+ if (address === "Erased") {
11
+ return [];
12
+ } else {
13
+ return [];
14
+ }
15
+ }
16
+ let address$1 = address._0;
9
17
  return [[
10
- sourceId + `:` + address,
18
+ sourceId + `:` + address$1,
11
19
  {
12
20
  customerId: sourceId,
13
- address: address
21
+ address: address$1
14
22
  }
15
23
  ]];
16
24
  }
17
- let address$1 = event.address;
25
+ let address$2 = event.address;
26
+ if (typeof address$2 !== "object") {
27
+ if (address$2 === "Erased") {
28
+ return [];
29
+ } else {
30
+ return [];
31
+ }
32
+ }
33
+ let address$3 = address$2._0;
18
34
  return [[
19
- sourceId + `:` + address$1,
35
+ sourceId + `:` + address$3,
20
36
  {
21
37
  customerId: sourceId,
22
- address: address$1
38
+ address: address$3
23
39
  }
24
40
  ]];
25
41
  }
@@ -11,11 +11,11 @@
11
11
  // because a settled address owes nothing and the slice must not re-open it.
12
12
  @schema
13
13
  type consumedEvent =
14
- | Registered({email: string, address: string})
15
- | EmailUpdated({email: string})
14
+ | Registered({@pii email: string, @pii address: string})
15
+ | EmailUpdated({@pii email: string})
16
16
 
17
17
  @schema
18
- type outboundItem = {customerId: string, email: string}
18
+ type outboundItem = {customerId: string, @pii("customerId") email: string}
19
19
 
20
20
  // Reported to the challenge ledger rather than to `Customer` — the aggregate
21
21
  // learns nothing until a proof settles. Mirrors that slice's command exactly.
@@ -23,7 +23,7 @@ type outboundItem = {customerId: string, email: string}
23
23
  type inboundCommand =
24
24
  | IssueEmailChallenge({
25
25
  customerId: CustomerId.t,
26
- email: string,
26
+ @pii("customerId") email: string,
27
27
  purpose: string,
28
28
  proofHash: string,
29
29
  issuedAt: string,
@@ -1,30 +1,31 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
3
  import * as Sury from "sury";
4
+ import * as Pii$Reventless from "@reventlessdev/reventless-spec/src/components/Pii.res.mjs";
4
5
  import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
5
6
  import * as CustomerId$OrderingPlugin from "../CustomerId.res.mjs";
6
7
 
7
8
  let consumedEventSchema = Sury.union([
8
9
  Sury.$schema(s => ({
9
10
  TAG: "Registered",
10
- email: s.m(Sury.string),
11
- address: s.m(Sury.string)
11
+ email: s.m(Pii$Reventless.marked("$stream", undefined, Sury.string)),
12
+ address: s.m(Pii$Reventless.marked("$stream", undefined, Sury.string))
12
13
  })),
13
14
  Sury.$schema(s => ({
14
15
  TAG: "EmailUpdated",
15
- email: s.m(Sury.string)
16
+ email: s.m(Pii$Reventless.marked("$stream", undefined, Sury.string))
16
17
  }))
17
18
  ]);
18
19
 
19
20
  let outboundItemSchema = Sury.$schema(s => ({
20
21
  customerId: s.m(Sury.string),
21
- email: s.m(Sury.string)
22
+ email: s.m(Pii$Reventless.mark("customerId", undefined, Sury.string))
22
23
  }));
23
24
 
24
25
  let inboundCommandSchema = Sury.$schema(s => ({
25
26
  TAG: "IssueEmailChallenge",
26
27
  customerId: s.m(DcbTag$Reventless.mark(CustomerId$OrderingPlugin.schema)),
27
- email: s.m(Sury.string),
28
+ email: s.m(Pii$Reventless.mark("customerId", undefined, Sury.string)),
28
29
  purpose: s.m(Sury.string),
29
30
  proofHash: s.m(Sury.string),
30
31
  issuedAt: s.m(Sury.string)
@@ -7,8 +7,10 @@ module V = ContactVerification
7
7
  // reason. `~sourceId` is the entity id, which an aggregate's payload omits.
8
8
  let collect = (event, ~sourceId) =>
9
9
  switch event {
10
- | Registered({email}) => [(`${sourceId}:${email}`, {customerId: sourceId, email})]
11
- | EmailUpdated({email}) => [(`${sourceId}:${email}`, {customerId: sourceId, email})]
10
+ | Registered({email: Value(email)}) => [(`${sourceId}:${email}`, {customerId: sourceId, email})]
11
+ | EmailUpdated({email: Value(email)}) => [(`${sourceId}:${email}`, {customerId: sourceId, email})]
12
+ // An erased customer is owed nothing.
13
+ | Registered(_) | EmailUpdated(_) => []
12
14
  }
13
15
 
14
16
  let policy = V.emailPolicy
@@ -8,20 +8,36 @@ import * as ContactVerification$OrderingPlugin from "../../ContactVerification.r
8
8
  function collect(event, sourceId) {
9
9
  if (event.TAG === "Registered") {
10
10
  let email = event.email;
11
+ if (typeof email !== "object") {
12
+ if (email === "Erased") {
13
+ return [];
14
+ } else {
15
+ return [];
16
+ }
17
+ }
18
+ let email$1 = email._0;
11
19
  return [[
12
- sourceId + `:` + email,
20
+ sourceId + `:` + email$1,
13
21
  {
14
22
  customerId: sourceId,
15
- email: email
23
+ email: email$1
16
24
  }
17
25
  ]];
18
26
  }
19
- let email$1 = event.email;
27
+ let email$2 = event.email;
28
+ if (typeof email$2 !== "object") {
29
+ if (email$2 === "Erased") {
30
+ return [];
31
+ } else {
32
+ return [];
33
+ }
34
+ }
35
+ let email$3 = email$2._0;
20
36
  return [[
21
- sourceId + `:` + email$1,
37
+ sourceId + `:` + email$3,
22
38
  {
23
39
  customerId: sourceId,
24
- email: email$1
40
+ email: email$3
25
41
  }
26
42
  ]];
27
43
  }