@flow-industries/id 0.26.3 → 0.26.4

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.
@@ -0,0 +1,42 @@
1
+ import { sql } from "drizzle-orm";
2
+ import { boolean, check, index, integer, pgTable, text, timestamp, } from "drizzle-orm/pg-core";
3
+ import { user } from "./schema";
4
+ export const signupPolicy = pgTable("signup_policy", {
5
+ id: integer("id").primaryKey(),
6
+ invitationOnly: boolean("invitation_only").notNull().default(false),
7
+ updatedBy: text("updated_by").references(() => user.id, {
8
+ onDelete: "set null",
9
+ }),
10
+ updatedAt: timestamp("updated_at").notNull().defaultNow(),
11
+ }, (table) => [check("signup_policy_singleton", sql `${table.id} = 1`)]);
12
+ export const invitation = pgTable("invitation", {
13
+ id: text("id").primaryKey(),
14
+ codeHash: text("code_hash").notNull().unique(),
15
+ inviterId: text("inviter_id").references(() => user.id, {
16
+ onDelete: "set null",
17
+ }),
18
+ createdBy: text("created_by").references(() => user.id, {
19
+ onDelete: "set null",
20
+ }),
21
+ maxUses: integer("max_uses").notNull().default(1),
22
+ usedCount: integer("used_count").notNull().default(0),
23
+ createdAt: timestamp("created_at").notNull().defaultNow(),
24
+ expiresAt: timestamp("expires_at").notNull(),
25
+ revokedAt: timestamp("revoked_at"),
26
+ }, (table) => [
27
+ check("invitation_capacity", sql `${table.maxUses} between 1 and 100 and ${table.usedCount} between 0 and ${table.maxUses}`),
28
+ ]);
29
+ export const invitationRedemption = pgTable("invitation_redemption", {
30
+ userId: text("user_id")
31
+ .primaryKey()
32
+ .references(() => user.id, { onDelete: "cascade" }),
33
+ invitationId: text("invitation_id")
34
+ .notNull()
35
+ .references(() => invitation.id),
36
+ inviterId: text("inviter_id").references(() => user.id, {
37
+ onDelete: "set null",
38
+ }),
39
+ redeemedAt: timestamp("redeemed_at").notNull().defaultNow(),
40
+ }, (table) => [
41
+ index("invitation_redemption_invitation_idx").on(table.invitationId),
42
+ ]);
@@ -4951,3 +4951,251 @@ export declare const oauthState: import("drizzle-orm/pg-core").PgTableWithColumn
4951
4951
  };
4952
4952
  dialect: "pg";
4953
4953
  }>;
