@sovereignfs/sdk 1.25.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 (45) hide show
  1. package/LICENSE +661 -0
  2. package/dist/chunk-MLKGABMK.js +9 -0
  3. package/dist/chunk-NQLGPAL6.js +62 -0
  4. package/dist/e2ee-crypto.d.ts +84 -0
  5. package/dist/e2ee-crypto.js +162 -0
  6. package/dist/e2ee-device.d.ts +21 -0
  7. package/dist/e2ee-device.js +13 -0
  8. package/dist/e2ee-object.d.ts +50 -0
  9. package/dist/e2ee-object.js +75 -0
  10. package/dist/e2ee-state-U-GEJ7oL.d.ts +411 -0
  11. package/dist/e2ee-state.d.ts +1 -0
  12. package/dist/e2ee-state.js +36 -0
  13. package/dist/index.d.ts +543 -0
  14. package/dist/index.js +652 -0
  15. package/package.json +50 -0
  16. package/src/__tests__/e2ee-crypto.test.ts +156 -0
  17. package/src/__tests__/e2ee-object.test.ts +90 -0
  18. package/src/__tests__/e2ee-state.test.ts +83 -0
  19. package/src/__tests__/sdk.test.ts +427 -0
  20. package/src/__tests__/sessions.test.ts +63 -0
  21. package/src/activity.ts +19 -0
  22. package/src/auth.ts +134 -0
  23. package/src/connections.ts +106 -0
  24. package/src/data.ts +88 -0
  25. package/src/db.ts +34 -0
  26. package/src/directory.ts +31 -0
  27. package/src/e2ee-crypto.ts +260 -0
  28. package/src/e2ee-device.ts +75 -0
  29. package/src/e2ee-object.ts +118 -0
  30. package/src/e2ee-state.ts +72 -0
  31. package/src/e2ee.ts +65 -0
  32. package/src/env.ts +37 -0
  33. package/src/errors.ts +46 -0
  34. package/src/host.ts +251 -0
  35. package/src/index.ts +160 -0
  36. package/src/mailer.ts +7 -0
  37. package/src/notifications.ts +36 -0
  38. package/src/platform.ts +10 -0
  39. package/src/plugins.ts +146 -0
  40. package/src/portability.ts +176 -0
  41. package/src/secrets.ts +68 -0
  42. package/src/sessions.ts +36 -0
  43. package/src/storage.ts +49 -0
  44. package/src/types.ts +418 -0
  45. package/src/unimplemented.ts +48 -0
