@foir/sdk 0.21.0 → 0.23.0

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 (62) hide show
  1. package/CHANGELOG.md +135 -1
  2. package/README.md +15 -15
  3. package/dist/app/client.d.ts +93 -86
  4. package/dist/app/contract/proto/apps/v1/apps_pb.d.ts +14 -13
  5. package/dist/app/dispatch.d.ts +5 -5
  6. package/dist/app/errors.d.ts +17 -15
  7. package/dist/app/index.d.ts +4 -4
  8. package/dist/app/naming.d.ts +1 -1
  9. package/dist/app/ticket.d.ts +2 -2
  10. package/dist/app/vocabulary.generated.d.ts +2 -2
  11. package/dist/app-contract.js +3 -3
  12. package/dist/app.js +92 -90
  13. package/dist/auth/access.d.ts +19 -19
  14. package/dist/auth/auth.d.ts +251 -117
  15. package/dist/auth/grant-table.generated.d.ts +5 -4
  16. package/dist/auth/hosted.d.ts +38 -14
  17. package/dist/auth/index.d.ts +9 -9
  18. package/dist/auth/operations.d.ts +153 -33
  19. package/dist/auth/ops.d.ts +39 -21
  20. package/dist/auth/session-client.d.ts +3 -3
  21. package/dist/auth-session.js +3 -3
  22. package/dist/auth.js +400 -250
  23. package/dist/client.js +5 -8
  24. package/dist/codegen/preset.d.ts +1 -1
  25. package/dist/data/builtins.d.ts +26 -26
  26. package/dist/data/client.d.ts +3 -3
  27. package/dist/data/decimal.d.ts +1 -1
  28. package/dist/data/index.d.ts +1 -1
  29. package/dist/data/manifest.d.ts +1 -1
  30. package/dist/data/schema.d.ts +2 -2
  31. package/dist/data/transport.d.ts +14 -13
  32. package/dist/data/ws-transport.d.ts +1 -1
  33. package/dist/data.js +8 -11
  34. package/dist/graphql/content-client.d.ts +13 -13
  35. package/dist/index.js +1 -4
  36. package/dist/live/drift.d.ts +1 -1
  37. package/dist/media/screen-capture.d.ts +1 -1
  38. package/dist/next/index.d.ts +2 -2
  39. package/dist/next/session.d.ts +10 -10
  40. package/dist/next.js +78 -60
  41. package/dist/placement/index.d.ts +13 -13
  42. package/dist/placement.js +127 -116
  43. package/dist/push.js +62 -44
  44. package/dist/react/FoirFeedback.d.ts +2 -2
  45. package/dist/react/FoirProvider.d.ts +24 -24
  46. package/dist/react/SignIn.d.ts +4 -4
  47. package/dist/react/UserButton.d.ts +1 -1
  48. package/dist/react/feedback-notes.d.ts +8 -6
  49. package/dist/react/index.d.ts +3 -3
  50. package/dist/react.js +238 -209
  51. package/dist/realtime/index.d.ts +1 -1
  52. package/dist/server/callback-client.d.ts +4 -4
  53. package/dist/server/events-client.d.ts +21 -21
  54. package/dist/server/operation-types.d.ts +8 -8
  55. package/dist/server/require-scoped-token.d.ts +3 -3
  56. package/dist/server/types.d.ts +2 -2
  57. package/dist/server/verify-scoped-token.d.ts +3 -3
  58. package/dist/server.js +130 -126
  59. package/dist/transport/foir-http.d.ts +14 -14
  60. package/dist/transport/key-kind.d.ts +1 -12
  61. package/dist/types/index.d.ts +2 -2
  62. package/package.json +1 -1
package/dist/react.js CHANGED
@@ -18,10 +18,7 @@ import { print as print2 } from "graphql";
18
18
  var KEY_PREFIXES = [
19
19
  ["foir_pub_", "publishable"],
20
20
  ["foir_srv_", "server"],
21
- ["foir_adm_", "admin"],
22
- ["pk_", "publishable"],
23
- ["sk_", "older"],
24
- ["tc_", "older"]
21
+ ["foir_adm_", "admin"]
25
22
  ];