4954
+ export declare const managedPdsOperation: import("drizzle-orm/pg-core").PgTableWithColumns<{
4955
+ name: "managed_pds_operation";
4956
+ schema: undefined;
4957
+ columns: {
4958
+ id: import("drizzle-orm/pg-core").PgColumn<{
4959
+ name: "id";
4960
+ tableName: "managed_pds_operation";
4961
+ dataType: "string";
4962
+ columnType: "PgText";
4963
+ data: string;
4964
+ driverParam: string;
4965
+ notNull: true;
4966
+ hasDefault: false;
4967
+ isPrimaryKey: true;
4968
+ isAutoincrement: false;
4969
+ hasRuntimeDefault: false;
4970
+ enumValues: [string, ...string[]];
4971
+ baseColumn: never;
4972
+ identity: undefined;
4973
+ generated: undefined;
4974
+ }, {}, {}>;
4975
+ userId: import("drizzle-orm/pg-core").PgColumn<{
4976
+ name: "user_id";
4977
+ tableName: "managed_pds_operation";
4978
+ dataType: "string";
4979
+ columnType: "PgText";
4980
+ data: string;
4981
+ driverParam: string;
4982
+ notNull: false;
4983
+ hasDefault: false;
4984
+ isPrimaryKey: false;
4985
+ isAutoincrement: false;
4986
+ hasRuntimeDefault: false;
4987
+ enumValues: [string, ...string[]];
4988
+ baseColumn: never;
4989
+ identity: undefined;
4990
+ generated: undefined;
4991
+ }, {}, {}>;
4992
+ handle: import("drizzle-orm/pg-core").PgColumn<{
4993
+ name: "handle";
4994
+ tableName: "managed_pds_operation";
4995
+ dataType: "string";
4996
+ columnType: "PgText";
4997
+ data: string;
4998
+ driverParam: string;
4999
+ notNull: true;
5000
+ hasDefault: false;
5001
+ isPrimaryKey: false;
5002
+ isAutoincrement: false;
5003
+ hasRuntimeDefault: false;
5004
+ enumValues: [string, ...string[]];
5005
+ baseColumn: never;
5006
+ identity: undefined;
5007
+ generated: undefined;
5008
+ }, {}, {}>;
5009
+ inviteReference: import("drizzle-orm/pg-core").PgColumn<{
5010
+ name: "invite_reference";
5011
+ tableName: "managed_pds_operation";
5012
+ dataType: "string";
5013
+ columnType: "PgText";
5014
+ data: string;
5015
+ driverParam: string;
5016
+ notNull: true;
5017
+ hasDefault: false;
5018
+ isPrimaryKey: false;
5019
+ isAutoincrement: false;
5020
+ hasRuntimeDefault: false;
5021
+ enumValues: [string, ...string[]];
5022
+ baseColumn: never;
5023
+ identity: undefined;
5024
+ generated: undefined;
5025
+ }, {}, {}>;
5026
+ state: import("drizzle-orm/pg-core").PgColumn<{
5027
+ name: "state";
5028
+ tableName: "managed_pds_operation";
5029
+ dataType: "string";
5030
+ columnType: "PgText";
5031
+ data: import("../types").ManagedPdsState;
5032
+ driverParam: string;
5033
+ notNull: true;
5034
+ hasDefault: true;
5035
+ isPrimaryKey: false;
5036
+ isAutoincrement: false;
5037
+ hasRuntimeDefault: false;
5038
+ enumValues: [string, ...string[]];
5039
+ baseColumn: never;
5040
+ identity: undefined;
5041
+ generated: undefined;
5042
+ }, {}, {
5043
+ $type: import("../types").ManagedPdsState;
5044
+ }>;
5045
+ did: import("drizzle-orm/pg-core").PgColumn<{
5046
+ name: "did";
5047
+ tableName: "managed_pds_operation";
5048
+ dataType: "string";
5049
+ columnType: "PgText";
5050
+ data: string;
5051
+ driverParam: string;
5052
+ notNull: false;
5053
+ hasDefault: false;
5054
+ isPrimaryKey: false;
5055
+ isAutoincrement: false;
5056
+ hasRuntimeDefault: false;
5057
+ enumValues: [string, ...string[]];
5058
+ baseColumn: never;
5059
+ identity: undefined;
5060
+ generated: undefined;
5061
+ }, {}, {}>;
5062
+ pdsEndpoint: import("drizzle-orm/pg-core").PgColumn<{
5063
+ name: "pds_endpoint";
5064
+ tableName: "managed_pds_operation";
5065
+ dataType: "string";
5066
+ columnType: "PgText";
5067
+ data: string;
5068
+ driverParam: string;
5069
+ notNull: true;
5070
+ hasDefault: false;
5071
+ isPrimaryKey: false;
5072
+ isAutoincrement: false;
5073
+ hasRuntimeDefault: false;
5074
+ enumValues: [string, ...string[]];
5075
+ baseColumn: never;
5076
+ identity: undefined;
5077
+ generated: undefined;
5078
+ }, {}, {}>;
5079
+ identityVersion: import("drizzle-orm/pg-core").PgColumn<{
5080
+ name: "identity_version";
5081
+ tableName: "managed_pds_operation";
5082
+ dataType: "number";
5083
+ columnType: "PgInteger";
5084
+ data: number;
5085
+ driverParam: string | number;
5086
+ notNull: true;
5087
+ hasDefault: true;
5088
+ isPrimaryKey: false;
5089
+ isAutoincrement: false;
5090
+ hasRuntimeDefault: false;
5091
+ enumValues: undefined;
5092
+ baseColumn: never;
5093
+ identity: undefined;
5094
+ generated: undefined;
5095
+ }, {}, {}>;
5096
+ fence: import("drizzle-orm/pg-core").PgColumn<{
5097
+ name: "fence";
5098
+ tableName: "managed_pds_operation";
5099
+ dataType: "number";
5100
+ columnType: "PgInteger";
5101
+ data: number;
5102
+ driverParam: string | number;
5103
+ notNull: true;
5104
+ hasDefault: true;
5105
+ isPrimaryKey: false;
5106
+ isAutoincrement: false;
5107
+ hasRuntimeDefault: false;
5108
+ enumValues: undefined;
5109
+ baseColumn: never;
5110
+ identity: undefined;
5111
+ generated: undefined;
5112
+ }, {}, {}>;
5113
+ attempts: import("drizzle-orm/pg-core").PgColumn<{
5114
+ name: "attempts";
5115
+ tableName: "managed_pds_operation";
5116
+ dataType: "number";
5117
+ columnType: "PgInteger";
5118
+ data: number;
5119
+ driverParam: string | number;
5120
+ notNull: true;
5121
+ hasDefault: true;
5122
+ isPrimaryKey: false;
5123
+ isAutoincrement: false;
5124
+ hasRuntimeDefault: false;
5125
+ enumValues: undefined;
5126
+ baseColumn: never;
5127
+ identity: undefined;
5128
+ generated: undefined;
5129
+ }, {}, {}>;
5130
+ leaseUntil: import("drizzle-orm/pg-core").PgColumn<{
5131
+ name: "lease_until";
5132
+ tableName: "managed_pds_operation";
5133
+ dataType: "date";
5134
+ columnType: "PgTimestamp";
5135
+ data: Date;
5136
+ driverParam: string;
5137
+ notNull: false;
5138
+ hasDefault: false;
5139
+ isPrimaryKey: false;
5140
+ isAutoincrement: false;
5141
+ hasRuntimeDefault: false;
5142
+ enumValues: undefined;
5143
+ baseColumn: never;
5144
+ identity: undefined;
5145
+ generated: undefined;
5146
+ }, {}, {}>;
5147
+ failureCode: import("drizzle-orm/pg-core").PgColumn<{
5148
+ name: "failure_code";
5149
+ tableName: "managed_pds_operation";
5150
+ dataType: "string";
5151
+ columnType: "PgText";
5152
+ data: string;
5153
+ driverParam: string;
5154
+ notNull: false;
5155
+ hasDefault: false;
5156
+ isPrimaryKey: false;
5157
+ isAutoincrement: false;
5158
+ hasRuntimeDefault: false;
5159
+ enumValues: [string, ...string[]];
5160
+ baseColumn: never;
5161
+ identity: undefined;
5162
+ generated: undefined;
5163
+ }, {}, {}>;
5164
+ createdAt: import("drizzle-orm/pg-core").PgColumn<{
5165
+ name: "created_at";
5166
+ tableName: "managed_pds_operation";
5167
+ dataType: "date";
5168
+ columnType: "PgTimestamp";
5169
+ data: Date;
5170
+ driverParam: string;
5171
+ notNull: true;
5172
+ hasDefault: true;
5173
+ isPrimaryKey: false;
5174
+ isAutoincrement: false;
5175
+ hasRuntimeDefault: false;
5176
+ enumValues: undefined;
5177
+ baseColumn: never;
5178
+ identity: undefined;
5179
+ generated: undefined;
5180
+ }, {}, {}>;
5181
+ updatedAt: import("drizzle-orm/pg-core").PgColumn<{
5182
+ name: "updated_at";
5183
+ tableName: "managed_pds_operation";
5184
+ dataType: "date";
5185
+ columnType: "PgTimestamp";
5186
+ data: Date;
5187
+ driverParam: string;
5188
+ notNull: true;
5189
+ hasDefault: true;
5190
+ isPrimaryKey: false;
5191
+ isAutoincrement: false;
5192
+ hasRuntimeDefault: false;
5193
+ enumValues: undefined;
5194
+ baseColumn: never;
5195
+ identity: undefined;
5196
+ generated: undefined;
5197
+ }, {}, {}>;
5198
+ };
5199
+ dialect: "pg";
5200
+ }>;
5201
+ export { invitation, invitationRedemption, signupPolicy } from "./invitations";
@@ -876,3 +876,28 @@ export const oauthState = pgTable("oauth_state", {
876
876
  data: text("data").notNull(),
877
877
  expiresAt: timestamp("expires_at").notNull(),
878
878
  }, (table) => [primaryKey({ columns: [table.providerId, table.id] })]);
