@foir/sdk 0.21.0 → 0.22.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 (58) hide show
  1. package/CHANGELOG.md +84 -1
  2. package/README.md +9 -9
  3. package/dist/app/client.d.ts +90 -84
  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 +11 -11
  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 +216 -114
  15. package/dist/auth/hosted.d.ts +14 -14
  16. package/dist/auth/index.d.ts +7 -7
  17. package/dist/auth/operations.d.ts +128 -32
  18. package/dist/auth/ops.d.ts +39 -21
  19. package/dist/auth/session-client.d.ts +3 -3
  20. package/dist/auth-session.js +3 -3
  21. package/dist/auth.js +234 -135
  22. package/dist/client.js +4 -4
  23. package/dist/data/builtins.d.ts +26 -26
  24. package/dist/data/client.d.ts +2 -2
  25. package/dist/data/decimal.d.ts +1 -1
  26. package/dist/data/index.d.ts +1 -1
  27. package/dist/data/manifest.d.ts +1 -1
  28. package/dist/data/schema.d.ts +1 -1
  29. package/dist/data/transport.d.ts +10 -10
  30. package/dist/data/ws-transport.d.ts +1 -1
  31. package/dist/data.js +6 -6
  32. package/dist/graphql/content-client.d.ts +13 -13
  33. package/dist/live/drift.d.ts +1 -1
  34. package/dist/media/screen-capture.d.ts +1 -1
  35. package/dist/next/index.d.ts +2 -2
  36. package/dist/next/session.d.ts +10 -10
  37. package/dist/next.js +77 -56
  38. package/dist/placement/index.d.ts +13 -13
  39. package/dist/placement.js +9 -6
  40. package/dist/push.js +61 -40
  41. package/dist/react/FoirFeedback.d.ts +2 -2
  42. package/dist/react/FoirProvider.d.ts +23 -23
  43. package/dist/react/SignIn.d.ts +4 -4
  44. package/dist/react/UserButton.d.ts +1 -1
  45. package/dist/react/feedback-notes.d.ts +4 -4
  46. package/dist/react/index.d.ts +3 -3
  47. package/dist/react.js +119 -95
  48. package/dist/realtime/index.d.ts +1 -1
  49. package/dist/server/callback-client.d.ts +4 -4
  50. package/dist/server/events-client.d.ts +16 -16
  51. package/dist/server/operation-types.d.ts +8 -8
  52. package/dist/server/require-scoped-token.d.ts +3 -3
  53. package/dist/server/types.d.ts +1 -1
  54. package/dist/server/verify-scoped-token.d.ts +3 -3
  55. package/dist/server.js +16 -13
  56. package/dist/transport/foir-http.d.ts +13 -13
  57. package/dist/types/index.d.ts +2 -2
  58. package/package.json +3 -3
