@reventlessdev/reventless-local 3.0.0-alpha.300 → 3.0.0-alpha.302

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 (28) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/package.json +11 -11
  3. package/src/EmitCapabilities.res +12 -5
  4. package/src/EmitCapabilities.res.mjs +13 -1
  5. package/src/Platform.res +6 -7
  6. package/src/Platform.res.mjs +10 -12
  7. package/src/adapter/Auth/{UserStore.res → AccountStore.res} +17 -17
  8. package/src/adapter/Auth/{UserStore.res.mjs → AccountStore.res.mjs} +11 -11
  9. package/src/adapter/Auth/LocalAuth.res +5 -5
  10. package/src/adapter/LocalCapabilities.res +2 -2
  11. package/src/adapter/LocalCapabilities.res.mjs +1 -1
  12. package/src/adapter/ObjectStore/ObjectStoreStorage_FileSystem.res +1 -1
  13. package/src/capability/{Capability_IdentityProvider_UserStore.res → Capability_IdentityProvider_AccountStore.res} +1 -1
  14. package/tests/EmitCapabilitiesTest.res +6 -0
  15. package/tests/EmitCapabilitiesTest.res.mjs +6 -0
  16. package/tests/adapter/{LocalAuthUserStoreTest.res → LocalAuthAccountStoreTest.res} +48 -48
  17. package/tests/adapter/{LocalAuthUserStoreTest.res.mjs → LocalAuthAccountStoreTest.res.mjs} +44 -44
  18. package/tests/capability/{Capability_IdentityProvider_UserStoreTest.res → Capability_IdentityProvider_AccountStoreTest.res} +15 -13
  19. package/tests/capability/{Capability_IdentityProvider_UserStoreTest.res.mjs → Capability_IdentityProvider_AccountStoreTest.res.mjs} +15 -15
  20. package/tests/capability/LocalCapabilitiesTest.res +2 -2
  21. package/tests/capability/LocalCapabilitiesTest.res.mjs +3 -3
  22. package/tests/components/dcb/DcbRepeatTest.res +291 -0
  23. package/tests/components/dcb/DcbRepeatTest.res.mjs +420 -0
  24. package/tests/components/readmodel/DcbReadModelTypoFailFastTest.res +71 -15
  25. package/tests/components/readmodel/DcbReadModelTypoFailFastTest.res.mjs +119 -14
  26. package/tests/plugin/Plugin_Fixtures.res +1 -3
  27. package/tests/plugin/Plugin_Fixtures.res.mjs +1 -2
  28. /package/src/capability/{Capability_IdentityProvider_UserStore.res.mjs → Capability_IdentityProvider_AccountStore.res.mjs} +0 -0
@@ -1,4 +1,4 @@
1
- // Stage A4 — UserStore.load resolution order and YAML parsing.
1
+ // Stage A4 — AccountStore.load resolution order and YAML parsing.
2
2
 
3
3
  @@warning("-44")
4
4
 
@@ -7,12 +7,12 @@ open JestGlobals
7
7
  let resetAll = () => {
8
8
  LocalAuth.resetUsers()
9
9
  LocalAuth.Login.resetStore()
10
- UserStore.resetResolution()
10
+ AccountStore.resetResolution()
11
11
  }
12
12
 
13
13
  let _writeYamlFile = (contents: string): string => {
14
14
  let dir = NodeFs.mkdtempSync(NodePath.join([NodeOs.tmpdir(), "reventless-userstore-"]))
15
- let path = NodePath.join([dir, "users.yaml"])
15
+ let path = NodePath.join([dir, "accounts.yaml"])
16
16
  NodeFs.writeFileSync(path, contents)
17
17
  path
18
18
  }
