@feelflow/ffid-sdk 5.12.0 → 5.14.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.
- package/dist/{chunk-KB2JG64Z.js → chunk-4II4R7NR.js} +392 -10
- package/dist/{chunk-AOJDV3UO.cjs → chunk-BVDUQQHP.cjs} +395 -9
- package/dist/components/index.cjs +8 -8
- package/dist/components/index.d.cts +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +1 -1
- package/dist/{ffid-client-5IprSUVR.d.ts → ffid-client-9-lh0G_h.d.ts} +384 -134
- package/dist/{ffid-client-Dx4oc4Cw.d.cts → ffid-client-CKFxY60u.d.cts} +384 -134
- package/dist/{index-DqsWKU16.d.cts → index-CsVJTuPv.d.cts} +14 -112
- package/dist/{index-DqsWKU16.d.ts → index-CsVJTuPv.d.ts} +14 -112
- package/dist/index.cjs +53 -37
- package/dist/index.d.cts +436 -4
- package/dist/index.d.ts +436 -4
- package/dist/index.js +2 -2
- package/dist/legal/index.cjs +14 -0
- package/dist/legal/index.d.cts +16 -1
- package/dist/legal/index.d.ts +16 -1
- package/dist/legal/index.js +14 -0
- package/dist/server/index.cjs +241 -3
- package/dist/server/index.d.cts +2 -2
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +241 -3
- package/dist/server/test/index.d.cts +1 -1
- package/dist/server/test/index.d.ts +1 -1
- package/dist/webhooks/index.cjs +5 -2
- package/dist/webhooks/index.js +5 -2
- package/package.json +1 -1
|
@@ -799,6 +799,300 @@ interface FFIDRetryPaymentSummary {
|
|
|
799
799
|
failures: FFIDRetryPaymentFailure[];
|
|
800
800
|
}
|
|
801
801
|
|
|
802
|
+
/**
|
|
803
|
+
* Login history types (ext API).
|
|
804
|
+
*
|
|
805
|
+
* Mirrors the data shape returned by `GET /api/v1/users/ext/me/login-history`
|
|
806
|
+
* (and its cookie counterpart `/api/v1/users/me/login-history`), which is
|
|
807
|
+
* derived from `audit_logs` rows. Field names are `camelCase` to match the
|
|
808
|
+
* route's `data` payload.
|
|
809
|
+
*/
|
|
810
|
+
/**
|
|
811
|
+
* A single login-history entry.
|
|
812
|
+
*
|
|
813
|
+
* Each entry corresponds to one auth audit event (sign-in / sign-out /
|
|
814
|
+
* password-reset). Failed attempts are flagged via {@link isSuspicious}.
|
|
815
|
+
*/
|
|
816
|
+
interface FFIDLoginHistoryEntry {
|
|
817
|
+
/** Audit log entry id (UUID). */
|
|
818
|
+
id: string;
|
|
819
|
+
/** ISO 8601 timestamp of the event. */
|
|
820
|
+
timestamp: string;
|
|
821
|
+
/** Source IP address, or `null` when not recorded. */
|
|
822
|
+
ipAddress: string | null;
|
|
823
|
+
/** User agent string, or `null` when not recorded. */
|
|
824
|
+
userAgent: string | null;
|
|
825
|
+
/** Audit action (e.g. `auth.signin`, `auth.signout`, `auth.password_reset`). */
|
|
826
|
+
action: string;
|
|
827
|
+
/** Whether the auth event succeeded or failed. */
|
|
828
|
+
result: 'success' | 'failure';
|
|
829
|
+
/** `true` for failed attempts (currently equivalent to `result === 'failure'`). */
|
|
830
|
+
isSuspicious: boolean;
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
* Response payload from `getLoginHistory`.
|
|
834
|
+
*
|
|
835
|
+
* `total` is the number of entries returned (not a global count) — it equals
|
|
836
|
+
* `history.length`, matching the route's `{ history, total }` envelope.
|
|
837
|
+
*/
|
|
838
|
+
interface FFIDLoginHistoryResponse {
|
|
839
|
+
/** Recent login-history entries, newest first. */
|
|
840
|
+
history: FFIDLoginHistoryEntry[];
|
|
841
|
+
/** Number of entries returned (equal to `history.length`). */
|
|
842
|
+
total: number;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
/**
|
|
846
|
+
* Types for the organization verified-domains ext API.
|
|
847
|
+
*
|
|
848
|
+
* Mirrors the `VerifiedDomain` row shape returned by the FFID server route
|
|
849
|
+
* `GET /api/v1/organizations/ext/domains` (data field of the response).
|
|
850
|
+
*
|
|
851
|
+
* @see Issue #3783 (non-contract SDK coverage)
|
|
852
|
+
* @see Issue #3757 (verified-domain claims)
|
|
853
|
+
*/
|
|
854
|
+
/** A single organization verified-domain claim. */
|
|
855
|
+
interface FFIDOrganizationDomain {
|
|
856
|
+
/** Domain claim ID (UUID) */
|
|
857
|
+
id: string;
|
|
858
|
+
/** Owning organization ID (UUID) */
|
|
859
|
+
organizationId: string;
|
|
860
|
+
/** Claimed domain (normalized, e.g. `example.com`) */
|
|
861
|
+
domain: string;
|
|
862
|
+
/** Token to publish as a DNS TXT record to prove ownership */
|
|
863
|
+
verificationToken: string;
|
|
864
|
+
/** When ownership was verified, or `null` while the claim is still pending */
|
|
865
|
+
verifiedAt: string | null;
|
|
866
|
+
/** User ID (UUID) that verified the claim, or `null` while pending */
|
|
867
|
+
verifiedBy: string | null;
|
|
868
|
+
/** Whether same-domain users can discover & request to join (only meaningful once verified) */
|
|
869
|
+
discoverable: boolean;
|
|
870
|
+
/** When the claim was created */
|
|
871
|
+
createdAt: string;
|
|
872
|
+
/** When the claim was last updated */
|
|
873
|
+
updatedAt: string;
|
|
874
|
+
}
|
|
875
|
+
/** Response from getOrganizationDomains (ext). */
|
|
876
|
+
interface FFIDOrganizationDomainsResponse {
|
|
877
|
+
domains: FFIDOrganizationDomain[];
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
/**
|
|
881
|
+
* Organization billing notification preference types (ext API).
|
|
882
|
+
*
|
|
883
|
+
* Mirrors the FFID backend `billing_notification_preferences` shape exposed via
|
|
884
|
+
* `GET /api/v1/organizations/ext/notification-preferences` and the matching
|
|
885
|
+
* `PATCH`. Keys use the backend's snake_case casing because they map directly to
|
|
886
|
+
* the stored JSONB column.
|
|
887
|
+
*/
|
|
888
|
+
/**
|
|
889
|
+
* An organization's billing notification preferences.
|
|
890
|
+
*
|
|
891
|
+
* `payment_failed` is a legal obligation and is always `true` — the server
|
|
892
|
+
* forces it on read and write regardless of the requested value.
|
|
893
|
+
*/
|
|
894
|
+
interface FFIDOrganizationNotificationPreferences {
|
|
895
|
+
/** Whether renewal reminder notifications are enabled */
|
|
896
|
+
renewal_reminders: boolean;
|
|
897
|
+
/** Whether monthly usage/summary notifications are enabled */
|
|
898
|
+
monthly_summary: boolean;
|
|
899
|
+
/** Always true — payment failure notifications cannot be disabled (legal obligation) */
|
|
900
|
+
payment_failed: boolean;
|
|
901
|
+
}
|
|
902
|
+
/** Response from getNotificationPreferences / updateNotificationPreferences (ext) */
|
|
903
|
+
interface FFIDOrganizationNotificationPreferencesResponse {
|
|
904
|
+
preferences: FFIDOrganizationNotificationPreferences;
|
|
905
|
+
}
|
|
906
|
+
/**
|
|
907
|
+
* Request payload for updateNotificationPreferences (ext).
|
|
908
|
+
*
|
|
909
|
+
* Partial of the writable keys — only the supplied keys are updated. Omitted
|
|
910
|
+
* keys are reset to their default (`true`) on the server. `payment_failed` is
|
|
911
|
+
* not writable: it is always forced to `true`.
|
|
912
|
+
*/
|
|
913
|
+
type FFIDUpdateNotificationPreferencesRequest = Partial<Pick<FFIDOrganizationNotificationPreferences, 'renewal_reminders' | 'monthly_summary'>>;
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* Invitation status returned by the ext invite endpoint.
|
|
917
|
+
*
|
|
918
|
+
* A freshly created invitation is always `pending`; the broader union is
|
|
919
|
+
* included to match the route's `status` field (sourced from the invitations
|
|
920
|
+
* table) so consumers can narrow safely.
|
|
921
|
+
*/
|
|
922
|
+
type FFIDInvitationStatus = 'pending' | 'accepted' | 'expired' | 'cancelled';
|
|
923
|
+
/**
|
|
924
|
+
* Response from inviteMember (ext).
|
|
925
|
+
*
|
|
926
|
+
* Matches the `/api/v1/organizations/ext/invite` route data exactly:
|
|
927
|
+
* `{ id, email, role, status, expiresAt }`.
|
|
928
|
+
*/
|
|
929
|
+
interface FFIDInviteMemberResponse {
|
|
930
|
+
/** Invitation ID (UUID) */
|
|
931
|
+
id: string;
|
|
932
|
+
/** Invited email address (normalized server-side) */
|
|
933
|
+
email: string;
|
|
934
|
+
/** Role assigned to the invitation */
|
|
935
|
+
role: FFIDMemberRole;
|
|
936
|
+
/** Invitation lifecycle status (always `pending` on creation) */
|
|
937
|
+
status: FFIDInvitationStatus;
|
|
938
|
+
/** ISO 8601 timestamp when the invitation expires */
|
|
939
|
+
expiresAt: string;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
/**
|
|
943
|
+
* Types for the user-scoped organization membership methods (ext API).
|
|
944
|
+
*
|
|
945
|
+
* Backs `leaveOrganization` — a DESTRUCTIVE self-leave operation against
|
|
946
|
+
* `DELETE /api/v1/users/ext/me/organizations/:organizationId`.
|
|
947
|
+
*/
|
|
948
|
+
/**
|
|
949
|
+
* Parameters for `leaveOrganization`.
|
|
950
|
+
*
|
|
951
|
+
* `userId` is REQUIRED in `service-key` auth mode (there is no ambient user on
|
|
952
|
+
* a service credential, so the leaving user must be named explicitly). In
|
|
953
|
+
* `token` / `cookie` modes it is derived server-side from the credential and
|
|
954
|
+
* may be omitted; if provided in those modes it is ignored by the server.
|
|
955
|
+
*/
|
|
956
|
+
interface FFIDLeaveOrganizationParams {
|
|
957
|
+
/** The organization the user is leaving (UUID). */
|
|
958
|
+
organizationId: string;
|
|
959
|
+
/**
|
|
960
|
+
* The leaving user's id (UUID). Required for `service-key` mode; optional
|
|
961
|
+
* (and server-ignored) for `token` / `cookie` modes.
|
|
962
|
+
*/
|
|
963
|
+
userId?: string;
|
|
964
|
+
}
|
|
965
|
+
/**
|
|
966
|
+
* Response from `leaveOrganization` (ext).
|
|
967
|
+
*
|
|
968
|
+
* Matches the route's success `data` shape `{ message }`.
|
|
969
|
+
*/
|
|
970
|
+
interface FFIDLeaveOrganizationResponse {
|
|
971
|
+
/** Human-readable confirmation message (Japanese). */
|
|
972
|
+
message: string;
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
/**
|
|
976
|
+
* User profile types (ext API: `GET` / `PUT /api/v1/users/ext/me`).
|
|
977
|
+
*
|
|
978
|
+
* Extracted from `./index.ts` to keep the types barrel under the file-size
|
|
979
|
+
* limit, consistent with the per-domain extraction already used for
|
|
980
|
+
* `service-access`, `organization-members`, `contract-resources`, etc. The
|
|
981
|
+
* barrel re-exports these so the public import path (`@feelflow/ffid-sdk`)
|
|
982
|
+
* is unchanged.
|
|
983
|
+
*/
|
|
984
|
+
/**
|
|
985
|
+
* User profile for the authenticated user (returned by `getProfile` / `updateProfile`).
|
|
986
|
+
*
|
|
987
|
+
* Mirrors the FFID backend `UserProfile` shape exposed via
|
|
988
|
+
* `GET /api/v1/users/ext/me` and `PUT /api/v1/users/ext/me`.
|
|
989
|
+
*/
|
|
990
|
+
interface FFIDUserProfile {
|
|
991
|
+
/** User ID (UUID) */
|
|
992
|
+
id: string;
|
|
993
|
+
/** Email address */
|
|
994
|
+
email: string;
|
|
995
|
+
/** Display name (nullable when not set) */
|
|
996
|
+
displayName: string | null;
|
|
997
|
+
/** Avatar URL (nullable when not set) */
|
|
998
|
+
avatarUrl: string | null;
|
|
999
|
+
/** Phone number (nullable when not set) */
|
|
1000
|
+
phone: string | null;
|
|
1001
|
+
/** Company name (nullable when not set) */
|
|
1002
|
+
companyName: string | null;
|
|
1003
|
+
/** Department (nullable when not set) */
|
|
1004
|
+
department: string | null;
|
|
1005
|
+
/** Job title (nullable when not set) */
|
|
1006
|
+
jobTitle: string | null;
|
|
1007
|
+
/** IANA timezone (e.g. 'Asia/Tokyo') */
|
|
1008
|
+
timezone: string;
|
|
1009
|
+
/** Locale (e.g. 'ja', 'en') */
|
|
1010
|
+
locale: string;
|
|
1011
|
+
/** Arbitrary user preferences bag */
|
|
1012
|
+
preferences: Record<string, unknown>;
|
|
1013
|
+
/** Account creation timestamp (ISO 8601) */
|
|
1014
|
+
createdAt: string;
|
|
1015
|
+
/** Profile last-updated timestamp (ISO 8601) */
|
|
1016
|
+
updatedAt: string;
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* Per-call options for profile methods (`getProfile` / `updateProfile`).
|
|
1020
|
+
*
|
|
1021
|
+
* Supply `accessToken` to forward an end-user Bearer token for the single call
|
|
1022
|
+
* without mutating client-level auth state. Designed for server runtimes (Cloudflare
|
|
1023
|
+
* Workers, Edge, Node) that receive a user-scoped Bearer per request and want to
|
|
1024
|
+
* act as that user against `/api/v1/users/ext/me`.
|
|
1025
|
+
*
|
|
1026
|
+
* When `accessToken` is supplied with a non-empty value, it overrides the client's
|
|
1027
|
+
* configured auth mode: authentication for that request uses only
|
|
1028
|
+
* `Authorization: Bearer <accessToken>` (no service key, no cookie, no token-store
|
|
1029
|
+
* lookup, no auto-refresh on 401). Non-auth headers such as `Content-Type` are
|
|
1030
|
+
* still attached. SDK metadata headers (`User-Agent` / `X-FFID-SDK-Version`) are
|
|
1031
|
+
* attached on non-browser runtimes only (Node.js / Cloudflare Workers / Edge /
|
|
1032
|
+
* Deno); browsers receive an empty object to avoid iOS WebKit `fetch()` breakage
|
|
1033
|
+
* (see #2417).
|
|
1034
|
+
*
|
|
1035
|
+
* Runtime semantics:
|
|
1036
|
+
* - `accessToken` omitted (or `undefined`) → no override, configured `authMode` is used
|
|
1037
|
+
* - `accessToken` is empty string / whitespace-only → rejected as `VALIDATION_ERROR`
|
|
1038
|
+
* before any network call (prevents silent impersonation fallback when a caller
|
|
1039
|
+
* extracts a missing/blank `Authorization` header into this field)
|
|
1040
|
+
* - `accessToken` is a non-empty string → override activated
|
|
1041
|
+
*/
|
|
1042
|
+
interface FFIDProfileCallOptions {
|
|
1043
|
+
/**
|
|
1044
|
+
* End-user Bearer token forwarded for this single request.
|
|
1045
|
+
*
|
|
1046
|
+
* Must be a non-empty string when supplied. Passing `''` or a whitespace-only
|
|
1047
|
+
* string is treated as a caller error and surfaces as `VALIDATION_ERROR` —
|
|
1048
|
+
* this guards against the common footgun where a server runtime extracts the
|
|
1049
|
+
* Bearer from an incoming request without checking the header is present.
|
|
1050
|
+
*/
|
|
1051
|
+
accessToken?: string;
|
|
1052
|
+
}
|
|
1053
|
+
/**
|
|
1054
|
+
* Request payload for `updateProfile`.
|
|
1055
|
+
*
|
|
1056
|
+
* Mirrors the FFID backend `UpdateUserProfileRequest` shape. All fields are
|
|
1057
|
+
* optional — only the supplied keys will be updated (partial update semantics).
|
|
1058
|
+
*
|
|
1059
|
+
* Per-field value semantics:
|
|
1060
|
+
* - `undefined` / key omitted → field is untouched (partial update)
|
|
1061
|
+
* - `null` → clears the field (stores SQL NULL in the DB)
|
|
1062
|
+
* - `""` (empty string) → stored as a literal empty string, **not** treated as
|
|
1063
|
+
* a clear. Use `null` when you want the DB value to become NULL
|
|
1064
|
+
*
|
|
1065
|
+
* `timezone` and `locale` are intentionally modeled as non-null in this
|
|
1066
|
+
* request type (application-level invariant — the DB columns have DEFAULT
|
|
1067
|
+
* values but no NOT NULL constraint, yet the server-side normalization
|
|
1068
|
+
* pipeline assumes a string is always present). Pass a string to update the
|
|
1069
|
+
* value, or omit the key to leave the current value in place. Do not pass
|
|
1070
|
+
* `null` to clear — there is no meaningful "no timezone" state for a user.
|
|
1071
|
+
*
|
|
1072
|
+
* `preferences: null` is accepted and clears the column. Subsequent reads
|
|
1073
|
+
* return `{}` because the FFID backend normalizes a null `preferences` column
|
|
1074
|
+
* to an empty object (`toUserProfile` helper) before serializing the response —
|
|
1075
|
+
* the SDK itself does not transform the payload.
|
|
1076
|
+
*/
|
|
1077
|
+
interface FFIDUpdateUserProfileRequest {
|
|
1078
|
+
/** Display name (null clears the field) */
|
|
1079
|
+
displayName?: string | null;
|
|
1080
|
+
/** Phone number (null clears the field) */
|
|
1081
|
+
phone?: string | null;
|
|
1082
|
+
/** Company name (null clears the field) */
|
|
1083
|
+
companyName?: string | null;
|
|
1084
|
+
/** Department (null clears the field) */
|
|
1085
|
+
department?: string | null;
|
|
1086
|
+
/** Job title (null clears the field) */
|
|
1087
|
+
jobTitle?: string | null;
|
|
1088
|
+
/** IANA timezone (non-null; omit the key to leave unchanged) */
|
|
1089
|
+
timezone?: string;
|
|
1090
|
+
/** Locale (non-null; omit the key to leave unchanged) */
|
|
1091
|
+
locale?: string;
|
|
1092
|
+
/** Arbitrary user preferences bag (null clears the column; reads return {}) */
|
|
1093
|
+
preferences?: Record<string, unknown> | null;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
802
1096
|
/**
|
|
803
1097
|
* FFID SDK Type Definitions
|
|
804
1098
|
*
|
|
@@ -955,6 +1249,17 @@ interface FFIDOAuthUserInfoSubscription {
|
|
|
955
1249
|
interface FFIDOAuthUserInfo {
|
|
956
1250
|
sub: string;
|
|
957
1251
|
email: string | null;
|
|
1252
|
+
/**
|
|
1253
|
+
* Whether the user's email is verified on the FFID side (#3791). Use this to
|
|
1254
|
+
* safely gate email-based auto account-linking (account-takeover prevention):
|
|
1255
|
+
* never auto-link on an unverified email.
|
|
1256
|
+
*
|
|
1257
|
+
* `undefined` means the FFID server predates the field (older deployment) or
|
|
1258
|
+
* the verification path could not populate it — NOT "unverified". Treat
|
|
1259
|
+
* `undefined` as "unknown" and fall back to a stricter linking policy rather
|
|
1260
|
+
* than coercing it to `false`/`true`.
|
|
1261
|
+
*/
|
|
1262
|
+
emailVerified?: boolean | undefined;
|
|
958
1263
|
name: string | null;
|
|
959
1264
|
picture: string | null;
|
|
960
1265
|
companyName?: string | null | undefined;
|
|
@@ -1124,75 +1429,6 @@ type FFIDApiResponse<T> = {
|
|
|
1124
1429
|
error: FFIDError;
|
|
1125
1430
|
};
|
|
1126
1431
|
|
|
1127
|
-
/**
|
|
1128
|
-
* User profile for the authenticated user (returned by `getProfile` / `updateProfile`).
|
|
1129
|
-
*
|
|
1130
|
-
* Mirrors the FFID backend `UserProfile` shape exposed via
|
|
1131
|
-
* `GET /api/v1/users/ext/me` and `PUT /api/v1/users/ext/me`.
|
|
1132
|
-
*/
|
|
1133
|
-
interface FFIDUserProfile {
|
|
1134
|
-
/** User ID (UUID) */
|
|
1135
|
-
id: string;
|
|
1136
|
-
/** Email address */
|
|
1137
|
-
email: string;
|
|
1138
|
-
/** Display name (nullable when not set) */
|
|
1139
|
-
displayName: string | null;
|
|
1140
|
-
/** Avatar URL (nullable when not set) */
|
|
1141
|
-
avatarUrl: string | null;
|
|
1142
|
-
/** Phone number (nullable when not set) */
|
|
1143
|
-
phone: string | null;
|
|
1144
|
-
/** Company name (nullable when not set) */
|
|
1145
|
-
companyName: string | null;
|
|
1146
|
-
/** Department (nullable when not set) */
|
|
1147
|
-
department: string | null;
|
|
1148
|
-
/** Job title (nullable when not set) */
|
|
1149
|
-
jobTitle: string | null;
|
|
1150
|
-
/** IANA timezone (e.g. 'Asia/Tokyo') */
|
|
1151
|
-
timezone: string;
|
|
1152
|
-
/** Locale (e.g. 'ja', 'en') */
|
|
1153
|
-
locale: string;
|
|
1154
|
-
/** Arbitrary user preferences bag */
|
|
1155
|
-
preferences: Record<string, unknown>;
|
|
1156
|
-
/** Account creation timestamp (ISO 8601) */
|
|
1157
|
-
createdAt: string;
|
|
1158
|
-
/** Profile last-updated timestamp (ISO 8601) */
|
|
1159
|
-
updatedAt: string;
|
|
1160
|
-
}
|
|
1161
|
-
/**
|
|
1162
|
-
* Per-call options for profile methods (`getProfile` / `updateProfile`).
|
|
1163
|
-
*
|
|
1164
|
-
* Supply `accessToken` to forward an end-user Bearer token for the single call
|
|
1165
|
-
* without mutating client-level auth state. Designed for server runtimes (Cloudflare
|
|
1166
|
-
* Workers, Edge, Node) that receive a user-scoped Bearer per request and want to
|
|
1167
|
-
* act as that user against `/api/v1/users/ext/me`.
|
|
1168
|
-
*
|
|
1169
|
-
* When `accessToken` is supplied with a non-empty value, it overrides the client's
|
|
1170
|
-
* configured auth mode: authentication for that request uses only
|
|
1171
|
-
* `Authorization: Bearer <accessToken>` (no service key, no cookie, no token-store
|
|
1172
|
-
* lookup, no auto-refresh on 401). Non-auth headers such as `Content-Type` are
|
|
1173
|
-
* still attached. SDK metadata headers (`User-Agent` / `X-FFID-SDK-Version`) are
|
|
1174
|
-
* attached on non-browser runtimes only (Node.js / Cloudflare Workers / Edge /
|
|
1175
|
-
* Deno); browsers receive an empty object to avoid iOS WebKit `fetch()` breakage
|
|
1176
|
-
* (see #2417).
|
|
1177
|
-
*
|
|
1178
|
-
* Runtime semantics:
|
|
1179
|
-
* - `accessToken` omitted (or `undefined`) → no override, configured `authMode` is used
|
|
1180
|
-
* - `accessToken` is empty string / whitespace-only → rejected as `VALIDATION_ERROR`
|
|
1181
|
-
* before any network call (prevents silent impersonation fallback when a caller
|
|
1182
|
-
* extracts a missing/blank `Authorization` header into this field)
|
|
1183
|
-
* - `accessToken` is a non-empty string → override activated
|
|
1184
|
-
*/
|
|
1185
|
-
interface FFIDProfileCallOptions {
|
|
1186
|
-
/**
|
|
1187
|
-
* End-user Bearer token forwarded for this single request.
|
|
1188
|
-
*
|
|
1189
|
-
* Must be a non-empty string when supplied. Passing `''` or a whitespace-only
|
|
1190
|
-
* string is treated as a caller error and surfaces as `VALIDATION_ERROR` —
|
|
1191
|
-
* this guards against the common footgun where a server runtime extracts the
|
|
1192
|
-
* Bearer from an incoming request without checking the header is present.
|
|
1193
|
-
*/
|
|
1194
|
-
accessToken?: string;
|
|
1195
|
-
}
|
|
1196
1432
|
/**
|
|
1197
1433
|
* Response shape from `GET /api/v1/ext/analytics/config?service=<code>`.
|
|
1198
1434
|
*
|
|
@@ -1216,48 +1452,6 @@ interface FFIDAnalyticsConfig {
|
|
|
1216
1452
|
*/
|
|
1217
1453
|
isActive: boolean;
|
|
1218
1454
|
}
|
|
1219
|
-
/**
|
|
1220
|
-
* Request payload for `updateProfile`.
|
|
1221
|
-
*
|
|
1222
|
-
* Mirrors the FFID backend `UpdateUserProfileRequest` shape. All fields are
|
|
1223
|
-
* optional — only the supplied keys will be updated (partial update semantics).
|
|
1224
|
-
*
|
|
1225
|
-
* Per-field value semantics:
|
|
1226
|
-
* - `undefined` / key omitted → field is untouched (partial update)
|
|
1227
|
-
* - `null` → clears the field (stores SQL NULL in the DB)
|
|
1228
|
-
* - `""` (empty string) → stored as a literal empty string, **not** treated as
|
|
1229
|
-
* a clear. Use `null` when you want the DB value to become NULL
|
|
1230
|
-
*
|
|
1231
|
-
* `timezone` and `locale` are intentionally modeled as non-null in this
|
|
1232
|
-
* request type (application-level invariant — the DB columns have DEFAULT
|
|
1233
|
-
* values but no NOT NULL constraint, yet the server-side normalization
|
|
1234
|
-
* pipeline assumes a string is always present). Pass a string to update the
|
|
1235
|
-
* value, or omit the key to leave the current value in place. Do not pass
|
|
1236
|
-
* `null` to clear — there is no meaningful "no timezone" state for a user.
|
|
1237
|
-
*
|
|
1238
|
-
* `preferences: null` is accepted and clears the column. Subsequent reads
|
|
1239
|
-
* return `{}` because the FFID backend normalizes a null `preferences` column
|
|
1240
|
-
* to an empty object (`toUserProfile` helper) before serializing the response —
|
|
1241
|
-
* the SDK itself does not transform the payload.
|
|
1242
|
-
*/
|
|
1243
|
-
interface FFIDUpdateUserProfileRequest {
|
|
1244
|
-
/** Display name (null clears the field) */
|
|
1245
|
-
displayName?: string | null;
|
|
1246
|
-
/** Phone number (null clears the field) */
|
|
1247
|
-
phone?: string | null;
|
|
1248
|
-
/** Company name (null clears the field) */
|
|
1249
|
-
companyName?: string | null;
|
|
1250
|
-
/** Department (null clears the field) */
|
|
1251
|
-
department?: string | null;
|
|
1252
|
-
/** Job title (null clears the field) */
|
|
1253
|
-
jobTitle?: string | null;
|
|
1254
|
-
/** IANA timezone (non-null; omit the key to leave unchanged) */
|
|
1255
|
-
timezone?: string;
|
|
1256
|
-
/** Locale (non-null; omit the key to leave unchanged) */
|
|
1257
|
-
locale?: string;
|
|
1258
|
-
/** Arbitrary user preferences bag (null clears the column; reads return {}) */
|
|
1259
|
-
preferences?: Record<string, unknown> | null;
|
|
1260
|
-
}
|
|
1261
1455
|
/**
|
|
1262
1456
|
* Discriminant for redirect failures that callers need to handle
|
|
1263
1457
|
* programmatically (vs. logging the human-readable `error` string).
|
|
@@ -1353,32 +1547,24 @@ interface ContractWizardSubscriptionOptions {
|
|
|
1353
1547
|
organizationId?: string;
|
|
1354
1548
|
}
|
|
1355
1549
|
|
|
1356
|
-
/**
|
|
1550
|
+
/** Login history methods - getLoginHistory (ext API) */
|
|
1357
1551
|
|
|
1358
|
-
/**
|
|
1359
|
-
|
|
1360
|
-
* Forwards to Supabase Auth signup screen; only the `'signup'` value is
|
|
1361
|
-
* propagated (no-op when `'login'` or omitted).
|
|
1362
|
-
*/
|
|
1363
|
-
declare const SCREEN_HINT_SIGNUP: "signup";
|
|
1364
|
-
/** Options for redirectToAuthorize */
|
|
1365
|
-
interface RedirectToAuthorizeOptions {
|
|
1366
|
-
/** Target organization ID — triggers org-scoped OAuth re-authorization */
|
|
1367
|
-
organizationId?: string;
|
|
1552
|
+
/** Parameters accepted by `getLoginHistory`. */
|
|
1553
|
+
interface FFIDGetLoginHistoryParams {
|
|
1368
1554
|
/**
|
|
1369
|
-
*
|
|
1555
|
+
* Target user id (UUID).
|
|
1370
1556
|
*
|
|
1371
|
-
*
|
|
1372
|
-
*
|
|
1373
|
-
*
|
|
1374
|
-
* -
|
|
1375
|
-
* login screen is shown.
|
|
1376
|
-
*
|
|
1377
|
-
* In cookie mode, `'signup'` redirects to the FFID `/signup` page instead
|
|
1378
|
-
* of `/login` so the SDK contract (signup-screen intent) stays consistent
|
|
1379
|
-
* regardless of `authMode`.
|
|
1557
|
+
* **Required in `service-key` auth mode** — an `X-Service-Api-Key` request
|
|
1558
|
+
* has no ambient user, so the server requires `?userId=` to know whose
|
|
1559
|
+
* history to return. In `token` / `cookie` auth modes the user is derived
|
|
1560
|
+
* server-side from the credential, so `userId` is ignored if supplied.
|
|
1380
1561
|
*/
|
|
1381
|
-
|
|
1562
|
+
userId?: string;
|
|
1563
|
+
/**
|
|
1564
|
+
* Maximum number of entries to return. Clamped server-side to the route's
|
|
1565
|
+
* ceiling (20); omit to use the default.
|
|
1566
|
+
*/
|
|
1567
|
+
limit?: number;
|
|
1382
1568
|
}
|
|
1383
1569
|
|
|
1384
1570
|
/**
|
|
@@ -1422,6 +1608,53 @@ interface TokenStore {
|
|
|
1422
1608
|
*/
|
|
1423
1609
|
declare function createTokenStore(storageType?: 'localStorage' | 'memory'): TokenStore;
|
|
1424
1610
|
|
|
1611
|
+
/** OAuth token operations - exchangeCodeForTokens / refreshAccessToken / signOutToken */
|
|
1612
|
+
|
|
1613
|
+
/**
|
|
1614
|
+
* Optional OAuth `state` validation for {@link exchangeCodeForTokens}.
|
|
1615
|
+
*
|
|
1616
|
+
* If a `state` is supplied on EITHER side — `expectedState` (the value persisted
|
|
1617
|
+
* at `redirectToAuthorize`) or `actualState` (the value returned on the callback
|
|
1618
|
+
* URL) — both must be present and equal before any token exchange. A mismatch
|
|
1619
|
+
* OR an omitted counterpart fails closed (no exchange) to defend against CSRF
|
|
1620
|
+
* (RFC 6749 §10.12 / #3841). Validation is skipped only when BOTH are omitted
|
|
1621
|
+
* (backward compatible — callers that don't opt in are unaffected).
|
|
1622
|
+
*/
|
|
1623
|
+
interface ExchangeCodeForTokensOptions {
|
|
1624
|
+
/** Stored state from `redirectToAuthorize` (e.g. `retrieveState()`) */
|
|
1625
|
+
expectedState?: string;
|
|
1626
|
+
/** State returned on the OAuth callback URL */
|
|
1627
|
+
actualState?: string;
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1630
|
+
/** Redirect and URL generation - redirectToLogin / redirectToAuthorize / redirectToLogout / getLoginUrl / getSignupUrl / getLogoutUrl */
|
|
1631
|
+
|
|
1632
|
+
/**
|
|
1633
|
+
* `screen_hint=signup` query value for `/oauth/authorize` (#2908 / #2911).
|
|
1634
|
+
* Forwards to Supabase Auth signup screen; only the `'signup'` value is
|
|
1635
|
+
* propagated (no-op when `'login'` or omitted).
|
|
1636
|
+
*/
|
|
1637
|
+
declare const SCREEN_HINT_SIGNUP: "signup";
|
|
1638
|
+
/** Options for redirectToAuthorize */
|
|
1639
|
+
interface RedirectToAuthorizeOptions {
|
|
1640
|
+
/** Target organization ID — triggers org-scoped OAuth re-authorization */
|
|
1641
|
+
organizationId?: string;
|
|
1642
|
+
/**
|
|
1643
|
+
* Initial Supabase Auth screen hint (#2908 / #2911).
|
|
1644
|
+
*
|
|
1645
|
+
* - `'signup'`: forwards `?screen_hint=signup` so the FFID OAuth flow lands
|
|
1646
|
+
* on the signup screen (used by external services that want to deep-link
|
|
1647
|
+
* new users into the signup CTA).
|
|
1648
|
+
* - `'login'` / `undefined`: no `screen_hint` param is added — the default
|
|
1649
|
+
* login screen is shown.
|
|
1650
|
+
*
|
|
1651
|
+
* In cookie mode, `'signup'` redirects to the FFID `/signup` page instead
|
|
1652
|
+
* of `/login` so the SDK contract (signup-screen intent) stays consistent
|
|
1653
|
+
* regardless of `authMode`.
|
|
1654
|
+
*/
|
|
1655
|
+
screenHint?: typeof SCREEN_HINT_SIGNUP | 'login';
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1425
1658
|
/** Creates an FFID API client instance */
|
|
1426
1659
|
declare function createFFIDClient(config: FFIDConfig): {
|
|
1427
1660
|
getSession: () => Promise<FFIDApiResponse<FFIDSessionResponse>>;
|
|
@@ -1433,7 +1666,7 @@ declare function createFFIDClient(config: FFIDConfig): {
|
|
|
1433
1666
|
getLogoutUrl: (postLogoutRedirectUri?: string) => string;
|
|
1434
1667
|
getSignupUrl: (redirectUrl?: string) => string;
|
|
1435
1668
|
createError: (code: string, message: string) => FFIDError;
|
|
1436
|
-
exchangeCodeForTokens: (code: string, codeVerifier?: string) => Promise<FFIDApiResponse<void>>;
|
|
1669
|
+
exchangeCodeForTokens: (code: string, codeVerifier?: string, opts?: ExchangeCodeForTokensOptions) => Promise<FFIDApiResponse<void>>;
|
|
1437
1670
|
refreshAccessToken: () => Promise<FFIDApiResponse<void>>;
|
|
1438
1671
|
checkSubscription: (params: {
|
|
1439
1672
|
userId?: string;
|
|
@@ -1459,6 +1692,23 @@ declare function createFFIDClient(config: FFIDConfig): {
|
|
|
1459
1692
|
}) => Promise<FFIDApiResponse<FFIDRemoveMemberResponse>>;
|
|
1460
1693
|
getProfile: (options?: FFIDProfileCallOptions) => Promise<FFIDApiResponse<FFIDUserProfile>>;
|
|
1461
1694
|
updateProfile: (data: FFIDUpdateUserProfileRequest, options?: FFIDProfileCallOptions) => Promise<FFIDApiResponse<FFIDUserProfile>>;
|
|
1695
|
+
getLoginHistory: (params?: FFIDGetLoginHistoryParams) => Promise<FFIDApiResponse<FFIDLoginHistoryResponse>>;
|
|
1696
|
+
getOrganizationDomains: (params: {
|
|
1697
|
+
organizationId: string;
|
|
1698
|
+
}) => Promise<FFIDApiResponse<FFIDOrganizationDomainsResponse>>;
|
|
1699
|
+
getNotificationPreferences: (params: {
|
|
1700
|
+
organizationId: string;
|
|
1701
|
+
}) => Promise<FFIDApiResponse<FFIDOrganizationNotificationPreferencesResponse>>;
|
|
1702
|
+
updateNotificationPreferences: (params: {
|
|
1703
|
+
organizationId: string;
|
|
1704
|
+
preferences: FFIDUpdateNotificationPreferencesRequest;
|
|
1705
|
+
}) => Promise<FFIDApiResponse<FFIDOrganizationNotificationPreferencesResponse>>;
|
|
1706
|
+
inviteMember: (params: {
|
|
1707
|
+
organizationId: string;
|
|
1708
|
+
email: string;
|
|
1709
|
+
role?: FFIDAssignableMemberRole;
|
|
1710
|
+
}) => Promise<FFIDApiResponse<FFIDInviteMemberResponse>>;
|
|
1711
|
+
leaveOrganization: (params: FFIDLeaveOrganizationParams) => Promise<FFIDApiResponse<FFIDLeaveOrganizationResponse>>;
|
|
1462
1712
|
getAnalyticsConfig: (serviceCode: string, options?: FFIDProfileCallOptions) => Promise<FFIDApiResponse<FFIDAnalyticsConfig>>;
|
|
1463
1713
|
createCheckoutSession: (params: FFIDCreateCheckoutParams) => Promise<FFIDApiResponse<FFIDCheckoutSessionResponse>>;
|
|
1464
1714
|
createPortalSession: (params: FFIDCreatePortalParams) => Promise<FFIDApiResponse<FFIDPortalSessionResponse>>;
|