@fias/arche-sdk 2.28.0 → 2.30.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 (42) hide show
  1. package/dist/bridge.d.ts +42 -6
  2. package/dist/bridge.d.ts.map +1 -1
  3. package/dist/bridge.js +93 -2
  4. package/dist/bridge.js.map +1 -1
  5. package/dist/bridge.test.js +89 -0
  6. package/dist/bridge.test.js.map +1 -1
  7. package/dist/entity-ops.d.ts +27 -1
  8. package/dist/entity-ops.d.ts.map +1 -1
  9. package/dist/entity-ops.js +84 -6
  10. package/dist/entity-ops.js.map +1 -1
  11. package/dist/generated/permissions.d.ts +1 -1
  12. package/dist/generated/permissions.d.ts.map +1 -1
  13. package/dist/generated/permissions.js +10 -0
  14. package/dist/generated/permissions.js.map +1 -1
  15. package/dist/generated/surfaces.d.ts +119 -5
  16. package/dist/generated/surfaces.d.ts.map +1 -1
  17. package/dist/generated/surfaces.js +14 -6
  18. package/dist/generated/surfaces.js.map +1 -1
  19. package/dist/hooks.d.ts +220 -18
  20. package/dist/hooks.d.ts.map +1 -1
  21. package/dist/hooks.js +792 -39
  22. package/dist/hooks.js.map +1 -1
  23. package/dist/hooks.test.js +702 -0
  24. package/dist/hooks.test.js.map +1 -1
  25. package/dist/index.d.ts +4 -2
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +24 -2
  28. package/dist/index.js.map +1 -1
  29. package/dist/index.mjs +771 -28
  30. package/dist/limits.d.ts +72 -0
  31. package/dist/limits.d.ts.map +1 -0
  32. package/dist/limits.js +75 -0
  33. package/dist/limits.js.map +1 -0
  34. package/dist/types.d.ts +720 -10
  35. package/dist/types.d.ts.map +1 -1
  36. package/dist/use-fias-access.render.test.d.ts +12 -0
  37. package/dist/use-fias-access.render.test.d.ts.map +1 -0
  38. package/dist/use-fias-access.render.test.js +407 -0
  39. package/dist/use-fias-access.render.test.js.map +1 -0
  40. package/package.json +3 -2
  41. package/templates/default/AGENTS.md +391 -13
  42. package/templates/default/CLAUDE.md +391 -13
package/dist/types.d.ts CHANGED
@@ -595,6 +595,32 @@ export interface ImageGenerationParams {
595
595
  * `referenceImage` is provided.
596
596
  */
597
597
  referenceStrength?: number;
598
+ /**
599
+ * Generate in a style from the user's Creative Library (ADR-035) — a style
600
+ * made in FiasWorks Studio, say. Needs `vault:creative:read`. The platform
601
+ * adds the style's reference pictures after your own references (up to
602
+ * three, while the model has room) and its words to the prompt; with no
603
+ * room left it carries the style in words, which needs a description
604
+ * (STYLE_NEEDS_DESCRIPTION otherwise). `version` pins one version of the
605
+ * style; leave it out for the current one. `pictures` chooses which of the
606
+ * style's pictures go, in order (1–3 of its `referenceDocumentIds`; an indoor
607
+ * picture for an indoor scene) — leave it out for its first. Get ids from
608
+ * `useCreativeLibrary`.
609
+ *
610
+ * Or `{ shipped: key }`: a style this arche ships for its players — listed
611
+ * in the manifest's `styles` with its pictures in the asset library tagged
612
+ * `style:<key>` (ADR-035 D7). No permission beyond this one. It is read
613
+ * from the arche's PUBLISHED version — publish once with the style before
614
+ * relying on it; the dev harness has none (SHIPPED_STYLE_UNAVAILABLE). The
615
+ * player pays, as for any generation.
616
+ */
617
+ creativeStyle?: {
618
+ styleId: string;
619
+ version?: number;
620
+ pictures?: string[];
621
+ } | {
622
+ shipped: string;
623
+ };
598
624
  }
599
625
  /**
600
626
  * A reference image for `useImageGeneration`: an asset from this arche's
@@ -799,6 +825,91 @@ export interface AudioGenerationApi {
799
825
  result: AudioGenerationResult | null;
800
826
  error: Error | null;
801
827
  }
828
+ /**
829
+ * The host chrome around a plugin's arche, as the host reports it (`init`
830
+ * and every `chrome_update`). See `useFiasChrome`.
831
+ *
832
+ * "Focus mode" is the platform's expand: the platform header, the arche's
833
+ * own header and the suggested-arches sidebar are hidden so the arche fills
834
+ * the viewport, and the host draws a thin bar with the way back — Fias home,
835
+ * Worktop, Fias AI, Collapse — unless the plugin suppresses it and draws its
836
+ * own.
837
+ */
838
+ export interface FiasChromeState {
839
+ /** The arche is expanded (platform header + sidebar hidden). */
840
+ focusMode: boolean;
841
+ /**
842
+ * Whether focus mode exists on this surface at all — only the normal
843
+ * signed-in layout has chrome to hide. False on public, full-screen and
844
+ * embedded views, where `setFocusMode` is ignored.
845
+ */
846
+ focusModeAvailable: boolean;
847
+ /**
848
+ * Whether the layout draws the suggested-arches sidebar for this arche —
849
+ * false where the manifest declined it (`showSidebar: false`) and on
850
+ * surfaces that never had one. Hide your sidebar toggle when false.
851
+ */
852
+ sidebarAvailable: boolean;
853
+ /** The sidebar is collapsed (only meaningful when `sidebarAvailable`). */
854
+ sidebarCollapsed: boolean;
855
+ /**
856
+ * In focus mode, the host draws its thin bar (Fias home · Worktop · Fias
857
+ * AI · Collapse). False when the plugin suppressed it to draw its own.
858
+ */
859
+ hostExpandedBar: boolean;
860
+ /**
861
+ * The host draws its default expand button over the plugin. False once a
862
+ * plugin takes the chrome over (mounting `useFiasChrome` does that) or
863
+ * when the manifest declined it (`showExpandButton: false`). The takeover
864
+ * also removes the host's re-open control for a collapsed sidebar — a
865
+ * plugin that owns its chrome draws its own (`setSidebarCollapsed(false)`).
866
+ */
867
+ hostExpandButton: boolean;
868
+ }
869
+ /** What `chrome_set` may carry — every present key a boolean. */
870
+ export interface FiasChromeSetPayload {
871
+ focusMode?: boolean;
872
+ sidebarCollapsed?: boolean;
873
+ hostExpandedBar?: boolean;
874
+ hostExpandButton?: boolean;
875
+ }
876
+ /** The host destinations a plugin may leave for — a closed enum, never a URL. */
877
+ export type FiasChromeNavigateTarget = 'home' | 'worktop';
878
+ /**
879
+ * Host-chrome API available via useFiasChrome() — the state above plus the
880
+ * controls the platform's own focus-mode bar carries, so a plugin can place
881
+ * them where its design wants them.
882
+ */
883
+ export interface FiasChromeApi extends FiasChromeState {
884
+ /**
885
+ * The host delivered chrome state. False before `init` lands and on a host
886
+ * older than this API — the state fields then hold inert defaults and the
887
+ * setters are no-ops, so a plugin can render unconditionally.
888
+ */
889
+ supported: boolean;
890
+ /** Expand (`true`) or collapse (`false`) — the platform's own expand/contract. */
891
+ setFocusMode: (on: boolean) => void;
892
+ /** Collapse or reopen the suggested-arches sidebar (when `sidebarAvailable`). */
893
+ setSidebarCollapsed: (collapsed: boolean) => void;
894
+ /**
895
+ * Keep (`true`, the default) or suppress (`false`) the host's focus-mode
896
+ * bar. Suppress it ONLY if you draw your own way back — once the chrome is
897
+ * hidden that bar is the only one. Focus mode you set persists across
898
+ * reloads only while the bar is kept; with it suppressed a reload restores
899
+ * the chrome, so a broken collapse control of yours is never a trap.
900
+ */
901
+ setHostExpandedBar: (shown: boolean) => void;
902
+ /** Leave the arche for Fias home (`/`). */
903
+ goToFiasHome: () => void;
904
+ /** Leave the arche for the user's Worktop. */
905
+ goToWorktop: () => void;
906
+ /**
907
+ * Ask the host to open the Fias AI panel. No permission needed; no text can
908
+ * be passed (the assistant's input belongs to the user); the host debounces
909
+ * and honours the user's last dismissal — never call it on mount or in a loop.
910
+ */
911
+ openAssistant: () => void;
912
+ }
802
913
  /**
803
914
  * Navigation API available via useFiasNavigation() hook.
804
915
  */
