@flow-industries/id 0.14.0 → 0.16.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/sdk/client/create-flow.js +7 -1
- package/dist/sdk/client/profile-button.js +14 -0
- package/dist/sdk/client/session.js +6 -2
- package/dist/sdk/client/signing.js +5 -0
- package/dist/sdk/types/auth.d.ts +64 -1
- package/dist/sdk/types/dialog.d.ts +13 -0
- package/dist/sdk/types/events.d.ts +9 -3
- package/dist/sdk/types/index.d.ts +3 -3
- package/dist/sdk/types/messenger.d.ts +7 -0
- package/dist/sdk/types/protocol.d.ts +2 -1
- package/dist/sdk/types/rooms.d.ts +28 -0
- package/dist/sdk/types/sdk.d.ts +6 -2
- package/package.json +3 -2
|
@@ -393,7 +393,13 @@ export function createFlow(options = {}) {
|
|
|
393
393
|
});
|
|
394
394
|
await installSession(refreshToken, session.jwt);
|
|
395
395
|
deliverAdditionalSessions(additionalSessions);
|
|
396
|
-
|
|
396
|
+
// webauthn implies a passkey ceremony ran, but the types allow an
|
|
397
|
+
// email-only session — finalize only with a real credential/address.
|
|
398
|
+
if (accessKeyModule &&
|
|
399
|
+
accessKeyPrep &&
|
|
400
|
+
webauthn &&
|
|
401
|
+
session.credential &&
|
|
402
|
+
session.address) {
|
|
397
403
|
await accessKeyModule.finalizeAccessKey({
|
|
398
404
|
address: session.address,
|
|
399
405
|
credential: session.credential,
|
|
@@ -81,6 +81,13 @@ export function createProfileButton(options) {
|
|
|
81
81
|
? { username: user.username, isGuest: user.isGuest === true }
|
|
82
82
|
: null;
|
|
83
83
|
}
|
|
84
|
+
// The widget's only credential. `getToken` refreshes a token that is missing
|
|
85
|
+
// or near expiry, so a widget open on a page left idle past the 1h access-
|
|
86
|
+
// token lifetime still gets a live one instead of a 401.
|
|
87
|
+
async function answerTokenRequest(bridge, id) {
|
|
88
|
+
const token = await flow.getToken().catch(() => null);
|
|
89
|
+
void bridge.send("__internal", { type: "profile-token", id, token });
|
|
90
|
+
}
|
|
84
91
|
// ----- the persistent pill (stays mounted; sizes to its own content) -----
|
|
85
92
|
const pill = makeFrame();
|
|
86
93
|
let pillWidth = 0;
|
|
@@ -105,6 +112,9 @@ export function createProfileButton(options) {
|
|
|
105
112
|
else if (payload.type === "profile-expand") {
|
|
106
113
|
showDialog();
|
|
107
114
|
}
|
|
115
|
+
else if (payload.type === "profile-token-request") {
|
|
116
|
+
void answerTokenRequest(pillBridge, payload.id);
|
|
117
|
+
}
|
|
108
118
|
});
|
|
109
119
|
// ----- the dialog overlay (lazy; a separate fullscreen iframe layered ABOVE
|
|
110
120
|
// the pill, so the pill shows through its dimmed backdrop) -----
|
|
@@ -131,6 +141,10 @@ export function createProfileButton(options) {
|
|
|
131
141
|
hideDialog();
|
|
132
142
|
void flow.logout().catch(() => { });
|
|
133
143
|
}
|
|
144
|
+
else if (payload.type === "profile-token-request") {
|
|
145
|
+
if (dialogBridge)
|
|
146
|
+
void answerTokenRequest(dialogBridge, payload.id);
|
|
147
|
+
}
|
|
134
148
|
});
|
|
135
149
|
void dialogBridge.send("__internal", {
|
|
136
150
|
type: "profile-identity",
|
|
@@ -41,8 +41,12 @@ export async function runLogin(params) {
|
|
|
41
41
|
{ capabilities },
|
|
42
42
|
]));
|
|
43
43
|
const { jwt, refreshToken, user, credential, webauthn, additionalSessions } = result;
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
// An email-only login carries no credential — mirror the guest handling:
|
|
45
|
+
// nothing is persisted to IDB (reserved for a real passkey credential) and
|
|
46
|
+
// the address stays null until a passkey is added.
|
|
47
|
+
const address = credential ? credentialToAddress(credential) : null;
|
|
48
|
+
if (credential)
|
|
49
|
+
await idb.set(CREDENTIAL_KEY, credential);
|
|
46
50
|
store.setState({ user, jwt, credential, address });
|
|
47
51
|
return {
|
|
48
52
|
session: { user, jwt, credential, address },
|
|
@@ -4,6 +4,11 @@ import { Account, walletNamespaceCompat } from "viem/tempo";
|
|
|
4
4
|
import { buildAccessKeyAccount, clearAccessKey, consumePendingAuthorization, isExpired, loadAccessKey, } from "./access-key";
|
|
5
5
|
function requireAuth(state) {
|
|
6
6
|
if (!state.credential || !state.address) {
|
|
7
|
+
// An email-only or guest session is authenticated but has no passkey to
|
|
8
|
+
// sign with — distinguish that from being signed out entirely.
|
|
9
|
+
if (state.user) {
|
|
10
|
+
throw new Error("This session has no passkey — add one to your account to sign");
|
|
11
|
+
}
|
|
7
12
|
throw new Error("Not authenticated — call flow.login() first");
|
|
8
13
|
}
|
|
9
14
|
return { credential: state.credential, address: state.address };
|
package/dist/sdk/types/auth.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { JWTPayload } from "jose";
|
|
2
|
+
import type { AuthEventName } from "./events";
|
|
2
3
|
export type FlowUser = {
|
|
3
4
|
id: string;
|
|
4
5
|
username: string;
|
|
@@ -14,6 +15,17 @@ export type FlowCredential = {
|
|
|
14
15
|
id: string;
|
|
15
16
|
publicKey: string;
|
|
16
17
|
};
|
|
18
|
+
/** The better-auth session user with Flow's additional fields — the one
|
|
19
|
+
* shape routes cast `session.user` to instead of ad-hoc inline casts. */
|
|
20
|
+
export interface SessionUser {
|
|
21
|
+
id: string;
|
|
22
|
+
email?: string | null;
|
|
23
|
+
emailVerified?: boolean;
|
|
24
|
+
username?: string | null;
|
|
25
|
+
isGuest?: boolean;
|
|
26
|
+
role?: string | null;
|
|
27
|
+
image?: string | null;
|
|
28
|
+
}
|
|
17
29
|
/**
|
|
18
30
|
* A session minted for one of the ADDITIONAL audiences a login requested
|
|
19
31
|
* (AUTH-39): its own refresh-token lineage and access JWT, both bound to
|
|
@@ -30,7 +42,8 @@ export type AuthResponse = {
|
|
|
30
42
|
jwt: string;
|
|
31
43
|
refreshToken: string;
|
|
32
44
|
user: FlowUser;
|
|
33
|
-
|
|
45
|
+
/** Null for an email-only session (no passkey on the account yet). */
|
|
46
|
+
credential: FlowCredential | null;
|
|
34
47
|
additionalSessions?: AdditionalSession[];
|
|
35
48
|
};
|
|
36
49
|
export type AuthConfig = {
|
|
@@ -60,6 +73,56 @@ export type VerifyOptions = {
|
|
|
60
73
|
audience: string;
|
|
61
74
|
issuerUrl?: string;
|
|
62
75
|
};
|
|
76
|
+
/**
|
|
77
|
+
* One entry in the signed-in user's session list (`GET /api/account/sessions`).
|
|
78
|
+
* An entry is either a cookie session (with the activity of its linked app
|
|
79
|
+
* refresh lineages folded in) or an app-only refresh lineage whose cookie
|
|
80
|
+
* session no longer exists. `id` is an opaque revocation handle — never a
|
|
81
|
+
* token, and never another user's row.
|
|
82
|
+
*/
|
|
83
|
+
export type AccountSession = {
|
|
84
|
+
id: string;
|
|
85
|
+
/** The app origin the session was opened for; null on a pre-audience row. */
|
|
86
|
+
audience: string | null;
|
|
87
|
+
/** Coarse "Browser · OS" from the sign-in user agent; null when unknown. */
|
|
88
|
+
device: string | null;
|
|
89
|
+
createdAt: string;
|
|
90
|
+
/** Latest activity across the cookie session and its app refresh lineages. */
|
|
91
|
+
lastSeenAt: string;
|
|
92
|
+
expiresAt: string;
|
|
93
|
+
/** True for the session serving this request. */
|
|
94
|
+
isCurrent: boolean;
|
|
95
|
+
};
|
|
96
|
+
export type AccountSessionsResponse = {
|
|
97
|
+
sessions: AccountSession[];
|
|
98
|
+
};
|
|
99
|
+
/** Result of `DELETE /api/account/sessions/:id`. */
|
|
100
|
+
export type RevokeSessionResponse = {
|
|
101
|
+
revoked: true;
|
|
102
|
+
/** True when the caller revoked the session serving the request itself. */
|
|
103
|
+
wasCurrent: boolean;
|
|
104
|
+
};
|
|
105
|
+
/** Result of `POST /api/account/sessions/revoke-all`. */
|
|
106
|
+
export type RevokeAllSessionsResponse = {
|
|
107
|
+
revokedSessions: number;
|
|
108
|
+
revokedLineages: number;
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* One entry of the user-facing security feed
|
|
112
|
+
* (`GET /api/account/security-events`). Country and coarse device only —
|
|
113
|
+
* the stored ip and raw user agent never leave the server.
|
|
114
|
+
*/
|
|
115
|
+
export type SecurityActivityEntry = {
|
|
116
|
+
id: string;
|
|
117
|
+
event: AuthEventName;
|
|
118
|
+
audience: string | null;
|
|
119
|
+
country: string | null;
|
|
120
|
+
device: string | null;
|
|
121
|
+
createdAt: string;
|
|
122
|
+
};
|
|
123
|
+
export type SecurityActivityResponse = {
|
|
124
|
+
events: SecurityActivityEntry[];
|
|
125
|
+
};
|
|
63
126
|
export type VerifiedFlowJWT = JWTPayload & {
|
|
64
127
|
sub: string;
|
|
65
128
|
username?: string;
|
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Async view state for a dialog panel — the three states every fetched
|
|
3
|
+
* section renders (spinner / retry row / content), so "empty" stays
|
|
4
|
+
* distinguishable from "not loaded yet".
|
|
5
|
+
*/
|
|
6
|
+
export type Loadable<T> = {
|
|
7
|
+
status: "loading";
|
|
8
|
+
} | {
|
|
9
|
+
status: "error";
|
|
10
|
+
} | {
|
|
11
|
+
status: "ready";
|
|
12
|
+
data: T;
|
|
13
|
+
};
|
|
1
14
|
export type DialogReferrer = {
|
|
2
15
|
icon?: string | {
|
|
3
16
|
light: string;
|
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
* here are the contract every dashboard/alert query depends on — changing one
|
|
5
5
|
* is a breaking change to the dashboard.
|
|
6
6
|
*/
|
|
7
|
+
import type { GlobalRole } from "./rooms";
|
|
7
8
|
export type AuthOutcome = "success" | "failure" | "info";
|
|
8
9
|
export type AuthMode = "sign-up" | "sign-in";
|
|
9
10
|
/** Client-only funnel steps reported via the `/api/events` beacon. */
|
|
10
|
-
export type FunnelStep = "mode_selected" | "email_entered" | "ceremony_started" | "done_shown";
|
|
11
|
-
export type AuthEventName = "auth.username.checked" | "auth.signup.succeeded" | "auth.signup.failed" | "auth.otp.sent" | "auth.otp.verified" | "auth.otp.failed" | "auth.email.verify.sent" | "auth.email.verify.succeeded" | "auth.email.verify.failed" | "auth.email.changed" | "auth.avatar.upload.succeeded" | "auth.avatar.upload.failed" | "auth.challenge.issued" | "auth.signin.succeeded" | "auth.signin.failed" | "auth.restore.succeeded" | "auth.restore.failed" | "auth.restore.no_session" | "auth.refresh.succeeded" | "auth.refresh.failed" | "auth.refresh.reuse" | "auth.refresh.grace" | "auth.jwt.verified" | "auth.jwt.rejected" | "auth.signout" | "auth.audience.rejected" | "auth.audience.minted" | "auth.guest.created" | "auth.guest.restored" | "auth.guest.upgraded" | "auth.guest.failed" | "auth.funnel.mode_selected" | "auth.funnel.email_entered" | "auth.funnel.ceremony_started" | "auth.funnel.done_shown";
|
|
12
|
-
export type AuthErrorCode = "username_taken" | "credential_taken" | "email_taken" | "email_not_verified" | "no_email" | "image_upload_forbidden" | "image_upload_rate_limited" | "invalid_image_type" | "image_too_large" | "image_upload_failed" | "otp_invalid" | "otp_expired" | "otp_attempts_exceeded" | "otp_resend_cooldown" | "otp_resend_limit" | "otp_global_limit" | "otp_send_failed" | "challenge_expired" | "unknown_credential" | "invalid_assertion_type" | "invalid_assertion_origin" | "user_verification_required" | "invalid_signature" | "user_not_found" | "missing_audience" | "audience_not_allowed" | "audience_mismatch" | "no_session" | "no_passkey" | "refresh_token_invalid" | "refresh_token_expired" | "refresh_epoch_stale" | "refresh_reuse_detected" | "guest_rate_limited" | "guest_global_limit" | "guest_username_exhausted" | "already_upgraded" | "malformed_token" | "unknown_key" | "verification_failed" | "internal_error";
|
|
11
|
+
export type FunnelStep = "mode_selected" | "email_entered" | "ceremony_started" | "ceremony_failed" | "done_shown";
|
|
12
|
+
export type AuthEventName = "auth.username.checked" | "auth.signup.succeeded" | "auth.signup.failed" | "auth.otp.sent" | "auth.otp.verified" | "auth.otp.failed" | "auth.email.verify.sent" | "auth.email.verify.succeeded" | "auth.email.verify.failed" | "auth.email.changed" | "auth.avatar.upload.succeeded" | "auth.avatar.upload.failed" | "auth.challenge.issued" | "auth.signin.succeeded" | "auth.signin.failed" | "auth.passkey.added" | "auth.passkey.add_failed" | "auth.restore.succeeded" | "auth.restore.failed" | "auth.restore.no_session" | "auth.refresh.succeeded" | "auth.refresh.failed" | "auth.refresh.reuse" | "auth.refresh.grace" | "auth.jwt.verified" | "auth.jwt.rejected" | "auth.signout" | "auth.session.revoked" | "auth.session.revoked_all" | "auth.audience.rejected" | "auth.audience.minted" | "auth.guest.created" | "auth.guest.restored" | "auth.guest.upgraded" | "auth.guest.failed" | "auth.role.granted" | "auth.role.revoked" | "auth.funnel.mode_selected" | "auth.funnel.email_entered" | "auth.funnel.ceremony_started" | "auth.funnel.ceremony_failed" | "auth.funnel.done_shown";
|
|
13
|
+
export type AuthErrorCode = "username_taken" | "credential_taken" | "email_taken" | "email_not_verified" | "no_email" | "image_upload_forbidden" | "image_upload_rate_limited" | "invalid_image_type" | "image_too_large" | "image_upload_failed" | "otp_invalid" | "otp_expired" | "otp_attempts_exceeded" | "otp_resend_cooldown" | "otp_resend_limit" | "otp_global_limit" | "otp_send_failed" | "challenge_expired" | "unknown_credential" | "invalid_assertion_type" | "invalid_assertion_origin" | "user_verification_required" | "invalid_signature" | "user_not_found" | "missing_audience" | "audience_not_allowed" | "audience_mismatch" | "no_session" | "no_passkey" | "refresh_token_invalid" | "refresh_token_expired" | "refresh_epoch_stale" | "refresh_user_epoch_stale" | "refresh_reuse_detected" | "guest_rate_limited" | "guest_global_limit" | "guest_username_exhausted" | "guest_session" | "passkey_exists" | "already_upgraded" | "malformed_token" | "unknown_key" | "verification_failed" | "webauthn_not_allowed" | "webauthn_security" | "webauthn_invalid_state" | "webauthn_not_supported" | "webauthn_constraint" | "webauthn_aborted" | "webauthn_unknown" | "internal_error";
|
|
13
14
|
/** One flat record per event = one row in the `auth_events` stream. */
|
|
14
15
|
export interface AuthEventRecord {
|
|
15
16
|
service: "auth";
|
|
@@ -26,6 +27,11 @@ export interface AuthEventRecord {
|
|
|
26
27
|
mode: AuthMode | null;
|
|
27
28
|
step: FunnelStep | null;
|
|
28
29
|
errorCode: AuthErrorCode | null;
|
|
30
|
+
/** Role-audit fields: who changed whose global role, from what, to what.
|
|
31
|
+
* `userId`/`username` carry the target. */
|
|
32
|
+
actorId: string | null;
|
|
33
|
+
roleFrom: GlobalRole | null;
|
|
34
|
+
roleTo: GlobalRole | null;
|
|
29
35
|
ip: string | null;
|
|
30
36
|
country: string | null;
|
|
31
37
|
userAgent: string | null;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export type { AdditionalSession, AuthConfig, AuthResponse, AuthResponseWithWebAuthn, FlowCredential, FlowUser, PasskeyPluginOptions, VerifiedFlowJWT, VerifyOptions, WebAuthnSignature, } from "./auth";
|
|
2
|
-
export type { BoundaryError, DialogCustomFeatures, DialogCustomLabels, DialogError, DialogReferrer, DialogState, ProfileData, ProfileIdentity, } from "./dialog";
|
|
1
|
+
export type { AccountSession, AccountSessionsResponse, AdditionalSession, AuthConfig, AuthResponse, AuthResponseWithWebAuthn, FlowCredential, FlowUser, PasskeyPluginOptions, RevokeAllSessionsResponse, RevokeSessionResponse, SecurityActivityEntry, SecurityActivityResponse, SessionUser, VerifiedFlowJWT, VerifyOptions, WebAuthnSignature, } from "./auth";
|
|
2
|
+
export type { BoundaryError, DialogCustomFeatures, DialogCustomLabels, DialogError, DialogReferrer, DialogState, Loadable, ProfileData, ProfileIdentity, } from "./dialog";
|
|
3
3
|
export type { AuthErrorCode, AuthEventName, AuthEventRecord, AuthMode, AuthOutcome, BeaconBody, FunnelStep, } from "./events";
|
|
4
4
|
export type { Bridge, BridgeParameters, FlowAccount, FlowRemote, FlowRemoteConfig, FromWindowOptions, MessageResponse, Messenger, OneOf, Payload, QueuedRequest, ReadyOptions, RemoteFlowState, RemoteState, Schema, Storage, Topic, WithReady, } from "./messenger";
|
|
5
5
|
export type { Call, ConnectCapabilities, ConnectRequest, ConnectResponse, GuestRequest, GuestResponse, MethodName, MethodParams, MethodResult, RestoreResponse, RpcRequest, SendCallsParams, SendCallsRequest, SendCallsResponse, SendTransactionParams, SendTransactionRequest, SendTransactionResponse, SignMessageRequest, SignMessageResponse, SignOutRequest, SignOutResponse, SignTypedDataRequest, SignTypedDataResponse, TransactionArgs, TypedData, TypedDataDomain, TypedDataField, } from "./protocol";
|
|
6
6
|
export { getConnectCapabilities, isPersonalSignParams, isSendCallsParams, isSendTransactionParams, } from "./protocol";
|
|
7
|
-
export type { CreateRoomInput, MyRooms, RoomChannel, RoomDetail, RoomList, RoomMemberEntry, RoomMembers, RoomOccupancy, RoomOwner, RoomPresenceEntry, RoomPresenceSnapshot, RoomRestrictionKind, RoomRole, RoomSummary, RoomSurfaceSettings, RoomsApi, RoomVisibility, UpdateRoomInput, VerifyRoomContext, } from "./rooms";
|
|
7
|
+
export type { CreateRoomInput, GlobalRole, ModerationSubject, MyRooms, RoleChangeVerdict, RoomChannel, RoomDetail, RoomList, RoomMemberEntry, RoomMembers, RoomOccupancy, RoomOwner, RoomPresenceEntry, RoomPresenceSnapshot, RoomRestrictionKind, RoomRole, RoomSummary, RoomSurfaceSettings, RoomsApi, RoomVisibility, StaffEntry, UpdateRoomInput, VerifyRoomContext, } from "./rooms";
|
|
8
8
|
export type { AccessKeyOptions, AccessKeyPreparation, Address, CreateDialogHostOptions, CreateFlowOptions, DialogHost, DialogOpenOptions, FinalizeAccessKeyParams, Flow, FlowConnectorParameters, FlowCookieNames, FlowIdProviderProps, FlowSessionState, FlowState, Listener, LoginOptions, MountProfileOptions, PrepareArgsWithAuth, PrepareTransactionRequestPhase, ProfileButtonHandle, ProfileButtonProps, ProfilePosition, ResolveAccountParams, ResolvedAccessKeyOptions, RootCredential, RunLoginParams, RunLoginResult, SendCallsArgs, SendTransactionArgs, Session, SigningContext, SignMessageArgs, SignTypedDataArgs, Store, StoredAccessKey, WagmiConnectCapabilities, WagmiConnectParams, } from "./sdk";
|
|
9
9
|
export type { ResolvedFlowSession, ResolveSessionOptions, SessionRouteOptions, SessionRouteResponse, SessionRouteSession, } from "./server";
|
|
10
10
|
export type { CoinAsset, IdentifiedTx, TxApprove, TxConvert, TxSend, TxSwap, } from "./tx";
|
|
@@ -90,6 +90,13 @@ export type Schema = [
|
|
|
90
90
|
username: string;
|
|
91
91
|
isGuest: boolean;
|
|
92
92
|
} | null;
|
|
93
|
+
} | {
|
|
94
|
+
type: "profile-token-request";
|
|
95
|
+
id: string;
|
|
96
|
+
} | {
|
|
97
|
+
type: "profile-token";
|
|
98
|
+
id: string;
|
|
99
|
+
token: string | null;
|
|
93
100
|
} | {
|
|
94
101
|
type: "profile-login";
|
|
95
102
|
mode: "signin" | "signup";
|
|
@@ -29,7 +29,8 @@ export type ConnectResponse = {
|
|
|
29
29
|
/** First-party rotating refresh token; the SDK persists it in the app origin. */
|
|
30
30
|
refreshToken: string;
|
|
31
31
|
user: FlowUser;
|
|
32
|
-
|
|
32
|
+
/** Null when the user registered or signed in with email only (no passkey). */
|
|
33
|
+
credential: FlowCredential | null;
|
|
33
34
|
webauthn?: WebAuthnSignature;
|
|
34
35
|
additionalSessions?: AdditionalSession[];
|
|
35
36
|
};
|
|
@@ -5,6 +5,34 @@ export type RoomVisibility = "public" | "unlisted" | "private";
|
|
|
5
5
|
* Member rows carry moderator|member.
|
|
6
6
|
*/
|
|
7
7
|
export type RoomRole = "owner" | "moderator" | "member";
|
|
8
|
+
/**
|
|
9
|
+
* Global permission tier held on the user row, composing over room roles: an
|
|
10
|
+
* admin holds owner-power in any room, a platform moderator holds mod-power
|
|
11
|
+
* anywhere. Read from the DB at enforcement time — never a JWT claim — so a
|
|
12
|
+
* demotion is instant.
|
|
13
|
+
*/
|
|
14
|
+
export type GlobalRole = "user" | "moderator" | "admin";
|
|
15
|
+
/** What the moderation lattice ranks: a subject's global tier plus their
|
|
16
|
+
* room-axis role (`owner` from `room.ownerId`, else the member row). */
|
|
17
|
+
export interface ModerationSubject {
|
|
18
|
+
globalRole: GlobalRole;
|
|
19
|
+
roomRole: RoomRole | null;
|
|
20
|
+
}
|
|
21
|
+
/** One row of `GET /api/admin/staff` — a user holding a non-`user` tier. */
|
|
22
|
+
export interface StaffEntry {
|
|
23
|
+
userId: string;
|
|
24
|
+
username: string;
|
|
25
|
+
role: GlobalRole;
|
|
26
|
+
}
|
|
27
|
+
/** Outcome of a global-role change request: refused with a reason, or
|
|
28
|
+
* allowed with the audit event it is (`null` for a no-op). */
|
|
29
|
+
export type RoleChangeVerdict = {
|
|
30
|
+
allowed: true;
|
|
31
|
+
event: "auth.role.granted" | "auth.role.revoked" | null;
|
|
32
|
+
} | {
|
|
33
|
+
allowed: false;
|
|
34
|
+
reason: "self_target" | "guest_target";
|
|
35
|
+
};
|
|
8
36
|
export type RoomChannel = "game" | "voice" | "text";
|
|
9
37
|
export type RoomRestrictionKind = "ban" | "mute";
|
|
10
38
|
export interface RoomOwner {
|
package/dist/sdk/types/sdk.d.ts
CHANGED
|
@@ -140,8 +140,12 @@ export type LoginOptions = {
|
|
|
140
140
|
export type Session = {
|
|
141
141
|
user: FlowUser;
|
|
142
142
|
jwt: string;
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
/**
|
|
144
|
+
* Null for an email-only session (registered or signed in without a
|
|
145
|
+
* passkey). Signing requires a credential — gate wallet UI on its presence.
|
|
146
|
+
*/
|
|
147
|
+
credential: FlowCredential | null;
|
|
148
|
+
address: Address | null;
|
|
145
149
|
};
|
|
146
150
|
export type RootCredential = {
|
|
147
151
|
credential: FlowCredential;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flow-industries/id",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"main": "./dist/sdk/client/index.js",
|
|
5
5
|
"module": "./dist/sdk/client/index.js",
|
|
6
6
|
"types": "./dist/sdk/client/index.d.ts",
|
|
@@ -91,6 +91,7 @@
|
|
|
91
91
|
"devDependencies": {
|
|
92
92
|
"@better-auth/cli": "^1.4.17",
|
|
93
93
|
"@biomejs/biome": "2.4.12",
|
|
94
|
+
"@electric-sql/pglite": "^0.5.4",
|
|
94
95
|
"@flow-industries/lint": "0.1.0",
|
|
95
96
|
"@react-email/ui": "^6.6.0",
|
|
96
97
|
"@tailwindcss/vite": "^4.1.18",
|
|
@@ -112,7 +113,7 @@
|
|
|
112
113
|
},
|
|
113
114
|
"dependencies": {
|
|
114
115
|
"@aws-sdk/client-s3": "^3.1073.0",
|
|
115
|
-
"@flow-industries/ui": "^0.
|
|
116
|
+
"@flow-industries/ui": "^0.19.0",
|
|
116
117
|
"@hono/otel": "^1.1.2",
|
|
117
118
|
"@openobserve/browser-logs": "^0.3.1",
|
|
118
119
|
"@openobserve/browser-rum": "^0.3.1",
|