26
23
  function foirKeyKind(apiKey) {
27
24
  if (typeof apiKey !== "string") return void 0;
@@ -205,8 +202,8 @@ var FoirAuthDowngradedError = class extends FoirRequestError {
205
202
  downgrade;
206
203
  constructor(downgrade) {
207
204
  super(
208
- `[foir] your customer token was ${downgrade.customerToken} (${downgrade.reason}), so the request was served as ${downgrade.servedAs}`,
209
- { graphQLErrors: [{ message: "customer token rejected", extensions: { code: "AUTH_DOWNGRADED" } }] }
205
+ `[foir] your user token was ${downgrade.userToken} (${downgrade.reason}), so the request was served as ${downgrade.servedAs}`,
206
+ { graphQLErrors: [{ message: "user token rejected", extensions: { code: "AUTH_DOWNGRADED" } }] }
210
207
  );
211
208
  this.name = "FoirAuthDowngradedError";
212
209
  this.downgrade = downgrade;
@@ -214,7 +211,7 @@ var FoirAuthDowngradedError = class extends FoirRequestError {
214
211
  };
215
212
  var FoirSessionExpiredError = class extends FoirRequestError {
216
213
  constructor(options) {
217
- super("[foir] the customer session has expired and could not be refreshed: sign in again", {
214
+ super("[foir] the user session has expired and could not be refreshed: sign in again", {
218
215
  cause: options?.cause,
219
216
  graphQLErrors: [{ message: "session expired", extensions: { code: "SESSION_EXPIRED" } }]
220
217
  });
@@ -231,7 +228,7 @@ function reportAuthDowngrade(envelope) {
231
228
  if (warnedDowngrade === downgrade.reason) return;
232
229
  warnedDowngrade = downgrade.reason;
233
230
  console.warn(
234
- `[foir] your customer token was ${downgrade.customerToken} (${downgrade.reason}) \u2014 this request was served as ${downgrade.servedAs}, so auth-targeted content resolved to its anonymous variant. ` + (downgrade.reason === "expired" ? "Re-exchange the token and retry." : "Check which credential you are sending.")
231
+ `[foir] your user token was ${downgrade.userToken} (${downgrade.reason}) \u2014 this request was served as ${downgrade.servedAs}, so auth-targeted content resolved to its anonymous variant. ` + (downgrade.reason === "expired" ? "Re-exchange the token and retry." : "Check which credential you are sending.")
235
232
  );
236
233
  }
237
234
  function refusePrunedDocument(json, options) {
@@ -950,42 +947,63 @@ var AUTH_OPS = {
950
947
  authConfig: "authConfig",
951
948
  authProviders: "authProviders",
952
949
  defaultAuthProvider: "defaultAuthProvider",
953
- customerSignupContext: "customerSignupContext",
950
+ signupContext: "signupContext",
954
951
  // Post-credential self reads.
955
952
  currentUser: "currentUser",
956
953
  myProviderToken: "myProviderToken",
957
- // What the calling credential may do, and for a signed-in customer the roles
954
+ // What the calling credential may do, and for a signed-in user the roles
958
955
  // they hold. `./access` reads it.
959
956
  whoami: "whoami",
960
957
  // Methods.
961
- customerLogin: "customerLogin",
962
- customerRegister: "customerRegister",
963
- customerRequestOTP: "customerRequestOTP",
964
- customerLoginOTP: "customerLoginOTP",
958
+ login: "login",
959
+ register: "register",
960
+ requestOTP: "requestOTP",
961
+ loginWithOTP: "loginWithOTP",
965
962
  // Session lifecycle.
966
- customerRefreshToken: "customerRefreshToken",
967
- customerLogout: "customerLogout",
968
- customerJoinWaitlist: "customerJoinWaitlist",
969
- // Password management and account lifecycle — the block that had no path.
970
- customerRequestPasswordReset: "customerRequestPasswordReset",
971
- customerResetPassword: "customerResetPassword",
972
- customerUpdatePassword: "customerUpdatePassword",
973
- customerVerifyEmail: "customerVerifyEmail",
963
+ refreshToken: "refreshToken",
964
+ logout: "logout",
965
+ joinWaitlist: "joinWaitlist",
966
+ // Password management and account lifecycle.
967
+ requestPasswordReset: "requestPasswordReset",
968
+ resetPassword: "resetPassword",
969
+ updatePassword: "updatePassword",
970
+ verifyEmail: "verifyEmail",
974
971
  deleteMyAccount: "deleteMyAccount",
975
- // The operator's organization context. TWO ops and no third: one to read
976
- // which organizations the caller may stand in, one to say which. There is
977
- // deliberately no per-call org argument anywhere in this SDK — the claim the
978
- // row layer reads is resolved from the caller's own membership row on every
979
- // request, so an application that never names an org cannot name the wrong
980
- // one.
972
+ // The user's own profile, and the apps they have agreed may act for them.
973
+ updateMyProfile: "updateMyProfile",
974
+ myAuthorizedApps: "myAuthorizedApps",
975
+ revokeAuthorizedApp: "revokeAuthorizedApp",
976
+ // Where they are signed in, their personal access tokens, and the
977
+ // providers they sign in with.
978
+ mySessions: "mySessions",
979
+ endMySession: "endMySession",
980
+ signOutEverywhere: "signOutEverywhere",
981
+ createPersonalAccessToken: "createPersonalAccessToken",
982
+ mySignInMethods: "mySignInMethods",
983
+ connectSignInMethod: "connectSignInMethod",
984
+ disconnectSignInMethod: "disconnectSignInMethod",
985
+ // Their second factors. A change needs one proven first, by a step-up.
986
+ myFactors: "myFactors",
987
+ beginStepUp: "beginStepUp",
988
+ completeStepUp: "completeStepUp",
989
+ beginFactorEnrollment: "beginFactorEnrollment",
990
+ completeFactorEnrollment: "completeFactorEnrollment",
991
+ removeFactor: "removeFactor",
992
+ makeRecoveryCodes: "makeRecoveryCodes",
993
+ // The organizations the caller may stand in. Nothing selects one: a request
994
+ // names the organization it acts in (`orgId` or `orgUrl` below), and the
995
+ // platform checks the caller stands there every time.
981
996
  myOrganizations: "myOrganizations",
982
- selectMyOrganization: "selectMyOrganization",
983
997
  // Founding one. Present in a manifest only when the project opted in.
984
- registerOperatorOrganization: "registerOperatorOrganization",
998
+ registerOrganization: "registerOrganization",
985
999
  // External identity providers.
986
- customerLoginWithProvider: "customerLoginWithProvider",
987
- customerProviderCallback: "customerProviderCallback",
988
- customerProviderVerifyOTP: "customerProviderVerifyOTP"
1000
+ loginWithProvider: "loginWithProvider",
1001
+ providerCallback: "providerCallback",
1002
+ providerVerifyOTP: "providerVerifyOTP",
1003
+ // A provider sign-in that names an address somebody already holds, waiting
1004
+ // for the code sent to it.
1005
+ confirmProviderLink: "confirmProviderLink",
1006
+ resendProviderLinkCode: "resendProviderLinkCode"
989
1007
  };
990
1008
  function authClientConfig(env, options) {
991
1009
  const apiKey = resolveFoirApiKey(env);
@@ -1048,28 +1066,28 @@ function stripUndefined(args) {
1048
1066
  // src/auth/auth.ts
1049
1067
  var TOKEN_KEY = "foir:token";
1050
1068
  var REFRESH_KEY = "foir:refreshToken";
1051
- var CUSTOMER_ID_KEY = "foir:customerId";
1069
+ var USER_ID_KEY = "foir:userId";
1052
1070
  var EMAIL_KEY = "foir:email";
1053
- async function customerLogin(env, vars) {
1054
- return authOp(env, AUTH_OPS.customerLogin, vars);
1071
+ async function login(env, vars) {
1072
+ return authOp(env, AUTH_OPS.login, vars);
1055
1073
  }
1056
- async function customerRegister(env, vars) {
1057
- return authOp(env, AUTH_OPS.customerRegister, vars);
1074
+ async function register(env, vars) {
1075
+ return authOp(env, AUTH_OPS.register, vars);
1058
1076
  }
1059
- async function customerRequestOTP(env, email) {
1060
- return authOp(env, AUTH_OPS.customerRequestOTP, { email });
1077
+ async function requestOTP(env, email) {
1078
+ return authOp(env, AUTH_OPS.requestOTP, { email });
1061
1079
  }
1062
- async function customerLoginOTP(env, vars) {
1063
- return authOp(env, AUTH_OPS.customerLoginOTP, vars);
1080
+ async function loginWithOTP(env, vars) {
1081
+ return authOp(env, AUTH_OPS.loginWithOTP, vars);
1064
1082
  }
1065
- async function customerRefreshToken(env, refreshToken) {
1066
- return authOp(env, AUTH_OPS.customerRefreshToken, { refreshToken });
1083
+ async function refreshTokens(env, refreshToken) {
1084
+ return authOp(env, AUTH_OPS.refreshToken, { refreshToken });
1067
1085
  }
1068
- async function customerLoginWithProvider(env, input) {
1069
- return authOp(env, AUTH_OPS.customerLoginWithProvider, { input });
1086
+ async function loginWithProvider(env, input) {
1087
+ return authOp(env, AUTH_OPS.loginWithProvider, { input });
1070
1088
  }
1071
- async function customerProviderCallback(env, input) {
1072
- return authOp(env, AUTH_OPS.customerProviderCallback, { input });
1089
+ async function providerCallback(env, input) {
1090
+ return authOp(env, AUTH_OPS.providerCallback, { input });
1073
1091
  }
1074
1092
  async function getAuthProviders(env) {
1075
1093
  return authOp(env, AUTH_OPS.authProviders);
@@ -1077,42 +1095,42 @@ async function getAuthProviders(env) {
1077
1095
  async function saveSession(adapter, result) {
1078
1096
  await adapter.set(TOKEN_KEY, result.token);
1079
1097
  await adapter.set(REFRESH_KEY, result.refreshToken);
1080
- if (!result.customerId) {
1081
- return await getSessionCustomer(adapter) ?? { id: "", email: "" };
1098
+ if (!result.userId) {
1099
+ return await getSessionUser(adapter) ?? { id: "", email: "" };
1082
1100
  }
1083
- await adapter.set(CUSTOMER_ID_KEY, result.customerId);
1101
+ await adapter.set(USER_ID_KEY, result.userId);
1084
1102
  await adapter.set(EMAIL_KEY, result.email);
1085
- return { id: result.customerId, email: result.email };
1103
+ return { id: result.userId, email: result.email };
1086
1104
  }
1087
1105
  async function clearSession(adapter) {
1088
1106
  await adapter.unset(TOKEN_KEY);
1089
1107
  await adapter.unset(REFRESH_KEY);
1090
- await adapter.unset(CUSTOMER_ID_KEY);
1108
+ await adapter.unset(USER_ID_KEY);
1091
1109
  await adapter.unset(EMAIL_KEY);
1092
1110
  }
1093
1111
  async function getSessionToken(adapter) {
1094
1112
  return await adapter.get(TOKEN_KEY) ?? null;
1095
1113
  }
1096
- async function getSessionCustomer(adapter) {
1097
- const id = await adapter.get(CUSTOMER_ID_KEY) ?? null;
1114
+ async function getSessionUser(adapter) {
1115
+ const id = await adapter.get(USER_ID_KEY) ?? null;
1098
1116
  const email = await adapter.get(EMAIL_KEY) ?? null;
1099
1117
  if (!id) return null;
1100
1118
  return { id, email: email ?? "" };
1101
1119
  }
1102
- async function loginWithPassword(adapter, env, vars) {
1103
- return saveSession(adapter, await customerLogin(env, vars));
1120
+ async function signInWithPassword(adapter, env, vars) {
1121
+ return saveSession(adapter, await login(env, vars));
1104
1122
  }
1105
- async function registerWithPassword(adapter, env, vars) {
1106
- return saveSession(adapter, await customerRegister(env, vars));
1123
+ async function signUpWithPassword(adapter, env, vars) {
1124
+ return saveSession(adapter, await register(env, vars));
1107
1125
  }
1108
- async function loginWithOTP(adapter, env, vars) {
1109
- return saveSession(adapter, await customerLoginOTP(env, vars));
1126
+ async function signInWithOTP(adapter, env, vars) {
1127
+ return saveSession(adapter, await loginWithOTP(env, vars));
1110
1128
  }
1111
1129
  async function refreshSession(adapter, env) {
1112
1130
  const refreshToken = await adapter.get(REFRESH_KEY) ?? null;
1113
1131
  if (!refreshToken) return null;
1114
1132
  try {
1115
- const result = await customerRefreshToken(env, refreshToken);
1133
+ const result = await refreshTokens(env, refreshToken);
1116
1134
  await saveSession(adapter, result);
1117
1135
  return { token: result.token, refreshToken: result.refreshToken };
1118
1136
  } catch {
@@ -1179,122 +1197,125 @@ async function authedOp(adapter, env, op, args) {
1179
1197
 
1180
1198
  // src/auth/grant-table.generated.ts
1181
1199
  var GRANT_TABLE = [
1182
- ["records:read", true, ["own", "all"], []],
1183
- ["records:create", true, [], []],
1184
- ["records:write", true, ["own", "all"], []],
1185
- ["records:delete", true, ["own", "all"], []],
1186
- ["records:publish", true, ["own", "all"], []],
1187
- ["records:attribute", true, [], []],
1188
- ["search:read", true, [], []],
1189
- ["embeddings:read", false, [], []],
1190
- ["embeddings:write", false, [], []],
1191
- ["schemas:read", false, [], []],
1192
- ["drafts:read", false, [], []],
1193
- ["files:read", false, ["own", "all"], []],
1194
- ["files:write", false, ["own", "all"], []],
1195
- ["files:delete", false, ["own", "all"], []],
1196
- ["notifications:read", false, ["own", "all"], []],
1197
- ["notifications:write", false, ["own", "named", "all"], []],
1198
- ["notifications:consent", false, [], []],
1199
- ["pushcredentials:read", false, [], []],
1200
- ["pushcredentials:write", false, [], []],
1201
- ["notes:read", false, ["own", "all"], []],
1202
- ["notes:write", false, ["own", "all"], []],
1203
- ["notes:create", false, [], []],
1204
- ["approvals:read", false, [], []],
1205
- ["approvals:write", false, [], []],
1206
- ["rooms:read", true, [], []],
1207
- ["rooms:write", true, [], []],
1208
- ["presence:read", true, [], []],
1209
- ["operations:read", false, [], []],
1210
- ["operations:execute", true, [], []],
1211
- ["operations:write", false, [], []],
1212
- ["operations:complete", false, [], []],
1213
- ["status:write", false, [], []],
1214
- ["appconfig:read", false, [], []],
1215
- ["schedules:read", false, [], []],
1216
- ["schedules:write", false, [], []],
1217
- ["hooks:read", false, [], []],
1218
- ["hooks:write", false, [], []],
1219
- ["relyingparties:read", false, [], []],
1220
- ["relyingparties:write", false, [], []],
1221
- ["domains:read", false, [], []],
1222
- ["domains:write", false, [], []],
1223
- ["secrets:read", false, [], []],
1224
- ["secrets:list", false, [], []],
1225
- ["secrets:put", false, [], []],
1226
- ["secrets:delete", false, [], []],
1227
- ["appsecrets:read", false, [], []],
1228
- ["appsecrets:list", false, [], []],
1229
- ["appsecrets:put", false, [], []],
1230
- ["appsecrets:delete", false, [], []],
1231
- ["opsecrets:read", false, [], []],
1232
- ["opsecrets:write", false, [], []],
1233
- ["settings:read", false, [], []],
1234
- ["settings:write", false, [], []],
1235
- ["designtokens:read", false, [], []],
1236
- ["designtokens:write", false, [], []],
1237
- ["models:read", false, [], []],
1238
- ["models:write", false, [], []],
1239
- ["configs:read", false, [], []],
1240
- ["configs:write", false, [], []],
1241
- ["apps:read", false, [], []],
1242
- ["apps:write", false, [], []],
1243
- ["events:read", false, [], []],
1244
- ["targeting:debug", false, [], []],
1245
- ["visitors:forward", false, [], []],
1246
- ["apikeys:read", false, [], []],
1247
- ["apikeys:write", false, [], []],
1248
- ["organizations:read", false, [], []],
1249
- ["organizations:write", false, [], []],
1250
- ["organizations:create", false, [], []],
1251
- ["organizations:delete", false, [], []],
1252
- ["organizations:reach", false, [], []],
1253
- ["members:read", false, [], []],
1254
- ["members:write", false, [], []],
1255
- ["roles:read", false, [], []],
1256
- ["roles:write", false, [], []],
1257
- ["projects:read", false, [], []],
1258
- ["projects:write", false, [], []],
1259
- ["project:manage", false, [], ["records:read.all", "records:create", "records:write.all", "records:delete.all", "records:publish.all", "records:attribute", "search:read", "embeddings:read", "embeddings:write", "schemas:read", "drafts:read", "files:read.all", "files:write.all", "files:delete.all", "users:read.all", "identities:read", "users:create", "identities:delete", "users:write.all", "users:delete.all", "notifications:read.all", "notifications:write.all", "notifications:consent", "pushcredentials:read", "pushcredentials:write", "notes:read.all", "notes:write.all", "notes:create", "approvals:read", "approvals:write", "rooms:read", "rooms:write", "presence:read", "operations:read", "operations:execute", "operations:write", "appconfig:read", "schedules:read", "schedules:write", "hooks:read", "hooks:write", "auth:login_with_foir", "relyingparties:read", "relyingparties:write", "domains:read", "domains:write", "secrets:read", "secrets:list", "secrets:put", "secrets:delete", "appsecrets:read", "appsecrets:list", "appsecrets:put", "appsecrets:delete", "usersecrets:read", "usersecrets:list", "usersecrets:put", "usersecrets:delete", "opsecrets:read", "opsecrets:write", "settings:read", "settings:write", "designtokens:read", "designtokens:write", "models:read", "models:write", "configs:read", "configs:write", "signinproviders:read", "signinproviders:write", "apps:read", "apps:write", "events:read", "targeting:debug", "visitors:forward", "apikeys:read", "apikeys:write", "organizations:read", "organizations:create", "organizations:delete", "organizations:write", "organizations:reach", "members:read", "members:write", "roles:read", "roles:write", "projects:read", "projects:write", "audit:read"]],
1260
- ["projects:create", false, [], []],
1261
- ["projects:delete", false, [], []],
1262
- ["tenants:read", false, [], []],
1263
- ["tenants:write", false, [], []],
1264
- ["tenants:delete", false, [], []],
1265
- ["audit:read", false, [], []],
1266
- ["export:run", false, [], []],
1267
- ["billing:read", false, [], []],
1268
- ["billing:manage", false, [], []],
1269
- ["usage:read", false, [], []],
1270
- ["controlkeys:read", false, [], []],
1271
- ["controlkeys:write", false, [], []],
1272
- ["tenanthooks:read", false, [], []],
1273
- ["tenanthooks:write", false, [], []],
1274
- ["apps:install", false, [], []],
1275
- ["tenant:manage", false, [], ["project:manage", "projects:create", "projects:delete", "tenants:read", "tenants:write", "tenants:delete", "export:run", "billing:read", "billing:manage", "usage:read", "controlkeys:read", "controlkeys:write", "tenanthooks:read", "tenanthooks:write", "apps:install"]],
1276
- ["platform:read", false, [], []],
1277
- ["platform:manage", false, [], ["tenant:manage", "platform:read", "platform:create_workspace", "users:setup"]],
1278
- ["platform:create_workspace", false, [], []],
1279
- ["users:read", false, ["own", "named", "all"], []],
1280
- ["users:write", false, ["own", "all"], []],
1281
- ["users:setup", false, [], []],
1282
- ["users:delete", false, ["own", "all"], []],
1283
- ["users:create", false, [], []],
1284
- ["identities:read", false, [], []],
1285
- ["identities:delete", false, [], []],
1286
- ["usersecrets:read", false, [], []],
1287
- ["usersecrets:list", false, [], []],
1288
- ["usersecrets:put", false, [], []],
1289
- ["usersecrets:delete", false, [], []],
1290
- ["auth:login_with_foir", false, [], []],
1291
- ["signinproviders:read", false, [], []],
1292
- ["signinproviders:write", false, [], []]
1200
+ ["records:read", "model", ["own", "all"], []],
1201
+ ["records:create", "model", [], []],
1202
+ ["records:write", "model", ["own", "all"], []],
1203
+ ["records:delete", "model", ["own", "all"], []],
1204
+ ["records:publish", "model", ["own", "all"], []],
1205
+ ["records:attribute", "model", [], []],
1206
+ ["search:read", "model", [], []],
1207
+ ["embeddings:read", "none", [], []],
1208
+ ["embeddings:write", "none", [], []],
1209
+ ["schemas:read", "none", [], []],
1210
+ ["drafts:read", "none", [], []],
1211
+ ["files:read", "none", ["own", "all"], []],
1212
+ ["files:write", "none", ["own", "all"], []],
1213
+ ["files:delete", "none", ["own", "all"], []],
1214
+ ["notifications:read", "none", ["own", "all"], []],
1215
+ ["notifications:write", "none", ["own", "named", "all"], []],
1216
+ ["notifications:consent", "none", [], []],
1217
+ ["pushcredentials:read", "none", [], []],
1218
+ ["pushcredentials:write", "none", [], []],
1219
+ ["notes:read", "none", ["own", "all"], []],
1220
+ ["notes:write", "none", ["own", "all"], []],
1221
+ ["notes:create", "none", [], []],
1222
+ ["approvals:read", "none", [], []],
1223
+ ["approvals:write", "none", [], []],
1224
+ ["rooms:read", "model", [], []],
1225
+ ["rooms:write", "model", [], []],
1226
+ ["presence:read", "model", [], []],
1227
+ ["operations:read", "none", [], []],
1228
+ ["operations:execute", "operation", [], []],
1229
+ ["operations:write", "none", [], []],
1230
+ ["operations:complete", "none", [], []],
1231
+ ["status:write", "none", [], []],
1232
+ ["appconfig:read", "none", [], []],
1233
+ ["schedules:read", "none", [], []],
1234
+ ["schedules:write", "none", [], []],
1235
+ ["hooks:read", "none", [], []],
1236
+ ["hooks:write", "none", [], []],
1237
+ ["authclients:read", "none", [], []],
1238
+ ["authclients:write", "none", [], []],
1239
+ ["domains:read", "none", [], []],
1240
+ ["domains:write", "none", [], []],
1241
+ ["secrets:read", "none", [], []],
1242
+ ["secrets:list", "none", [], []],
1243
+ ["secrets:put", "none", [], []],
1244
+ ["secrets:delete", "none", [], []],
1245
+ ["appsecrets:read", "none", [], []],
1246
+ ["appsecrets:list", "none", [], []],
1247
+ ["appsecrets:put", "none", [], []],
1248
+ ["appsecrets:delete", "none", [], []],
1249
+ ["opsecrets:read", "none", [], []],
1250
+ ["opsecrets:write", "none", [], []],
1251
+ ["settings:read", "none", [], []],
1252
+ ["settings:write", "none", [], []],
1253
+ ["designtokens:read", "none", [], []],
1254
+ ["designtokens:write", "none", [], []],
1255
+ ["models:read", "none", [], []],
1256
+ ["models:write", "none", [], []],
1257
+ ["configs:read", "none", [], []],
1258
+ ["configs:write", "none", [], []],
1259
+ ["apps:read", "none", [], []],
1260
+ ["apps:write", "none", [], []],
1261
+ ["events:read", "none", [], []],
1262
+ ["targeting:debug", "none", [], []],
1263
+ ["visitors:forward", "none", [], []],
1264
+ ["apikeys:read", "none", [], []],
1265
+ ["apikeys:write", "none", [], []],
1266
+ ["organizations:read", "none", [], []],
1267
+ ["organizations:write", "none", [], []],
1268
+ ["organizations:create", "none", [], []],
1269
+ ["organizations:delete", "none", [], []],
1270
+ ["organizations:reach", "none", [], []],
1271
+ ["members:read", "none", [], []],
1272
+ ["members:write", "none", [], []],
1273
+ ["roles:read", "none", [], []],
1274
+ ["roles:write", "none", [], []],
1275
+ ["projects:read", "none", [], []],
1276
+ ["projects:write", "none", [], []],
1277
+ ["project:stand", "none", [], []],
1278
+ ["project:manage", "none", [], ["project:stand", "records:read.all", "records:create", "records:write.all", "records:delete.all", "records:publish.all", "records:attribute", "search:read", "embeddings:read", "embeddings:write", "schemas:read", "drafts:read", "files:read.all", "files:write.all", "files:delete.all", "users:read.all", "identities:read", "users:create", "identities:delete", "users:write.all", "users:setup", "users:delete.all", "notifications:read.all", "notifications:write.all", "notifications:consent", "pushcredentials:read", "pushcredentials:write", "notes:read.all", "notes:write.all", "notes:create", "approvals:read", "approvals:write", "rooms:read", "rooms:write", "presence:read", "operations:read", "operations:execute", "operations:write", "appconfig:read", "schedules:read", "schedules:write", "hooks:read", "hooks:write", "auth:login_with_foir", "authclients:read", "authclients:write", "domains:read", "domains:write", "secrets:read", "secrets:list", "secrets:put", "secrets:delete", "appsecrets:read", "appsecrets:list", "appsecrets:put", "appsecrets:delete", "usersecrets:read", "usersecrets:list", "usersecrets:put", "usersecrets:delete", "opsecrets:read", "opsecrets:write", "settings:read", "settings:write", "designtokens:read", "designtokens:write", "models:read", "models:write", "configs:read", "configs:write", "signinproviders:read", "signinproviders:write", "apps:read", "apps:write", "events:read", "targeting:debug", "visitors:forward", "apikeys:read", "apikeys:write", "organizations:read", "organizations:create", "organizations:delete", "organizations:write", "organizations:reach", "members:read", "members:write", "roles:read", "roles:write", "projects:read", "projects:write", "audit:read"]],
1279
+ ["projects:create", "none", [], []],
1280
+ ["projects:delete", "none", [], []],
1281
+ ["tenants:read", "none", [], []],
1282
+ ["tenants:write", "none", [], []],
1283
+ ["tenants:delete", "none", [], []],
1284
+ ["audit:read", "none", [], []],
1285
+ ["export:run", "none", [], []],
1286
+ ["billing:read", "none", [], []],
1287
+ ["billing:manage", "none", [], []],
1288
+ ["usage:read", "none", [], []],
1289
+ ["controlkeys:read", "none", [], []],
1290
+ ["controlkeys:write", "none", [], []],
1291
+ ["tenanthooks:read", "none", [], []],
1292
+ ["tenanthooks:write", "none", [], []],
1293
+ ["apps:install", "none", [], []],
1294
+ ["tenant:manage", "none", [], ["project:manage", "projects:create", "projects:delete", "tenants:read", "tenants:write", "tenants:delete", "export:run", "billing:read", "billing:manage", "usage:read", "controlkeys:read", "controlkeys:write", "tenanthooks:read", "tenanthooks:write", "apps:install"]],
1295
+ ["platform:read", "none", [], []],
1296
+ ["platform:manage", "none", [], ["tenant:manage", "platform:read", "platform:create_workspace"]],
1297
+ ["platform:create_workspace", "none", [], []],
1298
+ ["users:read", "none", ["own", "named", "all"], []],
1299
+ ["users:write", "none", ["own", "all"], []],
1300
+ ["users:setup", "none", [], []],
1301
+ ["users:delete", "none", ["own", "all"], []],
1302
+ ["users:create", "none", [], []],
1303
+ ["identities:read", "none", [], []],
1304
+ ["identities:delete", "none", [], []],
1305
+ ["usersecrets:read", "none", [], []],
1306
+ ["usersecrets:list", "none", [], []],
1307
+ ["usersecrets:put", "none", [], []],
1308
+ ["usersecrets:delete", "none", [], []],
1309
+ ["auth:login_with_foir", "none", [], []],
1310
+ ["signinproviders:read", "none", [], []],
1311
+ ["signinproviders:write", "none", [], []]
1293
1312
  ];
1294
1313
 
1295
1314
  // src/auth/grants.ts
1296
1315
  var WILDCARD = "*";
1297
1316
  var RESOURCE_WILDCARD = ":*";
1317
+ var FIELD_PERMISSIONS = ["records:read", "records:write"];
1318
+ var FIELD_KEY = /^[A-Za-z_][A-Za-z0-9_]*$/;
1298
1319
  var index;
1299
1320
  function catalogue() {
1300
1321
  if (!index) {
@@ -1335,15 +1356,23 @@ function parseGrant(s) {
1335
1356
  let target = "";
1336
1357
  if (rest.startsWith(":")) {
1337
1358
  target = rest.slice(1);
1338
- if (!permission[1]) return null;
1359
+ if (permission[1] === "none") return null;
1339
1360
  if (target === "" || /[: \t\n*]/.test(target)) return null;
1361
+ const dot = target.indexOf(".");
1362
+ if (permission[1] === "model" && dot >= 0) {
1363
+ if (!FIELD_PERMISSIONS.includes(name) || dot === 0 || !FIELD_KEY.test(target.slice(dot + 1))) return null;
1364
+ }
1340
1365
  }
1341
1366
  return { permission, reach, target };
1342
1367
  }
1343
1368
  return null;
1344
1369
  }
1345
1370
  function covers(held, required) {
1346
- return held.permission === required.permission && reachRank[held.reach] >= reachRank[required.reach] && (held.target === "" || held.target === required.target);
1371
+ if (held.permission !== required.permission || reachRank[held.reach] < reachRank[required.reach]) return false;
1372
+ if (required.permission[1] === "model" && required.target.includes(".")) {
1373
+ return held.target === required.target || held.target === "" && held.reach === "all";
1374
+ }
1375
+ return held.target === "" || held.target === required.target;
1347
1376
  }
1348
1377
  function resourceWildcard(held) {
1349
1378
  if (!held.endsWith(RESOURCE_WILDCARD)) return null;
@@ -1373,15 +1402,15 @@ function holds(held, required) {
1373
1402
 
1374
1403
  // src/auth/access.ts
1375
1404
  function accessFrom(who) {
1376
- const customer = who?.credential?.customer;
1377
- if (!customer?.id) return null;
1405
+ const user = who?.credential?.user;
1406
+ if (!user?.id) return null;
1378
1407
  return {
1379
- customerId: customer.id,
1380
- roles: Array.isArray(customer.roles) ? [...customer.roles] : null,
1408
+ userId: user.id,
1409
+ roles: Array.isArray(user.roles) ? [...user.roles] : null,
1381
1410
  scopes: [...who?.authority?.effective ?? []]
1382
1411
  };
1383
1412
  }
1384
- async function customerAccess(env, options) {
1413
+ async function userAccess(env, options) {
1385
1414
  return accessFrom(await authOp(env, AUTH_OPS.whoami, void 0, options));
1386
1415
  }
1387
1416
  async function getSessionAccess(adapter, env) {
@@ -1461,14 +1490,14 @@ function createFoirSessionClient(config) {
1461
1490
  } catch {
1462
1491
  return cached;
1463
1492
  }
1464
- if (!json.access_token || !json.customer_id) return cached;
1493
+ if (!json.access_token || !json.user_id) return cached;
1465
1494
  const expiresIn = typeof json.expires_in === "number" ? json.expires_in : 0;
1466
1495
  const next = {
1467
1496
  token: json.access_token,
1468
1497
  expiresAt: Date.now() + expiresIn * 1e3,
1469
- user: { customerId: json.customer_id, email: json.email ?? "" }
1498
+ user: { userId: json.user_id, email: json.email ?? "" }
1470
1499
  };
1471
- const changed = cached?.user.customerId !== next.user.customerId;
1500
+ const changed = cached?.user.userId !== next.user.userId;
1472
1501
  cached = next;
1473
1502
  scheduleRefresh(next.expiresAt);
1474
1503
  if (changed) emit(next.user);
@@ -1569,13 +1598,13 @@ function FoirProvider({
1569
1598
  const adapterRef = useRef(adapter ?? createLocalStorageAdapter());
1570
1599
  if (adapter && adapter !== adapterRef.current) adapterRef.current = adapter;
1571
1600
  const [status, setStatus] = useState("loading");
1572
- const [customer, setCustomer] = useState(null);
1601
+ const [user, setUser] = useState(null);
1573
1602
  const [access, setAccess] = useState(null);
1574
1603
  const [accessStatus, setAccessStatus] = useState("idle");
1575
1604
  const accessRead = useRef(0);
1576
1605
  const accessPending = useRef(null);
1577
1606
  const apply = useCallback((c) => {
1578
- setCustomer(c);
1607
+ setUser(c);
1579
1608
  setStatus(c ? "authenticated" : "unauthenticated");
1580
1609
  accessRead.current += 1;
1581
1610
  setAccess(null);
@@ -1600,10 +1629,10 @@ function FoirProvider({
1600
1629
  void (async () => {
1601
1630
  if (hosted) {
1602
1631
  const u = await hosted.getUser();
1603
- if (!cancelled) apply(u ? { id: u.customerId, email: u.email } : null);
1632
+ if (!cancelled) apply(u ? { id: u.userId, email: u.email } : null);
1604
1633
  return;
1605
1634
  }
1606
- const c = await getSessionCustomer(adapterRef.current);
1635
+ const c = await getSessionUser(adapterRef.current);
1607
1636
  if (!cancelled) apply(c);
1608
1637
  })();
1609
1638
  return () => {
@@ -1618,7 +1647,7 @@ function FoirProvider({
1618
1647
  (action) => {
1619
1648
  if (hosted) {
1620
1649
  throw new Error(
1621
- `[foir] ${action}() is not available in hostedSession mode \u2014 the customer signs in at your Foir login domain. Redirect to hostedSignInUrl() instead.`
1650
+ `[foir] ${action}() is not available in hostedSession mode \u2014 the user signs in at your Foir login domain. Redirect to hostedSignInUrl() instead.`
1622
1651
  );
1623
1652
  }
1624
1653
  },
@@ -1627,16 +1656,16 @@ function FoirProvider({
1627
1656
  const signIn = useCallback(
1628
1657
  async (vars) => {
1629
1658
  assertTokenMode("signIn");
1630
- const c = await loginWithPassword(adapterRef.current, envRef.current, vars);
1659
+ const c = await signInWithPassword(adapterRef.current, envRef.current, vars);
1631
1660
  apply(c);
1632
1661
  return c;
1633
1662
  },
1634
1663
  [apply, assertTokenMode]
1635
1664
  );
1636
- const register = useCallback(
1665
+ const register2 = useCallback(
1637
1666
  async (vars) => {
1638
1667
  assertTokenMode("register");
1639
- const c = await registerWithPassword(adapterRef.current, envRef.current, vars);
1668
+ const c = await signUpWithPassword(adapterRef.current, envRef.current, vars);
1640
1669
  apply(c);
1641
1670
  return c;
1642
1671
  },
@@ -1645,14 +1674,14 @@ function FoirProvider({
1645
1674
  const requestOtp = useCallback(
1646
1675
  (email) => {
1647
1676
  assertTokenMode("requestOtp");
1648
- return customerRequestOTP(envRef.current, email);
1677
+ return requestOTP(envRef.current, email);
1649
1678
  },
1650
1679
  [assertTokenMode]
1651
1680
  );
1652
1681
  const signInWithOtp = useCallback(
1653
1682
  async (vars) => {
1654
1683
  assertTokenMode("signInWithOtp");
1655
- const c = await loginWithOTP(adapterRef.current, envRef.current, vars);
1684
+ const c = await signInWithOTP(adapterRef.current, envRef.current, vars);
1656
1685
  apply(c);
1657
1686
  return c;
1658
1687
  },
@@ -1661,7 +1690,7 @@ function FoirProvider({
1661
1690
  const signInWithProvider = useCallback(
1662
1691
  async (providerKey, opts) => {
1663
1692
  assertTokenMode("signInWithProvider");
1664
- const res = await customerLoginWithProvider(envRef.current, {
1693
+ const res = await loginWithProvider(envRef.current, {
1665
1694
  providerKey,
1666
1695
  ...opts
1667
1696
  });
@@ -1674,7 +1703,7 @@ function FoirProvider({
1674
1703
  const completeProviderLogin = useCallback(
1675
1704
  async (input) => {
1676
1705
  assertTokenMode("completeProviderLogin");
1677
- const result = await customerProviderCallback(envRef.current, input);
1706
+ const result = await providerCallback(envRef.current, input);
1678
1707
  const c = await saveSession(adapterRef.current, result);
1679
1708
  apply(c);
1680
1709
  return c;
@@ -1710,7 +1739,7 @@ function FoirProvider({
1710
1739
  const pending = (async () => {
1711
1740
  try {
1712
1741
  const next = hosted ? await hosted.getToken().then(
1713
- (bearerToken) => bearerToken ? customerAccess(envRef.current, { bearerToken }) : null
1742
+ (bearerToken) => bearerToken ? userAccess(envRef.current, { bearerToken }) : null
1714
1743
  ) : await getSessionAccess(adapterRef.current, envRef.current);
1715
1744
  if (accessRead.current !== read) return;
1716
1745
  setAccess(next);
@@ -1745,7 +1774,7 @@ function FoirProvider({
1745
1774
  const value = useMemo(
1746
1775
  () => ({
1747
1776
  status,
1748
- customer,
1777
+ user,
1749
1778
  access,
1750
1779
  accessStatus,
1751
1780
  loadAccess,
@@ -1753,7 +1782,7 @@ function FoirProvider({
1753
1782
  env,
1754
1783
  adapter: adapterRef.current,
1755
1784
  signIn,
1756
- register,
1785
+ register: register2,
1757
1786
  requestOtp,
1758
1787
  signInWithOtp,
1759
1788
  signInWithProvider,
@@ -1766,14 +1795,14 @@ function FoirProvider({
1766
1795
  }),
1767
1796
  [
1768
1797
  status,
1769
- customer,
1798
+ user,
1770
1799
  access,
1771
1800
  accessStatus,
1772
1801
  loadAccess,
1773
1802
  ensureAccess,
1774
1803
  env,
1775
1804
  signIn,
1776
- register,
1805
+ register2,
1777
1806
  requestOtp,
1778
1807
  signInWithOtp,
1779
1808
  signInWithProvider,
@@ -1795,16 +1824,16 @@ function useFoirContext() {
1795
1824
  return ctx;
1796
1825
  }
1797
1826
  function useFoirSession() {
1798
- const { status, customer } = useFoirContext();
1827
+ const { status, user } = useFoirContext();
1799
1828
  return {
1800
1829
  status,
1801
- customer,
1830
+ user,
1802
1831
  isLoading: status === "loading",
1803
1832
  isAuthenticated: status === "authenticated"
1804
1833
  };
1805
1834
  }
1806
1835
  function useFoirUser() {
1807
- return useFoirContext().customer;
1836
+ return useFoirContext().user;
1808
1837
  }
1809
1838
  function useFoirAccess() {
1810
1839
  const { status, access, accessStatus, loadAccess, ensureAccess } = useFoirContext();
@@ -1827,7 +1856,7 @@ function useFoirAccess() {
1827
1856
  function useFoirAuth() {
1828
1857
  const {
1829
1858
  signIn,
1830
- register,
1859
+ register: register2,
1831
1860
  requestOtp,
1832
1861
  signInWithOtp,
1833
1862
  signInWithProvider,
@@ -1840,7 +1869,7 @@ function useFoirAuth() {
1840
1869
  } = useFoirContext();
1841
1870
  return {
1842
1871
  signIn,
1843
- register,
1872
+ register: register2,
1844
1873
  requestOtp,
1845
1874
  signInWithOtp,
1846
1875
  signInWithProvider,
@@ -1948,8 +1977,8 @@ function SignIn({
1948
1977
  if (hostedUrl) {
1949
1978
  return /* @__PURE__ */ jsx3("div", { className, "data-foir-signin": true, children: /* @__PURE__ */ jsx3("a", { href: hostedUrl, "data-foir-hosted-login": true, style: styled ? submitStyle : void 0, children: "Sign in" }) });
1950
1979
  }
1951
- const finish = (customer) => {
1952
- onSignIn?.(customer);
1980
+ const finish = (user) => {
1981
+ onSignIn?.(user);
1953
1982
  if (afterSignInUrl && typeof window !== "undefined") {
1954
1983
  window.location.assign(afterSignInUrl);
1955
1984
  }
@@ -2225,7 +2254,7 @@ async function uploadFeedbackAttachment(client, screenshot, fetchImpl = globalTh
2225
2254
  const files = client.ns.files;
2226
2255
  if (!files) {
2227
2256
  throw new Error(
2228
- "[foir] this client cannot reach the files namespace, so a screenshot cannot be uploaded. Attaching one needs `files:write` on the key and on the signed-in customer's role."
2257
+ "[foir] this client cannot reach the files namespace, so a screenshot cannot be uploaded. Attaching one needs `files:write` on the key and on the signed-in user's role."
2229
2258
  );
2230
2259
  }
2231
2260
  const ticket = readUploadTicket(
@@ -2617,7 +2646,7 @@ function failureCopy(fault) {
2617
2646
  function reportFault(fault, err, action) {
2618
2647
  if (fault.kind === "scope") {
2619
2648
  console.error(
2620
- `[foir] <FoirFeedback>: the API refused with "missing required scope: ${fault.scope}". This is not a bad API key: the key reached the surface. The signed-in CUSTOMER's role does not grant ${fault.scope}, and a new project's default customer role does not carry the notes scopes. Add it to the role that customer holds, or to the project's default customer role, and this works with no code change.`,
2649
+ `[foir] <FoirFeedback>: the API refused with "missing required scope: ${fault.scope}". This is not a bad API key: the key reached the surface. The signed-in USER's role does not grant ${fault.scope}, and a new project's default user role does not carry the notes scopes. Add it to the role that user holds, or to the project's default user role, and this works with no code change.`,
2621
2650
  err
2622
2651
  );
2623
2652
  return;