@@ -26,7 +26,7 @@ testPromise("parseString decodes a well-formed YAML document", async () => {
26
26
  password: bob-pw
27
27
  groups: []
28
28
  `
29
- switch UserStore.parseString(yaml) {
29
+ switch AccountStore.parseString(yaml) {
30
30
  | Ok(entries) =>
31
31
  expect(entries->Array.length)->toEqual(2)
32
32
  let first = entries->Array.getUnsafe(0)
@@ -38,7 +38,7 @@ testPromise("parseString decodes a well-formed YAML document", async () => {
38
38
  })
39
39
 
40
40
  testPromise("parseString rejects malformed YAML", async () => {
41
- switch UserStore.parseString("not: valid: yaml: at all: ::") {
41
+ switch AccountStore.parseString("not: valid: yaml: at all: ::") {
42
42
  | Error(_) => ()
43
43
  | Ok(_) => JsError.throwWithMessage("expected Error for malformed YAML")
44
44
  }
@@ -49,21 +49,21 @@ testPromise("parseString rejects entries missing required fields", async () => {
49
49
  - username: alice
50
50
  groups: [Editor]
51
51
  `
52
- switch UserStore.parseString(yaml) {
52
+ switch AccountStore.parseString(yaml) {
53
53
  | Error(_) => ()
54
54
  | Ok(_) => JsError.throwWithMessage("expected Error for missing password")
55
55
  }
56
56
  })
57
57
 
58
- testPromise("load(~users) registers credentials and returns InlineUsers", async () => {
58
+ testPromise("load(~accounts) registers credentials and returns InlineAccounts", async () => {
59
59
  resetAll()
60
- let entries: array<UserStore.entry> = [
60
+ let entries: array<AccountStore.entry> = [
61
61
  {username: "alice", password: "alice-pw", groups: ["Editor"]},
62
62
  {username: "bob", password: "bob-pw", groups: [], userId: "u-bob"},
63
63
  ]
64
- switch UserStore.load(~users=entries, ()) {
65
- | Ok(InlineUsers) => ()
66
- | Ok(_) => JsError.throwWithMessage("expected InlineUsers")
64
+ switch AccountStore.load(~accounts=entries, ()) {
65
+ | Ok(InlineAccounts) => ()
66
+ | Ok(_) => JsError.throwWithMessage("expected InlineAccounts")
67
67
  | Error(msg) => JsError.throwWithMessage("load failed: " ++ msg)
68
68
  }
69
69
  // Verify Login.issue accepts the credentials.
@@ -79,16 +79,16 @@ testPromise("load(~users) registers credentials and returns InlineUsers", async
79
79
  }
80
80
  })
81
81
 
82
- testPromise("load(~usersFile) reads a YAML file from disk", async () => {
82
+ testPromise("load(~accountsFile) reads a YAML file from disk", async () => {
83
83
  resetAll()
84
84
  let path = _writeYamlFile(`
85
85
  - username: carol
86
86
  password: carol-pw
87
87
  groups: [Admin]
88
88
  `)
89
- switch UserStore.load(~usersFile=path, ()) {
90
- | Ok(UsersFile(p)) => expect(p)->toEqual(path)
91
- | Ok(_) => JsError.throwWithMessage("expected UsersFile resolution")
89
+ switch AccountStore.load(~accountsFile=path, ()) {
90
+ | Ok(AccountsFile(p)) => expect(p)->toEqual(path)
91
+ | Ok(_) => JsError.throwWithMessage("expected AccountsFile resolution")
92
92
  | Error(msg) => JsError.throwWithMessage("load failed: " ++ msg)
93
93
  }
94
94
  let result = await LocalAuth.Login.issue(~username="carol", ~password="carol-pw")
@@ -99,9 +99,9 @@ testPromise("load(~usersFile) reads a YAML file from disk", async () => {
99
99
  NodeFs.rmSync(path, {force: true})
100
100
  })
101
101
 
102
- testPromise("load(~usersFile) returns Error when the file is missing", async () => {
102
+ testPromise("load(~accountsFile) returns Error when the file is missing", async () => {
103
103
  resetAll()
104
- switch UserStore.load(~usersFile="/tmp/does-not-exist-reventless.yaml", ()) {
104
+ switch AccountStore.load(~accountsFile="/tmp/does-not-exist-reventless.yaml", ()) {
105
105
  | Error(_) => ()
106
106
  | Ok(_) => JsError.throwWithMessage("expected Error for missing file")
107
107
  }
@@ -109,12 +109,12 @@ testPromise("load(~usersFile) returns Error when the file is missing", async ()
109
109
 
110
110
  testPromise("load() with no args + no default file returns Empty", async () => {
111
111
  resetAll()
112
- // The test's cwd has no .reventless/users.yaml — verify Empty is returned.
112
+ // The test's cwd has no .reventless/accounts.yaml — verify Empty is returned.
113
113
  // (The package's own cwd is reventless-local/ during `pnpm test`, where
114
114
  // no such file exists.)
115
- switch UserStore.load() {
115
+ switch AccountStore.load() {
116
116
  | Ok(Empty) => ()
117
- | Ok(DefaultFile(_)) => // If a .reventless/users.yaml happens to exist in CI, accept it.
117
+ | Ok(DefaultFile(_)) => // If a .reventless/accounts.yaml happens to exist in CI, accept it.
118
118
  ()
119
119
  | Ok(_) => JsError.throwWithMessage("expected Empty or DefaultFile")
120
120
  | Error(msg) => JsError.throwWithMessage("load failed: " ++ msg)
@@ -128,12 +128,12 @@ testPromise("inline users win over a file path", async () => {
128
128
  password: file-pw
129
129
  groups: []
130
130
  `)
131
- let inline: array<UserStore.entry> = [
131
+ let inline: array<AccountStore.entry> = [
132
132
  {username: "inline-user", password: "inline-pw", groups: []},
133
133
  ]
134
- switch UserStore.load(~users=inline, ~usersFile=path, ()) {
135
- | Ok(InlineUsers) => ()
136
- | Ok(_) => JsError.throwWithMessage("expected InlineUsers (inline should win)")
134
+ switch AccountStore.load(~accounts=inline, ~accountsFile=path, ()) {
135
+ | Ok(InlineAccounts) => ()
136
+ | Ok(_) => JsError.throwWithMessage("expected InlineAccounts (inline should win)")
137
137
  | Error(msg) => JsError.throwWithMessage("load failed: " ++ msg)
138
138
  }
139
139
  // file-user must NOT be in the registry.
@@ -150,10 +150,10 @@ testPromise("inline users win over a file path", async () => {
150
150
 
151
151
  testPromise("autoLoadOnce is a no-op after an explicit load", async () => {
152
152
  resetAll()
153
- let _ = UserStore.load(~users=[{username: "x", password: "x", groups: []}], ())
154
- // Second call should not crash even if .reventless/users.yaml doesn't
153
+ let _ = AccountStore.load(~accounts=[{username: "x", password: "x", groups: []}], ())
154
+ // Second call should not crash even if .reventless/accounts.yaml doesn't
155
155
  // exist; resolved=true prevents the default-discovery branch.
156
- UserStore.autoLoadOnce()
156
+ AccountStore.autoLoadOnce()
157
157
  // Sanity: explicit-load registration persists.
158
158
  switch LocalAuth.lookupUser("x") {
159
159
  | Some(_) => ()
@@ -162,7 +162,7 @@ testPromise("autoLoadOnce is a no-op after an explicit load", async () => {
162
162
  })
163
163
 
164
164
  // What the role check counts as provided, before the servers load the store.
165
- describe("UserStore.providedGroups", () => {
165
+ describe("AccountStore.providedGroups", () => {
166
166
  // Runs `f` in a directory holding `files` (path relative to it → contents).
167
167
  let inDir = (files: array<(string, string)>, f) => {
168
168
  let dir = NodeFs.mkdtempSync(NodePath.join([NodeOs.tmpdir(), "reventless-provided-"]))
@@ -188,8 +188,8 @@ describe("UserStore.providedGroups", () => {
188
188
  testSync("counts the default file the servers will load", () => {
189
189
  resetAll()
190
190
  let groups = inDir(
191
- [(".reventless/users.yaml", manifest("Merchandiser"))],
192
- () => UserStore.providedGroups(),
191
+ [(".reventless/accounts.yaml", manifest("Merchandiser"))],
192
+ () => AccountStore.providedGroups(),
193
193
  )
194
194
  expect(has("Merchandiser", groups))->toBe(true)
195
195
  })
@@ -197,27 +197,27 @@ describe("UserStore.providedGroups", () => {
197
197
  testSync("counts the template where setup has not made the file yet", () => {
198
198
  resetAll()
199
199
  let groups = inDir(
200
- [("users.example.yaml", manifest("Fulfilment"))],
201
- () => UserStore.providedGroups(),
200
+ [("accounts.example.yaml", manifest("Fulfilment"))],
201
+ () => AccountStore.providedGroups(),
202
202
  )
203
203
  expect(has("Fulfilment", groups))->toBe(true)
204
204
  })
205
205
 
206
206
  testSync("once loaded from elsewhere, counts those accounts and not the directory's", () => {
207
207
  resetAll()
208
- let _ = UserStore.load(~users=[{username: "i", password: "i", groups: ["Inline"]}], ())
208
+ let _ = AccountStore.load(~accounts=[{username: "i", password: "i", groups: ["Inline"]}], ())
209
209
  let groups = inDir(
210
- [(".reventless/users.yaml", manifest("Merchandiser"))],
211
- () => UserStore.providedGroups(),
210
+ [(".reventless/accounts.yaml", manifest("Merchandiser"))],
211
+ () => AccountStore.providedGroups(),
212
212
  )
213
213
  expect((has("Inline", groups), has("Merchandiser", groups)))->toEqual((true, false))
214
214
  })
215
215
 
216
216
  testSync("loading other accounts after a plugin was checked is refused", () => {
217
217
  resetAll()
218
- UserStore.pluginChecked := true
219
- let refused = switch UserStore.load(
220
- ~users=[{username: "late", password: "l", groups: ["Late"]}],
218
+ AccountStore.pluginChecked := true
219
+ let refused = switch AccountStore.load(
220
+ ~accounts=[{username: "late", password: "l", groups: ["Late"]}],
221
221
  (),
222
222
  ) {
223
223
  | _ => false
@@ -228,13 +228,13 @@ describe("UserStore.providedGroups", () => {
228
228
 
229
229
  testSync("the default load after a plugin was checked is the one the check read", () => {
230
230
  resetAll()
231
- UserStore.pluginChecked := true
232
- let loaded = inDir([], () => UserStore.load()->Result.isOk)
231
+ AccountStore.pluginChecked := true
232
+ let loaded = inDir([], () => AccountStore.load()->Result.isOk)
233
233
  expect(loaded)->toBe(true)
234
234
  })
235
235
  })
236
236
 
237
- describe("UserStore.reload", () => {
237
+ describe("AccountStore.reload", () => {
238
238
  let signsIn = async (~username, ~password) =>
239
239
  switch await LocalAuth.Login.issue(~username, ~password) {
240
240
  | Ok(_) => true
@@ -251,7 +251,7 @@ describe("UserStore.reload", () => {
251
251
  password: b1
252
252
  groups: []
253
253
  `)
254
- let _ = UserStore.load(~usersFile=path, ())
254
+ let _ = AccountStore.load(~accountsFile=path, ())
255
255
  NodeFs.writeFileSync(
256
256
  path,
257
257
  `
@@ -263,7 +263,7 @@ describe("UserStore.reload", () => {
263
263
  groups: [Driver]
264
264
  `,
265
265
  )
266
- switch UserStore.reload(path) {
266
+ switch AccountStore.reload(path) {
267
267
  | Ok(said) => expect(said)->toEqual("2 accounts, removed: bob")
268
268
  | Error(e) => JsError.throwWithMessage(e)
269
269
  }
@@ -281,9 +281,9 @@ describe("UserStore.reload", () => {
281
281
  password: a1
282
282
  groups: [Editor]
283
283
  `)
284
- let _ = UserStore.load(~usersFile=path, ())
284
+ let _ = AccountStore.load(~accountsFile=path, ())
285
285
  NodeFs.writeFileSync(path, "- username: alice\n groups: [Editor]\n")
286
- expect(UserStore.reload(path)->Result.isError)->toBe(true)
286
+ expect(AccountStore.reload(path)->Result.isError)->toBe(true)
287
287
  expect(await signsIn(~username="alice", ~password="a1"))->toBe(true)
288
288
  })
289
289
 
@@ -294,8 +294,8 @@ describe("UserStore.reload", () => {
294
294
  password: a1
295
295
  groups: [Editor]
296
296
  `)
297
- let _ = UserStore.load(~usersFile=path, ())
298
- UserStore.watch(path)
297
+ let _ = AccountStore.load(~accountsFile=path, ())
298
+ AccountStore.watch(path)
299
299
  NodeFs.writeFileSync(
300
300
  path,
301
301
  `
@@ -317,7 +317,7 @@ describe("UserStore.reload", () => {
317
317
  await waitFor(tries - 1)
318
318
  }
319
319
  let added = await waitFor(60)
320
- UserStore.unwatch()
320
+ AccountStore.unwatch()
321
321
  expect(added)->toBe(true)
322
322
  })
323
323
  })
@@ -7,23 +7,23 @@ import * as Stdlib_Result from "@rescript/runtime/lib/es6/Stdlib_Result.js";
7
7
  import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
8
8
  import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
9
9
  import * as LocalAuth$ReventlessLocal from "../../src/adapter/Auth/LocalAuth.res.mjs";
10
- import * as UserStore$ReventlessLocal from "../../src/adapter/Auth/UserStore.res.mjs";
10
+ import * as AccountStore$ReventlessLocal from "../../src/adapter/Auth/AccountStore.res.mjs";
11
11
 
12
12
  function resetAll() {
13
13
  LocalAuth$ReventlessLocal.resetUsers();
14
14
  LocalAuth$ReventlessLocal.Login.resetStore();
15
- UserStore$ReventlessLocal.resetResolution();
15
+ AccountStore$ReventlessLocal.resetResolution();
16
16
  }
17
17
 
18
18
  function _writeYamlFile(contents) {
19
19
  let dir = Nodefs.mkdtempSync(Nodepath.join(Nodeos.tmpdir(), "reventless-userstore-"));
20
- let path = Nodepath.join(dir, "users.yaml");
20
+ let path = Nodepath.join(dir, "accounts.yaml");
21
21
  Nodefs.writeFileSync(path, contents, "utf8");
22
22
  return path;
23
23
  }
24
24
 
25
25
  globalThis.test("parseString decodes a well-formed YAML document", async () => {
26
- let entries = UserStore$ReventlessLocal.parseString(`
26
+ let entries = AccountStore$ReventlessLocal.parseString(`
27
27
  - username: alice
28
28
  password: alice-pw
29
29
  groups: [Editor]
@@ -43,14 +43,14 @@ globalThis.test("parseString decodes a well-formed YAML document", async () => {
43
43
  });
44
44
 
45
45
  globalThis.test("parseString rejects malformed YAML", async () => {
46
- let match = UserStore$ReventlessLocal.parseString("not: valid: yaml: at all: ::");
46
+ let match = AccountStore$ReventlessLocal.parseString("not: valid: yaml: at all: ::");
47
47
  if (match.TAG === "Ok") {
48
48
  return Stdlib_JsError.throwWithMessage("expected Error for malformed YAML");
49
49
  }
50
50
  });
51
51
 
52
52
  globalThis.test("parseString rejects entries missing required fields", async () => {
53
- let match = UserStore$ReventlessLocal.parseString(`
53
+ let match = AccountStore$ReventlessLocal.parseString(`
54
54
  - username: alice
55
55
  groups: [Editor]
56
56
  `);
@@ -59,7 +59,7 @@ globalThis.test("parseString rejects entries missing required fields", async ()
59
59
  }
60
60
  });
61
61
 
62
- globalThis.test("load(~users) registers credentials and returns InlineUsers", async () => {
62
+ globalThis.test("load(~accounts) registers credentials and returns InlineAccounts", async () => {
63
63
  resetAll();
64
64
  let entries = [
65
65
  {
@@ -74,11 +74,11 @@ globalThis.test("load(~users) registers credentials and returns InlineUsers", as
74
74
  userId: "u-bob"
75
75
  }
76
76
  ];
77
- let msg = UserStore$ReventlessLocal.load(entries, undefined, undefined);
77
+ let msg = AccountStore$ReventlessLocal.load(entries, undefined, undefined);
78
78
  if (msg.TAG === "Ok") {
79
79
  let tmp = msg._0;
80
- if (typeof tmp === "object" || tmp !== "InlineUsers") {
81
- Stdlib_JsError.throwWithMessage("expected InlineUsers");
80
+ if (typeof tmp === "object" || tmp !== "InlineAccounts") {
81
+ Stdlib_JsError.throwWithMessage("expected InlineAccounts");
82
82
  }
83
83
  } else {
84
84
  Stdlib_JsError.throwWithMessage("load failed: " + msg._0);
@@ -96,18 +96,18 @@ globalThis.test("load(~users) registers credentials and returns InlineUsers", as
96
96
  }
97
97
  });
98
98
 
99
- globalThis.test("load(~usersFile) reads a YAML file from disk", async () => {
99
+ globalThis.test("load(~accountsFile) reads a YAML file from disk", async () => {
100
100
  resetAll();
101
101
  let path = _writeYamlFile(`
102
102
  - username: carol
103
103
  password: carol-pw
104
104
  groups: [Admin]
105
105
  `);
106
- let msg = UserStore$ReventlessLocal.load(undefined, path, undefined);
106
+ let msg = AccountStore$ReventlessLocal.load(undefined, path, undefined);
107
107
  if (msg.TAG === "Ok") {
108
108
  let p = msg._0;
109
- if (typeof p !== "object" || p.TAG !== "UsersFile") {
110
- Stdlib_JsError.throwWithMessage("expected UsersFile resolution");
109
+ if (typeof p !== "object" || p.TAG !== "AccountsFile") {
110
+ Stdlib_JsError.throwWithMessage("expected AccountsFile resolution");
111
111
  } else {
112
112
  globalThis.expect(p._0).toEqual(path);
113
113
  }
@@ -123,9 +123,9 @@ globalThis.test("load(~usersFile) reads a YAML file from disk", async () => {
123
123
  });
124
124
  });
125
125
 
126
- globalThis.test("load(~usersFile) returns Error when the file is missing", async () => {
126
+ globalThis.test("load(~accountsFile) returns Error when the file is missing", async () => {
127
127
  resetAll();
128
- let match = UserStore$ReventlessLocal.load(undefined, "/tmp/does-not-exist-reventless.yaml", undefined);
128
+ let match = AccountStore$ReventlessLocal.load(undefined, "/tmp/does-not-exist-reventless.yaml", undefined);
129
129
  if (match.TAG === "Ok") {
130
130
  return Stdlib_JsError.throwWithMessage("expected Error for missing file");
131
131
  }
@@ -133,18 +133,18 @@ globalThis.test("load(~usersFile) returns Error when the file is missing", async
133
133
 
134
134
  globalThis.test("load() with no args + no default file returns Empty", async () => {
135
135
  resetAll();
136
- let msg = UserStore$ReventlessLocal.load(undefined, undefined, undefined);
136
+ let msg = AccountStore$ReventlessLocal.load(undefined, undefined, undefined);
137
137
  if (msg.TAG !== "Ok") {
138
138
  return Stdlib_JsError.throwWithMessage("load failed: " + msg._0);
139
139
  }
140
140
  let tmp = msg._0;
141
141
  if (typeof tmp !== "object") {
142
- if (tmp === "InlineUsers") {
142
+ if (tmp === "InlineAccounts") {
143
143
  return Stdlib_JsError.throwWithMessage("expected Empty or DefaultFile");
144
144
  } else {
145
145
  return;
146
146
  }
147
- } else if (tmp.TAG === "UsersFile") {
147
+ } else if (tmp.TAG === "AccountsFile") {
148
148
  return Stdlib_JsError.throwWithMessage("expected Empty or DefaultFile");
149
149
  } else {
150
150
  return;
@@ -163,11 +163,11 @@ globalThis.test("inline users win over a file path", async () => {
163
163
  password: "inline-pw",
164
164
  groups: []
165
165
  }];
166
- let msg = UserStore$ReventlessLocal.load(inline, path, undefined);
166
+ let msg = AccountStore$ReventlessLocal.load(inline, path, undefined);
167
167
  if (msg.TAG === "Ok") {
168
168
  let tmp = msg._0;
169
- if (typeof tmp === "object" || tmp !== "InlineUsers") {
170
- Stdlib_JsError.throwWithMessage("expected InlineUsers (inline should win)");
169
+ if (typeof tmp === "object" || tmp !== "InlineAccounts") {
170
+ Stdlib_JsError.throwWithMessage("expected InlineAccounts (inline should win)");
171
171
  }
172
172
  } else {
173
173
  Stdlib_JsError.throwWithMessage("load failed: " + msg._0);
@@ -189,12 +189,12 @@ globalThis.test("inline users win over a file path", async () => {
189
189
 
190
190
  globalThis.test("autoLoadOnce is a no-op after an explicit load", async () => {
191
191
  resetAll();
192
- UserStore$ReventlessLocal.load([{
192
+ AccountStore$ReventlessLocal.load([{
193
193
  username: "x",
194
194
  password: "x",
195
195
  groups: []
196
196
  }], undefined, undefined);
197
- UserStore$ReventlessLocal.autoLoadOnce();
197
+ AccountStore$ReventlessLocal.autoLoadOnce();
198
198
  let match = LocalAuth$ReventlessLocal.lookupUser("x");
199
199
  if (match !== undefined) {
200
200
  return;
@@ -203,7 +203,7 @@ globalThis.test("autoLoadOnce is a no-op after an explicit load", async () => {
203
203
  }
204
204
  });
205
205
 
206
- globalThis.describe("UserStore.providedGroups", () => {
206
+ globalThis.describe("AccountStore.providedGroups", () => {
207
207
  let inDir = (files, f) => {
208
208
  let dir = Nodefs.mkdtempSync(Nodepath.join(Nodeos.tmpdir(), "reventless-provided-"));
209
209
  files.forEach(param => {
@@ -232,30 +232,30 @@ globalThis.describe("UserStore.providedGroups", () => {
232
232
  globalThis.test("counts the default file the servers will load", () => {
233
233
  resetAll();
234
234
  let groups = inDir([[
235
- ".reventless/users.yaml",
235
+ ".reventless/accounts.yaml",
236
236
  `- username: m\n password: m\n groups: [` + "Merchandiser" + `]\n`
237
- ]], () => UserStore$ReventlessLocal.providedGroups());
237
+ ]], () => AccountStore$ReventlessLocal.providedGroups());
238
238
  globalThis.expect(groups.includes("Merchandiser")).toBe(true);
239
239
  });
240
240
  globalThis.test("counts the template where setup has not made the file yet", () => {
241
241
  resetAll();
242
242
  let groups = inDir([[
243
- "users.example.yaml",
243
+ "accounts.example.yaml",
244
244
  `- username: m\n password: m\n groups: [` + "Fulfilment" + `]\n`
245
- ]], () => UserStore$ReventlessLocal.providedGroups());
245
+ ]], () => AccountStore$ReventlessLocal.providedGroups());
246
246
  globalThis.expect(groups.includes("Fulfilment")).toBe(true);
247
247
  });
248
248
  globalThis.test("once loaded from elsewhere, counts those accounts and not the directory's", () => {
249
249
  resetAll();
250
- UserStore$ReventlessLocal.load([{
250
+ AccountStore$ReventlessLocal.load([{
251
251
  username: "i",
252
252
  password: "i",
253
253
  groups: ["Inline"]
254
254
  }], undefined, undefined);
255
255
  let groups = inDir([[
256
- ".reventless/users.yaml",
256
+ ".reventless/accounts.yaml",
257
257
  `- username: m\n password: m\n groups: [` + "Merchandiser" + `]\n`
258
- ]], () => UserStore$ReventlessLocal.providedGroups());
258
+ ]], () => AccountStore$ReventlessLocal.providedGroups());
259
259
  globalThis.expect([
260
260
  groups.includes("Inline"),
261
261
  groups.includes("Merchandiser")
@@ -266,10 +266,10 @@ globalThis.describe("UserStore.providedGroups", () => {
266
266
  });
267
267
  globalThis.test("loading other accounts after a plugin was checked is refused", () => {
268
268
  resetAll();
269
- UserStore$ReventlessLocal.pluginChecked.contents = true;
269
+ AccountStore$ReventlessLocal.pluginChecked.contents = true;
270
270
  let refused;
271
271
  try {
272
- UserStore$ReventlessLocal.load([{
272
+ AccountStore$ReventlessLocal.load([{
273
273
  username: "late",
274
274
  password: "l",
275
275
  groups: ["Late"]
@@ -287,13 +287,13 @@ globalThis.describe("UserStore.providedGroups", () => {
287
287
  });
288
288
  globalThis.test("the default load after a plugin was checked is the one the check read", () => {
289
289
  resetAll();
290
- UserStore$ReventlessLocal.pluginChecked.contents = true;
291
- let loaded = inDir([], () => Stdlib_Result.isOk(UserStore$ReventlessLocal.load(undefined, undefined, undefined)));
290
+ AccountStore$ReventlessLocal.pluginChecked.contents = true;
291
+ let loaded = inDir([], () => Stdlib_Result.isOk(AccountStore$ReventlessLocal.load(undefined, undefined, undefined)));
292
292
  globalThis.expect(loaded).toBe(true);
293
293
  });
294
294
  });
295
295
 
296
- globalThis.describe("UserStore.reload", () => {
296
+ globalThis.describe("AccountStore.reload", () => {
297
297
  let signsIn = async (username, password) => {
298
298
  let match = await LocalAuth$ReventlessLocal.Login.issue(username, password, undefined);
299
299
  return match.TAG === "Ok";
@@ -308,7 +308,7 @@ globalThis.describe("UserStore.reload", () => {
308
308
  password: b1
309
309
  groups: []
310
310
  `);
311
- UserStore$ReventlessLocal.load(undefined, path, undefined);
311
+ AccountStore$ReventlessLocal.load(undefined, path, undefined);
312
312
  Nodefs.writeFileSync(path, `
313
313
  - username: alice
314
314
  password: a2
@@ -317,7 +317,7 @@ globalThis.describe("UserStore.reload", () => {
317
317
  password: driver
318
318
  groups: [Driver]
319
319
  `, "utf8");
320
- let said = UserStore$ReventlessLocal.reload(path);
320
+ let said = AccountStore$ReventlessLocal.reload(path);
321
321
  if (said.TAG === "Ok") {
322
322
  globalThis.expect(said._0).toEqual("2 accounts, removed: bob");
323
323
  } else {
@@ -336,9 +336,9 @@ globalThis.describe("UserStore.reload", () => {
336
336
  password: a1
337
337
  groups: [Editor]
338
338
  `);
339
- UserStore$ReventlessLocal.load(undefined, path, undefined);
339
+ AccountStore$ReventlessLocal.load(undefined, path, undefined);
340
340
  Nodefs.writeFileSync(path, "- username: alice\n groups: [Editor]\n", "utf8");
341
- globalThis.expect(Stdlib_Result.isError(UserStore$ReventlessLocal.reload(path))).toBe(true);
341
+ globalThis.expect(Stdlib_Result.isError(AccountStore$ReventlessLocal.reload(path))).toBe(true);
342
342
  globalThis.expect(await signsIn("alice", "a1")).toBe(true);
343
343
  });
344
344
  globalThis.test("watch reads the file again once it is saved", async () => {
@@ -348,8 +348,8 @@ globalThis.describe("UserStore.reload", () => {
348
348
  password: a1
349
349
  groups: [Editor]
350
350
  `);
351
- UserStore$ReventlessLocal.load(undefined, path, undefined);
352
- UserStore$ReventlessLocal.watch(path);
351
+ AccountStore$ReventlessLocal.load(undefined, path, undefined);
352
+ AccountStore$ReventlessLocal.watch(path);
353
353
  Nodefs.writeFileSync(path, `
354
354
  - username: alice
355
355
  password: a1
@@ -371,7 +371,7 @@ globalThis.describe("UserStore.reload", () => {
371
371
  }
372
372
  };
373
373
  let added = await waitFor(60);
374
- UserStore$ReventlessLocal.unwatch();
374
+ AccountStore$ReventlessLocal.unwatch();
375
375
  globalThis.expect(added).toBe(true);
376
376
  });
377
377
  });
@@ -8,26 +8,28 @@ let email = address => Reventless.Messaging.ToEmail(Reventless.Email.unsafe(addr
8
8
 
9
9
  let freshFile = (): string => {
10
10
  let dir = NodeFs.mkdtempSync(NodePath.join([NodeOs.tmpdir(), "reventless-identity-"]))
11
- NodePath.join([dir, ".reventless", "users.yaml"])
11
+ NodePath.join([dir, ".reventless", "accounts.yaml"])
12
12
  }
13
13
 
14
14
  let resetAll = () => {
15
15
  LocalAuth.resetUsers()
16
16
  LocalAuth.Login.resetStore()
17
- UserStore.resetResolution()
17
+ AccountStore.resetResolution()
18
18
  }
19
19
 
20
20
  let restartFrom = (file: string): unit => {
21
21
  resetAll()
22
- switch UserStore.load(~usersFile=file, ()) {
22
+ switch AccountStore.load(~accountsFile=file, ()) {
23
23
  | Ok(_) => ()
24
24
  | Error(message) => JsError.throwWithMessage(`reload failed: ${message}`)
25
25
  }
26
26
  }
27
27
 
28
- describe("Capability_IdentityProvider_UserStore", () => {
28
+ describe("Capability_IdentityProvider_AccountStore", () => {
29
29
  testSync("publishes all four operations", () =>
30
- expect(Capability_IdentityProvider_UserStore.make(~path=freshFile(), ()).operations)->toEqual([
30
+ expect(
31
+ Capability_IdentityProvider_AccountStore.make(~path=freshFile(), ()).operations,
32
+ )->toEqual([
31
33
  Reventless.IdentityProvider.CreatePrincipal,
32
34
  AddToGroup,
33
35
  RemoveFromGroup,
@@ -38,7 +40,7 @@ describe("Capability_IdentityProvider_UserStore", () => {
38
40
  testPromise("a created principal can log in now and after a restart", async () => {
39
41
  resetAll()
40
42
  let file = freshFile()
41
- let provider = Capability_IdentityProvider_UserStore.make(~path=file, ())
43
+ let provider = Capability_IdentityProvider_AccountStore.make(~path=file, ())
42
44
  let created = await provider.createPrincipal(
43
45
  ~contact=email("new@example.com"),
44
46
  ~credential=Password("secret-1"),
@@ -66,7 +68,7 @@ describe("Capability_IdentityProvider_UserStore", () => {
66
68
 
67
69
  testPromise("the same contact twice is a Conflict, not a second account", async () => {
68
70
  resetAll()
69
- let provider = Capability_IdentityProvider_UserStore.make(~path=freshFile(), ())
71
+ let provider = Capability_IdentityProvider_AccountStore.make(~path=freshFile(), ())
70
72
  let create = () =>
71
73
  provider.createPrincipal(
72
74
  ~contact=email("twice@example.com"),
@@ -81,7 +83,7 @@ describe("Capability_IdentityProvider_UserStore", () => {
81
83
  // exists for the next provisioning step without a credential anyone holds.
82
84
  testPromise("NoCredential writes an account no password opens", async () => {
83
85
  resetAll()
84
- let provider = Capability_IdentityProvider_UserStore.make(~path=freshFile(), ())
86
+ let provider = Capability_IdentityProvider_AccountStore.make(~path=freshFile(), ())
85
87
  let _ = await provider.createPrincipal(
86
88
  ~contact=email("later@example.com"),
87
89
  ~credential=NoCredential,
@@ -94,7 +96,7 @@ describe("Capability_IdentityProvider_UserStore", () => {
94
96
  })
95
97
 
96
98
  testPromise("a push address is refused, since nothing signs in with one", async () => {
97
- let provider = Capability_IdentityProvider_UserStore.make(~path=freshFile(), ())
99
+ let provider = Capability_IdentityProvider_AccountStore.make(~path=freshFile(), ())
98
100
  let answer = await provider.createPrincipal(
99
101
  ~contact=ToPush(Fcm({registrationToken: "tok"})),
100
102
  ~credential=NoCredential,
@@ -111,7 +113,7 @@ describe("Capability_IdentityProvider_UserStore", () => {
111
113
  testPromise("groups round-trip through the file", async () => {
112
114
  resetAll()
113
115
  let file = freshFile()
114
- let provider = Capability_IdentityProvider_UserStore.make(~path=file, ())
116
+ let provider = Capability_IdentityProvider_AccountStore.make(~path=file, ())
115
117
  let principal: Reventless.IdentityProvider.principal = {providerId: "grp@example.com"}
116
118
  let _ = await provider.createPrincipal(
117
119
  ~contact=email("grp@example.com"),
@@ -133,7 +135,7 @@ describe("Capability_IdentityProvider_UserStore", () => {
133
135
 
134
136
  testPromise("grouping a principal that does not exist is refused", async () => {
135
137
  resetAll()
136
- let provider = Capability_IdentityProvider_UserStore.make(~path=freshFile(), ())
138
+ let provider = Capability_IdentityProvider_AccountStore.make(~path=freshFile(), ())
137
139
  let answer = await provider.addToGroup(~principal={providerId: "ghost"}, ~group="Shopper")
138
140
  expect(answer)->toEqual(Error(Reventless.IdentityProvider.Refused("no principal ghost")))
139
141
  })
@@ -141,7 +143,7 @@ describe("Capability_IdentityProvider_UserStore", () => {
141
143
  testPromise("deleting removes the account from the file and the login, twice", async () => {
142
144
  resetAll()
143
145
  let file = freshFile()
144
- let provider = Capability_IdentityProvider_UserStore.make(~path=file, ())
146
+ let provider = Capability_IdentityProvider_AccountStore.make(~path=file, ())
145
147
  let principal: Reventless.IdentityProvider.principal = {providerId: "gone@example.com"}
146
148
  let _ = await provider.createPrincipal(
147
149
  ~contact=email("gone@example.com"),
@@ -166,7 +168,7 @@ describe("Capability_IdentityProvider_UserStore", () => {
166
168
  groups: [Admin]
167
169
  `,
168
170
  )
169
- let provider = Capability_IdentityProvider_UserStore.make(~path=file, ())
171
+ let provider = Capability_IdentityProvider_AccountStore.make(~path=file, ())
170
172
  let _ = await provider.createPrincipal(
171
173
  ~contact=email("c@example.com"),
172
174
  ~credential=Password("pw"),