879
+ export const managedPdsOperation = pgTable("managed_pds_operation", {
880
+ id: text("id").primaryKey(),
881
+ userId: text("user_id").references(() => user.id, { onDelete: "set null" }),
882
+ handle: text("handle").notNull(),
883
+ inviteReference: text("invite_reference").notNull(),
884
+ state: text("state")
885
+ .$type()
886
+ .notNull()
887
+ .default("queued"),
888
+ did: text("did"),
889
+ pdsEndpoint: text("pds_endpoint").notNull(),
890
+ identityVersion: integer("identity_version").notNull().default(1),
891
+ fence: integer("fence").notNull().default(0),
892
+ attempts: integer("attempts").notNull().default(0),
893
+ leaseUntil: timestamp("lease_until"),
894
+ failureCode: text("failure_code"),
895
+ createdAt: timestamp("created_at").notNull().defaultNow(),
896
+ updatedAt: timestamp("updated_at").notNull().defaultNow(),
897
+ }, (table) => [
898
+ uniqueIndex("managed_pds_user_idx").on(table.userId),
899
+ uniqueIndex("managed_pds_handle_idx").on(table.handle),
900
+ uniqueIndex("managed_pds_did_idx").on(table.did),
901
+ index("managed_pds_work_idx").on(table.state, table.leaseUntil),
902
+ ]);
903
+ export { invitation, invitationRedemption, signupPolicy } from "./invitations";
@@ -0,0 +1,15 @@
1
+ import type { SessionUser } from "./types";
2
+ /** The audience a session was minted for. */
3
+ export declare const audienceOf: <T>(session: T) => string | undefined;
4
+ /** A session's own id. */
5
+ export declare const sessionIdOf: <T>(session: T) => string | undefined;
6
+ /** Whether the account is a guest. Absent means "not a guest". */
7
+ export declare const isGuestOf: <T>(user: T) => boolean;
8
+ /** The account's username. */
9
+ export declare const usernameOf: <T>(user: T) => string | undefined;
10
+ /**
11
+ * better-auth types `session.user` from its own base schema. Flow declares the extra columns
12
+ * through `additionalFields`, so every user row this server reads or writes carries them; the
13
+ * assertion names that configured shape rather than guessing at one.
14
+ */
15
+ export declare function sessionUserOf<T>(user: T): SessionUser;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * better-auth types `User` and `Session` from its own schema, so the fields Flow adds through
3
+ * `additionalFields` (audience, isGuest, username, walletAddress) are absent from those types.
4
+ *
5
+ * These read the added fields off the value without asserting a shape onto it, so a missing or
6
+ * wrongly-typed field answers `undefined` rather than becoming a lie the compiler believes.
7
+ * `String(x) === x` holds only for string primitives, which is the check without a `typeof`.
8
+ */
9
+ function textField(value, key) {
10
+ const found = Object.entries(Object(value)).find(([k]) => k === key)?.[1];
11
+ return String(found) === found ? found : undefined;
12
+ }
13
+ function boolField(value, key) {
14
+ return Object.entries(Object(value)).find(([k]) => k === key)?.[1] === true;
15
+ }
16
+ /** The audience a session was minted for. */
17
+ export const audienceOf = (session) => textField(session, "audience");
18
+ /** A session's own id. */
19
+ export const sessionIdOf = (session) => textField(session, "id");
20
+ /** Whether the account is a guest. Absent means "not a guest". */
21
+ export const isGuestOf = (user) => boolField(user, "isGuest");
22
+ /** The account's username. */
23
+ export const usernameOf = (user) => textField(user, "username");
24
+ /**
25
+ * better-auth types `session.user` from its own base schema. Flow declares the extra columns
26
+ * through `additionalFields`, so every user row this server reads or writes carries them; the
27
+ * assertion names that configured shape rather than guessing at one.
28
+ */
29
+ export function sessionUserOf(user) {
30
+ // SAFETY: the fields are declared in the plugin config; see the doc comment.
31
+ return user;
32
+ }
@@ -0,0 +1,46 @@
1
+ import type { Context } from "hono";
2
+ import type { Caller } from "../caller";
3
+ import type { AtprotoResolution } from "./atproto";
4
+ import type { ManagedPdsState } from "./managed-provisioning";
5
+ export type AtprotoMapping = Pick<AtprotoResolution, "flowUserId" | "did" | "identityVersion" | "lifecycle">;
6
+ export type DidDocumentInput = {
7
+ id: string;
8
+ service?: unknown[];
9
+ };
10
+ export type AtprotoResolverDeps = {
11
+ testOrigin?: string;
12
+ resolveIdentity: (did: string, options: {
13
+ noCache: boolean;
14
+ signal: AbortSignal;
15
+ }) => Promise<{
16
+ did: string;
17
+ didDoc: DidDocumentInput;
18
+ handle: string;
19
+ }>;
20
+ assertPublicEndpoint: (endpoint: string) => Promise<void>;
21
+ authorization: (did: string, endpoint: string, signal: AbortSignal) => Promise<AtprotoResolution["authorization"]>;
22
+ flowPdsOrigins: ReadonlySet<string>;
23
+ ttlMs: number;
24
+ now?: () => number;
25
+ };
26
+ export type ManagedResolverState = {
27
+ lifecycle: ManagedPdsState;
28
+ identityVersion: number;
29
+ };
30
+ export type AtprotoResolverRouteDeps = {
31
+ admit: (userId: string) => Promise<boolean>;
32
+ resolveCaller: (context: Context) => Promise<Caller | null>;
33
+ activeAccountOf?: (headers: Headers) => Promise<string | null | undefined>;
34
+ readMapping: (userId: string) => Promise<AtprotoMapping>;
35
+ resolve: (mapping: AtprotoMapping, freshness: "cached" | "refresh", signal?: AbortSignal) => Promise<AtprotoResolution>;
36
+ };
37
+ export type AtprotoResolverAdmissionCaps = {
38
+ userHourly: number;
39
+ globalHourly: number;
40
+ };
41
+ export type AtprotoStoredGrant = {
42
+ sub: string;
43
+ aud: string;
44
+ iss: string;
45
+ expires_at?: string;
46
+ };
File without changes
@@ -1,5 +1,6 @@
1
1
  export type AtprotoStartRequest = {
2
2
  identifier: string;
3
+ invitationCode?: string;
3
4
  intent: "login" | "link";
4
5
  transaction?: string;
5
6
  expectedUserId?: string;
@@ -23,3 +24,24 @@ export type AtprotoStatus = {
23
24
  canUnlink: boolean;
24
25
  unlinkBlockReason: string | null;
25
26
  };
27
+ export type AtprotoResolutionFailure = "SIGN_IN_REQUIRED" | "NO_AT_IDENTITY" | "PROVISIONING_PENDING" | "PROVISIONING_FAILED" | "ACCOUNT_CHANGED" | "UNSUPPORTED_DID_METHOD" | "IDENTITY_INVALID" | "RESOLUTION_UNAVAILABLE";
28
+ export type AtprotoResolution = {
29
+ flowUserId: string;
30
+ did: string;
31
+ handle: string | null;
32
+ pdsUrl: string;
33
+ hosting: "flow" | "external";
34
+ lifecycle: "active" | "suspended" | "migrated" | "deletion_pending";
35
+ authorization: "connected" | "reconnect_required";
36
+ resolvedAt: string;
37
+ expiresAt: string;
38
+ identityVersion: string;
39
+ };
40
+ export type AtprotoResolveOptions = {
41
+ freshness?: "cached" | "refresh";
42
+ signal?: AbortSignal;
43
+ };
44
+ export type AtprotoApi = {
45
+ resolve(options?: AtprotoResolveOptions): Promise<AtprotoResolution>;
46
+ invalidate(): void;
47
+ };
@@ -1,5 +1,6 @@
1
1
  import type { JWTPayload } from "jose";
2
2
  import type { AuthEventName } from "./events";
3
+ import type { ManagedPdsEnrollment } from "./managed-provisioning";
3
4
  export type FlowUser = {
4
5
  id: string;
5
6
  username: string;
@@ -74,6 +75,7 @@ export type AuthResponse = {
74
75
  additionalSessions?: AdditionalSession[];
75
76
  };
76
77
  export type AuthConfig = {
78
+ managedPdsEnabled?: boolean;
77
79
  atprotoEnabled?: boolean;
78
80
  rpId: string;
79
81
  rpName: string;
@@ -96,6 +98,7 @@ export type AuthResponseWithWebAuthn = AuthResponse & {
96
98
  export type PasskeyPluginOptions = {
97
99
  rpId: string;
98
100
  rpName?: string;
101
+ enrollManagedPds?: ManagedPdsEnrollment;
99
102
  };
100
103
  export type VerifyOptions = {
101
104
  audience: string;
@@ -169,6 +172,7 @@ export type PasskeyEnrollment = {
169
172
  credential: FlowCredential;
170
173
  };
171
174
  export type AccountRegistration = {
175
+ invitationCode?: string;
172
176
  username: string;
173
177
  email: string;
174
178
  subscribedToNews: boolean;
@@ -90,6 +90,9 @@ export type DialogState = {
90
90
  customLabels?: DialogCustomLabels;
91
91
  };
92
92
  export type SignUpProps = {
93
+ managedPdsEnabled?: boolean;
94
+ invitationCode?: string;
95
+ invitation?: import("react").ReactNode;
93
96
  verifiedEmail?: {
94
97
  email: string;
95
98
  nonce: string;
@@ -0,0 +1,23 @@
1
+ import type { AppDb } from "../db/handle";
2
+ export interface HostedOAuthTransaction {
3
+ issuer: string;
4
+ pds: string;
5
+ requestUri: string;
6
+ deviceId: string;
7
+ clientId: string;
8
+ }
9
+ export interface HostedOAuthMapping {
10
+ did: string;
11
+ pds: string;
12
+ version: string;
13
+ }
14
+ /** Called under the canonical user lock; returns only active managed identities. */
15
+ export type HostedOAuthMappingReader = (database: AppDb, userId: string) => Promise<HostedOAuthMapping | null>;
16
+ export interface HostedOAuthProofOptions {
17
+ testOrigin?: string;
18
+ issuer: string;
19
+ pds: string;
20
+ lifetimeMs: number;
21
+ maximumPendingProofs: number;
22
+ readMapping: HostedOAuthMappingReader;
23
+ }
File without changes
@@ -0,0 +1,28 @@
1
+ export interface HostingQuotaPolicy {
2
+ totalBytes: number;
3
+ uploadBytes: number;
4
+ scratchBytes: number;
5
+ concurrentUploads: number;
6
+ }
7
+ export interface HostingQuotaReservation {
8
+ bytes: number;
9
+ fence: number;
10
+ expiresAt: number;
11
+ state: "active" | "cleanup";
12
+ }
13
+ export interface HostingQuotaLedger {
14
+ revision: number;
15
+ nextFence: number;
16
+ certain: boolean;
17
+ recordBytes: number;
18
+ blobs: Record<string, number>;
19
+ deletionDebt: Record<string, {
20
+ bytes: number;
21
+ fence: number;
22
+ }>;
23
+ reservations: Record<string, HostingQuotaReservation>;
24
+ }
25
+ export interface HostingQuotaAdmission {
26
+ ledger: HostingQuotaLedger;
27
+ fence: number;
28
+ }
File without changes
@@ -1,6 +1,7 @@
1
1
  export type { AccountDeleteRequest, AccountDeleteResponse, AccountErasureCounts, AccountErasureEntry, AccountErasureFeed, AccountErasureResult, AccountExport, AccountExportAccount, AccountExportActionEvent, AccountExportActionSession, AccountExportAttendance, AccountExportAuthoredEvent, AccountExportCharacterStateTime, AccountExportFollow, AccountExportGameEvent, AccountExportNotification, AccountExportOtherService, AccountExportOwnedRoom, AccountExportPasskey, AccountExportRoomEvents, AccountExportRoomMembership, AccountExportRoomPlayerState, AccountExportRoomPresence, AccountExportRoomRestriction, AccountExportRoomSettings, AccountExportRooms, AccountExportRsvp, AccountExportSettingsSurface, AccountExportStudySubject, AccountExportXpGrant, AccountExportXpSummary, } from "./account-data";
2
2
  export type { ActionCurve, ActionEventRequest, ActionEventResponse, ActionsApi, ActiveActionState, FinishActionRequest, ListStudySessionsOptions, ListStudySubjectsOptions, StartActionInput, StartActionResult, StudyApi, StudySubjectResponse, UseActiveActionOptions, XpEstimateContext, } from "./actions";
3
- export type { AtprotoCompletion, AtprotoStartRequest, AtprotoStatus, } from "./atproto";
3
+ export type { AtprotoApi, AtprotoCompletion, AtprotoResolution, AtprotoResolutionFailure, AtprotoResolveOptions, AtprotoStartRequest, AtprotoStatus, } from "./atproto";
4
+ export type { AtprotoMapping, AtprotoResolverAdmissionCaps, AtprotoResolverDeps, AtprotoResolverRouteDeps, AtprotoStoredGrant, DidDocumentInput, ManagedResolverState, } from "./atproto-resolver";
4
5
  export type { AccountRegistration, AccountSession, AccountSessionsResponse, AdditionalSession, AuthConfig, AuthorizationTransaction, AuthPageBootstrap, AuthResponse, AuthResponseWithWebAuthn, BioNormalization, BioRejection, BioWriteRefusal, BioWriteResult, FlowCredential, FlowUser, PasskeyEnrollment, PasskeyPluginOptions, RevokeAllSessionsResponse, RevokeSessionResponse, SecurityActivityEntry, SecurityActivityResponse, SessionUser, VerifiedFlowJWT, VerifyOptions, WebAuthnSignature, } from "./auth";
5
6
  export type { BrowserAccount, BrowserAccounts } from "./browser-accounts";
6
7
  export type { BodyRegion, CosmeticItem, CosmeticMaterial, CosmeticPaint, CosmeticSlot, EquipConflict, EquippedCosmetic, EquippedCosmetics, EquipRegion, PaintSlot, SettingsConflict, } from "./cosmetics";
@@ -10,7 +11,10 @@ export type { AuthErrorCode, AuthEventName, AuthEventRecord, AuthMode, AuthOutco
10
11
  export type { ActiveAction, CatalogFieldRef, ClockAnchor, FinishedSummary, FocusApi, FocusPhase, FocusSessionEvent, FocusSessionState, StartFocusRequest, StudySearchHit, } from "./focus";
11
12
  export type { GameEventReport, GameLifecycleEventName, GameLifecycleFeedEvent, GameLifecycleFeedPage, GamePlayerSession, } from "./game";
12
13
  export { GAME_LIFECYCLE_EVENT_NAMES } from "./game";
14
+ export type { HostedOAuthMapping, HostedOAuthMappingReader, HostedOAuthProofOptions, HostedOAuthTransaction, } from "./hosted-oauth";
15
+ export type { HostingQuotaAdmission, HostingQuotaLedger, HostingQuotaPolicy, HostingQuotaReservation, } from "./hosting-quota";
13
16
  export type { AccountProfileData } from "./landing";
17
+ export type * from "./managed-provisioning";
14
18
  export type { Bridge, BridgeParameters, FlowAccount, FlowRemote, FlowRemoteConfig, FromWindowOptions, MessageResponse, Messenger, OneOf, Payload, QueuedRequest, ReadyOptions, RemoteFlowState, RemoteState, Schema, Storage, Topic, WithReady, } from "./messenger";
15
19
  export type { MarkNotificationsReadInput, NotificationCounts, NotificationEntry, NotificationPage, NotificationReadResult, NotificationRefusal, } from "./notifications";
16
20
  export type { OtpVerificationFailure, OtpVerificationResult, VerificationAdapter, } from "./otp";
@@ -0,0 +1,51 @@
1
+ import type { AppDb } from "../db/handle";
2
+ /** Queues a reservation in the enrollment transaction; remote provisioning runs after commit. */
3
+ export type ManagedPdsEnrollment = (database: AppDb, userId: string) => Promise<void>;
4
+ export type ManagedPdsState = "queued" | "provisioning" | "active" | "failed" | "suspended" | "migrated" | "deletion_pending";
5
+ export interface ManagedPdsReservation {
6
+ operationId: string;
7
+ handle: string;
8
+ pdsEndpoint: string;
9
+ inviteReference: string;
10
+ }
11
+ export interface ManagedPdsIdentity {
12
+ did: string;
13
+ handle: string;
14
+ pdsEndpoint: string;
15
+ }
16
+ export type ManagedPdsRecovery = {
17
+ outcome: "committed";
18
+ identity: ManagedPdsIdentity;
19
+ } | {
20
+ outcome: "absent";
21
+ } | {
22
+ outcome: "pending";
23
+ };
24
+ /**
25
+ * Server-only adapter for an authenticated operator API. It must durably bind
26
+ * operationId to key material before PLC publication and replay the same DID
27
+ * through every crash boundary. Stock createAccount does not implement this.
28
+ */
29
+ export interface ManagedPdsProvisioner {
30
+ contract: "durable-operation-idempotency-v1";
31
+ remove?(reservation: ManagedPdsReservation & {
32
+ did: string | null;
33
+ }): Promise<void>;
34
+ recover(reservation: ManagedPdsReservation): Promise<ManagedPdsRecovery>;
35
+ create(reservation: ManagedPdsReservation): Promise<ManagedPdsIdentity>;
36
+ }
37
+ export interface ManagedPdsWorkerLimits {
38
+ leaseMs: number;
39
+ maxAttempts: number;
40
+ }
41
+ export type ManagedPdsConfig = {
42
+ endpoint: string;
43
+ operatorEndpoint: string;
44
+ operatorToken: string;
45
+ };
46
+ export interface ManagedPdsTickReport {
47
+ active: number;
48
+ failed: number;
49
+ idle: number;
50
+ deleted?: number;
51
+ }
File without changes
@@ -2,6 +2,7 @@ import type { ReactNode } from "react";
2
2
  import type { Chain, Hex, PrepareTransactionRequestParameters, SendTransactionParameters, SignTypedDataParameters, Transport, WalletClient } from "viem";
3
3
  import type { SendCallsParameters } from "viem/actions";
4
4
  import type { RawValue } from "../json";
5
+ import type { AtprotoApi } from "./atproto";
5
6
  import type { AdditionalSession, FlowCredential, FlowUser, WebAuthnSignature } from "./auth";
6
7
  import type { BrowserAccount, BrowserAccounts } from "./browser-accounts";
7
8
  import type { ConnectCapabilities } from "./protocol";
@@ -377,6 +378,7 @@ export type Flow = {
377
378
  }): Promise<WalletClient>;
378
379
  /** Typed client for the room registry (browse, membership, settings, moderation). */
379
380
  rooms: RoomsApi;
381
+ atproto: AtprotoApi;
380
382
  subscribe(listener: Listener<FlowState>): () => void;
381
383
  getState(): FlowState;
382
384
  dialog: DialogHost;