@@ -1195,12 +1306,26 @@ export interface VaultDocumentUploadInitResult {
1195
1306
  requiredHeaders: Record<string, string>;
1196
1307
  /** ISO 8601 timestamp when the upload URL expires. */
1197
1308
  uploadUrlExpiresAt: string;
1309
+ /**
1310
+ * Where the file was kept: `'workspace'` when the user is working in a team
1311
+ * workspace that approved your arche to keep its files there (every member
1312
+ * using your arche can open it), `'personal'` otherwise (only this person
1313
+ * can). Absent on servers older than this field.
1314
+ */
1315
+ space?: 'workspace' | 'personal';
1198
1316
  }
1199
1317
  export interface VaultDocumentUploadResult {
1200
1318
  documentId: string;
1201
1319
  /** Status after finalize — `'uploaded'`, then `'available'` once the
1202
1320
  * extraction worker indexes the document for search. */
1203
1321
  status: string;
1322
+ /**
1323
+ * Where the file was kept: `'workspace'` when the user is working in a team
1324
+ * workspace that approved your arche to keep its files there (every member
1325
+ * using your arche can open it), `'personal'` otherwise (only this person
1326
+ * can). Absent on servers older than this field.
1327
+ */
1328
+ space?: 'workspace' | 'personal';
1204
1329
  /**
1205
1330
  * Only on a save into the user's Documents (`destination: 'documents'`,
1206
1331
  * `saveCopy`): the name the user kept — it may differ from the one you
@@ -1241,6 +1366,15 @@ export interface VaultDocumentReferenceResult {
1241
1366
  * - `vault:documents:read` — list, read, getDownloadUrl
1242
1367
  * - `vault:documents:write` — write, update, delete
1243
1368
  *
1369
+ * Where the files live: in the person's own Vault — or, while they work in a
1370
+ * team workspace whose owner or admin approved your arche, in that
1371
+ * workspace's Vault, counted against the workspace's storage. There the
1372
+ * files are the team's: every member using your arche lists and opens them,
1373
+ * members and above change them, viewers only open them
1374
+ * (`WORKSPACE_VIEWER_READ_ONLY`). A document id saved before the approval
1375
+ * still opens for the person who saved it. `write`/`upload` report which
1376
+ * one they used (`space`).
1377
+ *
1244
1378
  * Note: images returned from useImageGeneration() are auto-saved into
1245
1379
  * the arche's folder and the result includes a `documentId`. Pass that
1246
1380
  * documentId here to refresh the presigned URL after the original ~1h
@@ -1332,6 +1466,7 @@ export interface VaultDocumentsApi {
1332
1466
  * the bridge request body). For binaries or larger documents use `upload`. */
1333
1467
  write: (params: VaultDocumentWriteParams) => Promise<{
1334
1468
  documentId: string;
1469
+ space?: 'workspace' | 'personal';
1335
1470
  }>;
1336
1471
  /** Rename or retag a document. */
1337
1472
  update: (documentId: string, params: VaultDocumentUpdateParams) => Promise<void>;
@@ -1911,6 +2046,310 @@ export interface CompanyEmailSendResult {
1911
2046
  /** Recipients counted as sent (`accepted` + `unknown`). */
1912
2047
  sent: number;
1913
2048
  }
2049
+ /** An outside account the acting workspace lets this app use (ADR-029 §2). */
2050
+ export interface FiasConnection {
2051
+ connectionId: string;
2052
+ /** Provider id, e.g. `'x'`, `'linkedin'`. */
2053
+ provider: string;
2054
+ providerDisplayName: string;
2055
+ accountDisplayName: string | null;
2056
+ /** The account's handle, without `@`. */
2057
+ accountHandle: string | null;
2058
+ accountAvatarUrl: string | null;
2059
+ /** `needs_reconnect`: a person has to connect it again before it can be used. */
2060
+ status: 'active' | 'needs_reconnect';
2061
+ }
2062
+ export type FiasConnectResult = {
2063
+ connectionId: string;
2064
+ provider: string;
2065
+ } | {
2066
+ canceled: true;
2067
+ };
2068
+ export interface FiasConnectionsApi {
2069
+ /** The accounts the workspace the app is open in lets it use. */
2070
+ list: () => Promise<FiasConnection[]>;
2071
+ /**
2072
+ * Ask the person to connect an account at `provider`, or let this app use one
2073
+ * the workspace already connected. The HOST draws the screen and makes every
2074
+ * grant; resolves `{ canceled: true }` when they decline.
2075
+ */
2076
+ connect: (provider: string) => Promise<FiasConnectResult>;
2077
+ /** Give up this app's access to one connection. */
2078
+ release: (connectionId: string) => Promise<void>;
2079
+ }
2080
+ export type FiasCreativeItemKind = 'style' | 'character';
2081
+ /** A style or character, as the Creative Library returns it. */
2082
+ export interface FiasCreativeItem {
2083
+ itemId: string;
2084
+ kind: FiasCreativeItemKind;
2085
+ name: string;
2086
+ /** The version shown — the current one unless you asked for another. */
2087
+ version: number;
2088
+ currentVersion: number;
2089
+ /** A style's description, or a character's appearance. */
2090
+ words: string;
2091
+ /** Vault document ids of the reference pictures, best first. */
2092
+ referenceDocumentIds: string[];
2093
+ /** A character's style: a library style id or a built-in style key. Null for a style. */
2094
+ styleRef: string | null;
2095
+ /** YOUR arche's own fields on this item; other arches' are never shown. */
2096
+ extension: Record<string, unknown> | null;
2097
+ /** The arche that created it, when one did. */
2098
+ sourceArcheId: string | null;
2099
+ createdAt: string;
2100
+ updatedAt: string;
2101
+ deletedAt: string | null;
2102
+ /** `get` only: short-lived (5 minute) inline preview URLs of the reference pictures. */
2103
+ previews?: Array<{
2104
+ documentId: string;
2105
+ url: string;
2106
+ expiresAt: string;
2107
+ }>;
2108
+ }
2109
+ export interface FiasCreativeItemFields {
2110
+ name?: string;
2111
+ words?: string;
2112
+ /** Images THIS arche created (e.g. with `useVaultDocuments().upload`), in the same library. */
2113
+ referenceDocumentIds?: string[];
2114
+ styleRef?: string | null;
2115
+ /** Your arche's own fields; `null` removes them on update. At most 16 KB. */
2116
+ extension?: Record<string, unknown> | null;
2117
+ }
2118
+ export interface FiasCreativeLibraryApi {
2119
+ /**
2120
+ * Styles and characters, most recently changed first — the whole library
2121
+ * (it holds at most 500); with `includeDeleted`, the 500 most recently changed.
2122
+ */
2123
+ list: (options?: {
2124
+ kind?: FiasCreativeItemKind;
2125
+ includeDeleted?: boolean;
2126
+ }) => Promise<FiasCreativeItem[]>;
2127
+ /** One item, with preview URLs; pass `version` for an earlier version. */
2128
+ get: (itemId: string, version?: number) => Promise<FiasCreativeItem>;
2129
+ /** Needs `vault:creative:write`. A style has 1–12 pictures; a character exactly one. */
2130
+ create: (fields: FiasCreativeItemFields & {
2131
+ kind: FiasCreativeItemKind;
2132
+ name: string;
2133
+ }) => Promise<FiasCreativeItem>;
2134
+ /**
2135
+ * Writes the next version; fields left out carry forward. Pass
2136
+ * `expectedVersion` to fail with CREATIVE_VERSION_CONFLICT if someone else
2137
+ * changed it first.
2138
+ */
2139
+ update: (itemId: string, fields: FiasCreativeItemFields & {
2140
+ expectedVersion?: number;
2141
+ }) => Promise<FiasCreativeItem>;
2142
+ /** To the trash (versions kept); `restore` brings it back. */
2143
+ remove: (itemId: string) => Promise<FiasCreativeItem>;
2144
+ restore: (itemId: string) => Promise<FiasCreativeItem>;
2145
+ /**
2146
+ * Let the person pick one style or character in a sheet Fias draws, with
2147
+ * its pictures — what `list` would return, nothing more. Resolves with the
2148
+ * item picked, or `{ canceled: true }` when they close the sheet. Rejects
2149
+ * with `PICKER_UNAVAILABLE` where there is no picker (the dev harness, the
2150
+ * builder preview) and `SHEET_BUSY` while another Fias sheet is open.
2151
+ */
2152
+ pick: (options?: {
2153
+ kind?: FiasCreativeItemKind;
2154
+ }) => Promise<FiasCreativePickResult>;
2155
+ }
2156
+ /** What `useCreativeLibrary().pick()` resolves with. */
2157
+ export type FiasCreativePickResult = {
2158
+ item: {
2159
+ itemId: string;
2160
+ kind: FiasCreativeItemKind;
2161
+ name: string;
2162
+ version: number;
2163
+ };
2164
+ } | {
2165
+ canceled: true;
2166
+ };
2167
+ /** One X post. Images are Vault document ids: this app's own files, or ones shared with it. */
2168
+ export interface FiasXPostInput {
2169
+ text: string;
2170
+ /** Images (PNG, JPEG, WebP or GIF, 5 MB each) — at most 4 across the whole publish. */
2171
+ mediaDocumentIds?: string[];
2172
+ }
2173
+ export interface FiasXPublishParams {
2174
+ connectionId: string;
2175
+ /** One post, or a thread of up to 10. */
2176
+ posts: FiasXPostInput[];
2177
+ /** Reply to this post id. */
2178
+ replyToPostId?: string;
2179
+ /** A poll on a single post with no images. */
2180
+ poll?: {
2181
+ options: string[];
2182
+ durationMinutes: number;
2183
+ };
2184
+ }
2185
+ export interface FiasXPublishResult {
2186
+ posts: Array<{
2187
+ postId: string;
2188
+ url: string;
2189
+ }>;
2190
+ /** False when X stopped part-way through a thread: `posts` is what went out. */
2191
+ complete: boolean;
2192
+ /** Where a thread stopped (1-based) and X's reason; present only when `complete` is false. */
2193
+ stopped?: {
2194
+ atPost: number;
2195
+ reason: string;
2196
+ };
2197
+ }
2198
+ export interface FiasXUser {
2199
+ id: string;
2200
+ name: string;
2201
+ username: string;
2202
+ profileImageUrl?: string;
2203
+ description?: string;
2204
+ verified: boolean;
2205
+ verifiedType: 'blue' | 'government' | 'business' | 'none';
2206
+ followersCount: number;
2207
+ }
2208
+ export interface FiasXPost {
2209
+ postId: string;
2210
+ text: string;
2211
+ createdAt: string | null;
2212
+ mediaUrl: string | null;
2213
+ likes: number | null;
2214
+ replies: number | null;
2215
+ reposts: number | null;
2216
+ views: number | null;
2217
+ }
2218
+ export interface FiasXPostMetrics {
2219
+ postId: string;
2220
+ likes: number;
2221
+ replies: number;
2222
+ reposts: number;
2223
+ views: number;
2224
+ }
2225
+ export interface FiasXAccountStats {
2226
+ followers: number;
2227
+ following: number;
2228
+ posts: number;
2229
+ listed: number;
2230
+ }
2231
+ /**
2232
+ * X, as an account the workspace let this app use. Every call names the
2233
+ * connection (from `useFiasConnections`) and is charged to the user per X
2234
+ * request. `publishPost` shows the person a confirm sheet first — the text,
2235
+ * every image and the cost — and resolves only once they approve; a decline
2236
+ * rejects with `USER_DECLINED`, and a host already showing another sheet with
2237
+ * `SHEET_BUSY`. The approval covers the images' exact bytes: an image file
2238
+ * changed after asking rejects with `MEDIA_CHANGED` and nothing is posted.
2239
+ */
2240
+ export interface FiasXApi {
2241
+ publishPost: (params: FiasXPublishParams) => Promise<FiasXPublishResult>;
2242
+ searchUsers: (connectionId: string, query: string, options?: {
2243
+ maxResults?: number;
2244
+ }) => Promise<FiasXUser[]>;
2245
+ /**
2246
+ * Recent posts by `userId`, or by the connected account when omitted.
2247
+ * `sinceId`: only posts newer than that one — re-reading an account pays
2248
+ * only for its new posts, since each post returned is billed.
2249
+ */
2250
+ getUserPosts: (connectionId: string, options?: {
2251
+ userId?: string;
2252
+ maxResults?: number;
2253
+ sinceId?: string;
2254
+ }) => Promise<FiasXPost[]>;
2255
+ getPostMetrics: (connectionId: string, postIds: string[]) => Promise<FiasXPostMetrics[]>;
2256
+ getAccountStats: (connectionId: string) => Promise<FiasXAccountStats>;
2257
+ }
2258
+ export interface FiasLinkedInPublishParams {
2259
+ connectionId: string;
2260
+ /** Up to 3,000 characters. */
2261
+ text: string;
2262
+ /** Up to 9 images (PNG, JPEG or GIF, 8 MB each): this app's files or ones shared with it. */
2263
+ mediaDocumentIds?: string[];
2264
+ /** A link LinkedIn previews (when there are no images). */
2265
+ link?: string;
2266
+ /** Organizations to mention; each `name` must appear in `text`. */
2267
+ mentions?: Array<{
2268
+ name: string;
2269
+ urn: string;
2270
+ }>;
2271
+ visibility?: 'PUBLIC' | 'CONNECTIONS' | 'LOGGED_IN';
2272
+ }
2273
+ export interface FiasLinkedInOrganization {
2274
+ id: string;
2275
+ name: string;
2276
+ /** `urn:li:organization:<id>` — what a mention names. */
2277
+ urn: string;
2278
+ }
2279
+ /**
2280
+ * LinkedIn, as a member account the workspace let this app use. Every call
2281
+ * names the connection and is charged to the user. `publishPost` shows the
2282
+ * person a confirm sheet first; a decline rejects with `USER_DECLINED`.
2283
+ */
2284
+ export interface FiasLinkedInApi {
2285
+ publishPost: (params: FiasLinkedInPublishParams) => Promise<{
2286
+ postUrn: string;
2287
+ url: string | null;
2288
+ }>;
2289
+ searchOrganizations: (connectionId: string, vanityName: string) => Promise<FiasLinkedInOrganization[]>;
2290
+ }
2291
+ /** One call to schedule for later (ADR-029 §5). */
2292
+ export interface FiasScheduleParams {
2293
+ /** The entity, e.g. `X_ENTITY_ID`. */
2294
+ entityId: string;
2295
+ /** A verb that can be scheduled, e.g. `'publish_post'`. */
2296
+ verb: string;
2297
+ /** Exactly what the verb takes now (without `op`) — e.g. `{ connectionId, posts }`. */
2298
+ payload: Record<string, unknown>;
2299
+ /** When to send it: 5 minutes to 60 days from now. */
2300
+ fireAt: Date | string;
2301
+ }
2302
+ export interface FiasSchedule {
2303
+ scheduleId: string;
2304
+ entityId: string;
2305
+ verb: string;
2306
+ /** What it does, in the platform's words ("Post to X"). */
2307
+ summary: string;
2308
+ fireAt: string | null;
2309
+ /**
2310
+ * `refused`: something changed before it was due (the account was
2311
+ * disconnected, the app lost access, the approved time passed while it was
2312
+ * paused, …) and nothing was sent — see `refusal`. `partial`: a thread the
2313
+ * provider stopped part-way; some of it went out. `paused`: the person paused
2314
+ * it in Fias.
2315
+ */
2316
+ status: 'scheduled' | 'paused' | 'sent' | 'partial' | 'refused' | 'failed' | 'cancelled';
2317
+ refusal?: {
2318
+ code: string;
2319
+ message: string;
2320
+ };
2321
+ /**
2322
+ * Once `sent` or `partial`: what the call returned — the same output an
2323
+ * immediate call gives (for X `publish_post`, `{ posts: [{ postId, url }], complete }`),
2324
+ * so the app can record where it went. Absent before then, or if too large to relay.
2325
+ */
2326
+ output?: Record<string, unknown>;
2327
+ }
2328
+ export interface FiasScheduleListOptions {
2329
+ /** How many to return, 1–100. Default 20, or the number of `scheduleIds`. */
2330
+ limit?: number;
2331
+ /** Only these schedules (1–100 ids from `schedule()`); ids that are not this app's are left out. */
2332
+ scheduleIds?: string[];
2333
+ }
2334
+ /**
2335
+ * Schedule ONE call for later. For an action outside Fias the person approves
2336
+ * exactly what will be sent, and when, in a confirm sheet first; a decline
2337
+ * rejects with `USER_DECLINED`. There is no edit: cancel, and schedule again.
2338
+ */
2339
+ export interface FiasSchedulesApi {
2340
+ schedule: (params: FiasScheduleParams) => Promise<{
2341
+ scheduleId: string;
2342
+ fireAt: string;
2343
+ }>;
2344
+ /**
2345
+ * This app's schedules in the workspace it is open in, newest first: the
2346
+ * newest 20 unless `limit` says otherwise (at most 100). Pass `scheduleIds`
2347
+ * to follow just the schedules you are waiting on.
2348
+ */
2349
+ list: (options?: FiasScheduleListOptions) => Promise<FiasSchedule[]>;
2350
+ /** Cancel one before it is sent. */
2351
+ cancel: (scheduleId: string) => Promise<void>;
2352
+ }
1914
2353
  export interface CompanyEmailApi {
1915
2354
  /**
1916
2355
  * Send one email AS the Company this app is being used in, from its verified
@@ -1923,7 +2362,7 @@ export interface CompanyEmailApi {
1923
2362
  /**
1924
2363
  * Message types sent from the plugin iframe to the parent frame.
1925
2364
  */
1926
- export type PluginToHostMessageType = 'ready' | 'resize' | 'toast' | 'get_user' | 'get_theme' | 'storage_read' | 'storage_write' | 'storage_list' | 'storage_delete' | 'entity_invoke' | 'client_entity_invoke' | 'image_generate' | 'entities_list_image' | 'audio_generate' | 'surface_invoke' | 'navigate' | 'open_arche' | 'data_create_collection' | 'data_list_collections' | 'data_delete_collection' | 'data_put' | 'data_get' | 'data_query' | 'data_delete' | 'data_batch' | 'data_search' | 'workspace_create' | 'workspace_list' | 'workspace_get' | 'workspace_archive' | 'workspace_list_members' | 'workspace_add_member' | 'workspace_update_member' | 'workspace_remove_member' | 'store_get_products' | 'store_purchase' | 'store_get_entitlements' | 'store_get_purchase_history' | 'store_restore' | 'store_cancel_subscription' | 'vault_documents_list' | 'vault_documents_read' | 'vault_documents_read_many' | 'vault_documents_download_url' | 'vault_documents_get_urls' | 'vault_documents_search' | 'vault_documents_write' | 'vault_documents_update' | 'vault_documents_delete' | 'vault_documents_attach' | 'vault_documents_detach' | 'vault_documents_upload_init' | 'vault_documents_upload_finalize' | 'vault_documents_upload' | 'vault_documents_pick' | 'arche_assets_list' | 'arche_assets_index' | 'arche_assets_get_url' | 'preview_state' | 'subscription_unsubscribe' | 'ai_actions_declare' | 'ai_state' | 'ai_action_result' | 'ai_open';
2365
+ export type PluginToHostMessageType = 'ready' | 'resize' | 'toast' | 'get_user' | 'get_theme' | 'storage_read' | 'storage_write' | 'storage_list' | 'storage_delete' | 'entity_invoke' | 'client_entity_invoke' | 'image_generate' | 'entities_list_image' | 'audio_generate' | 'surface_invoke' | 'navigate' | 'open_arche' | 'data_create_collection' | 'data_list_collections' | 'data_delete_collection' | 'data_put' | 'data_get' | 'data_query' | 'data_delete' | 'data_batch' | 'data_search' | 'workspace_create' | 'workspace_list' | 'workspace_get' | 'workspace_archive' | 'workspace_list_members' | 'workspace_add_member' | 'workspace_update_member' | 'workspace_remove_member' | 'store_get_products' | 'store_purchase' | 'store_get_entitlements' | 'store_get_purchase_history' | 'store_restore' | 'store_cancel_subscription' | 'vault_documents_list' | 'vault_documents_read' | 'vault_documents_read_many' | 'vault_documents_download_url' | 'vault_documents_get_urls' | 'vault_documents_search' | 'vault_documents_write' | 'vault_documents_update' | 'vault_documents_delete' | 'vault_documents_attach' | 'vault_documents_detach' | 'vault_documents_upload_init' | 'vault_documents_upload_finalize' | 'vault_documents_upload' | 'vault_documents_pick' | 'arche_assets_list' | 'arche_assets_index' | 'arche_assets_get_url' | 'preview_state' | 'subscription_unsubscribe' | 'ai_actions_declare' | 'ai_state' | 'ai_action_result' | 'ai_open' | 'chrome_set' | 'chrome_navigate';
1927
2366
  /**
1928
2367
  * One Fias AI action a plugin declares — what the platform assistant may do
1929
2368
  * in this plugin's UI while it is open. Mirrors the platform's
@@ -1963,18 +2402,33 @@ export interface FiasAIActionsDeclaration {
1963
2402
  /**
1964
2403
  * Why a realtime subscription ended (ADR-012 Phase M4). Closed union so
1965
2404
  * hooks can distinguish terminal endings (`authorization_revoked`,
1966
- * `collection_deleted`) from ones worth resubscribing after conditions
1967
- * change (`limit`, `transport_error`, `lease_expired`).
2405
+ * `collection_deleted` — the observed resource is gone, whatever its kind)
2406
+ * from ones worth resubscribing after conditions change (`limit`,
2407
+ * `transport_error`, `lease_expired`).
1968
2408
  */
1969
2409
  export type SubscriptionEndedReason = 'authorization_revoked' | 'lease_expired' | 'collection_deleted' | 'limit' | 'transport_error' | 'unsubscribed';
1970
2410
  /**
1971
- * State reported by useDataSubscription().
2411
+ * A realtime invalidation delivered to a subscriber (ADR-012 Phase M4).
2412
+ * Notify-then-refetch: it says only that the observed resource changed.
2413
+ * `resource` is the resource's public identifier as you subscribed to it —
2414
+ * a datastore collection's name, a chat channel's id.
1972
2415
  */
1973
- export interface DataSubscriptionState {
2416
+ export interface SubscriptionEvent {
2417
+ resource: string;
2418
+ changed: true;
2419
+ /** @deprecated Alias of `resource`, kept for bundles built before the `resource` rename; removed in the next major. */
2420
+ collection?: string;
2421
+ }
2422
+ /**
2423
+ * State reported by useEntitySubscription() and useDataSubscription().
2424
+ */
2425
+ export interface EntitySubscriptionState {
1974
2426
  status: 'subscribing' | 'active' | 'ended';
1975
2427
  /** Set once status === 'ended'. */
1976
2428
  endedReason?: SubscriptionEndedReason;
1977
2429
  }
2430
+ /** State reported by useDataSubscription() — the same shape as every entity subscription. */
2431
+ export type DataSubscriptionState = EntitySubscriptionState;
1978
2432
  /**
1979
2433
  * Step navigation API available via useStepNavigation() hook.
1980
2434
  */
@@ -2000,7 +2454,7 @@ export interface StepNavigationOptions {
2000
2454
  /**
2001
2455
  * Message types sent from the parent frame to the plugin iframe.
2002
2456
  */
2003
- export type HostToPluginMessageType = 'init' | 'response' | 'theme_update' | 'navigate_update' | 'step_navigate' | 'stream_token' | 'text_models_update' | 'preview_state_capture' | 'preview_state_restore' | 'subscription_event' | 'subscription_ended' | 'ai_action_dispatch' | 'arche_handoff';
2457
+ export type HostToPluginMessageType = 'init' | 'response' | 'theme_update' | 'access_update' | 'navigate_update' | 'chrome_update' | 'step_navigate' | 'stream_token' | 'text_models_update' | 'preview_state_capture' | 'preview_state_restore' | 'subscription_event' | 'subscription_ended' | 'ai_action_dispatch' | 'arche_handoff';
2004
2458
  /**
2005
2459
  * Base message structure for all bridge communication.
2006
2460
  */
@@ -2091,6 +2545,23 @@ export interface FiasTextModel {
2091
2545
  outputCreditsPerMillionTokens: number;
2092
2546
  } | null;
2093
2547
  }
2548
+ /**
2549
+ * The Fias workspace the plugin was opened in — the user's own (`personal`) or
2550
+ * an organization's (`org`) — and the user's role there. Fixed for as long as
2551
+ * the plugin is open: when the user switches workspace, the host offers to
2552
+ * reopen the plugin there, and the reopened plugin receives the new value.
2553
+ *
2554
+ * It carries no id and no name, and grants nothing; the platform applies the
2555
+ * workspace to every call on its own. An org workspace that has approved the
2556
+ * app gives it a shared space (`useFiasWorkspaces().openForWorkspace()`), named
2557
+ * after the workspace — that space's id is the plugin's key for per-workspace
2558
+ * data.
2559
+ */
2560
+ export interface FiasHolder {
2561
+ type: 'personal' | 'org';
2562
+ /** The user's role in it. Always `owner` for a personal workspace. */
2563
+ role: 'owner' | 'admin' | 'member' | 'viewer';
2564
+ }
2094
2565
  export interface BridgeInitMessage {
2095
2566
  type: 'init';
2096
2567
  messageId: string;
@@ -2100,6 +2571,12 @@ export interface BridgeInitMessage {
2100
2571
  theme: FiasTheme;
2101
2572
  /** Plugin-relative path — see `FiasNavigationApi.currentPath`. */
2102
2573
  currentPath: string;
2574
+ /**
2575
+ * The host-chrome state for this arche — see `FiasChromeState`. Absent
2576
+ * from hosts older than `useFiasChrome` (the hook then reports
2577
+ * `supported: false`), and null on a surface with no chrome of its own.
2578
+ */
2579
+ chrome?: FiasChromeState | null;
2103
2580
  /**
2104
2581
  * Self-hosted vendored-library asset URLs (keyed by import specifier) —
2105
2582
  * present only when the plugin declared `sandbox:vendored-libraries` and the
@@ -2113,6 +2590,12 @@ export interface BridgeInitMessage {
2113
2590
  * backwards compat with older hosts.
2114
2591
  */
2115
2592
  textModels?: FiasTextModel[] | null;
2593
+ /**
2594
+ * The workspace the plugin was opened in — present only when the plugin
2595
+ * declared `user:profile:read` or `data:workspace`. `null`/absent when the
2596
+ * host could not resolve it, and from older hosts.
2597
+ */
2598
+ holder?: FiasHolder | null;
2116
2599
  /**
2117
2600
  * Bridge protocol version the HOST speaks. Optional for backwards
2118
2601
  * compat with hosts pre-dating the versioning work — absence is
@@ -2168,6 +2651,20 @@ export interface DataStoreCollection {
2168
2651
  * plugin can VERIFY its declared constraints took effect.
2169
2652
  */
2170
2653
  constraints?: DataStoreCollectionConstraints | null;
2654
+ /**
2655
+ * The app-role permissions that protect this collection (workspace scope,
2656
+ * apps that declare `access` in fias-plugin.json); null = none. Set once,
2657
+ * from the manifest only. Returned so a plugin can VERIFY its declaration
2658
+ * took effect — absent from older platforms.
2659
+ */
2660
+ readPermission?: string | null;
2661
+ writePermission?: string | null;
2662
+ /**
2663
+ * The audiences (manifest `access.audiences`) this collection's documents
2664
+ * may be placed in (ADR-034); null = none. Set with the permissions, then
2665
+ * only grows. Absent from older platforms.
2666
+ */
2667
+ audiences?: string[] | null;
2171
2668
  /**
2172
2669
  * Which plugin project created this collection, as the dev harness reported
2173
2670
  * it. Display metadata only — never a scope or an authorization input.
@@ -2337,9 +2834,15 @@ export interface DataStoreBatchOptions {
2337
2834
  * read-back. Absent on platforms without conditional-write support.
2338
2835
  */
2339
2836
  export interface DataStoreBatchResult {
2837
+ /**
2838
+ * Each put's key — the server-generated one for a put without a key, in a
2839
+ * collection with audiences — its version, and the audience it sits in
2840
+ * (where it has one).
2841
+ */
2340
2842
  written?: {
2341
2843
  key: string;
2342
2844
  version?: number;
2845
+ audience?: string;
2343
2846
  }[];
2344
2847
  }
2345
2848
  /**
@@ -2350,6 +2853,14 @@ export interface DataStoreBatchResult {
2350
2853
  */
2351
2854
  export interface DataStorePutResult {
2352
2855
  version?: number;
2856
+ /**
2857
+ * The document's key — the one the server generated for a create in a
2858
+ * collection with audiences (see {@link FiasDataStoreApi.create}). Absent
2859
+ * from hosts that predate audiences.
2860
+ */
2861
+ key?: string;
2862
+ /** The audience the document sits in, in a collection with audiences. */
2863
+ audience?: string;
2353
2864
  }
2354
2865
  /**
2355
2866
  * A document returned from the data store.
@@ -2375,6 +2886,12 @@ export interface DataStoreDocument<T = Record<string, unknown>> {
2375
2886
  * absent otherwise.
2376
2887
  */
2377
2888
  authoredByCollaborator?: boolean;
2889
+ /**
2890
+ * The audience the document is placed in, in a collection with audiences
2891
+ * (ADR-034): who may read it is decided by the platform from the
2892
+ * audience's readers, never by your code. Absent elsewhere.
2893
+ */
2894
+ audience?: string;
2378
2895
  }
2379
2896
  /**
2380
2897
  * Filter condition for querying documents.
@@ -2463,6 +2980,8 @@ export interface DataStoreSearchMatch<T = Record<string, unknown>> {
2463
2980
  version?: number;
2464
2981
  /** Present on shared-scope matches: see {@link DataStoreDocument.authoredByCollaborator}. */
2465
2982
  authoredByCollaborator?: boolean;
2983
+ /** The match's audience, in a collection with audiences — see {@link DataStoreDocument.audience}. */
2984
+ audience?: string;
2466
2985
  }
2467
2986
  /**
2468
2987
  * Data Store API available via useFiasDataStore() hook.
@@ -2497,7 +3016,14 @@ export interface FiasDataStoreApi {
2497
3016
  }) => Promise<DataStoreCollection>;
2498
3017
  /** List all collections for this arche. */
2499
3018
  listCollections: () => Promise<DataStoreCollection[]>;
2500
- /** Delete a collection and all its documents. */
3019
+ /**
3020
+ * Delete a collection and all its documents. Only an arche collaborator
3021
+ * (owner or publisher) may; anyone else gets `FORBIDDEN`. On a published app
3022
+ * it works only while the collection is EMPTY: one that still holds
3023
+ * documents (every user's, workspace's and tenant's) is refused with
3024
+ * `COLLECTION_NOT_EMPTY`. Sandbox tenants (fias-dev, builder preview, test
3025
+ * channel) can delete any.
3026
+ */
2501
3027
  deleteCollection: (name: string) => Promise<void>;
2502
3028
  /**
2503
3029
  * Write (upsert) a document by key. For a `workspace`-scoped collection pass
@@ -2507,7 +3033,30 @@ export interface FiasDataStoreApi {
2507
3033
  * Resolves with the document's post-write `version` (ADR-014) so a follow-up
2508
3034
  * conditional batch can assert it without a read-back.
2509
3035
  */
2510
- put: <T extends Record<string, unknown> = Record<string, unknown>>(collection: string, key: string, data: T, options?: DataStoreScopeOptions) => Promise<DataStorePutResult>;
3036
+ put: <T extends Record<string, unknown> = Record<string, unknown>>(collection: string,
3037
+ /**
3038
+ * The document to write. In a collection with audiences keys are made by
3039
+ * the server: pass `null` to create one (or use {@link create}); a key
3040
+ * names an existing document you may change, and anything else —
3041
+ * missing, or in an audience you cannot read — is refused alike
3042
+ * (`DOCUMENT_NOT_FOUND`). Passing `{ audience }` with a key MOVES the
3043
+ * document to that audience.
3044
+ */
3045
+ key: string | null, data: T, options?: DataStoreScopeOptions) => Promise<DataStorePutResult>;
3046
+ /**
3047
+ * Create a document in a collection with audiences (ADR-034): the server
3048
+ * makes its key and places it in `options.audience`, which you must name.
3049
+ * Placing needs the audience's `disclosedBy` permission — not its read
3050
+ * permission, so a person can file something they will not see afterwards.
3051
+ * Resolves with the new key. Only in collections with audiences — in one
3052
+ * without, a create is `INVALID_DOCUMENT_KEY` (keys there are yours). A
3053
+ * platform that predates audiences rejects the call as invalid parameters
3054
+ * (`INVALID_PARAMS`); `AUDIENCES_UNAVAILABLE` is only a backstop for a host
3055
+ * that accepted it yet returned no key.
3056
+ */
3057
+ create: <T extends Record<string, unknown> = Record<string, unknown>>(collection: string, data: T, options: DataStoreScopeOptions & {
3058
+ audience: string;
3059
+ }) => Promise<Required<Pick<DataStorePutResult, 'key'>> & DataStorePutResult>;
2511
3060
  /** Get a document by key. Returns null if not found. Pass `{ workspaceId }`
2512
3061
  * for a workspace-scoped collection. */
2513
3062
  get: <T extends Record<string, unknown> = Record<string, unknown>>(collection: string, key: string, options?: DataStoreScopeOptions) => Promise<T | null>;
@@ -2557,6 +3106,15 @@ export interface FiasDataStoreApi {
2557
3106
  export interface DataStoreScopeOptions {
2558
3107
  /** Target workspace for a `workspace`-scoped collection. */
2559
3108
  workspaceId?: string;
3109
+ /**
3110
+ * An audience of a collection with audiences (ADR-034, the manifest's
3111
+ * `access.audiences`): where `put`/`create` places the document, or the one
3112
+ * audience `get`/`query`/`search` look in (by default they read every
3113
+ * audience the user reads). Ignored by `delete`. Naming one before the
3114
+ * workspace has turned the app's roles on is refused
3115
+ * (`ACCESS_SETUP_REQUIRED`).
3116
+ */
3117
+ audience?: string;
2560
3118
  }
2561
3119
  /**
2562
3120
  * One write in an atomic batch (see {@link FiasDataStoreApi.batch}). A `put`
@@ -2566,9 +3124,12 @@ export interface DataStoreScopeOptions {
2566
3124
  export type DataStoreBatchOp = {
2567
3125
  op: 'put';
2568
3126
  collection: string;
2569
- key: string;
3127
+ /** Omit to create with a server-generated key (collections with audiences). */
3128
+ key?: string;
2570
3129
  data: Record<string, unknown>;
2571
3130
  workspaceId?: string;
3131
+ /** Where to place (or move) the document — see {@link DataStoreScopeOptions.audience}. */
3132
+ audience?: string;
2572
3133
  } | {
2573
3134
  op: 'delete';
2574
3135
  collection: string;
@@ -2586,6 +3147,13 @@ export interface DataStoreWorkspace {
2586
3147
  createdAt: string;
2587
3148
  /** Soft-archive timestamp; null while active. */
2588
3149
  archivedAt: string | null;
3150
+ /**
3151
+ * True for the shared space of a Fias workspace (see
3152
+ * `FiasWorkspacesApi.openForWorkspace`): its members are the Fias
3153
+ * workspace's members, so the member methods refuse with
3154
+ * `HOLDER_BACKED_WORKSPACE`. Absent from older hosts.
3155
+ */
3156
+ holderBacked?: boolean;
2589
3157
  }
2590
3158
  /** A member of a workspace. Members are addressed by username — the platform
2591
3159
  * userId is internal and never exposed to plugins or users. */
@@ -2615,11 +3183,27 @@ export interface DataStoreWorkspaceMember {
2615
3183
  export interface FiasWorkspacesApi {
2616
3184
  /** Create a workspace; the caller becomes its owner. */
2617
3185
  create: (displayName: string) => Promise<DataStoreWorkspace>;
3186
+ /**
3187
+ * Open the shared space of the Fias org workspace the plugin was opened in
3188
+ * (see `useFiasHolder`), creating it on first use. It exists only once a
3189
+ * workspace owner or admin has approved the app. Its `displayName` is the
3190
+ * workspace's name, and its members are that workspace's members, with their
3191
+ * workspace roles — nobody manages a member list, and someone who leaves the
3192
+ * workspace loses access at once. Every member gets the same space, and it
3193
+ * answers only while the plugin is open in that workspace. Rejects with
3194
+ * `HOLDER_NOT_ELIGIBLE` in a personal workspace, before the workspace has
3195
+ * approved the app, and for a viewer when the space does not exist yet.
3196
+ */
3197
+ openForWorkspace: () => Promise<DataStoreWorkspace>;
2618
3198
  /** List the workspaces the caller is an active member of. */
2619
3199
  list: () => Promise<DataStoreWorkspace[]>;
2620
3200
  /** Get a single workspace (caller must be a member). */
2621
3201
  get: (workspaceId: string) => Promise<DataStoreWorkspace>;
2622
- /** Archive a workspace (owner only). */
3202
+ /**
3203
+ * Archive a workspace (owner only). Final: an archived workspace cannot be
3204
+ * reopened, and it is deleted with its documents 30 days later — tell your
3205
+ * user before they archive.
3206
+ */
2623
3207
  archive: (workspaceId: string) => Promise<void>;
2624
3208
  /** List a workspace's members (any member). */
2625
3209
  listMembers: (workspaceId: string) => Promise<DataStoreWorkspaceMember[]>;
@@ -2632,6 +3216,132 @@ export interface FiasWorkspacesApi {
2632
3216
  /** Remove a member by username (owner/admin, or yourself; keeps the one-owner invariant). */
2633
3217
  removeMember: (workspaceId: string, username: string) => Promise<void>;
2634
3218
  }
3219
+ /**
3220
+ * The current user's access in one workspace where only workspace TIERS
3221
+ * (owner/admin/member/viewer) apply: an app that declares no roles, or a
3222
+ * workspace outside an organization, where roles never apply.
3223
+ */
3224
+ export interface FiasTierAccess {
3225
+ mode: 'tier';
3226
+ workspaceId: string;
3227
+ /**
3228
+ * The user's tier in this workspace, or `null` when they have none: not a
3229
+ * member, an expired or removed membership, or a workspace this app cannot
3230
+ * see from where it is open.
3231
+ */
3232
+ tier: WorkspaceRole | null;
3233
+ /** ISO-8601 expiry of the user's membership, or `null` when it does not expire. */
3234
+ expiresAt: string | null;
3235
+ }
3236
+ /**
3237
+ * An app that declares roles (manifest `access`), in an org workspace that has
3238
+ * not turned them on: it runs on TIERS until an owner activates roles. Collections that existed before the app declared roles work
3239
+ * as before; one created already protected is refused with
3240
+ * `ACCESS_SETUP_REQUIRED`.
3241
+ */
3242
+ export interface FiasLegacyAccess {
3243
+ mode: 'legacy';
3244
+ workspaceId: string;
3245
+ tier: WorkspaceRole;
3246
+ /** ISO-8601 expiry of the user's membership, or `null` when it does not expire. */
3247
+ expiresAt: string | null;
3248
+ }
3249
+ /** One app role the user holds that counts now. */
3250
+ export interface FiasAccessRole {
3251
+ /** The role id your manifest declares. */
3252
+ id: string;
3253
+ /** ISO-8601 expiry of this assignment, or `null` when it does not expire. */
3254
+ expiresAt: string | null;
3255
+ }
3256
+ /**
3257
+ * An app that declares roles, in an org workspace where they are on: the
3258
+ * user's roles that count at their current tier, and the permissions those
3259
+ * roles grant. A role whose `minTier` the user's tier does not meet is left
3260
+ * out — it grants nothing until they are promoted.
3261
+ */
3262
+ export interface FiasRolesAccess {
3263
+ mode: 'roles';
3264
+ workspaceId: string;
3265
+ tier: WorkspaceRole;
3266
+ /** ISO-8601 expiry of the user's membership, or `null` when it does not expire. */
3267
+ expiresAt: string | null;
3268
+ roles: FiasAccessRole[];
3269
+ /** The permission ids the user holds here, sorted. */
3270
+ permissions: string[];
3271
+ /**
3272
+ * The audiences (manifest `access.audiences`) those permissions read, and
3273
+ * the ones they may place documents in. Across the app — a collection lists
3274
+ * which of them it uses, and reading one also needs the collection's own
3275
+ * read permission. Empty while the workspace is still placing its existing
3276
+ * documents. Absent from hosts that predate audiences.
3277
+ */
3278
+ audiences?: {
3279
+ readable: string[];
3280
+ disclosable: string[];
3281
+ };
3282
+ }
3283
+ /**
3284
+ * The current user's own access in a workspace, from `useFiasAccess()`.
3285
+ *
3286
+ * `mode` says which model answered: `'tier'` for an app without roles (or a
3287
+ * workspace outside an organization, where roles never apply), `'legacy'`
3288
+ * for an app whose roles this workspace has not turned on yet, and
3289
+ * `'roles'` when they are on. Handle a `mode` you do not recognise by hiding
3290
+ * the controls it would gate, never by showing them.
3291
+ *
3292
+ * **A UI hint, never security.** The platform checks every read and write on
3293
+ * arrival; this only lets you hide controls a user could not use anyway.
3294
+ */
3295
+ export type FiasAccess = FiasTierAccess | FiasLegacyAccess | FiasRolesAccess;
3296
+ /** What `useFiasAccess()` returns. */
3297
+ export interface FiasAccessState {
3298
+ /** The user's access, or `null` while loading, on error, or with no workspace given. */
3299
+ access: FiasAccess | null;
3300
+ /**
3301
+ * True until the first answer for this workspace. A later ask (focus,
3302
+ * `access_update`, `refetch()`) keeps the answer it has and does not set it.
3303
+ */
3304
+ isLoading: boolean;
3305
+ /** A failure other than "no access here" (which is `access.tier === null`). */
3306
+ error: Error | null;
3307
+ /**
3308
+ * Whether the user holds `permission` here: true only in `'roles'` mode,
3309
+ * with that permission. Always false in `'tier'` and `'legacy'` mode, where
3310
+ * permissions are not in force — branch on `access.mode` (and the tier)
3311
+ * there.
3312
+ */
3313
+ can: (permission: string) => boolean;
3314
+ /**
3315
+ * Whether the user reads `audience` here — true only in `'roles'` mode. A
3316
+ * UI hint like `can()`: the platform only ever returns documents of the
3317
+ * audiences the user reads. Reading a document also needs its collection's
3318
+ * `readPermission`; this does not check that — `can()` it too.
3319
+ */
3320
+ canReadAudience: (audience: string) => boolean;
3321
+ /** Whether the user may place documents in `audience` here — true only in `'roles'` mode. */
3322
+ canDiscloseTo: (audience: string) => boolean;
3323
+ /**
3324
+ * Ask again. The answer is a snapshot and is NOT pushed when the user's
3325
+ * access changes elsewhere, so call this when it may have: after the app
3326
+ * changes a membership itself, or when the platform refuses an action with
3327
+ * `FORBIDDEN` / `NOT_A_MEMBER`. A refetch of the same workspace keeps the
3328
+ * current answer until the new one arrives.
3329
+ */
3330
+ refetch: () => void;
3331
+ /**
3332
+ * Open Fias's access sheet for the workspace the person is acting in: their
3333
+ * own access to this app's data, why, asking for more, and — for an access
3334
+ * manager — managing roles. Drawn by Fias; the app passes nothing and
3335
+ * changes nothing itself. Resolves once the person closes it (and refetches
3336
+ * when their access changed); rejects with `NOT_IN_WORKSPACE` in a Personal
3337
+ * workspace, where app roles never apply, `SHEET_BUSY` while another Fias
3338
+ * sheet is open, or `ACCESS_UNAVAILABLE` where no Fias host can draw it (the
3339
+ * dev harness). Requires `data:workspace`.
3340
+ */
3341
+ openAccessDialog: () => Promise<{
3342
+ changed: boolean;
3343
+ }>;
3344
+ }
2635
3345
  /**
2636
3346
  * IAP product type (mirrors Apple StoreKit).
2637
3347
  */