@reventlessdev/reventless-local 3.0.0-alpha.299 → 3.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.
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
+ # 3.0.0-alpha.301 (2026-10-25)
7
+
8
+ **Note:** Version bump only for package @reventlessdev/reventless-local
9
+
10
+
11
+
12
+
13
+
14
+ # 3.0.0-alpha.300 (2026-10-25)
15
+
16
+ **Note:** Version bump only for package @reventlessdev/reventless-local
17
+
18
+
19
+
20
+
21
+
6
22
  # 3.0.0-alpha.299 (2026-10-25)
7
23
 
8
24
  * refactor!: internal results and tool records whose parts may be absent are optional fields ([7009ddf](https://github.com/ReventlessDev/reventless-core/commit/7009ddf5d522f39ec9946a3b5cd062ceae889bbf))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reventlessdev/reventless-local",
3
- "version": "3.0.0-alpha.299",
3
+ "version": "3.0.0-alpha.301",
4
4
  "description": "Local platform for Reventless (in-memory or SQLite backend, for development and testing without AWS)",
5
5
  "license": "Apache-2.0",
6
6
  "bin": {
@@ -35,23 +35,23 @@
35
35
  "sury": "11.0.0",
36
36
  "ws": "^8.18.0",
37
37
  "@reventlessdev/rescript-effect": "1.0.0-alpha.1",
38
+ "@reventlessdev/rescript-graphql-yoga": "1.0.0-alpha.29",
38
39
  "@reventlessdev/rescript-jest": "1.0.0-alpha.13",
39
40
  "@reventlessdev/rescript-mcp-sdk": "1.0.0-alpha.24",
40
41
  "@reventlessdev/rescript-node": "2.0.0-alpha.23",
41
- "@reventlessdev/rescript-graphql-yoga": "1.0.0-alpha.29",
42
42
  "@reventlessdev/rescript-pulumi-pulumi": "3.0.0-alpha.0",
43
- "@reventlessdev/reventless-graphql-server": "1.0.0-alpha.156",
44
- "@reventlessdev/reventless-gwt": "1.0.0-alpha.256",
45
- "@reventlessdev/reventless-core": "3.0.0-alpha.308",
46
- "@reventlessdev/reventless-postgres": "3.0.0-alpha.172",
47
- "@reventlessdev/reventless-spec": "3.0.0-alpha.176",
48
- "@reventlessdev/reventless-seed": "1.0.0-alpha.37",
49
- "@reventlessdev/reventless-infra": "3.0.0-alpha.205"
43
+ "@reventlessdev/reventless-core": "3.0.0-alpha.310",
44
+ "@reventlessdev/reventless-gwt": "1.0.0-alpha.258",
45
+ "@reventlessdev/reventless-graphql-server": "1.0.0-alpha.158",
46
+ "@reventlessdev/reventless-infra": "3.0.0-alpha.207",
47
+ "@reventlessdev/reventless-seed": "1.0.0-alpha.38",
48
+ "@reventlessdev/reventless-postgres": "3.0.0-alpha.174",
49
+ "@reventlessdev/reventless-spec": "3.0.0-alpha.178"
50
50
  },
51
51
  "devDependencies": {
52
52
  "rescript": "12.3.1",
53
53
  "sury-ppx": "11.0.0",
54
- "@reventlessdev/reventless-ppx": "1.0.0-alpha.107"
54
+ "@reventlessdev/reventless-ppx": "1.0.0-alpha.108"
55
55
  },
56
56
  "peerDependencies": {
57
57
  "rescript": "^12.3.1"
package/src/Platform.res CHANGED
@@ -109,7 +109,7 @@ module MakeWithConfig = (
109
109
  // What this platform provides for the roles its plugins need: every account it
110
110
  // can sign in as, built-in and loaded alike, or the file the store will load
111
111
  // when the servers start — after the plugins are built and checked.
112
- Reventless.Role.provideGroupsFrom(UserStore.providedGroups)
112
+ Reventless.Role.provideGroupsFrom(AccountStore.providedGroups)
113
113
  // Activate Pulumi mock mode — must happen before any component creation.
114
114
  // Idempotent, so safe to call even if TestRunner.setup() was already called.
115
115
  let _ = TestRunner.setup()
@@ -1377,11 +1377,11 @@ module MakeWithConfig = (
1377
1377
  // this is a no-op (start() is called inline inside makePlatform/deployPlugin).
1378
1378
  let startServers = () => {
1379
1379
  if Config.splitApi {
1380
- // Hydrate Login store from .reventless/users.yaml (or ~users/~usersFile
1380
+ // Hydrate Login store from .reventless/accounts.yaml (or ~accounts/~accountsFile
1381
1381
  // if provided programmatically) before the Domain server accepts
1382
1382
  // requests. Unified mode does this in makePlatform; split mode defers
1383
1383
  // server startup to here so it must do the same.
1384
- UserStore.autoLoadOnce()
1384
+ AccountStore.autoLoadOnce()
1385
1385
  DomainGraphQL_Server.start(~port=domainPort, ())
1386
1386
  DomainMCP_Server.start(~port=domainMcpPort, ())
1387
1387
  PlatformGraphQL_Server.start(
@@ -1579,7 +1579,7 @@ module MakeWithConfig = (
1579
1579
  geocoderPlaceIndex?: ReventlessInfra.Platform.geocoderIndex,
1580
1580
  messagingSender?: ReventlessInfra.Platform.messagingSender,
1581
1581
  // Local only, until the AWS platform has a provider to pass the same way:
1582
- // `Capability_IdentityProvider_UserStore.make()`, writing the accounts file
1582
+ // `Capability_IdentityProvider_AccountStore.make()`, writing the accounts file
1583
1583
  // the auth adapter loads.
1584
1584
  identityProvider?: Reventless.IdentityProvider.t,
1585
1585
  uploadBucket?: ReventlessInfra.Platform.objectStore,
@@ -2350,7 +2350,7 @@ module MakeWithConfig = (
2350
2350
  // (domain and platform) can register their schema first.
2351
2351
  // In unified mode, start immediately (backwards-compatible).
2352
2352
  if !Config.splitApi {
2353
- UserStore.autoLoadOnce()
2353
+ AccountStore.autoLoadOnce()
2354
2354
  DomainGraphQL_Server.start()
2355
2355
  DomainMCP_Server.start()
2356
2356
  }
@@ -2534,7 +2534,7 @@ module MakeWithConfig = (
2534
2534
 
2535
2535
  // The role check below reads the accounts as they stand; a user store
2536
2536
  // loaded from elsewhere after this would leave it compared with the wrong ones.
2537
- UserStore.pluginChecked := true
2537
+ AccountStore.pluginChecked := true
2538
2538
 
2539
2539
  // Set the active deploy target so resolveTargetGraphQL/MCP() and QueryDb serverRef/relayRef
2540
2540
  // route registrations to the correct server. Mirrors AWS resolveTargetApi() pattern.
@@ -30,12 +30,12 @@ import * as AdmissionCheck$Reventless from "@reventlessdev/reventless-spec/src/t
30
30
  import * as Api_Naming$ReventlessCore from "@reventlessdev/reventless-core/src/components/Api/Api_Naming.res.mjs";
31
31
  import * as CommandOutcome$Reventless from "@reventlessdev/reventless-spec/src/components/CommandOutcome.res.mjs";
32
32
  import * as PluginSpec$ReventlessCore from "@reventlessdev/reventless-core/src/plugin/lifecycle/PluginSpec.res.mjs";
33
- import * as UserStore$ReventlessLocal from "./adapter/Auth/UserStore.res.mjs";
34
33
  import * as TestRunner$ReventlessLocal from "./test/TestRunner.res.mjs";
35
34
  import * as UiFragments$ReventlessCore from "@reventlessdev/reventless-core/src/admin/UiFragmentRegistry/StateView/UiFragments.res.mjs";
36
35
  import * as CommandTopic$ReventlessCore from "@reventlessdev/reventless-core/src/components/CommandTopic/CommandTopic.res.mjs";
37
36
  import * as EffectLogger$ReventlessCore from "@reventlessdev/reventless-core/src/util/EffectLogger.res.mjs";
38
37
  import * as ShellConfig$ReventlessLocal from "./ShellConfig.res.mjs";
38
+ import * as AccountStore$ReventlessLocal from "./adapter/Auth/AccountStore.res.mjs";
39
39
  import * as BackendState$ReventlessLocal from "./adapter/BackendState.res.mjs";
40
40
  import * as ComponentType$ReventlessCore from "@reventlessdev/reventless-core/src/ComponentType.res.mjs";
41
41
  import * as SqliteDriver$ReventlessLocal from "./adapter/SqliteDriver.res.mjs";
@@ -146,7 +146,7 @@ function decodeUiFragmentRegistryEventEnvelope(eventJson) {
146
146
  }
147
147
 
148
148
  function MakeWithConfig(Config) {
149
- Role$Reventless.provideGroupsFrom(UserStore$ReventlessLocal.providedGroups);
149
+ Role$Reventless.provideGroupsFrom(AccountStore$ReventlessLocal.providedGroups);
150
150
  TestRunner$ReventlessLocal.setup();
151
151
  let match = Config.backend;
152
152
  if (typeof match !== "object") {
@@ -1151,7 +1151,7 @@ function MakeWithConfig(Config) {
1151
1151
  };
1152
1152
  let startServers = () => {
1153
1153
  if (Config.splitApi) {
1154
- UserStore$ReventlessLocal.autoLoadOnce();
1154
+ AccountStore$ReventlessLocal.autoLoadOnce();
1155
1155
  DomainGraphQL_Server$ReventlessLocal.start(domainPort, undefined, undefined);
1156
1156
  DomainMCP_Server$ReventlessLocal.start(domainMcpPort, undefined);
1157
1157
  PlatformGraphQL_Server$ReventlessLocal.start(platformPort, Auth_GraphqlContext$ReventlessLocal.buildAuthContext, undefined);
@@ -1694,7 +1694,7 @@ function MakeWithConfig(Config) {
1694
1694
  }
1695
1695
  currentDeployTarget.contents = "Domain";
1696
1696
  if (!Config.splitApi) {
1697
- UserStore$ReventlessLocal.autoLoadOnce();
1697
+ AccountStore$ReventlessLocal.autoLoadOnce();
1698
1698
  DomainGraphQL_Server$ReventlessLocal.start(undefined, undefined, undefined);
1699
1699
  return DomainMCP_Server$ReventlessLocal.start(undefined, undefined);
1700
1700
  }
@@ -1795,7 +1795,7 @@ function MakeWithConfig(Config) {
1795
1795
  let tmp;
1796
1796
  tmp = apiTarget === "Domain" ? "Domain" : "Platform";
1797
1797
  log.info("Platform", undefined, `deployPlugin target=` + tmp);
1798
- UserStore$ReventlessLocal.pluginChecked.contents = true;
1798
+ AccountStore$ReventlessLocal.pluginChecked.contents = true;
1799
1799
  currentDeployTarget.contents = apiTarget;
1800
1800
  StateViewSliceMaker.QueryDbResolvers.serverRef.contents = resolveTargetGraphQL();
1801
1801
  let tmp$1;
@@ -1948,7 +1948,7 @@ function MakeWithConfig(Config) {
1948
1948
 
1949
1949
  function Make($star) {
1950
1950
  let backend = Backend$ReventlessLocal.fromEnv();
1951
- Role$Reventless.provideGroupsFrom(UserStore$ReventlessLocal.providedGroups);
1951
+ Role$Reventless.provideGroupsFrom(AccountStore$ReventlessLocal.providedGroups);
1952
1952
  TestRunner$ReventlessLocal.setup();
1953
1953
  if (typeof backend !== "object") {
1954
1954
  BackendState$ReventlessLocal.setMemory();
@@ -2945,7 +2945,7 @@ function Make($star) {
2945
2945
  });
2946
2946
  };
2947
2947
  let startServers = () => {
2948
- UserStore$ReventlessLocal.autoLoadOnce();
2948
+ AccountStore$ReventlessLocal.autoLoadOnce();
2949
2949
  DomainGraphQL_Server$ReventlessLocal.start(domainPort, undefined, undefined);
2950
2950
  DomainMCP_Server$ReventlessLocal.start(domainMcpPort, undefined);
2951
2951
  PlatformGraphQL_Server$ReventlessLocal.start(platformPort, Auth_GraphqlContext$ReventlessLocal.buildAuthContext, undefined);
@@ -3576,7 +3576,7 @@ function Make($star) {
3576
3576
  let tmp;
3577
3577
  tmp = apiTarget === "Domain" ? "Domain" : "Platform";
3578
3578
  log.info("Platform", undefined, `deployPlugin target=` + tmp);
3579
- UserStore$ReventlessLocal.pluginChecked.contents = true;
3579
+ AccountStore$ReventlessLocal.pluginChecked.contents = true;
3580
3580
  currentDeployTarget.contents = apiTarget;
3581
3581
  StateViewSliceMaker.QueryDbResolvers.serverRef.contents = resolveTargetGraphQL();
3582
3582
  let tmp$1;
@@ -1,13 +1,13 @@
1
1
  // In-memory user store loader. Hydrates `LocalAuth.Login.store` from
2
2
  // three resolution paths (first match wins):
3
- // 1. `~users` arg — explicit list passed by the caller
4
- // 2. `~usersFile` arg — explicit YAML path
5
- // 3. `.reventless/users.yaml` (relative to process.cwd()) — auto-discovery
3
+ // 1. `~accounts` arg — explicit list passed by the caller
4
+ // 2. `~accountsFile` arg — explicit YAML path
5
+ // 3. `.reventless/accounts.yaml` (relative to process.cwd()) — auto-discovery
6
6
  //
7
7
  // All three are silent on absence: when no path is provided and no default
8
8
  // file exists, the store stays empty and `LocalAuth.Login.issue` rejects
9
9
  // every credential. A one-line stdout hint is printed so developers know to
10
- // either set the file or pass `~users` programmatically.
10
+ // either set the file or pass `~accounts` programmatically.
11
11
 
12
12
  open Reventless
13
13
 
@@ -45,13 +45,13 @@ let _defaultPath = AccountsManifest.defaultPath
45
45
 
46
46
  /**
47
47
  * Hydrates the Login store. Returns the resolution path actually used
48
- * (`InlineUsers`, `UsersFile(path)`, `DefaultFile(path)`, or `Empty`).
48
+ * (`InlineAccounts`, `AccountsFile(path)`, `DefaultFile(path)`, or `Empty`).
49
49
  * Errors from a *resolved* path are returned as `Error`; absence of the
50
50
  * auto-discovered default file is silent.
51
51
  */
52
52
  type resolution =
53
- | InlineUsers
54
- | UsersFile(string)
53
+ | InlineAccounts
54
+ | AccountsFile(string)
55
55
  | DefaultFile(string)
56
56
  | Empty
57
57
 
@@ -79,29 +79,29 @@ makes it from). Never the working directory once another source was loaded.
79
79
  let providedGroups = (): array<string> =>
80
80
  LocalAuth.knownGroups()->Array.concat(resolved.contents ? [] : AccountsManifest.declaredGroups())
81
81
 
82
- let load = (~users: option<array<entry>>=?, ~usersFile: option<string>=?, ()): result<
82
+ let load = (~accounts: option<array<entry>>=?, ~accountsFile: option<string>=?, ()): result<
83
83
  resolution,
84
84
  string,
85
85
  > => {
86
86
  // The default file is what the check already read; any other source arrives
87
87
  // after it, and the check would have compared the plugins with other accounts.
88
- if pluginChecked.contents && (users->Option.isSome || usersFile->Option.isSome) {
88
+ if pluginChecked.contents && (accounts->Option.isSome || accountsFile->Option.isSome) {
89
89
  JsError.throwWithMessage(
90
- "UserStore.load(~users / ~usersFile) after a plugin was built — the check that every role it needs has a group read other accounts. Call UserStore.load before deploying plugins.",
90
+ "AccountStore.load(~accounts / ~accountsFile) after a plugin was built — the check that every role it needs has a group read other accounts. Call AccountStore.load before deploying plugins.",
91
91
  )
92
92
  }
93
93
  resolved := true
94
- switch users {
94
+ switch accounts {
95
95
  | Some(entries) =>
96
96
  _registerEntries(entries)
97
- Ok(InlineUsers)
97
+ Ok(InlineAccounts)
98
98
  | None =>
99
- switch usersFile {
99
+ switch accountsFile {
100
100
  | Some(path) =>
101
101
  parseFile(path)->Result.map(entries => {
102
102
  _registerEntries(entries)
103
103
  fromFile := entries->Array.map(e => e.username)
104
- UsersFile(path)
104
+ AccountsFile(path)
105
105
  })
106
106
  | None =>
107
107
  let defaultPath = _defaultPath()
@@ -113,7 +113,7 @@ let load = (~users: option<array<entry>>=?, ~usersFile: option<string>=?, ()): r
113
113
  })
114
114
  } else {
115
115
  Console.log(
116
- "[LocalAuth] no users configured — POST /__inmemory/login will reject all. " ++ "Provide ~users / ~usersFile or create .reventless/users.yaml relative to cwd.",
116
+ "[LocalAuth] no accounts configured — POST /__inmemory/login will reject all. " ++ "Provide ~accounts / ~accountsFile or create .reventless/accounts.yaml relative to cwd.",
117
117
  )
118
118
  Ok(Empty)
119
119
  }
@@ -212,14 +212,14 @@ let watch = (path: string): unit => {
212
212
 
213
213
  /**
214
214
  * Idempotent auto-discovery. Platform.startServers calls this before
215
- * `DomainGraphQL_Server.start`, so a `.reventless/users.yaml` in cwd
215
+ * `DomainGraphQL_Server.start`, so a `.reventless/accounts.yaml` in cwd
216
216
  * hydrates the Login store automatically, and follows the file from then on.
217
217
  * No-op once `load` has been called from anywhere.
218
218
  */
219
219
  let autoLoadOnce = (): unit =>
220
220
  if !resolved.contents {
221
221
  switch load() {
222
- | Ok(DefaultFile(path)) | Ok(UsersFile(path)) => watch(path)
222
+ | Ok(DefaultFile(path)) | Ok(AccountsFile(path)) => watch(path)
223
223
  | _ => ()
224
224
  }
225
225
  }
@@ -49,25 +49,25 @@ function providedGroups() {
49
49
  return LocalAuth$ReventlessLocal.knownGroups().concat(resolved.contents ? [] : AccountsManifest$Reventless.declaredGroups());
50
50
  }
51
51
 
52
- function load(users, usersFile, param) {
53
- if (pluginChecked.contents && (Stdlib_Option.isSome(users) || Stdlib_Option.isSome(usersFile))) {
54
- Stdlib_JsError.throwWithMessage("UserStore.load(~users / ~usersFile) after a plugin was built — the check that every role it needs has a group read other accounts. Call UserStore.load before deploying plugins.");
52
+ function load(accounts, accountsFile, param) {
53
+ if (pluginChecked.contents && (Stdlib_Option.isSome(accounts) || Stdlib_Option.isSome(accountsFile))) {
54
+ Stdlib_JsError.throwWithMessage("AccountStore.load(~accounts / ~accountsFile) after a plugin was built — the check that every role it needs has a group read other accounts. Call AccountStore.load before deploying plugins.");
55
55
  }
56
56
  resolved.contents = true;
57
- if (users !== undefined) {
58
- _registerEntries(users);
57
+ if (accounts !== undefined) {
58
+ _registerEntries(accounts);
59
59
  return {
60
60
  TAG: "Ok",
61
- _0: "InlineUsers"
61
+ _0: "InlineAccounts"
62
62
  };
63
63
  }
64
- if (usersFile !== undefined) {
65
- return Stdlib_Result.map(AccountsManifest$Reventless.parseFile(usersFile), entries => {
64
+ if (accountsFile !== undefined) {
65
+ return Stdlib_Result.map(AccountsManifest$Reventless.parseFile(accountsFile), entries => {
66
66
  _registerEntries(entries);
67
67
  fromFile.contents = entries.map(e => e.username);
68
68
  return {
69
- TAG: "UsersFile",
70
- _0: usersFile
69
+ TAG: "AccountsFile",
70
+ _0: accountsFile
71
71
  };
72
72
  });
73
73
  }
@@ -82,7 +82,7 @@ function load(users, usersFile, param) {
82
82
  };
83
83
  });
84
84
  } else {
85
- console.log("[LocalAuth] no users configured — POST /__inmemory/login will reject all. Provide ~users / ~usersFile or create .reventless/users.yaml relative to cwd.");
85
+ console.log("[LocalAuth] no accounts configured — POST /__inmemory/login will reject all. Provide ~accounts / ~accountsFile or create .reventless/accounts.yaml relative to cwd.");
86
86
  return {
87
87
  TAG: "Ok",
88
88
  _0: "Empty"
@@ -8,7 +8,7 @@
8
8
  // none of the above → Authenticated(defaultUser) (dev default)
9
9
  //
10
10
  // Stage A4 adds the `Login` submodule (token issuance + verification) and
11
- // the companion `UserStore` module (YAML hydration).
11
+ // the companion `AccountStore` module (YAML hydration).
12
12
 
13
13
  open Reventless
14
14
 
@@ -33,7 +33,7 @@ let adminUser = (): Identity.t => {
33
33
  // ── User registry ─────────────────────────────────────────────────────────
34
34
  //
35
35
  // A `dict<Identity.t>` keyed by `username`. A4 hydrates this from
36
- // `.reventless/users.yaml`; tests inject via `registerUser`. The built-in
36
+ // `.reventless/accounts.yaml`; tests inject via `registerUser`. The built-in
37
37
  // `admin` is answered on lookup, for the reason above, unless one is registered.
38
38
 
39
39
  let initialUsers = () => Dict.fromArray([("user", defaultUser)])
@@ -86,7 +86,7 @@ let getHeader = (headers: dict<string>, name: string): option<string> =>
86
86
  module Login = {
87
87
  type credentials = {password: string, identity: Identity.t}
88
88
 
89
- // Hydrated by `UserStore` at platform start; tests can inject directly.
89
+ // Hydrated by `AccountStore` at platform start; tests can inject directly.
90
90
  let store: ref<dict<credentials>> = ref(Dict.make())
91
91
 
92
92
  let setCredentials = (~username: string, ~password: string, ~identity: Identity.t): unit => {
@@ -127,13 +127,13 @@ module Login = {
127
127
  // that has no `.reventless/` to write to.
128
128
  //
129
129
  // The directory is used but never created. Its presence is what distinguishes
130
- // a platform someone develops against — `pnpm run setup` puts `users.yaml`
130
+ // a platform someone develops against — `pnpm run setup` puts `accounts.yaml`
131
131
  // there, so anything with logins to preserve has one — from a unit test, and
132
132
  // an auth module that made directories would leave one in every test's cwd.
133
133
  //
134
134
  // Local dev only, as the whole module is: these tokens are not security-grade
135
135
  // and AWS never sees them. The file sits in a gitignored directory beside
136
- // `users.yaml`, which already holds plaintext dev passwords.
136
+ // `accounts.yaml`, which already holds plaintext dev passwords.
137
137
 
138
138
  let _secretFileName = "token-secret"
139
139
  let _secretDir = (): string => NodePath.join([NodeProcess.cwd(), ".reventless"])
@@ -31,7 +31,7 @@ let registerMessagingSender = (sender: string) => messagingSenderRef := sender
31
31
  let identityProviderRef = ref(Reventless.Capabilities.none.identityProvider)
32
32
 
33
33
  /** Provision the identity provider. Called by `makePlatform` from the handle a
34
- root declared, `Capability_IdentityProvider_UserStore.make()`. */
34
+ root declared, `Capability_IdentityProvider_AccountStore.make()`. */
35
35
  let registerIdentityProvider = (provider: Reventless.IdentityProvider.t) =>
36
36
  identityProviderRef := provider
37
37
 
@@ -70,7 +70,7 @@ let unmetWarning = (~declared: array<(string, string)>): option<string> =>
70
70
  | Messaging =>
71
71
  `\n Messaging is \`Capability_Messaging_Log.make()\`, passed to the platform as ` ++ `\`~messagingSender\`.`
72
72
  | IdentityProvider =>
73
- `\n IdentityProvider is \`Capability_IdentityProvider_UserStore.make()\`, passed to the ` ++ `platform as \`~identityProvider\`.`
73
+ `\n IdentityProvider is \`Capability_IdentityProvider_AccountStore.make()\`, passed to the ` ++ `platform as \`~identityProvider\`.`
74
74
  // Never unmet here: the local platform always provisions one.
75
75
  | Stash => ``
76
76
  }
@@ -43,7 +43,7 @@ function unmetWarning(declared) {
43
43
  case "Messaging" :
44
44
  return `\n Messaging is \`Capability_Messaging_Log.make()\`, passed to the platform as \`~messagingSender\`.`;
45
45
  case "IdentityProvider" :
46
- return `\n IdentityProvider is \`Capability_IdentityProvider_UserStore.make()\`, passed to the platform as \`~identityProvider\`.`;
46
+ return `\n IdentityProvider is \`Capability_IdentityProvider_AccountStore.make()\`, passed to the platform as \`~identityProvider\`.`;
47
47
  case "Stash" :
48
48
  return ``;
49
49
  }
@@ -205,7 +205,7 @@ let deleteOffloadAll = (~root: string): int => {
205
205
  }
206
206
 
207
207
  // Removes the three trees, leaving the rest of the root (the database file, the
208
- // dev `users.yaml`) untouched.
208
+ // dev `accounts.yaml`) untouched.
209
209
  let reset = (~root: string): unit =>
210
210
  [objectsDir(~root), metaDir(~root), offloadDir(~root)]->Array.forEach(dir =>
211
211
  try NodeFs.rmSync(dir, {recursive: true, force: true}) catch {
@@ -4,7 +4,7 @@
4
4
  // `~identityProvider` in `~hostUiBundle`, and the platform puts it on the
5
5
  // capability record every slice's `translate` receives.
6
6
  //
7
- // Its store is `.reventless/users.yaml`, the file the in-memory auth adapter
7
+ // Its store is `.reventless/accounts.yaml`, the file the in-memory auth adapter
8
8
  // already loads at startup, so an account made here survives a restart with no
9
9
  // second store to keep in step. Every write goes to the file and to the live
10
10
  // `LocalAuth.Login` store together, so the running process and the next one
@@ -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"),
@@ -7,9 +7,9 @@ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
7
7
  import * as Stdlib_Result from "@rescript/runtime/lib/es6/Stdlib_Result.js";
8
8
  import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.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";
11
10
  import * as Auth_UserId$ReventlessCore from "@reventlessdev/reventless-core/src/adapter/Auth/Auth_UserId.res.mjs";
12
- import * as Capability_IdentityProvider_UserStore$ReventlessLocal from "../../src/capability/Capability_IdentityProvider_UserStore.res.mjs";
11
+ import * as AccountStore$ReventlessLocal from "../../src/adapter/Auth/AccountStore.res.mjs";
12
+ import * as Capability_IdentityProvider_AccountStore$ReventlessLocal from "../../src/capability/Capability_IdentityProvider_AccountStore.res.mjs";
13
13
 
14
14
  function email(address) {
15
15
  return {
@@ -20,18 +20,18 @@ function email(address) {
20
20
 
21
21
  function freshFile() {
22
22
  let dir = Nodefs.mkdtempSync(Nodepath.join(Nodeos.tmpdir(), "reventless-identity-"));
23
- return Nodepath.join(dir, ".reventless", "users.yaml");
23
+ return Nodepath.join(dir, ".reventless", "accounts.yaml");
24
24
  }
25
25
 
26
26
  function resetAll() {
27
27
  LocalAuth$ReventlessLocal.resetUsers();
28
28
  LocalAuth$ReventlessLocal.Login.resetStore();
29
- UserStore$ReventlessLocal.resetResolution();
29
+ AccountStore$ReventlessLocal.resetResolution();
30
30
  }
31
31
 
32
32
  function restartFrom(file) {
33
33
  resetAll();
34
- let message = UserStore$ReventlessLocal.load(undefined, file, undefined);
34
+ let message = AccountStore$ReventlessLocal.load(undefined, file, undefined);
35
35
  if (message.TAG === "Ok") {
36
36
  return;
37
37
  } else {
@@ -39,9 +39,9 @@ function restartFrom(file) {
39
39
  }
40
40
  }
41
41
 
42
- globalThis.describe("Capability_IdentityProvider_UserStore", () => {
42
+ globalThis.describe("Capability_IdentityProvider_AccountStore", () => {
43
43
  globalThis.test("publishes all four operations", () => {
44
- globalThis.expect(Capability_IdentityProvider_UserStore$ReventlessLocal.make(freshFile(), undefined).operations).toEqual([
44
+ globalThis.expect(Capability_IdentityProvider_AccountStore$ReventlessLocal.make(freshFile(), undefined).operations).toEqual([
45
45
  "CreatePrincipal",
46
46
  "AddToGroup",
47
47
  "RemoveFromGroup",
@@ -51,7 +51,7 @@ globalThis.describe("Capability_IdentityProvider_UserStore", () => {
51
51
  globalThis.test("a created principal can log in now and after a restart", async () => {
52
52
  resetAll();
53
53
  let file = freshFile();
54
- let provider = Capability_IdentityProvider_UserStore$ReventlessLocal.make(file, undefined);
54
+ let provider = Capability_IdentityProvider_AccountStore$ReventlessLocal.make(file, undefined);
55
55
  let created = await provider.createPrincipal({
56
56
  TAG: "ToEmail",
57
57
  _0: "new@example.com"
@@ -75,7 +75,7 @@ globalThis.describe("Capability_IdentityProvider_UserStore", () => {
75
75
  });
76
76
  globalThis.test("the same contact twice is a Conflict, not a second account", async () => {
77
77
  resetAll();
78
- let provider = Capability_IdentityProvider_UserStore$ReventlessLocal.make(freshFile(), undefined);
78
+ let provider = Capability_IdentityProvider_AccountStore$ReventlessLocal.make(freshFile(), undefined);
79
79
  let create = () => provider.createPrincipal({
80
80
  TAG: "ToEmail",
81
81
  _0: "twice@example.com"
@@ -88,7 +88,7 @@ globalThis.describe("Capability_IdentityProvider_UserStore", () => {
88
88
  });
89
89
  globalThis.test("NoCredential writes an account no password opens", async () => {
90
90
  resetAll();
91
- let provider = Capability_IdentityProvider_UserStore$ReventlessLocal.make(freshFile(), undefined);
91
+ let provider = Capability_IdentityProvider_AccountStore$ReventlessLocal.make(freshFile(), undefined);
92
92
  await provider.createPrincipal({
93
93
  TAG: "ToEmail",
94
94
  _0: "later@example.com"
@@ -97,7 +97,7 @@ globalThis.describe("Capability_IdentityProvider_UserStore", () => {
97
97
  globalThis.expect(Stdlib_Result.isOk(await LocalAuth$ReventlessLocal.Login.issue("later@example.com", "", undefined))).toBe(true);
98
98
  });
99
99
  globalThis.test("a push address is refused, since nothing signs in with one", async () => {
100
- let provider = Capability_IdentityProvider_UserStore$ReventlessLocal.make(freshFile(), undefined);
100
+ let provider = Capability_IdentityProvider_AccountStore$ReventlessLocal.make(freshFile(), undefined);
101
101
  let answer = await provider.createPrincipal({
102
102
  TAG: "ToPush",
103
103
  _0: {
@@ -117,7 +117,7 @@ globalThis.describe("Capability_IdentityProvider_UserStore", () => {
117
117
  globalThis.test("groups round-trip through the file", async () => {
118
118
  resetAll();
119
119
  let file = freshFile();
120
- let provider = Capability_IdentityProvider_UserStore$ReventlessLocal.make(file, undefined);
120
+ let provider = Capability_IdentityProvider_AccountStore$ReventlessLocal.make(file, undefined);
121
121
  let principal = {
122
122
  providerId: "grp@example.com"
123
123
  };
@@ -150,7 +150,7 @@ globalThis.describe("Capability_IdentityProvider_UserStore", () => {
150
150
  });
151
151
  globalThis.test("grouping a principal that does not exist is refused", async () => {
152
152
  resetAll();
153
- let provider = Capability_IdentityProvider_UserStore$ReventlessLocal.make(freshFile(), undefined);
153
+ let provider = Capability_IdentityProvider_AccountStore$ReventlessLocal.make(freshFile(), undefined);
154
154
  let answer = await provider.addToGroup({
155
155
  providerId: "ghost"
156
156
  }, "Shopper");
@@ -165,7 +165,7 @@ globalThis.describe("Capability_IdentityProvider_UserStore", () => {
165
165
  globalThis.test("deleting removes the account from the file and the login, twice", async () => {
166
166
  resetAll();
167
167
  let file = freshFile();
168
- let provider = Capability_IdentityProvider_UserStore$ReventlessLocal.make(file, undefined);
168
+ let provider = Capability_IdentityProvider_AccountStore$ReventlessLocal.make(file, undefined);
169
169
  let principal = {
170
170
  providerId: "gone@example.com"
171
171
  };
@@ -198,7 +198,7 @@ globalThis.describe("Capability_IdentityProvider_UserStore", () => {
198
198
  password: pw
199
199
  groups: [Admin]
200
200
  `, "utf8");
201
- let provider = Capability_IdentityProvider_UserStore$ReventlessLocal.make(file, undefined);
201
+ let provider = Capability_IdentityProvider_AccountStore$ReventlessLocal.make(file, undefined);
202
202
  await provider.createPrincipal({
203
203
  TAG: "ToEmail",
204
204
  _0: "c@example.com"
@@ -22,14 +22,14 @@ describe("LocalCapabilities.unmetWarning", () => {
22
22
  let message = LocalCapabilities.unmetWarning(~declared)->Option.getOr("")
23
23
  expect(message->String.includes("Geocoding (GeocodeAddress)"))->toBe(true)
24
24
  expect(message->String.includes("Capability_Messaging_Log.make()"))->toBe(true)
25
- expect(message->String.includes("Capability_IdentityProvider_UserStore.make()"))->toBe(true)
25
+ expect(message->String.includes("Capability_IdentityProvider_AccountStore.make()"))->toBe(true)
26
26
  })
27
27
 
28
28
  testSync("a registered provider leaves the warning", () => {
29
29
  reset()
30
30
  LocalCapabilities.registerMessagingSender("Shop <shop@example.test>")
31
31
  LocalCapabilities.registerIdentityProvider(
32
- Capability_IdentityProvider_UserStore.make(~path="/nonexistent/users.yaml", ()),
32
+ Capability_IdentityProvider_AccountStore.make(~path="/nonexistent/accounts.yaml", ()),
33
33
  )
34
34
  expect(LocalCapabilities.provisioned())->toEqual([
35
35
  Reventless.CapabilityNeed.Messaging,
@@ -3,7 +3,7 @@
3
3
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
4
4
  import * as Capabilities$Reventless from "@reventlessdev/reventless-spec/src/semantic/Capabilities.res.mjs";
5
5
  import * as LocalCapabilities$ReventlessLocal from "../../src/adapter/LocalCapabilities.res.mjs";
6
- import * as Capability_IdentityProvider_UserStore$ReventlessLocal from "../../src/capability/Capability_IdentityProvider_UserStore.res.mjs";
6
+ import * as Capability_IdentityProvider_AccountStore$ReventlessLocal from "../../src/capability/Capability_IdentityProvider_AccountStore.res.mjs";
7
7
 
8
8
  let declared = [
9
9
  [
@@ -32,12 +32,12 @@ globalThis.describe("LocalCapabilities.unmetWarning", () => {
32
32
  let message = Stdlib_Option.getOr(LocalCapabilities$ReventlessLocal.unmetWarning(declared), "");
33
33
  globalThis.expect(message.includes("Geocoding (GeocodeAddress)")).toBe(true);
34
34
  globalThis.expect(message.includes("Capability_Messaging_Log.make()")).toBe(true);
35
- globalThis.expect(message.includes("Capability_IdentityProvider_UserStore.make()")).toBe(true);
35
+ globalThis.expect(message.includes("Capability_IdentityProvider_AccountStore.make()")).toBe(true);
36
36
  });
37
37
  globalThis.test("a registered provider leaves the warning", () => {
38
38
  reset();
39
39
  LocalCapabilities$ReventlessLocal.registerMessagingSender("Shop <shop@example.test>");
40
- LocalCapabilities$ReventlessLocal.registerIdentityProvider(Capability_IdentityProvider_UserStore$ReventlessLocal.make("/nonexistent/users.yaml", undefined));
40
+ LocalCapabilities$ReventlessLocal.registerIdentityProvider(Capability_IdentityProvider_AccountStore$ReventlessLocal.make("/nonexistent/accounts.yaml", undefined));
41
41
  globalThis.expect(LocalCapabilities$ReventlessLocal.provisioned()).toEqual([
42
42
  "Messaging",
43
43
  "IdentityProvider",