@@ -0,0 +1,543 @@
1
+ import { C as ChangePasswordInput, S as Session, A as ActiveSession, D as DrizzleClient, M as MailOptions, P as PlatformConfig, a as SearchUsersInput, b as DirectoryUser, R as ResolveUsersInput, c as ActivityLogEntry, d as SendNotificationInput, e as StoragePutInput, f as StorageContext, g as StorageObject, E as E2eeContext, h as E2eeProfile, i as CreateE2eeProfileInput, j as E2eeRecoveryWrapper, k as SetE2eeRecoveryWrapperInput, l as EnrollE2eeDeviceInput, m as E2eeDeviceEnrollment, n as CreateSecretInput, o as SecretContext, p as SecretRef, q as SecretScope, r as CreateConnectionInput, s as ConnectionContext, t as ConnectionRef, u as ConnectionListFilter, U as UpdateConnectionInput, v as MarkConnectionErrorInput, O as OAuthStateInput, w as ConnectionOAuthState, x as ProviderConfig } from './e2ee-state-U-GEJ7oL.js';
2
+ export { y as ConnectionScope, z as ConnectionStatus, B as E2eeLocalState, F as E2eeProfileStatus, G as E2eeState, H as ProviderConfigSource, I as SanitizedConnectionError, J as ScheduleContext, K as ScheduleHandler, L as SessionUser, N as UpdateSecretInput } from './e2ee-state-U-GEJ7oL.js';
3
+ export { RecoveryWrappedCmk, WrappedCmk, WrappedDek } from './e2ee-crypto.js';
4
+ export { EncryptedBlob, EncryptedJson } from './e2ee-object.js';
5
+
6
+ /**
7
+ * A reference to a versioned data contract exposed by a *provider* plugin, used
8
+ * by a *consumer* plugin to request it.
9
+ */
10
+ interface DataContractRef {
11
+ /** The provider plugin's manifest `id`. */
12
+ providerId: string;
13
+ /** The named, read-only contract the provider exposes (e.g. `"expenses"`). */
14
+ contract: string;
15
+ /** Contract major version the consumer was built against. */
16
+ version: number;
17
+ }
18
+ /**
19
+ * A resolver a provider registers to answer read requests for one of its
20
+ * contracts. The runtime invokes it only for consumers that hold an active
21
+ * user consent grant, already scoped to the requesting user and tenant.
22
+ */
23
+ type DataContractResolver<TParams = unknown, TRow = unknown> = (params: TParams) => Promise<TRow[]>;
24
+
25
+ /** A data contract a plugin declares in its manifest `data.provides`. */
26
+ interface PluginContractSummary {
27
+ contract: string;
28
+ version: number;
29
+ }
30
+ /**
31
+ * Discovery status of an installed plugin, scoped to the requesting user
32
+ * (RFC 0051). Never exposes private provider data — only install/enable
33
+ * status, launch availability, and declared (not consented) contracts.
34
+ */
35
+ interface PluginAvailability {
36
+ id: string;
37
+ name: string;
38
+ routePrefix: string;
39
+ icon?: string;
40
+ /** Always `true` — `get()`/`list()` only ever return installed plugins. */
41
+ installed: true;
42
+ /** Whether the plugin is enabled instance-wide (Console toggle / example default). */
43
+ enabled: boolean;
44
+ /**
45
+ * Whether the *current* user could launch this plugin right now: enabled,
46
+ * not blocked by an `adminOnly` gate the user lacks `console:access` for,
47
+ * and not paywalled by an unmet entitlement (RFC 0003). `false` when called
48
+ * without an authenticated user in context.
49
+ */
50
+ availableToUser: boolean;
51
+ /** Data contracts this plugin exposes (`data.provides`), if any. */
52
+ providesContracts: PluginContractSummary[];
53
+ }
54
+ interface PluginListFilter {
55
+ /** Only return plugins that declare this contract name in `data.provides`. */
56
+ providesContract?: string;
57
+ }
58
+ /**
59
+ * Whether the current user has an active consent grant for a (consumer,
60
+ * provider, contract, version) tuple. `'not_granted'` covers both "never
61
+ * granted" and "revoked" — the platform does not distinguish the two once a
62
+ * grant is inactive; a consumer that needs to tell them apart should compare
63
+ * against its own last-known cached state.
64
+ */
65
+ type ConsentStatus = 'granted' | 'not_granted';
66
+ /**
67
+ * A standard, opaque reference to another plugin's record (RFC 0051). Store
68
+ * this shape (or split it into columns) in your own tables to point at a
69
+ * sibling plugin's data without a direct foreign key or copying private data.
70
+ * `resourceId` is opaque to the consumer — the provider decides its shape.
71
+ *
72
+ * References are never authorization: every dereference still goes through
73
+ * `sdk.data.query()` (or a tool contract) and the current user's live
74
+ * consent. Treat a stored reference as a nullable link — the provider may be
75
+ * uninstalled, disabled, have revoked consent, or have deleted the resource.
76
+ */
77
+ interface PluginReference {
78
+ /** The provider plugin's manifest `id`. */
79
+ providerId: string;
80
+ /** Provider-local resource kind (e.g. `"contact"`, `"invoice"`). */
81
+ resourceType: string;
82
+ /** Opaque to the consumer — a UUID, slug, or compound key the provider defines. */
83
+ resourceId: string;
84
+ /** The data contract this reference was resolved through, if any. */
85
+ contract?: string;
86
+ /** Contract major version at the time this reference was captured. */
87
+ version?: number;
88
+ /** A cached, possibly-stale display label — show it when the provider is unavailable. */
89
+ labelSnapshot?: string;
90
+ /** Consumer-defined extra metadata. */
91
+ metadata?: unknown;
92
+ /** ISO-8601 timestamp of when this reference was created. */
93
+ linkedAt: string;
94
+ }
95
+
96
+ /** Supplied by the runtime to an export resolver — scoped to the current user. */
97
+ interface ExportContext {
98
+ userId: string;
99
+ tenantId: string;
100
+ /** User-selected export scope (RFC 0052). */
101
+ options: ExportOptions;
102
+ }
103
+ /** User-selectable export scope, gathered by the Account Data tab. */
104
+ interface ExportOptions {
105
+ /** Whether to include plugin-contributed file blobs. Defaults to `true`. */
106
+ includeFiles: boolean;
107
+ }
108
+ /** Supplied by the runtime to an import handler — scoped to the importing user. */
109
+ interface ImportContext {
110
+ userId: string;
111
+ tenantId: string;
112
+ /**
113
+ * Maps an id from the source bundle to the id minted on this instance.
114
+ * Stable within one import: the same `originalId` always yields the same new
115
+ * id, so a plugin can preserve internal references (FKs) without breakage.
116
+ */
117
+ remapId(originalId: string): string;
118
+ }
119
+ /** Metadata about one of the plugin's own secrets, without its plaintext value. */
120
+ interface ExportSecretMetadata {
121
+ /** The secret's user-facing label (e.g. "Personal API key"). */
122
+ label: string;
123
+ /** The secret's provider/purpose (e.g. "openai", "smtp"). */
124
+ provider: string;
125
+ /** Whether a value is currently stored — never the value itself. */
126
+ exists: boolean;
127
+ }
128
+ /** One plugin's slice of a user's export. */
129
+ interface PluginExportSection {
130
+ /** The contributing plugin's manifest `id`. */
131
+ pluginId: string;
132
+ /**
133
+ * The installed manifest `version` of the contributing plugin, for provenance.
134
+ * A resolver may omit this — the runtime always overwrites it with the
135
+ * installed manifest's actual `version` before writing the bundle, so a
136
+ * plugin cannot misreport its own version.
137
+ */
138
+ pluginVersion?: string;
139
+ /** The plugin's own data-format version (for forward/backward compatibility). */
140
+ schemaVersion: number;
141
+ /** Plugin-defined JSON payload (rows, references). */
142
+ data: unknown;
143
+ /** Optional binary attachments, keyed by relative path within the section. */
144
+ blobs?: Record<string, Uint8Array>;
145
+ /**
146
+ * Metadata for secrets this plugin owns, scoped to the current user.
147
+ * Plaintext secret values must never appear here or anywhere in the export.
148
+ */
149
+ secretMetadata?: ExportSecretMetadata[];
150
+ /** Non-fatal notices about this section (e.g. a file that was skipped). */
151
+ warnings?: string[];
152
+ /**
153
+ * Opaque links this plugin holds to other plugins' records (RFC 0051).
154
+ * Exported and imported as **inert metadata only** — the platform never
155
+ * dereferences them, whether or not the referenced provider plugin is also
156
+ * part of the same export. Importing a reference never grants access to
157
+ * the provider plugin; a live dereference still goes through
158
+ * `sdk.data.query()` and the current user's consent.
159
+ */
160
+ references?: PluginReference[];
161
+ }
162
+ /** Produces one plugin's export section for the current user. */
163
+ type ExportResolver = (ctx: ExportContext) => Promise<PluginExportSection>;
164
+ /** Restores one plugin's export section into the importing user's account. */
165
+ type ImportHandler = (section: PluginExportSection, ctx: ImportContext) => Promise<void>;
166
+ /** Supplied to a deletion handler — scoped to the user being deleted. */
167
+ interface DeletionContext {
168
+ userId: string;
169
+ tenantId: string;
170
+ /** The plugin's own Drizzle client (same as `sdk.db.getClient()`). */
171
+ db: unknown;
172
+ }
173
+ /** What a deletion handler must return. */
174
+ interface DeletionResult {
175
+ /** Number of rows (or objects) deleted. */
176
+ deleted: number;
177
+ /** Non-fatal errors encountered during cleanup. */
178
+ errors?: string[];
179
+ }
180
+ /** Cleans up one plugin's user data when a user account is deleted. */
181
+ type DeletionHandler = (ctx: DeletionContext) => Promise<DeletionResult>;
182
+
183
+ /** Returns the current user session from runtime-injected headers, or null if unauthenticated. */
184
+ declare function getSession(): Promise<Session | null>;
185
+ /**
186
+ * Return true if the given session has the named capability (RFC 0021).
187
+ * Plugins should call this instead of comparing `session.user.role` directly
188
+ * to avoid coupling to the role-preset details.
189
+ */
190
+ declare function hasCapability(session: Session | null, capability: string): boolean;
191
+ /** Returns the current user session, throwing `NotAuthenticatedError` if unauthenticated. */
192
+ declare function requireSession(): Promise<Session>;
193
+ /**
194
+ * Change the current user's password (SRS ACC-04). Requires the current
195
+ * password; the current session is preserved (other sessions are kept too).
196
+ * Throws with better-auth's message on failure (e.g. wrong current password).
197
+ */
198
+ declare function changePassword(input: ChangePasswordInput): Promise<void>;
199
+ /** List the current user's active sessions, current one first (SRS ACC-05). */
200
+ declare function listSessions(): Promise<ActiveSession[]>;
201
+ /** Revoke a session by its token (SRS ACC-06). */
202
+ declare function revokeSession(token: string): Promise<void>;
203
+ /**
204
+ * Sign the current user out (SRS AUTH-02): ends the active session on the auth
205
+ * server. The caller is responsible for clearing the runtime's `session_data`
206
+ * cache cookies and redirecting — the platform's logout route does both.
207
+ */
208
+ declare function signOut(): Promise<void>;
209
+
210
+ declare const auth_changePassword: typeof changePassword;
211
+ declare const auth_getSession: typeof getSession;
212
+ declare const auth_hasCapability: typeof hasCapability;
213
+ declare const auth_listSessions: typeof listSessions;
214
+ declare const auth_requireSession: typeof requireSession;
215
+ declare const auth_revokeSession: typeof revokeSession;
216
+ declare const auth_signOut: typeof signOut;
217
+ declare namespace auth {
218
+ export { auth_changePassword as changePassword, auth_getSession as getSession, auth_hasCapability as hasCapability, auth_listSessions as listSessions, auth_requireSession as requireSession, auth_revokeSession as revokeSession, auth_signOut as signOut };
219
+ }
220
+
221
+ /**
222
+ * Returns the Drizzle client for this plugin's database.
223
+ *
224
+ * **Shared plugins** (the default, `database` omitted or `"shared"`) receive
225
+ * the platform DB. Tables must be slug-prefixed (e.g. `tasks_lists`) and carry
226
+ * a `tenant_id` column. `sdk.db.getClient()` is unchanged for these plugins —
227
+ * isolation is transparent to the caller.
228
+ *
229
+ * **Isolated plugins** (`database: "isolated"` in the manifest) receive a
230
+ * dedicated Drizzle instance backed by their own SQLite file or Postgres
231
+ * schema. No slug prefix is required inside an isolated store. Tables should
232
+ * still carry `tenant_id` for multi-tenancy readiness.
233
+ *
234
+ * The plugin ID is read from the `x-sovereign-plugin-id` request header
235
+ * injected by the runtime middleware. Outside a plugin route context (e.g.
236
+ * instrumentation startup code) the platform DB is returned.
237
+ *
238
+ * Async by contract: the platform DB is dialect-agnostic and Postgres has no
239
+ * synchronous query (SRS §3.6).
240
+ */
241
+ declare function getClient(): Promise<DrizzleClient>;
242
+
243
+ declare const db_getClient: typeof getClient;
244
+ declare namespace db {
245
+ export { db_getClient as getClient };
246
+ }
247
+
248
+ /** Sends an email via the platform mailer. No-ops when SMTP is not configured. */
249
+ declare function send(options: MailOptions): Promise<void>;
250
+
251
+ declare const mailer_send: typeof send;
252
+ declare namespace mailer {
253
+ export { mailer_send as send };
254
+ }
255
+
256
+ /**
257
+ * Returns the platform runtime configuration (SRS PLT-06). Async by contract:
258
+ * the platform DB is dialect-agnostic and Postgres has no synchronous query.
259
+ */
260
+ declare function getConfig(): Promise<PlatformConfig>;
261
+
262
+ declare const platform_getConfig: typeof getConfig;
263
+ declare namespace platform {
264
+ export { platform_getConfig as getConfig };
265
+ }
266
+
267
+ /**
268
+ * The host interface that the Sovereign runtime provides to the SDK.
269
+ * Every method that touches platform infrastructure (DB, mailer, config) is
270
+ * routed through this interface — the SDK itself has no runtime dependencies.
271
+ */
272
+ interface SdkHost {
273
+ db: {
274
+ /**
275
+ * `pluginId` is the calling plugin's manifest id, read from the
276
+ * `x-sovereign-plugin-id` request header by the SDK. `null` means the call
277
+ * happened outside a plugin route context; the platform DB is returned.
278
+ */
279
+ getClient(pluginId: string | null): Promise<DrizzleClient>;
280
+ };
281
+ mailer: {
282
+ send(options: MailOptions): Promise<void>;
283
+ };
284
+ platform: {
285
+ getConfig(): Promise<PlatformConfig>;
286
+ };
287
+ directory: {
288
+ /**
289
+ * Search active users in the current tenant. `requestingUserId` and
290
+ * `tenantId` come from runtime-injected request context, not plugin input.
291
+ */
292
+ searchUsers(input: SearchUsersInput, requestingUserId: string, tenantId: string): Promise<DirectoryUser[]>;
293
+ /**
294
+ * Resolve explicit user IDs to display-safe profile fields for active users
295
+ * in the current tenant.
296
+ */
297
+ resolveUsers(input: ResolveUsersInput, requestingUserId: string, tenantId: string): Promise<DirectoryUser[]>;
298
+ };
299
+ data: {
300
+ /** Register a resolver for a contract this plugin provides. */
301
+ provide(contract: string, resolver: DataContractResolver): void;
302
+ /**
303
+ * Query a provider plugin's contract for the current user.
304
+ * `consumerId` and `userId` are read from request headers by the SDK caller.
305
+ */
306
+ query(ref: DataContractRef, consumerId: string | null, userId: string | null, tenantId: string, params: unknown): Promise<unknown[]>;
307
+ };
308
+ activity: {
309
+ /**
310
+ * Record one activity event.
311
+ * `actorId`, `pluginId`, and `tenantId` are injected by the runtime host
312
+ * from request headers so plugins cannot forge actor identity.
313
+ */
314
+ log(entry: ActivityLogEntry, actorId: string | null, pluginId: string | null): Promise<void>;
315
+ };
316
+ portability: {
317
+ /**
318
+ * Register a plugin's export resolver, keyed by `pluginId` (resolved by the
319
+ * SDK from the request context). The runtime invokes it at export time.
320
+ */
321
+ provideExport(pluginId: string, resolver: ExportResolver): void;
322
+ /** Register a plugin's import handler, keyed by `pluginId`. */
323
+ provideImport(pluginId: string, handler: ImportHandler): void;
324
+ /** Register a plugin's deletion handler (RFC 0033), keyed by `pluginId`. */
325
+ provideDelete(pluginId: string, handler: DeletionHandler): void;
326
+ };
327
+ plugins: {
328
+ /** Discover one installed plugin's status (RFC 0051), scoped to the given user. */
329
+ get(id: string, userId: string | null, capabilities: readonly string[]): Promise<PluginAvailability | null>;
330
+ /** Discover installed plugins, optionally filtered, scoped to the given user. */
331
+ list(filter: PluginListFilter | undefined, userId: string | null, capabilities: readonly string[]): Promise<PluginAvailability[]>;
332
+ /** Whether `userId` has an active consent grant for `ref`, requested by `consumerId`. */
333
+ getConsentStatus(ref: DataContractRef, consumerId: string, userId: string): Promise<ConsentStatus>;
334
+ };
335
+ notifications: {
336
+ /**
337
+ * Deliver one notification to a user. The runtime injects `source`,
338
+ * `sourceType`, and `tenantId` from the request context so the plugin only
339
+ * supplies the payload fields.
340
+ */
341
+ send(input: SendNotificationInput, pluginId: string): Promise<void>;
342
+ };
343
+ storage: {
344
+ put(input: StoragePutInput, context: StorageContext): Promise<StorageObject>;
345
+ get(key: string, context: StorageContext): Promise<(StorageObject & {
346
+ body: ReadableStream;
347
+ }) | null>;
348
+ delete(key: string, context: StorageContext): Promise<void>;
349
+ list(prefix: string | undefined, context: StorageContext): Promise<StorageObject[]>;
350
+ getSignedUrl(key: string, options: {
351
+ expiresInSeconds?: number;
352
+ } | undefined, context: StorageContext): Promise<string>;
353
+ };
354
+ /**
355
+ * Client-side encryption profile persistence (RFC 0060). Pure metadata
356
+ * plumbing — no encryption happens here; the CMK is generated and
357
+ * wrapped/unwrapped entirely in the browser (`@sovereignfs/sdk`'s
358
+ * `e2ee-crypto`/`e2ee-device` modules) before these methods are ever
359
+ * called with the resulting ciphertext.
360
+ */
361
+ e2ee: {
362
+ getProfile(context: E2eeContext): Promise<E2eeProfile | null>;
363
+ createProfile(input: CreateE2eeProfileInput, context: E2eeContext): Promise<E2eeProfile>;
364
+ getRecoveryWrapper(context: E2eeContext): Promise<E2eeRecoveryWrapper | null>;
365
+ setRecoveryWrapper(input: SetE2eeRecoveryWrapperInput, context: E2eeContext): Promise<E2eeRecoveryWrapper>;
366
+ enrollDevice(input: EnrollE2eeDeviceInput, context: E2eeContext): Promise<E2eeDeviceEnrollment>;
367
+ listDevices(context: E2eeContext): Promise<E2eeDeviceEnrollment[]>;
368
+ revokeDevice(id: string, context: E2eeContext): Promise<void>;
369
+ };
370
+ secrets: {
371
+ create(input: CreateSecretInput, context: SecretContext): Promise<SecretRef>;
372
+ get(id: string, context: SecretContext): Promise<string | null>;
373
+ list(scope: SecretScope | undefined, context: SecretContext): Promise<SecretRef[]>;
374
+ update(id: string, value: string, context: SecretContext): Promise<SecretRef>;
375
+ delete(id: string, context: SecretContext): Promise<void>;
376
+ };
377
+ connections: {
378
+ create(input: CreateConnectionInput, context: ConnectionContext): Promise<ConnectionRef>;
379
+ list(filter: ConnectionListFilter | undefined, context: ConnectionContext): Promise<ConnectionRef[]>;
380
+ get(id: string, context: ConnectionContext): Promise<ConnectionRef | null>;
381
+ update(id: string, input: UpdateConnectionInput, context: ConnectionContext): Promise<ConnectionRef>;
382
+ disconnect(id: string, context: ConnectionContext): Promise<void>;
383
+ markUsed(id: string, context: ConnectionContext): Promise<void>;
384
+ markError(id: string, input: MarkConnectionErrorInput, context: ConnectionContext): Promise<ConnectionRef>;
385
+ createOAuthState(input: OAuthStateInput, context: ConnectionContext): Promise<string>;
386
+ verifyOAuthState(state: string, context: ConnectionContext): Promise<ConnectionOAuthState>;
387
+ getProviderConfig(provider: string, context: ConnectionContext): Promise<ProviderConfig>;
388
+ };
389
+ }
390
+ /**
391
+ * Register the platform host implementation. Called once at runtime startup
392
+ * (via `runtime/instrumentation.ts`) before any request is served.
393
+ *
394
+ * Exported from `@sovereignfs/sdk` so the runtime can call it; plugin code
395
+ * should never need to call this.
396
+ */
397
+ declare function provideHost(host: SdkHost): void;
398
+
399
+ /**
400
+ * Thrown by SDK surfaces that have no standalone implementation: the v1 methods
401
+ * that the Sovereign runtime supplies at runtime, and the post-v1 surfaces
402
+ * (storage, notifications, events) that are declared but not yet implemented.
403
+ */
404
+ declare class NotImplementedError extends Error {
405
+ constructor(message: string);
406
+ }
407
+ /** Thrown by `sdk.auth.requireSession()` when no authenticated session is present. */
408
+ declare class NotAuthenticatedError extends Error {
409
+ constructor();
410
+ }
411
+ /**
412
+ * Thrown by `sdk.data.query()` when the current user has not granted the calling
413
+ * (consumer) plugin consent to read the requested provider contract — the
414
+ * consent-gated cross-plugin data-sharing mechanism (RFC 0002). Reserved
415
+ * alongside that surface; not raised until the mechanism is implemented.
416
+ */
417
+ declare class ConsentRequiredError extends Error {
418
+ constructor(message?: string);
419
+ }
420
+ /**
421
+ * Thrown by `sdk.billing.requireEntitlement()` when the current user has no
422
+ * valid (active, unexpired) entitlement for the calling plugin (RFC 0003).
423
+ * The runtime middleware also enforces this at the route level, so most plugins
424
+ * never need to call `requireEntitlement()` directly — it is for in-plugin
425
+ * feature gating by tier.
426
+ */
427
+ declare class EntitlementRequiredError extends Error {
428
+ constructor(message?: string);
429
+ }
430
+
431
+ /**
432
+ * The Sovereign SDK — the only contract between a plugin and the platform.
433
+ *
434
+ * **Stable surface (covered by the v1.0.0 semver guarantee** — see
435
+ * `docs/sdk-stability.md`): `auth`, `db`, `mailer`, `platform`. These are
436
+ * implemented and will not change in breaking ways without a major bump +
437
+ * migration note (NFR-04).
438
+ *
439
+ * **Experimental / reserved (NOT covered by the stability guarantee):** `data`
440
+ * (cross-plugin data sharing, RFC 0002), `activity` (activity log, RFC 0005),
441
+ * `portability` (user data export/import, RFC 0007), `env` (plugin-scoped env
442
+ * vars, RFC 0018), `notifications` (notification center, RFC 0015),
443
+ * `directory` (member selection, RFC 0041), `secrets` (plugin secret vault,
444
+ * RFC 0043), `storage` (plugin file storage, RFC 0044), `connections`
445
+ * (external provider connections, RFC 0049), `e2ee` (client-side encryption
446
+ * profile persistence, RFC 0060 — profile/device plumbing only; see
447
+ * `e2ee-crypto`/`e2ee-device`/`e2ee-object`/`e2ee-state` for the browser-only
448
+ * crypto and state helpers that produce the ciphertext these methods store),
449
+ * `plugins` (dependency discovery and cross-plugin references, RFC 0051),
450
+ * `billing` (plugin monetization / entitlement gating, RFC 0003), `events`.
451
+ * `data`, `activity`, `portability`, `env`, `notifications`, `directory`,
452
+ * `secrets`, `storage`, `connections`, `e2ee`, and `plugins` are implemented;
453
+ * `billing` and `events` throw `NotImplementedError` until their backing
454
+ * mechanisms ship. Their shape may change before they stabilise.
455
+ */
456
+ declare const sdk: {
457
+ auth: typeof auth;
458
+ db: typeof db;
459
+ mailer: typeof mailer;
460
+ platform: typeof platform;
461
+ data: {
462
+ provide<TParams = unknown, TRow = unknown>(contract: string, resolver: DataContractResolver<TParams, TRow>): void;
463
+ query<TParams = unknown, TRow = unknown>(ref: DataContractRef, params?: TParams): Promise<TRow[]>;
464
+ };
465
+ storage: {
466
+ put(input: StoragePutInput): Promise<StorageObject>;
467
+ get(key: string): Promise<(StorageObject & {
468
+ body: ReadableStream;
469
+ }) | null>;
470
+ delete(key: string): Promise<void>;
471
+ list(prefix?: string): Promise<StorageObject[]>;
472
+ getSignedUrl(key: string, options?: {
473
+ expiresInSeconds?: number;
474
+ }): Promise<string>;
475
+ };
476
+ directory: {
477
+ searchUsers(input: SearchUsersInput): Promise<DirectoryUser[]>;
478
+ resolveUsers(input: ResolveUsersInput): Promise<DirectoryUser[]>;
479
+ };
480
+ notifications: {
481
+ send(input: SendNotificationInput, requestHeaders?: Headers): Promise<void>;
482
+ };
483
+ secrets: {
484
+ create(input: CreateSecretInput): Promise<SecretRef>;
485
+ get(id: string): Promise<string | null>;
486
+ list(scope?: SecretScope): Promise<SecretRef[]>;
487
+ update(id: string, value: string): Promise<SecretRef>;
488
+ delete(id: string): Promise<void>;
489
+ };
490
+ connections: {
491
+ create(input: CreateConnectionInput): Promise<ConnectionRef>;
492
+ list(filter?: ConnectionListFilter): Promise<ConnectionRef[]>;
493
+ get(id: string): Promise<ConnectionRef | null>;
494
+ update(id: string, input: UpdateConnectionInput): Promise<ConnectionRef>;
495
+ disconnect(id: string): Promise<void>;
496
+ markUsed(id: string): Promise<void>;
497
+ markError(id: string, input: MarkConnectionErrorInput): Promise<ConnectionRef>;
498
+ createOAuthState(input: OAuthStateInput): Promise<string>;
499
+ verifyOAuthState(state: string): Promise<ConnectionOAuthState>;
500
+ getProviderConfig(provider: string): Promise<ProviderConfig>;
501
+ };
502
+ e2ee: {
503
+ getProfile(): Promise<E2eeProfile | null>;
504
+ createProfile(input: CreateE2eeProfileInput): Promise<E2eeProfile>;
505
+ getRecoveryWrapper(): Promise<E2eeRecoveryWrapper | null>;
506
+ setRecoveryWrapper(input: SetE2eeRecoveryWrapperInput): Promise<E2eeRecoveryWrapper>;
507
+ enrollDevice(input: EnrollE2eeDeviceInput): Promise<E2eeDeviceEnrollment>;
508
+ listDevices(): Promise<E2eeDeviceEnrollment[]>;
509
+ revokeDevice(id: string): Promise<void>;
510
+ };
511
+ events: {
512
+ publish(_event: string, _payload: unknown): Promise<void>;
513
+ subscribe(_event: string, _handler: (payload: unknown) => void): void;
514
+ };
515
+ activity: {
516
+ log(entry: ActivityLogEntry): Promise<void>;
517
+ };
518
+ portability: {
519
+ provideExport(resolver: ExportResolver): Promise<void>;
520
+ provideImport(handler: ImportHandler): Promise<void>;
521
+ provideDelete(handler: DeletionHandler): Promise<void>;
522
+ };
523
+ plugins: {
524
+ get(id: string): Promise<PluginAvailability | null>;
525
+ list(filter?: PluginListFilter): Promise<PluginAvailability[]>;
526
+ getConsentStatus(ref: DataContractRef): Promise<ConsentStatus>;
527
+ };
528
+ env: {
529
+ get(key: string): Promise<string | null>;
530
+ };
531
+ billing: {
532
+ getEntitlement(_headers: Headers): Promise<{
533
+ tier: string | null;
534
+ expiresAt: number | null;
535
+ } | null>;
536
+ requireEntitlement(_headers: Headers): Promise<{
537
+ tier: string | null;
538
+ expiresAt: number | null;
539
+ }>;
540
+ };
541
+ };
542
+
543
+ export { ActiveSession, ActivityLogEntry, ChangePasswordInput, ConnectionContext, ConnectionListFilter, ConnectionOAuthState, ConnectionRef, ConsentRequiredError, type ConsentStatus, CreateConnectionInput, CreateE2eeProfileInput, CreateSecretInput, type DataContractRef, type DataContractResolver, type DeletionContext, type DeletionHandler, type DeletionResult, DirectoryUser, DrizzleClient, E2eeContext, E2eeDeviceEnrollment, E2eeProfile, E2eeRecoveryWrapper, EnrollE2eeDeviceInput, EntitlementRequiredError, type ExportContext, type ExportOptions, type ExportResolver, type ExportSecretMetadata, type ImportContext, type ImportHandler, MailOptions, MarkConnectionErrorInput, NotAuthenticatedError, NotImplementedError, OAuthStateInput, PlatformConfig, type PluginAvailability, type PluginContractSummary, type PluginExportSection, type PluginListFilter, type PluginReference, ProviderConfig, ResolveUsersInput, type SdkHost, SearchUsersInput, SecretContext, SecretRef, SecretScope, SendNotificationInput, Session, SetE2eeRecoveryWrapperInput, StorageContext, StorageObject, StoragePutInput, UpdateConnectionInput, provideHost, sdk };