package/dist/next.js CHANGED
@@ -211,8 +211,8 @@ var FoirAuthDowngradedError = class extends FoirRequestError {
211
211
  downgrade;
212
212
  constructor(downgrade) {
213
213
  super(
214
- `[foir] your customer token was ${downgrade.customerToken} (${downgrade.reason}), so the request was served as ${downgrade.servedAs}`,
215
- { graphQLErrors: [{ message: "customer token rejected", extensions: { code: "AUTH_DOWNGRADED" } }] }
214
+ `[foir] your user token was ${downgrade.userToken} (${downgrade.reason}), so the request was served as ${downgrade.servedAs}`,
215
+ { graphQLErrors: [{ message: "user token rejected", extensions: { code: "AUTH_DOWNGRADED" } }] }
216
216
  );
217
217
  this.name = "FoirAuthDowngradedError";
218
218
  this.downgrade = downgrade;
@@ -220,7 +220,7 @@ var FoirAuthDowngradedError = class extends FoirRequestError {
220
220
  };
221
221
  var FoirSessionExpiredError = class extends FoirRequestError {
222
222
  constructor(options) {
223
- super("[foir] the customer session has expired and could not be refreshed: sign in again", {
223
+ super("[foir] the user session has expired and could not be refreshed: sign in again", {
224
224
  cause: options?.cause,
225
225
  graphQLErrors: [{ message: "session expired", extensions: { code: "SESSION_EXPIRED" } }]
226
226
  });
@@ -237,7 +237,7 @@ function reportAuthDowngrade(envelope) {
237
237
  if (warnedDowngrade === downgrade.reason) return;
238
238
  warnedDowngrade = downgrade.reason;
239
239
  console.warn(
240
- `[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.")
240
+ `[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.")
241
241
  );
242
242
  }
243
243
  function refusePrunedDocument(json, options) {
@@ -956,42 +956,63 @@ var AUTH_OPS = {
956
956
  authConfig: "authConfig",
957
957
  authProviders: "authProviders",
958
958
  defaultAuthProvider: "defaultAuthProvider",
959
- customerSignupContext: "customerSignupContext",
959
+ signupContext: "signupContext",
960
960
  // Post-credential self reads.
961
961
  currentUser: "currentUser",
962
962
  myProviderToken: "myProviderToken",
963
- // What the calling credential may do, and for a signed-in customer the roles
963
+ // What the calling credential may do, and for a signed-in user the roles
964
964
  // they hold. `./access` reads it.
965
965
  whoami: "whoami",
966
966
  // Methods.
967
- customerLogin: "customerLogin",
968
- customerRegister: "customerRegister",
969
- customerRequestOTP: "customerRequestOTP",
970
- customerLoginOTP: "customerLoginOTP",
967
+ login: "login",
968
+ register: "register",
969
+ requestOTP: "requestOTP",
970
+ loginWithOTP: "loginWithOTP",
971
971
  // Session lifecycle.
972
- customerRefreshToken: "customerRefreshToken",
973
- customerLogout: "customerLogout",
974
- customerJoinWaitlist: "customerJoinWaitlist",
975
- // Password management and account lifecycle — the block that had no path.
976
- customerRequestPasswordReset: "customerRequestPasswordReset",
977
- customerResetPassword: "customerResetPassword",
978
- customerUpdatePassword: "customerUpdatePassword",
979
- customerVerifyEmail: "customerVerifyEmail",
972
+ refreshToken: "refreshToken",
973
+ logout: "logout",
974
+ joinWaitlist: "joinWaitlist",
975
+ // Password management and account lifecycle.
976
+ requestPasswordReset: "requestPasswordReset",
977
+ resetPassword: "resetPassword",
978
+ updatePassword: "updatePassword",
979
+ verifyEmail: "verifyEmail",
980
980
  deleteMyAccount: "deleteMyAccount",
981
- // The operator's organization context. TWO ops and no third: one to read
982
- // which organizations the caller may stand in, one to say which. There is
983
- // deliberately no per-call org argument anywhere in this SDK — the claim the
984
- // row layer reads is resolved from the caller's own membership row on every
985
- // request, so an application that never names an org cannot name the wrong
986
- // one.
981
+ // The user's own profile, and the apps they have agreed may act for them.
982
+ updateMyProfile: "updateMyProfile",
983
+ myAuthorizedApps: "myAuthorizedApps",
984
+ revokeAuthorizedApp: "revokeAuthorizedApp",
985
+ // Where they are signed in, their personal access tokens, and the
986
+ // providers they sign in with.
987
+ mySessions: "mySessions",
988
+ endMySession: "endMySession",
989
+ signOutEverywhere: "signOutEverywhere",
990
+ createPersonalAccessToken: "createPersonalAccessToken",
991
+ mySignInMethods: "mySignInMethods",
992
+ connectSignInMethod: "connectSignInMethod",
993
+ disconnectSignInMethod: "disconnectSignInMethod",
994
+ // Their second factors. A change needs one proven first, by a step-up.
995
+ myFactors: "myFactors",
996
+ beginStepUp: "beginStepUp",
997
+ completeStepUp: "completeStepUp",
998
+ beginFactorEnrollment: "beginFactorEnrollment",
999
+ completeFactorEnrollment: "completeFactorEnrollment",
1000
+ removeFactor: "removeFactor",
1001
+ makeRecoveryCodes: "makeRecoveryCodes",
1002
+ // The organizations the caller may stand in. Nothing selects one: a request
1003
+ // names the organization it acts in (`orgId` or `orgUrl` below), and the
1004
+ // platform checks the caller stands there every time.
987
1005
  myOrganizations: "myOrganizations",
988
- selectMyOrganization: "selectMyOrganization",
989
1006
  // Founding one. Present in a manifest only when the project opted in.
990
- registerOperatorOrganization: "registerOperatorOrganization",
1007
+ registerOrganization: "registerOrganization",
991
1008
  // External identity providers.
992
- customerLoginWithProvider: "customerLoginWithProvider",
993
- customerProviderCallback: "customerProviderCallback",
994
- customerProviderVerifyOTP: "customerProviderVerifyOTP"
1009
+ loginWithProvider: "loginWithProvider",
1010
+ providerCallback: "providerCallback",
1011
+ providerVerifyOTP: "providerVerifyOTP",
1012
+ // A provider sign-in that names an address somebody already holds, waiting
1013
+ // for the code sent to it.
1014
+ confirmProviderLink: "confirmProviderLink",
1015
+ resendProviderLinkCode: "resendProviderLinkCode"
995
1016
  };
996
1017
  function authClientConfig(env, options) {
997
1018
  const apiKey = resolveFoirApiKey(env);
@@ -1054,58 +1075,58 @@ function stripUndefined(args) {
1054
1075
  // src/auth/auth.ts
1055
1076
  var TOKEN_KEY = "foir:token";
1056
1077
  var REFRESH_KEY = "foir:refreshToken";
1057
- var CUSTOMER_ID_KEY = "foir:customerId";
1078
+ var USER_ID_KEY = "foir:userId";
1058
1079
  var EMAIL_KEY = "foir:email";
1059
- async function customerLogin(env, vars) {
1060
- return authOp(env, AUTH_OPS.customerLogin, vars);
1080
+ async function login(env, vars) {
1081
+ return authOp(env, AUTH_OPS.login, vars);
1061
1082
  }
1062
- async function customerRegister(env, vars) {
1063
- return authOp(env, AUTH_OPS.customerRegister, vars);
1083
+ async function register(env, vars) {
1084
+ return authOp(env, AUTH_OPS.register, vars);
1064
1085
  }
1065
- async function customerLoginOTP(env, vars) {
1066
- return authOp(env, AUTH_OPS.customerLoginOTP, vars);
1086
+ async function loginWithOTP(env, vars) {
1087
+ return authOp(env, AUTH_OPS.loginWithOTP, vars);
1067
1088
  }
1068
- async function customerProviderCallback(env, input) {
1069
- return authOp(env, AUTH_OPS.customerProviderCallback, { input });
1089
+ async function providerCallback(env, input) {
1090
+ return authOp(env, AUTH_OPS.providerCallback, { input });
1070
1091
  }
1071
1092
  async function saveSession(adapter, result) {
1072
1093
  await adapter.set(TOKEN_KEY, result.token);
1073
1094
  await adapter.set(REFRESH_KEY, result.refreshToken);
1074
- if (!result.customerId) {
1075
- return await getSessionCustomer(adapter) ?? { id: "", email: "" };
1095
+ if (!result.userId) {
1096
+ return await getSessionUser(adapter) ?? { id: "", email: "" };
1076
1097
  }
1077
- await adapter.set(CUSTOMER_ID_KEY, result.customerId);
1098
+ await adapter.set(USER_ID_KEY, result.userId);
1078
1099
  await adapter.set(EMAIL_KEY, result.email);
1079
- return { id: result.customerId, email: result.email };
1100
+ return { id: result.userId, email: result.email };
1080
1101
  }
1081
1102
  async function clearSession(adapter) {
1082
1103
  await adapter.unset(TOKEN_KEY);
1083
1104
  await adapter.unset(REFRESH_KEY);
1084
- await adapter.unset(CUSTOMER_ID_KEY);
1105
+ await adapter.unset(USER_ID_KEY);
1085
1106
  await adapter.unset(EMAIL_KEY);
1086
1107
  }
1087
1108
  async function getSessionToken(adapter) {
1088
1109
  return await adapter.get(TOKEN_KEY) ?? null;
1089
1110
  }
1090
- async function getSessionCustomer(adapter) {
1091
- const id = await adapter.get(CUSTOMER_ID_KEY) ?? null;
1111
+ async function getSessionUser(adapter) {
1112
+ const id = await adapter.get(USER_ID_KEY) ?? null;
1092
1113
  const email = await adapter.get(EMAIL_KEY) ?? null;
1093
1114
  if (!id) return null;
1094
1115
  return { id, email: email ?? "" };
1095
1116
  }
1096
- async function loginWithPassword(adapter, env, vars) {
1097
- return saveSession(adapter, await customerLogin(env, vars));
1117
+ async function signInWithPassword(adapter, env, vars) {
1118
+ return saveSession(adapter, await login(env, vars));
1098
1119
  }
1099
- async function registerWithPassword(adapter, env, vars) {
1100
- return saveSession(adapter, await customerRegister(env, vars));
1120
+ async function signUpWithPassword(adapter, env, vars) {
1121
+ return saveSession(adapter, await register(env, vars));
1101
1122
  }
1102
- async function loginWithOTP(adapter, env, vars) {
1103
- return saveSession(adapter, await customerLoginOTP(env, vars));
1123
+ async function signInWithOTP(adapter, env, vars) {
1124
+ return saveSession(adapter, await loginWithOTP(env, vars));
1104
1125
  }
1105
1126
 
1106
1127
  // src/next/session.ts
1107
1128
  async function getFoirSession(store) {
1108
- return getSessionCustomer(createFoirCookieAdapter(store));
1129
+ return getSessionUser(createFoirCookieAdapter(store));
1109
1130
  }
1110
1131
  async function getFoirToken(store) {
1111
1132
  return getSessionToken(createFoirCookieAdapter(store));
@@ -1120,7 +1141,7 @@ function foirSignInWithPassword({
1120
1141
  password,
1121
1142
  cookieOptions
1122
1143
  }) {
1123
- return loginWithPassword(createFoirCookieAdapter(store, { cookieOptions }), env, {
1144
+ return signInWithPassword(createFoirCookieAdapter(store, { cookieOptions }), env, {
1124
1145
  email,
1125
1146
  password
1126
1147
  });
@@ -1132,7 +1153,7 @@ function foirRegisterWithPassword({
1132
1153
  password,
1133
1154
  cookieOptions
1134
1155
  }) {
1135
- return registerWithPassword(createFoirCookieAdapter(store, { cookieOptions }), env, {
1156
+ return signUpWithPassword(createFoirCookieAdapter(store, { cookieOptions }), env, {
1136
1157
  email,
1137
1158
  password
1138
1159
  });
@@ -1144,13 +1165,13 @@ function foirSignInWithOtp({
1144
1165
  otp,
1145
1166
  cookieOptions
1146
1167
  }) {
1147
- return loginWithOTP(createFoirCookieAdapter(store, { cookieOptions }), env, {
1168
+ return signInWithOTP(createFoirCookieAdapter(store, { cookieOptions }), env, {
1148
1169
  email,
1149
1170
  otp
1150
1171
  });
1151
1172
  }
1152
1173
  async function completeFoirProviderLogin(opts) {
1153
- const result = await customerProviderCallback(opts.env, {
1174
+ const result = await providerCallback(opts.env, {
1154
1175
  providerKey: opts.providerKey,
1155
1176
  code: opts.code,
1156
1177
  state: opts.state
@@ -1,11 +1,11 @@
1
1
  /**
2
- * `@foir/sdk/placement`: your app's own admin console, shown inside Foir's.
2
+ * `@foir/sdk/placement`: your app's own console, shown inside Foir's.
3
3
  *
4
4
  * A full-page placement is loaded in a frame on the Foir console. No cookie
5
5
  * reaches a cross-site frame, so the console hands the page a short-lived token
6
6
  * instead, by message, to your placement's origin only. The token is the
7
- * operator looking at the page, acting through your app at the level your app
8
- * is installed at, carrying what your placement declares and this operator
7
+ * person looking at the page, acting through your app at the level your app
8
+ * is installed at, carrying what your placement declares and this person
9
9
  * holds, as grants in the permission catalogue's names. Your page runs no
10
10
  * login of its own.
11
11
  *
@@ -21,7 +21,7 @@
21
21
  * ```
22
22
  *
23
23
  * The console also tells the page how it looks, so the page can match it: pass
24
- * `onAppearance` and apply the theme it names. The operator's console theme is
24
+ * `onAppearance` and apply the theme it names. Their console theme is
25
25
  * their own setting and need not be their system's.
26
26
  *
27
27
  * The browser shows the page blank, however well it is authenticated, unless
@@ -40,7 +40,7 @@ export declare const PLACEMENT_MESSAGE: {
40
40
  readonly refresh: "foir:placement:refresh";
41
41
  /** Console to page: no token, and why. */
42
42
  readonly refused: "foir:placement:refused";
43
- /** Console to page: the operator signed out. */
43
+ /** Console to page: the person signed out. */
44
44
  readonly signedOut: "foir:placement:signed-out";
45
45
  /** Console to page: how the console looks, now and whenever it changes. */
46
46
  readonly appearance: "foir:placement:appearance";
@@ -55,7 +55,7 @@ export interface PlacementGrant {
55
55
  orgId: string;
56
56
  /**
57
57
  * What the token carries: the grants your placement declares that this
58
- * operator holds, in the permission catalogue's names. A grant the operator
58
+ * person holds, in the permission catalogue's names. A grant the person
59
59
  * holds part of is carried as that part, so ask with `can` and not by
60
60
  * looking for a spelling here.
61
61
  */
@@ -71,7 +71,7 @@ type PlacementGrantMessage = Pick<PlacementGrant, 'accessToken' | 'expiresAt' |
71
71
  /** How the console looks, for an embedded page to match. */
72
72
  export interface PlacementAppearance {
73
73
  /**
74
- * The console's theme as the operator sees it: their own choice, or their
74
+ * The console's theme as the person sees it: their own choice, or their
75
75
  * system's when they left it to the system.
76
76
  */
77
77
  theme: 'light' | 'dark';
@@ -97,7 +97,7 @@ export type PlacementPageMessage = {
97
97
  };
98
98
  /**
99
99
  * The Foir consoles, per environment. A project that serves the console on its
100
- * own verified admin domain adds that origin too: the install preview lists it.
100
+ * own verified console domain adds that origin too: the install preview lists it.
101
101
  */
102
102
  export declare const FOIR_CONSOLE_ORIGINS: {
103
103
  readonly production: readonly ["https://app.foir.io"];
@@ -127,7 +127,7 @@ export interface ConnectPlacementOptions {
127
127
  refreshBeforeMs?: number;
128
128
  /**
129
129
  * Called with how the console looks: once as soon as the console says, which
130
- * is before the token arrives, and again whenever the operator changes it.
130
+ * is before the token arrives, and again whenever the person changes it.
131
131
  * Apply it instead of the system's preference, so the page matches the
132
132
  * console it is shown in.
133
133
  */
@@ -143,22 +143,22 @@ export interface PlacementSession {
143
143
  readonly grant: PlacementGrant;
144
144
  /**
145
145
  * How the console looks now, or null when the console has not said (a console
146
- * older than this). Kept current as the operator changes it.
146
+ * older than this). Kept current as the person changes it.
147
147
  */
148
148
  readonly appearance: PlacementAppearance | null;
149
149
  /**
150
- * Whether the token covers this grant, to hide or grey out what the operator
150
+ * Whether the token covers this grant, to hide or grey out what the person
151
151
  * cannot do. It answers as Foir's API would: a grant for every model covers
152
152
  * the same grant for one, and one for every owner's rows covers a person's
153
153
  * own. `can('records:read.all:order')` is true for a token that carries
154
154
  * `records:read.all`.
155
155
  */
156
156
  can(grant: string): boolean;
157
- /** A GraphQL request to Foir's API as the operator, through your app. */
157
+ /** A GraphQL request to Foir's API as the person, through your app. */
158
158
  request<TResult = unknown>(document: string | {
159
159
  toString(): string;
160
160
  }, variables?: Record<string, unknown>): Promise<TResult>;
161
- /** Called when the operator signs out; the session holds no token from then on. */
161
+ /** Called when the person signs out; the session holds no token from then on. */
162
162
  onSignedOut(listener: () => void): () => void;
163
163
  /** Stop listening and refreshing. */
164
164
  close(): void;
package/dist/placement.js CHANGED
@@ -77,7 +77,8 @@ var GRANT_TABLE = [
77
77
  ["roles:write", false, [], []],
78
78
  ["projects:read", false, [], []],
79
79
  ["projects:write", false, [], []],
80
- ["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"]],
80
+ ["project:stand", false, [], []],
81
+ ["project:manage", false, [], ["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", "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"]],
81
82
  ["projects:create", false, [], []],
82
83
  ["projects:delete", false, [], []],
83
84
  ["tenants:read", false, [], []],
@@ -90,12 +91,14 @@ var GRANT_TABLE = [
90
91
  ["usage:read", false, [], []],
91
92
  ["controlkeys:read", false, [], []],
92
93
  ["controlkeys:write", false, [], []],
94
+ ["tenantsigninproviders:read", false, [], []],
95
+ ["tenantsigninproviders:write", false, [], []],
93
96
  ["tenanthooks:read", false, [], []],
94
97
  ["tenanthooks:write", false, [], []],
95
98
  ["apps:install", false, [], []],
96
- ["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"]],
99
+ ["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", "tenantsigninproviders:read", "tenantsigninproviders:write", "apps:install"]],
97
100
  ["platform:read", false, [], []],
98
- ["platform:manage", false, [], ["tenant:manage", "platform:read", "platform:create_workspace", "users:setup"]],
101
+ ["platform:manage", false, [], ["tenant:manage", "platform:read", "platform:create_workspace"]],
99
102
  ["platform:create_workspace", false, [], []],
100
103
  ["users:read", false, ["own", "named", "all"], []],
101
104
  ["users:write", false, ["own", "all"], []],
@@ -202,7 +205,7 @@ var PLACEMENT_MESSAGE = {
202
205
  refresh: "foir:placement:refresh",
203
206
  /** Console to page: no token, and why. */
204
207
  refused: "foir:placement:refused",
205
- /** Console to page: the operator signed out. */
208
+ /** Console to page: the person signed out. */
206
209
  signedOut: "foir:placement:signed-out",
207
210
  /** Console to page: how the console looks, now and whenever it changes. */
208
211
  appearance: "foir:placement:appearance"
@@ -296,7 +299,7 @@ function connectPlacement(options) {
296
299
  };
297
300
  const session = {
298
301
  get grant() {
299
- if (!grant) throw new PlacementRefused("the operator has signed out");
302
+ if (!grant) throw new PlacementRefused("the person using the console has signed out");
300
303
  return grant;
301
304
  },
302
305
  get appearance() {
@@ -306,7 +309,7 @@ function connectPlacement(options) {
306
309
  // names a placement declared then; and by what the list covers.
307
310
  can: (asked) => grant ? grant.grants.includes(asked) || holds(grant.grants, asked) : false,
308
311
  async request(document, variables) {
309
- if (!grant) throw new PlacementRefused("the operator has signed out");
312
+ if (!grant) throw new PlacementRefused("the person using the console has signed out");
310
313
  const res = await doFetch(`${apiUrl}/graphql`, {
311
314
  method: "POST",
312
315
  headers: { "content-type": "application/json", authorization: `Bearer ${grant.accessToken}` },
package/dist/push.js CHANGED
@@ -217,8 +217,8 @@ var FoirAuthDowngradedError = class extends FoirRequestError {
217
217
  downgrade;
218
218
  constructor(downgrade) {
219
219
  super(
220
- `[foir] your customer token was ${downgrade.customerToken} (${downgrade.reason}), so the request was served as ${downgrade.servedAs}`,
221
- { graphQLErrors: [{ message: "customer token rejected", extensions: { code: "AUTH_DOWNGRADED" } }] }
220
+ `[foir] your user token was ${downgrade.userToken} (${downgrade.reason}), so the request was served as ${downgrade.servedAs}`,
221
+ { graphQLErrors: [{ message: "user token rejected", extensions: { code: "AUTH_DOWNGRADED" } }] }
222
222
  );
223
223
  this.name = "FoirAuthDowngradedError";
224
224
  this.downgrade = downgrade;
@@ -226,7 +226,7 @@ var FoirAuthDowngradedError = class extends FoirRequestError {
226
226
  };
227
227
  var FoirSessionExpiredError = class extends FoirRequestError {
228
228
  constructor(options) {
229
- super("[foir] the customer session has expired and could not be refreshed: sign in again", {
229
+ super("[foir] the user session has expired and could not be refreshed: sign in again", {
230
230
  cause: options?.cause,
231
231
  graphQLErrors: [{ message: "session expired", extensions: { code: "SESSION_EXPIRED" } }]
232
232
  });
@@ -243,7 +243,7 @@ function reportAuthDowngrade(envelope) {
243
243
  if (warnedDowngrade === downgrade.reason) return;
244
244
  warnedDowngrade = downgrade.reason;
245
245
  console.warn(
246
- `[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.")
246
+ `[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.")
247
247
  );
248
248
  }
249
249
  function refusePrunedDocument(json, options) {
@@ -1076,42 +1076,63 @@ var AUTH_OPS = {
1076
1076
  authConfig: "authConfig",
1077
1077
  authProviders: "authProviders",
1078
1078
  defaultAuthProvider: "defaultAuthProvider",
1079
- customerSignupContext: "customerSignupContext",
1079
+ signupContext: "signupContext",
1080
1080
  // Post-credential self reads.
1081
1081
  currentUser: "currentUser",
1082
1082
  myProviderToken: "myProviderToken",
1083
- // What the calling credential may do, and for a signed-in customer the roles
1083
+ // What the calling credential may do, and for a signed-in user the roles
1084
1084
  // they hold. `./access` reads it.
1085
1085
  whoami: "whoami",
1086
1086
  // Methods.
1087
- customerLogin: "customerLogin",
1088
- customerRegister: "customerRegister",
1089
- customerRequestOTP: "customerRequestOTP",
1090
- customerLoginOTP: "customerLoginOTP",
1087
+ login: "login",
1088
+ register: "register",
1089
+ requestOTP: "requestOTP",
1090
+ loginWithOTP: "loginWithOTP",
1091
1091
  // Session lifecycle.
1092
- customerRefreshToken: "customerRefreshToken",
1093
- customerLogout: "customerLogout",
1094
- customerJoinWaitlist: "customerJoinWaitlist",
1095
- // Password management and account lifecycle — the block that had no path.
1096
- customerRequestPasswordReset: "customerRequestPasswordReset",
1097
- customerResetPassword: "customerResetPassword",
1098
- customerUpdatePassword: "customerUpdatePassword",
1099
- customerVerifyEmail: "customerVerifyEmail",
1092
+ refreshToken: "refreshToken",
1093
+ logout: "logout",
1094
+ joinWaitlist: "joinWaitlist",
1095
+ // Password management and account lifecycle.
1096
+ requestPasswordReset: "requestPasswordReset",
1097
+ resetPassword: "resetPassword",
1098
+ updatePassword: "updatePassword",
1099
+ verifyEmail: "verifyEmail",
1100
1100
  deleteMyAccount: "deleteMyAccount",
1101
- // The operator's organization context. TWO ops and no third: one to read
1102
- // which organizations the caller may stand in, one to say which. There is
1103
- // deliberately no per-call org argument anywhere in this SDK — the claim the
1104
- // row layer reads is resolved from the caller's own membership row on every
1105
- // request, so an application that never names an org cannot name the wrong
1106
- // one.
1101
+ // The user's own profile, and the apps they have agreed may act for them.
1102
+ updateMyProfile: "updateMyProfile",
1103
+ myAuthorizedApps: "myAuthorizedApps",
1104
+ revokeAuthorizedApp: "revokeAuthorizedApp",
1105
+ // Where they are signed in, their personal access tokens, and the
1106
+ // providers they sign in with.
1107
+ mySessions: "mySessions",
1108
+ endMySession: "endMySession",
1109
+ signOutEverywhere: "signOutEverywhere",
1110
+ createPersonalAccessToken: "createPersonalAccessToken",
1111
+ mySignInMethods: "mySignInMethods",
1112
+ connectSignInMethod: "connectSignInMethod",
1113
+ disconnectSignInMethod: "disconnectSignInMethod",
1114
+ // Their second factors. A change needs one proven first, by a step-up.
1115
+ myFactors: "myFactors",
1116
+ beginStepUp: "beginStepUp",
1117
+ completeStepUp: "completeStepUp",
1118
+ beginFactorEnrollment: "beginFactorEnrollment",
1119
+ completeFactorEnrollment: "completeFactorEnrollment",
1120
+ removeFactor: "removeFactor",
1121
+ makeRecoveryCodes: "makeRecoveryCodes",
1122
+ // The organizations the caller may stand in. Nothing selects one: a request
1123
+ // names the organization it acts in (`orgId` or `orgUrl` below), and the
1124
+ // platform checks the caller stands there every time.
1107
1125
  myOrganizations: "myOrganizations",
1108
- selectMyOrganization: "selectMyOrganization",
1109
1126
  // Founding one. Present in a manifest only when the project opted in.
1110
- registerOperatorOrganization: "registerOperatorOrganization",
1127
+ registerOrganization: "registerOrganization",
1111
1128
  // External identity providers.
1112
- customerLoginWithProvider: "customerLoginWithProvider",
1113
- customerProviderCallback: "customerProviderCallback",
1114
- customerProviderVerifyOTP: "customerProviderVerifyOTP"
1129
+ loginWithProvider: "loginWithProvider",
1130
+ providerCallback: "providerCallback",
1131
+ providerVerifyOTP: "providerVerifyOTP",
1132
+ // A provider sign-in that names an address somebody already holds, waiting
1133
+ // for the code sent to it.
1134
+ confirmProviderLink: "confirmProviderLink",
1135
+ resendProviderLinkCode: "resendProviderLinkCode"
1115
1136
  };
1116
1137
  function authClientConfig(env, options) {
1117
1138
  const apiKey = resolveFoirApiKey(env);
@@ -1174,32 +1195,32 @@ function stripUndefined(args) {
1174
1195
  // src/auth/auth.ts
1175
1196
  var TOKEN_KEY = "foir:token";
1176
1197
  var REFRESH_KEY = "foir:refreshToken";
1177
- var CUSTOMER_ID_KEY = "foir:customerId";
1198
+ var USER_ID_KEY = "foir:userId";
1178
1199
  var EMAIL_KEY = "foir:email";
1179
- async function customerRefreshToken(env, refreshToken) {
1180
- return authOp(env, AUTH_OPS.customerRefreshToken, { refreshToken });
1200
+ async function refreshTokens(env, refreshToken) {
1201
+ return authOp(env, AUTH_OPS.refreshToken, { refreshToken });
1181
1202
  }
1182
1203
  async function saveSession(adapter, result) {
1183
1204
  await adapter.set(TOKEN_KEY, result.token);
1184
1205
  await adapter.set(REFRESH_KEY, result.refreshToken);
1185
- if (!result.customerId) {
1186
- return await getSessionCustomer(adapter) ?? { id: "", email: "" };
1206
+ if (!result.userId) {
1207
+ return await getSessionUser(adapter) ?? { id: "", email: "" };
1187
1208
  }
1188
- await adapter.set(CUSTOMER_ID_KEY, result.customerId);
1209
+ await adapter.set(USER_ID_KEY, result.userId);
1189
1210
  await adapter.set(EMAIL_KEY, result.email);
1190
- return { id: result.customerId, email: result.email };
1211
+ return { id: result.userId, email: result.email };
1191
1212
  }
1192
1213
  async function clearSession(adapter) {
1193
1214
  await adapter.unset(TOKEN_KEY);
1194
1215
  await adapter.unset(REFRESH_KEY);
1195
- await adapter.unset(CUSTOMER_ID_KEY);
1216
+ await adapter.unset(USER_ID_KEY);
1196
1217
  await adapter.unset(EMAIL_KEY);
1197
1218
  }
1198
1219
  async function getSessionToken(adapter) {
1199
1220
  return await adapter.get(TOKEN_KEY) ?? null;
1200
1221
  }
1201
- async function getSessionCustomer(adapter) {
1202
- const id = await adapter.get(CUSTOMER_ID_KEY) ?? null;
1222
+ async function getSessionUser(adapter) {
1223
+ const id = await adapter.get(USER_ID_KEY) ?? null;
1203
1224
  const email = await adapter.get(EMAIL_KEY) ?? null;
1204
1225
  if (!id) return null;
1205
1226
  return { id, email: email ?? "" };
@@ -1208,7 +1229,7 @@ async function refreshSession(adapter, env) {
1208
1229
  const refreshToken = await adapter.get(REFRESH_KEY) ?? null;
1209
1230
  if (!refreshToken) return null;
1210
1231
  try {
1211
- const result = await customerRefreshToken(env, refreshToken);
1232
+ const result = await refreshTokens(env, refreshToken);
1212
1233
  await saveSession(adapter, result);
1213
1234
  return { token: result.token, refreshToken: result.refreshToken };
1214
1235
  } catch {
@@ -1,4 +1,4 @@
1
- import type { FoirCustomerNote, FoirSubject, FoirSubjectRegistry } from '../data';
1
+ import type { FoirUserNote, FoirSubject, FoirSubjectRegistry } from '../data';
2
2
  import { type FoirFeedbackClient } from './feedback-notes';
3
3
  export type { FoirFeedbackClient } from './feedback-notes';
4
4
  export interface FoirFeedbackProps {
@@ -46,7 +46,7 @@ export interface FoirFeedbackProps {
46
46
  */
47
47
  onSignIn?: () => void;
48
48
  /** Called with the note once it is written. */
49
- onSubmitted?: (note: FoirCustomerNote) => void;
49
+ onSubmitted?: (note: FoirUserNote) => void;
50
50
  /**
51
51
  * Called with anything that failed. The widget also logs it — this is for
52
52
  * routing it into your own error reporting, not for making it visible.