@hypercerts-org/sdk-core 0.2.0-beta.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 (83) hide show
  1. package/.turbo/turbo-build.log +328 -0
  2. package/.turbo/turbo-test.log +118 -0
  3. package/CHANGELOG.md +16 -0
  4. package/LICENSE +21 -0
  5. package/README.md +100 -0
  6. package/dist/errors.cjs +260 -0
  7. package/dist/errors.cjs.map +1 -0
  8. package/dist/errors.d.ts +233 -0
  9. package/dist/errors.mjs +253 -0
  10. package/dist/errors.mjs.map +1 -0
  11. package/dist/index.cjs +4531 -0
  12. package/dist/index.cjs.map +1 -0
  13. package/dist/index.d.ts +3430 -0
  14. package/dist/index.mjs +4448 -0
  15. package/dist/index.mjs.map +1 -0
  16. package/dist/lexicons.cjs +420 -0
  17. package/dist/lexicons.cjs.map +1 -0
  18. package/dist/lexicons.d.ts +227 -0
  19. package/dist/lexicons.mjs +410 -0
  20. package/dist/lexicons.mjs.map +1 -0
  21. package/dist/storage.cjs +270 -0
  22. package/dist/storage.cjs.map +1 -0
  23. package/dist/storage.d.ts +474 -0
  24. package/dist/storage.mjs +267 -0
  25. package/dist/storage.mjs.map +1 -0
  26. package/dist/testing.cjs +415 -0
  27. package/dist/testing.cjs.map +1 -0
  28. package/dist/testing.d.ts +928 -0
  29. package/dist/testing.mjs +410 -0
  30. package/dist/testing.mjs.map +1 -0
  31. package/dist/types.cjs +220 -0
  32. package/dist/types.cjs.map +1 -0
  33. package/dist/types.d.ts +2118 -0
  34. package/dist/types.mjs +212 -0
  35. package/dist/types.mjs.map +1 -0
  36. package/eslint.config.mjs +22 -0
  37. package/package.json +90 -0
  38. package/rollup.config.js +75 -0
  39. package/src/auth/OAuthClient.ts +497 -0
  40. package/src/core/SDK.ts +410 -0
  41. package/src/core/config.ts +243 -0
  42. package/src/core/errors.ts +257 -0
  43. package/src/core/interfaces.ts +324 -0
  44. package/src/core/types.ts +281 -0
  45. package/src/errors.ts +57 -0
  46. package/src/index.ts +107 -0
  47. package/src/lexicons.ts +64 -0
  48. package/src/repository/BlobOperationsImpl.ts +199 -0
  49. package/src/repository/CollaboratorOperationsImpl.ts +288 -0
  50. package/src/repository/HypercertOperationsImpl.ts +1146 -0
  51. package/src/repository/LexiconRegistry.ts +332 -0
  52. package/src/repository/OrganizationOperationsImpl.ts +234 -0
  53. package/src/repository/ProfileOperationsImpl.ts +281 -0
  54. package/src/repository/RecordOperationsImpl.ts +340 -0
  55. package/src/repository/Repository.ts +482 -0
  56. package/src/repository/interfaces.ts +868 -0
  57. package/src/repository/types.ts +111 -0
  58. package/src/services/hypercerts/types.ts +87 -0
  59. package/src/storage/InMemorySessionStore.ts +127 -0
  60. package/src/storage/InMemoryStateStore.ts +146 -0
  61. package/src/storage.ts +63 -0
  62. package/src/testing/index.ts +67 -0
  63. package/src/testing/mocks.ts +142 -0
  64. package/src/testing/stores.ts +285 -0
  65. package/src/testing.ts +64 -0
  66. package/src/types.ts +86 -0
  67. package/tests/auth/OAuthClient.test.ts +164 -0
  68. package/tests/core/SDK.test.ts +176 -0
  69. package/tests/core/errors.test.ts +81 -0
  70. package/tests/repository/BlobOperationsImpl.test.ts +154 -0
  71. package/tests/repository/CollaboratorOperationsImpl.test.ts +323 -0
  72. package/tests/repository/HypercertOperationsImpl.test.ts +652 -0
  73. package/tests/repository/LexiconRegistry.test.ts +192 -0
  74. package/tests/repository/OrganizationOperationsImpl.test.ts +242 -0
  75. package/tests/repository/ProfileOperationsImpl.test.ts +254 -0
  76. package/tests/repository/RecordOperationsImpl.test.ts +375 -0
  77. package/tests/repository/Repository.test.ts +149 -0
  78. package/tests/utils/fixtures.ts +117 -0
  79. package/tests/utils/mocks.ts +109 -0
  80. package/tests/utils/repository-fixtures.ts +78 -0
  81. package/tsconfig.json +11 -0
  82. package/tsconfig.tsbuildinfo +1 -0
  83. package/vitest.config.ts +30 -0
@@ -0,0 +1,2118 @@
1
+ import { OAuthSession, NodeSavedSession, NodeSavedState } from '@atproto/oauth-client-node';
2
+ import { z } from 'zod';
3
+ import { EventEmitter } from 'eventemitter3';
4
+ import { OrgHypercertsClaim, OrgHypercertsCollection, OrgHypercertsClaimRights, AppCertifiedLocation, OrgHypercertsClaimContribution, OrgHypercertsClaimMeasurement, OrgHypercertsClaimEvaluation } from '@hypercerts-org/lexicon';
5
+
6
+ /**
7
+ * Decentralized Identifier (DID) - a unique, persistent identifier for AT Protocol users.
8
+ *
9
+ * DIDs are the canonical identifier for users in the AT Protocol ecosystem.
10
+ * Unlike handles which can change, DIDs remain constant for the lifetime of an account.
11
+ *
12
+ * @remarks
13
+ * AT Protocol supports multiple DID methods:
14
+ * - `did:plc:` - PLC (Public Ledger of Credentials) DIDs, most common for Bluesky users
15
+ * - `did:web:` - Web DIDs, resolved via HTTPS
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const did: DID = "did:plc:ewvi7nxzyoun6zhxrhs64oiz";
20
+ * const webDid: DID = "did:web:example.com";
21
+ * ```
22
+ *
23
+ * @see https://atproto.com/specs/did for DID specification
24
+ */
25
+ type DID = string;
26
+ /**
27
+ * OAuth session with DPoP (Demonstrating Proof of Possession) support.
28
+ *
29
+ * This type represents an authenticated user session. It wraps the
30
+ * `@atproto/oauth-client-node` OAuthSession and contains:
31
+ * - Access token for API requests
32
+ * - Refresh token for obtaining new access tokens
33
+ * - DPoP key pair for proof-of-possession
34
+ * - User's DID and other identity information
35
+ *
36
+ * @remarks
37
+ * Sessions are managed by the SDK and automatically refresh when tokens expire.
38
+ * Store the user's DID to restore sessions later with {@link ATProtoSDK.restoreSession}.
39
+ *
40
+ * Key properties from OAuthSession:
41
+ * - `did` or `sub`: The user's DID
42
+ * - `handle`: The user's handle (e.g., "user.bsky.social")
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * const session = await sdk.callback(params);
47
+ *
48
+ * // Access user identity
49
+ * console.log(`Logged in as: ${session.did}`);
50
+ *
51
+ * // Use session for repository operations
52
+ * const repo = sdk.repository(session);
53
+ * ```
54
+ *
55
+ * @see https://atproto.com/specs/oauth for OAuth specification
56
+ */
57
+ type Session = OAuthSession;
58
+ /**
59
+ * Zod schema for collaborator permissions in SDS repositories.
60
+ *
61
+ * Defines the granular permissions a collaborator can have on a shared repository.
62
+ * Permissions follow a hierarchical model where higher-level permissions
63
+ * typically imply lower-level ones.
64
+ */
65
+ declare const CollaboratorPermissionsSchema: z.ZodObject<{
66
+ /**
67
+ * Can read/view records in the repository.
68
+ * This is the most basic permission level.
69
+ */
70
+ read: z.ZodBoolean;
71
+ /**
72
+ * Can create new records in the repository.
73
+ * Typically implies `read` permission.
74
+ */
75
+ create: z.ZodBoolean;
76
+ /**
77
+ * Can modify existing records in the repository.
78
+ * Typically implies `read` and `create` permissions.
79
+ */
80
+ update: z.ZodBoolean;
81
+ /**
82
+ * Can delete records from the repository.
83
+ * Typically implies `read`, `create`, and `update` permissions.
84
+ */
85
+ delete: z.ZodBoolean;
86
+ /**
87
+ * Can manage collaborators and their permissions.
88
+ * Administrative permission that allows inviting/removing collaborators.
89
+ */
90
+ admin: z.ZodBoolean;
91
+ /**
92
+ * Full ownership of the repository.
93
+ * Owners have all permissions and cannot be removed by other admins.
94
+ * There must always be at least one owner.
95
+ */
96
+ owner: z.ZodBoolean;
97
+ }, "strip", z.ZodTypeAny, {
98
+ read: boolean;
99
+ create: boolean;
100
+ update: boolean;
101
+ delete: boolean;
102
+ admin: boolean;
103
+ owner: boolean;
104
+ }, {
105
+ read: boolean;
106
+ create: boolean;
107
+ update: boolean;
108
+ delete: boolean;
109
+ admin: boolean;
110
+ owner: boolean;
111
+ }>;
112
+ /**
113
+ * Collaborator permissions for SDS (Shared Data Server) repositories.
114
+ *
115
+ * These permissions control what actions a collaborator can perform
116
+ * on records within a shared repository.
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * // Read-only collaborator
121
+ * const readOnlyPerms: CollaboratorPermissions = {
122
+ * read: true,
123
+ * create: false,
124
+ * update: false,
125
+ * delete: false,
126
+ * admin: false,
127
+ * owner: false,
128
+ * };
129
+ *
130
+ * // Editor collaborator
131
+ * const editorPerms: CollaboratorPermissions = {
132
+ * read: true,
133
+ * create: true,
134
+ * update: true,
135
+ * delete: false,
136
+ * admin: false,
137
+ * owner: false,
138
+ * };
139
+ *
140
+ * // Admin collaborator
141
+ * const adminPerms: CollaboratorPermissions = {
142
+ * read: true,
143
+ * create: true,
144
+ * update: true,
145
+ * delete: true,
146
+ * admin: true,
147
+ * owner: false,
148
+ * };
149
+ * ```
150
+ */
151
+ type CollaboratorPermissions = z.infer<typeof CollaboratorPermissionsSchema>;
152
+ /**
153
+ * Zod schema for SDS organization data.
154
+ *
155
+ * Organizations are top-level entities in SDS that can own repositories
156
+ * and have multiple collaborators with different permission levels.
157
+ */
158
+ declare const OrganizationSchema: z.ZodObject<{
159
+ /**
160
+ * The organization's DID - unique identifier.
161
+ * Format: "did:plc:..." or "did:web:..."
162
+ */
163
+ did: z.ZodString;
164
+ /**
165
+ * The organization's handle - human-readable identifier.
166
+ * Format: "orgname.sds.hypercerts.org" or similar
167
+ */
168
+ handle: z.ZodString;
169
+ /**
170
+ * Display name for the organization.
171
+ */
172
+ name: z.ZodString;
173
+ /**
174
+ * Optional description of the organization's purpose.
175
+ */
176
+ description: z.ZodOptional<z.ZodString>;
177
+ /**
178
+ * ISO 8601 timestamp when the organization was created.
179
+ * Format: "2024-01-15T10:30:00.000Z"
180
+ */
181
+ createdAt: z.ZodString;
182
+ /**
183
+ * The current user's permissions within this organization.
184
+ */
185
+ permissions: z.ZodObject<{
186
+ /**
187
+ * Can read/view records in the repository.
188
+ * This is the most basic permission level.
189
+ */
190
+ read: z.ZodBoolean;
191
+ /**
192
+ * Can create new records in the repository.
193
+ * Typically implies `read` permission.
194
+ */
195
+ create: z.ZodBoolean;
196
+ /**
197
+ * Can modify existing records in the repository.
198
+ * Typically implies `read` and `create` permissions.
199
+ */
200
+ update: z.ZodBoolean;
201
+ /**
202
+ * Can delete records from the repository.
203
+ * Typically implies `read`, `create`, and `update` permissions.
204
+ */
205
+ delete: z.ZodBoolean;
206
+ /**
207
+ * Can manage collaborators and their permissions.
208
+ * Administrative permission that allows inviting/removing collaborators.
209
+ */
210
+ admin: z.ZodBoolean;
211
+ /**
212
+ * Full ownership of the repository.
213
+ * Owners have all permissions and cannot be removed by other admins.
214
+ * There must always be at least one owner.
215
+ */
216
+ owner: z.ZodBoolean;
217
+ }, "strip", z.ZodTypeAny, {
218
+ read: boolean;
219
+ create: boolean;
220
+ update: boolean;
221
+ delete: boolean;
222
+ admin: boolean;
223
+ owner: boolean;
224
+ }, {
225
+ read: boolean;
226
+ create: boolean;
227
+ update: boolean;
228
+ delete: boolean;
229
+ admin: boolean;
230
+ owner: boolean;
231
+ }>;
232
+ /**
233
+ * How the current user relates to this organization.
234
+ * - `"owner"`: User created or owns the organization
235
+ * - `"collaborator"`: User was invited to collaborate
236
+ */
237
+ accessType: z.ZodEnum<["owner", "collaborator"]>;
238
+ }, "strip", z.ZodTypeAny, {
239
+ did: string;
240
+ handle: string;
241
+ name: string;
242
+ createdAt: string;
243
+ permissions: {
244
+ read: boolean;
245
+ create: boolean;
246
+ update: boolean;
247
+ delete: boolean;
248
+ admin: boolean;
249
+ owner: boolean;
250
+ };
251
+ accessType: "owner" | "collaborator";
252
+ description?: string | undefined;
253
+ }, {
254
+ did: string;
255
+ handle: string;
256
+ name: string;
257
+ createdAt: string;
258
+ permissions: {
259
+ read: boolean;
260
+ create: boolean;
261
+ update: boolean;
262
+ delete: boolean;
263
+ admin: boolean;
264
+ owner: boolean;
265
+ };
266
+ accessType: "owner" | "collaborator";
267
+ description?: string | undefined;
268
+ }>;
269
+ /**
270
+ * SDS Organization entity.
271
+ *
272
+ * Represents an organization on a Shared Data Server. Organizations
273
+ * provide a way to group repositories and manage access for teams.
274
+ *
275
+ * @example
276
+ * ```typescript
277
+ * const org: Organization = {
278
+ * did: "did:plc:org123abc",
279
+ * handle: "my-team.sds.hypercerts.org",
280
+ * name: "My Team",
281
+ * description: "A team working on impact certificates",
282
+ * createdAt: "2024-01-15T10:30:00.000Z",
283
+ * permissions: {
284
+ * read: true,
285
+ * create: true,
286
+ * update: true,
287
+ * delete: true,
288
+ * admin: true,
289
+ * owner: true,
290
+ * },
291
+ * accessType: "owner",
292
+ * };
293
+ * ```
294
+ */
295
+ type Organization = z.infer<typeof OrganizationSchema>;
296
+ /**
297
+ * Zod schema for collaborator data.
298
+ *
299
+ * Represents a user who has been granted access to a shared repository
300
+ * or organization with specific permissions.
301
+ */
302
+ declare const CollaboratorSchema: z.ZodObject<{
303
+ /**
304
+ * The collaborator's DID - their unique identifier.
305
+ * Format: "did:plc:..." or "did:web:..."
306
+ */
307
+ userDid: z.ZodString;
308
+ /**
309
+ * The permissions granted to this collaborator.
310
+ */
311
+ permissions: z.ZodObject<{
312
+ /**
313
+ * Can read/view records in the repository.
314
+ * This is the most basic permission level.
315
+ */
316
+ read: z.ZodBoolean;
317
+ /**
318
+ * Can create new records in the repository.
319
+ * Typically implies `read` permission.
320
+ */
321
+ create: z.ZodBoolean;
322
+ /**
323
+ * Can modify existing records in the repository.
324
+ * Typically implies `read` and `create` permissions.
325
+ */
326
+ update: z.ZodBoolean;
327
+ /**
328
+ * Can delete records from the repository.
329
+ * Typically implies `read`, `create`, and `update` permissions.
330
+ */
331
+ delete: z.ZodBoolean;
332
+ /**
333
+ * Can manage collaborators and their permissions.
334
+ * Administrative permission that allows inviting/removing collaborators.
335
+ */
336
+ admin: z.ZodBoolean;
337
+ /**
338
+ * Full ownership of the repository.
339
+ * Owners have all permissions and cannot be removed by other admins.
340
+ * There must always be at least one owner.
341
+ */
342
+ owner: z.ZodBoolean;
343
+ }, "strip", z.ZodTypeAny, {
344
+ read: boolean;
345
+ create: boolean;
346
+ update: boolean;
347
+ delete: boolean;
348
+ admin: boolean;
349
+ owner: boolean;
350
+ }, {
351
+ read: boolean;
352
+ create: boolean;
353
+ update: boolean;
354
+ delete: boolean;
355
+ admin: boolean;
356
+ owner: boolean;
357
+ }>;
358
+ /**
359
+ * DID of the user who granted these permissions.
360
+ * Useful for audit trails.
361
+ */
362
+ grantedBy: z.ZodString;
363
+ /**
364
+ * ISO 8601 timestamp when permissions were granted.
365
+ * Format: "2024-01-15T10:30:00.000Z"
366
+ */
367
+ grantedAt: z.ZodString;
368
+ /**
369
+ * ISO 8601 timestamp when permissions were revoked, if applicable.
370
+ * Undefined if the collaborator is still active.
371
+ */
372
+ revokedAt: z.ZodOptional<z.ZodString>;
373
+ }, "strip", z.ZodTypeAny, {
374
+ permissions: {
375
+ read: boolean;
376
+ create: boolean;
377
+ update: boolean;
378
+ delete: boolean;
379
+ admin: boolean;
380
+ owner: boolean;
381
+ };
382
+ userDid: string;
383
+ grantedBy: string;
384
+ grantedAt: string;
385
+ revokedAt?: string | undefined;
386
+ }, {
387
+ permissions: {
388
+ read: boolean;
389
+ create: boolean;
390
+ update: boolean;
391
+ delete: boolean;
392
+ admin: boolean;
393
+ owner: boolean;
394
+ };
395
+ userDid: string;
396
+ grantedBy: string;
397
+ grantedAt: string;
398
+ revokedAt?: string | undefined;
399
+ }>;
400
+ /**
401
+ * Collaborator information for SDS repositories.
402
+ *
403
+ * Represents a user who has been granted access to collaborate on
404
+ * a shared repository or organization.
405
+ *
406
+ * @example
407
+ * ```typescript
408
+ * const collaborator: Collaborator = {
409
+ * userDid: "did:plc:user456def",
410
+ * permissions: {
411
+ * read: true,
412
+ * create: true,
413
+ * update: true,
414
+ * delete: false,
415
+ * admin: false,
416
+ * owner: false,
417
+ * },
418
+ * grantedBy: "did:plc:owner123abc",
419
+ * grantedAt: "2024-02-01T14:00:00.000Z",
420
+ * };
421
+ * ```
422
+ */
423
+ type Collaborator = z.infer<typeof CollaboratorSchema>;
424
+
425
+ /**
426
+ * Storage interface for persisting OAuth sessions.
427
+ *
428
+ * Implement this interface to provide persistent storage for user sessions.
429
+ * Sessions contain sensitive data including access tokens, refresh tokens,
430
+ * and DPoP key pairs.
431
+ *
432
+ * The SDK provides {@link InMemorySessionStore} for development/testing,
433
+ * but **production applications should implement persistent storage**
434
+ * (e.g., Redis, PostgreSQL, MongoDB).
435
+ *
436
+ * @remarks
437
+ * - Sessions are keyed by the user's DID (Decentralized Identifier)
438
+ * - The `NodeSavedSession` type comes from `@atproto/oauth-client-node`
439
+ * - Sessions may be large (~2-4KB) due to embedded cryptographic keys
440
+ * - Consider encrypting sessions at rest for additional security
441
+ *
442
+ * @example Redis implementation
443
+ * ```typescript
444
+ * import { Redis } from "ioredis";
445
+ * import type { SessionStore } from "@hypercerts-org/sdk";
446
+ * import type { NodeSavedSession } from "@atproto/oauth-client-node";
447
+ *
448
+ * class RedisSessionStore implements SessionStore {
449
+ * constructor(private redis: Redis, private prefix = "session:") {}
450
+ *
451
+ * async get(did: string): Promise<NodeSavedSession | undefined> {
452
+ * const data = await this.redis.get(this.prefix + did);
453
+ * return data ? JSON.parse(data) : undefined;
454
+ * }
455
+ *
456
+ * async set(did: string, session: NodeSavedSession): Promise<void> {
457
+ * // Set with 30-day expiry (sessions can be refreshed)
458
+ * await this.redis.setex(
459
+ * this.prefix + did,
460
+ * 30 * 24 * 60 * 60,
461
+ * JSON.stringify(session)
462
+ * );
463
+ * }
464
+ *
465
+ * async del(did: string): Promise<void> {
466
+ * await this.redis.del(this.prefix + did);
467
+ * }
468
+ * }
469
+ * ```
470
+ *
471
+ * @see {@link InMemorySessionStore} for the default in-memory implementation
472
+ */
473
+ interface SessionStore {
474
+ /**
475
+ * Retrieves a session by DID.
476
+ *
477
+ * @param did - The user's Decentralized Identifier (e.g., "did:plc:abc123...")
478
+ * @returns The stored session, or `undefined` if not found
479
+ */
480
+ get(did: string): Promise<NodeSavedSession | undefined>;
481
+ /**
482
+ * Stores or updates a session.
483
+ *
484
+ * This is called after successful authentication and whenever tokens are refreshed.
485
+ *
486
+ * @param did - The user's DID to use as the storage key
487
+ * @param session - The session data to store (contains tokens, DPoP keys, etc.)
488
+ */
489
+ set(did: string, session: NodeSavedSession): Promise<void>;
490
+ /**
491
+ * Deletes a session.
492
+ *
493
+ * Called when a user logs out or when a session is revoked.
494
+ *
495
+ * @param did - The user's DID
496
+ */
497
+ del(did: string): Promise<void>;
498
+ }
499
+ /**
500
+ * Storage interface for OAuth state during the authorization flow.
501
+ *
502
+ * Implement this interface to provide temporary storage for OAuth state
503
+ * parameters. State is used for CSRF protection and PKCE (Proof Key for
504
+ * Code Exchange) during the authorization flow.
505
+ *
506
+ * @remarks
507
+ * - State is short-lived (typically 10-15 minutes)
508
+ * - Keys are random state strings generated by the OAuth client
509
+ * - The `NodeSavedState` type comes from `@atproto/oauth-client-node`
510
+ * - State should be automatically cleaned up after expiry
511
+ *
512
+ * @example Redis implementation with automatic expiry
513
+ * ```typescript
514
+ * import { Redis } from "ioredis";
515
+ * import type { StateStore } from "@hypercerts-org/sdk";
516
+ * import type { NodeSavedState } from "@atproto/oauth-client-node";
517
+ *
518
+ * class RedisStateStore implements StateStore {
519
+ * constructor(
520
+ * private redis: Redis,
521
+ * private prefix = "oauth-state:",
522
+ * private ttlSeconds = 900 // 15 minutes
523
+ * ) {}
524
+ *
525
+ * async get(key: string): Promise<NodeSavedState | undefined> {
526
+ * const data = await this.redis.get(this.prefix + key);
527
+ * return data ? JSON.parse(data) : undefined;
528
+ * }
529
+ *
530
+ * async set(key: string, state: NodeSavedState): Promise<void> {
531
+ * await this.redis.setex(
532
+ * this.prefix + key,
533
+ * this.ttlSeconds,
534
+ * JSON.stringify(state)
535
+ * );
536
+ * }
537
+ *
538
+ * async del(key: string): Promise<void> {
539
+ * await this.redis.del(this.prefix + key);
540
+ * }
541
+ * }
542
+ * ```
543
+ *
544
+ * @see {@link InMemoryStateStore} for the default in-memory implementation
545
+ */
546
+ interface StateStore {
547
+ /**
548
+ * Retrieves OAuth state by key.
549
+ *
550
+ * @param key - The state key (random string from authorization URL)
551
+ * @returns The stored state, or `undefined` if not found or expired
552
+ */
553
+ get(key: string): Promise<NodeSavedState | undefined>;
554
+ /**
555
+ * Stores OAuth state temporarily.
556
+ *
557
+ * Called when starting the authorization flow. The state should be
558
+ * stored with a short TTL (10-15 minutes recommended).
559
+ *
560
+ * @param key - The state key to use for storage
561
+ * @param state - The OAuth state data (includes PKCE verifier, etc.)
562
+ */
563
+ set(key: string, state: NodeSavedState): Promise<void>;
564
+ /**
565
+ * Deletes OAuth state.
566
+ *
567
+ * Called after the state has been used (successful or failed callback).
568
+ *
569
+ * @param key - The state key to delete
570
+ */
571
+ del(key: string): Promise<void>;
572
+ }
573
+ /**
574
+ * Generic cache interface for profiles, metadata, and other data.
575
+ *
576
+ * Implement this interface to provide caching for frequently accessed data.
577
+ * Caching can significantly reduce API calls and improve performance.
578
+ *
579
+ * @remarks
580
+ * The SDK does not provide a default cache implementation - you must
581
+ * implement this interface if you want caching. Consider using:
582
+ * - In-memory cache (e.g., `lru-cache`) for single-instance applications
583
+ * - Redis for distributed applications
584
+ * - Database-backed cache for persistence
585
+ *
586
+ * @example LRU cache implementation
587
+ * ```typescript
588
+ * import { LRUCache } from "lru-cache";
589
+ * import type { CacheInterface } from "@hypercerts-org/sdk";
590
+ *
591
+ * class LRUCacheAdapter implements CacheInterface {
592
+ * private cache = new LRUCache<string, unknown>({
593
+ * max: 1000,
594
+ * ttl: 5 * 60 * 1000, // 5 minutes default
595
+ * });
596
+ *
597
+ * async get<T>(key: string): Promise<T | undefined> {
598
+ * return this.cache.get(key) as T | undefined;
599
+ * }
600
+ *
601
+ * async set<T>(key: string, value: T, ttlSeconds?: number): Promise<void> {
602
+ * this.cache.set(key, value, {
603
+ * ttl: ttlSeconds ? ttlSeconds * 1000 : undefined,
604
+ * });
605
+ * }
606
+ *
607
+ * async del(key: string): Promise<void> {
608
+ * this.cache.delete(key);
609
+ * }
610
+ *
611
+ * async clear(): Promise<void> {
612
+ * this.cache.clear();
613
+ * }
614
+ * }
615
+ * ```
616
+ */
617
+ interface CacheInterface {
618
+ /**
619
+ * Gets a cached value by key.
620
+ *
621
+ * @typeParam T - The expected type of the cached value
622
+ * @param key - The cache key
623
+ * @returns The cached value, or `undefined` if not found or expired
624
+ */
625
+ get<T>(key: string): Promise<T | undefined>;
626
+ /**
627
+ * Sets a cached value with optional TTL (time-to-live).
628
+ *
629
+ * @typeParam T - The type of the value being cached
630
+ * @param key - The cache key
631
+ * @param value - The value to cache
632
+ * @param ttlSeconds - Optional time-to-live in seconds. If not provided,
633
+ * the cache implementation should use its default TTL.
634
+ */
635
+ set<T>(key: string, value: T, ttlSeconds?: number): Promise<void>;
636
+ /**
637
+ * Deletes a cached value.
638
+ *
639
+ * @param key - The cache key to delete
640
+ */
641
+ del(key: string): Promise<void>;
642
+ /**
643
+ * Clears all cached values.
644
+ *
645
+ * Use with caution in production as this affects all cached data.
646
+ */
647
+ clear(): Promise<void>;
648
+ }
649
+ /**
650
+ * Logger interface for debugging and observability.
651
+ *
652
+ * Implement this interface to receive log messages from the SDK.
653
+ * The interface is compatible with `console` and most popular
654
+ * logging libraries (Pino, Winston, Bunyan, etc.).
655
+ *
656
+ * @remarks
657
+ * Log levels follow standard conventions:
658
+ * - `debug`: Detailed information for debugging (tokens, request details)
659
+ * - `info`: General operational messages (initialization, successful auth)
660
+ * - `warn`: Potentially problematic situations (deprecated features, retries)
661
+ * - `error`: Errors that don't crash the application (failed requests, validation)
662
+ *
663
+ * @example Using console
664
+ * ```typescript
665
+ * const sdk = new ATProtoSDK({
666
+ * // ...
667
+ * logger: console,
668
+ * });
669
+ * ```
670
+ *
671
+ * @example Using Pino
672
+ * ```typescript
673
+ * import pino from "pino";
674
+ *
675
+ * const logger = pino({ level: "debug" });
676
+ * const sdk = new ATProtoSDK({
677
+ * // ...
678
+ * logger: logger,
679
+ * });
680
+ * ```
681
+ *
682
+ * @example Custom logger with context
683
+ * ```typescript
684
+ * const logger: LoggerInterface = {
685
+ * debug: (msg, ...args) => console.debug(`[SDK] ${msg}`, ...args),
686
+ * info: (msg, ...args) => console.info(`[SDK] ${msg}`, ...args),
687
+ * warn: (msg, ...args) => console.warn(`[SDK] ${msg}`, ...args),
688
+ * error: (msg, ...args) => console.error(`[SDK] ${msg}`, ...args),
689
+ * };
690
+ * ```
691
+ */
692
+ interface LoggerInterface {
693
+ /**
694
+ * Logs debug-level messages.
695
+ *
696
+ * Used for detailed diagnostic information. May include sensitive
697
+ * data like request URLs and headers (but not tokens).
698
+ *
699
+ * @param message - The log message
700
+ * @param args - Additional arguments (objects, error details, etc.)
701
+ */
702
+ debug(message: string, ...args: unknown[]): void;
703
+ /**
704
+ * Logs info-level messages.
705
+ *
706
+ * Used for general operational information like successful
707
+ * initialization, authentication events, etc.
708
+ *
709
+ * @param message - The log message
710
+ * @param args - Additional arguments
711
+ */
712
+ info(message: string, ...args: unknown[]): void;
713
+ /**
714
+ * Logs warning-level messages.
715
+ *
716
+ * Used for potentially problematic situations that don't prevent
717
+ * operation but may indicate issues.
718
+ *
719
+ * @param message - The log message
720
+ * @param args - Additional arguments
721
+ */
722
+ warn(message: string, ...args: unknown[]): void;
723
+ /**
724
+ * Logs error-level messages.
725
+ *
726
+ * Used for error conditions that should be investigated.
727
+ * The SDK continues to operate after logging errors.
728
+ *
729
+ * @param message - The log message
730
+ * @param args - Additional arguments (typically includes the error object)
731
+ */
732
+ error(message: string, ...args: unknown[]): void;
733
+ }
734
+
735
+ /**
736
+ * Zod schema for OAuth configuration validation.
737
+ *
738
+ * @remarks
739
+ * All URLs must be valid and use HTTPS in production. The `jwkPrivate` field
740
+ * should contain the private key in JWK (JSON Web Key) format as a string.
741
+ */
742
+ declare const OAuthConfigSchema: z.ZodObject<{
743
+ /**
744
+ * URL to the OAuth client metadata JSON document.
745
+ * This document describes your application to the authorization server.
746
+ *
747
+ * @see https://atproto.com/specs/oauth#client-metadata
748
+ */
749
+ clientId: z.ZodString;
750
+ /**
751
+ * URL where users are redirected after authentication.
752
+ * Must match one of the redirect URIs in your client metadata.
753
+ */
754
+ redirectUri: z.ZodString;
755
+ /**
756
+ * OAuth scopes to request, space-separated.
757
+ * Common scopes: "atproto", "transition:generic"
758
+ */
759
+ scope: z.ZodString;
760
+ /**
761
+ * URL to your public JWKS (JSON Web Key Set) endpoint.
762
+ * Used by the authorization server to verify your client's signatures.
763
+ */
764
+ jwksUri: z.ZodString;
765
+ /**
766
+ * Private JWK (JSON Web Key) as a JSON string.
767
+ * Used for signing DPoP proofs and client assertions.
768
+ *
769
+ * @remarks
770
+ * This should be kept secret and never exposed to clients.
771
+ * Typically loaded from environment variables or a secrets manager.
772
+ */
773
+ jwkPrivate: z.ZodString;
774
+ }, "strip", z.ZodTypeAny, {
775
+ clientId: string;
776
+ redirectUri: string;
777
+ scope: string;
778
+ jwksUri: string;
779
+ jwkPrivate: string;
780
+ }, {
781
+ clientId: string;
782
+ redirectUri: string;
783
+ scope: string;
784
+ jwksUri: string;
785
+ jwkPrivate: string;
786
+ }>;
787
+ /**
788
+ * Zod schema for server URL configuration.
789
+ *
790
+ * @remarks
791
+ * At least one server (PDS or SDS) should be configured for the SDK to be useful.
792
+ */
793
+ declare const ServerConfigSchema: z.ZodObject<{
794
+ /**
795
+ * Personal Data Server URL - the user's own AT Protocol server.
796
+ * This is the primary server for user data operations.
797
+ *
798
+ * @example "https://bsky.social"
799
+ */
800
+ pds: z.ZodOptional<z.ZodString>;
801
+ /**
802
+ * Shared Data Server URL - for collaborative data storage.
803
+ * Required for collaborator and organization operations.
804
+ *
805
+ * @example "https://sds.hypercerts.org"
806
+ */
807
+ sds: z.ZodOptional<z.ZodString>;
808
+ }, "strip", z.ZodTypeAny, {
809
+ pds?: string | undefined;
810
+ sds?: string | undefined;
811
+ }, {
812
+ pds?: string | undefined;
813
+ sds?: string | undefined;
814
+ }>;
815
+ /**
816
+ * Zod schema for timeout configuration.
817
+ *
818
+ * @remarks
819
+ * All timeout values are in milliseconds.
820
+ */
821
+ declare const TimeoutConfigSchema: z.ZodObject<{
822
+ /**
823
+ * Timeout for fetching PDS metadata during identity resolution.
824
+ * @default 5000 (5 seconds, set by OAuthClient)
825
+ */
826
+ pdsMetadata: z.ZodOptional<z.ZodNumber>;
827
+ /**
828
+ * Timeout for general API requests to PDS/SDS.
829
+ * @default 30000 (30 seconds)
830
+ */
831
+ apiRequests: z.ZodOptional<z.ZodNumber>;
832
+ }, "strip", z.ZodTypeAny, {
833
+ pdsMetadata?: number | undefined;
834
+ apiRequests?: number | undefined;
835
+ }, {
836
+ pdsMetadata?: number | undefined;
837
+ apiRequests?: number | undefined;
838
+ }>;
839
+ /**
840
+ * Zod schema for SDK configuration validation.
841
+ *
842
+ * @remarks
843
+ * This schema validates only the primitive/serializable parts of the configuration.
844
+ * Storage interfaces ({@link SessionStore}, {@link StateStore}) cannot be validated
845
+ * with Zod as they are runtime objects.
846
+ */
847
+ declare const ATProtoSDKConfigSchema: z.ZodObject<{
848
+ oauth: z.ZodObject<{
849
+ /**
850
+ * URL to the OAuth client metadata JSON document.
851
+ * This document describes your application to the authorization server.
852
+ *
853
+ * @see https://atproto.com/specs/oauth#client-metadata
854
+ */
855
+ clientId: z.ZodString;
856
+ /**
857
+ * URL where users are redirected after authentication.
858
+ * Must match one of the redirect URIs in your client metadata.
859
+ */
860
+ redirectUri: z.ZodString;
861
+ /**
862
+ * OAuth scopes to request, space-separated.
863
+ * Common scopes: "atproto", "transition:generic"
864
+ */
865
+ scope: z.ZodString;
866
+ /**
867
+ * URL to your public JWKS (JSON Web Key Set) endpoint.
868
+ * Used by the authorization server to verify your client's signatures.
869
+ */
870
+ jwksUri: z.ZodString;
871
+ /**
872
+ * Private JWK (JSON Web Key) as a JSON string.
873
+ * Used for signing DPoP proofs and client assertions.
874
+ *
875
+ * @remarks
876
+ * This should be kept secret and never exposed to clients.
877
+ * Typically loaded from environment variables or a secrets manager.
878
+ */
879
+ jwkPrivate: z.ZodString;
880
+ }, "strip", z.ZodTypeAny, {
881
+ clientId: string;
882
+ redirectUri: string;
883
+ scope: string;
884
+ jwksUri: string;
885
+ jwkPrivate: string;
886
+ }, {
887
+ clientId: string;
888
+ redirectUri: string;
889
+ scope: string;
890
+ jwksUri: string;
891
+ jwkPrivate: string;
892
+ }>;
893
+ servers: z.ZodOptional<z.ZodObject<{
894
+ /**
895
+ * Personal Data Server URL - the user's own AT Protocol server.
896
+ * This is the primary server for user data operations.
897
+ *
898
+ * @example "https://bsky.social"
899
+ */
900
+ pds: z.ZodOptional<z.ZodString>;
901
+ /**
902
+ * Shared Data Server URL - for collaborative data storage.
903
+ * Required for collaborator and organization operations.
904
+ *
905
+ * @example "https://sds.hypercerts.org"
906
+ */
907
+ sds: z.ZodOptional<z.ZodString>;
908
+ }, "strip", z.ZodTypeAny, {
909
+ pds?: string | undefined;
910
+ sds?: string | undefined;
911
+ }, {
912
+ pds?: string | undefined;
913
+ sds?: string | undefined;
914
+ }>>;
915
+ timeouts: z.ZodOptional<z.ZodObject<{
916
+ /**
917
+ * Timeout for fetching PDS metadata during identity resolution.
918
+ * @default 5000 (5 seconds, set by OAuthClient)
919
+ */
920
+ pdsMetadata: z.ZodOptional<z.ZodNumber>;
921
+ /**
922
+ * Timeout for general API requests to PDS/SDS.
923
+ * @default 30000 (30 seconds)
924
+ */
925
+ apiRequests: z.ZodOptional<z.ZodNumber>;
926
+ }, "strip", z.ZodTypeAny, {
927
+ pdsMetadata?: number | undefined;
928
+ apiRequests?: number | undefined;
929
+ }, {
930
+ pdsMetadata?: number | undefined;
931
+ apiRequests?: number | undefined;
932
+ }>>;
933
+ }, "strip", z.ZodTypeAny, {
934
+ oauth: {
935
+ clientId: string;
936
+ redirectUri: string;
937
+ scope: string;
938
+ jwksUri: string;
939
+ jwkPrivate: string;
940
+ };
941
+ servers?: {
942
+ pds?: string | undefined;
943
+ sds?: string | undefined;
944
+ } | undefined;
945
+ timeouts?: {
946
+ pdsMetadata?: number | undefined;
947
+ apiRequests?: number | undefined;
948
+ } | undefined;
949
+ }, {
950
+ oauth: {
951
+ clientId: string;
952
+ redirectUri: string;
953
+ scope: string;
954
+ jwksUri: string;
955
+ jwkPrivate: string;
956
+ };
957
+ servers?: {
958
+ pds?: string | undefined;
959
+ sds?: string | undefined;
960
+ } | undefined;
961
+ timeouts?: {
962
+ pdsMetadata?: number | undefined;
963
+ apiRequests?: number | undefined;
964
+ } | undefined;
965
+ }>;
966
+ /**
967
+ * Configuration options for the ATProto SDK.
968
+ *
969
+ * This interface defines all configuration needed to initialize the SDK,
970
+ * including OAuth credentials, server endpoints, and optional customizations.
971
+ *
972
+ * @example Minimal configuration
973
+ * ```typescript
974
+ * const config: ATProtoSDKConfig = {
975
+ * oauth: {
976
+ * clientId: "https://my-app.com/client-metadata.json",
977
+ * redirectUri: "https://my-app.com/callback",
978
+ * scope: "atproto transition:generic",
979
+ * jwksUri: "https://my-app.com/.well-known/jwks.json",
980
+ * jwkPrivate: process.env.JWK_PRIVATE_KEY!,
981
+ * },
982
+ * servers: {
983
+ * pds: "https://bsky.social",
984
+ * },
985
+ * };
986
+ * ```
987
+ *
988
+ * @example Full configuration with custom storage
989
+ * ```typescript
990
+ * const config: ATProtoSDKConfig = {
991
+ * oauth: { ... },
992
+ * servers: {
993
+ * pds: "https://bsky.social",
994
+ * sds: "https://sds.hypercerts.org",
995
+ * },
996
+ * storage: {
997
+ * sessionStore: new RedisSessionStore(redisClient),
998
+ * stateStore: new RedisStateStore(redisClient),
999
+ * },
1000
+ * timeouts: {
1001
+ * pdsMetadata: 5000,
1002
+ * apiRequests: 30000,
1003
+ * },
1004
+ * logger: console,
1005
+ * };
1006
+ * ```
1007
+ */
1008
+ interface ATProtoSDKConfig {
1009
+ /**
1010
+ * OAuth 2.0 configuration for authentication.
1011
+ *
1012
+ * Required fields for the OAuth flow with DPoP (Demonstrating Proof of Possession).
1013
+ * Your application must host the client metadata and JWKS endpoints.
1014
+ *
1015
+ * @see https://atproto.com/specs/oauth for AT Protocol OAuth specification
1016
+ */
1017
+ oauth: z.infer<typeof OAuthConfigSchema>;
1018
+ /**
1019
+ * Server URLs for PDS and SDS connections.
1020
+ *
1021
+ * - **PDS**: Personal Data Server - user's own data storage
1022
+ * - **SDS**: Shared Data Server - collaborative storage with access control
1023
+ */
1024
+ servers?: z.infer<typeof ServerConfigSchema>;
1025
+ /**
1026
+ * Storage adapters for persisting OAuth sessions and state.
1027
+ *
1028
+ * If not provided, in-memory implementations are used automatically.
1029
+ * **Warning**: In-memory storage is lost on process restart - use persistent
1030
+ * storage (Redis, database, etc.) in production.
1031
+ *
1032
+ * @example
1033
+ * ```typescript
1034
+ * storage: {
1035
+ * sessionStore: new RedisSessionStore(redis),
1036
+ * stateStore: new RedisStateStore(redis),
1037
+ * }
1038
+ * ```
1039
+ */
1040
+ storage?: {
1041
+ /**
1042
+ * Persistent storage for OAuth sessions.
1043
+ * Sessions contain access tokens, refresh tokens, and DPoP keys.
1044
+ */
1045
+ sessionStore?: SessionStore;
1046
+ /**
1047
+ * Temporary storage for OAuth state during the authorization flow.
1048
+ * State is short-lived and used for PKCE and CSRF protection.
1049
+ */
1050
+ stateStore?: StateStore;
1051
+ };
1052
+ /**
1053
+ * Custom fetch implementation for HTTP requests.
1054
+ *
1055
+ * Use this to add custom headers, logging, or to use a different HTTP client.
1056
+ * Must be compatible with the standard Fetch API.
1057
+ *
1058
+ * @example
1059
+ * ```typescript
1060
+ * fetch: async (url, init) => {
1061
+ * console.log(`Fetching: ${url}`);
1062
+ * return globalThis.fetch(url, init);
1063
+ * }
1064
+ * ```
1065
+ */
1066
+ fetch?: typeof fetch;
1067
+ /**
1068
+ * Timeout configuration for network requests.
1069
+ * Values are in milliseconds.
1070
+ */
1071
+ timeouts?: z.infer<typeof TimeoutConfigSchema>;
1072
+ /**
1073
+ * Cache for profiles, metadata, and other frequently accessed data.
1074
+ *
1075
+ * Implementing caching can significantly reduce API calls and improve performance.
1076
+ * The SDK does not provide a default cache - you must implement {@link CacheInterface}.
1077
+ */
1078
+ cache?: CacheInterface;
1079
+ /**
1080
+ * Logger for debugging and observability.
1081
+ *
1082
+ * The logger receives debug, info, warn, and error messages from the SDK.
1083
+ * Compatible with `console` or any logger implementing {@link LoggerInterface}.
1084
+ *
1085
+ * @example
1086
+ * ```typescript
1087
+ * logger: console
1088
+ * // or
1089
+ * logger: pino()
1090
+ * // or
1091
+ * logger: winston.createLogger({ ... })
1092
+ * ```
1093
+ */
1094
+ logger?: LoggerInterface;
1095
+ }
1096
+
1097
+ /**
1098
+ * Result of validating a record against a lexicon schema.
1099
+ */
1100
+ interface ValidationResult {
1101
+ /**
1102
+ * Whether the record is valid according to the lexicon schema.
1103
+ */
1104
+ valid: boolean;
1105
+ /**
1106
+ * Error message if validation failed.
1107
+ *
1108
+ * Only present when `valid` is `false`.
1109
+ */
1110
+ error?: string;
1111
+ }
1112
+
1113
+ /**
1114
+ * Repository types - Shared types for repository operations
1115
+ * @packageDocumentation
1116
+ */
1117
+
1118
+ /**
1119
+ * Options for creating a repository instance
1120
+ */
1121
+ interface RepositoryOptions {
1122
+ /** Use "sds" for configured SDS server, or provide a custom URL */
1123
+ server?: "pds" | "sds" | string;
1124
+ /** Custom server URL (overrides server option) */
1125
+ serverUrl?: string;
1126
+ }
1127
+ /**
1128
+ * Result of a create operation
1129
+ */
1130
+ interface CreateResult {
1131
+ uri: string;
1132
+ cid: string;
1133
+ }
1134
+ /**
1135
+ * Result of an update operation
1136
+ */
1137
+ interface UpdateResult {
1138
+ uri: string;
1139
+ cid: string;
1140
+ }
1141
+ /**
1142
+ * Paginated list result
1143
+ */
1144
+ interface PaginatedList<T> {
1145
+ records: T[];
1146
+ cursor?: string;
1147
+ }
1148
+ /**
1149
+ * List parameters
1150
+ */
1151
+ interface ListParams {
1152
+ limit?: number;
1153
+ cursor?: string;
1154
+ }
1155
+ /**
1156
+ * Role for repository access
1157
+ */
1158
+ type RepositoryRole = "viewer" | "editor" | "admin" | "owner";
1159
+ /**
1160
+ * Repository access grant
1161
+ */
1162
+ interface RepositoryAccessGrant {
1163
+ userDid: string;
1164
+ role: RepositoryRole;
1165
+ permissions: CollaboratorPermissions;
1166
+ grantedBy: string;
1167
+ grantedAt: string;
1168
+ revokedAt?: string;
1169
+ }
1170
+ /**
1171
+ * Organization info
1172
+ */
1173
+ interface OrganizationInfo {
1174
+ did: string;
1175
+ handle: string;
1176
+ name: string;
1177
+ description?: string;
1178
+ createdAt: string;
1179
+ accessType: "owner" | "collaborator";
1180
+ permissions: CollaboratorPermissions;
1181
+ collaboratorCount?: number;
1182
+ profile?: {
1183
+ displayName?: string;
1184
+ avatar?: string;
1185
+ banner?: string;
1186
+ website?: string;
1187
+ };
1188
+ }
1189
+ /**
1190
+ * Progress step for long-running operations
1191
+ */
1192
+ interface ProgressStep {
1193
+ name: string;
1194
+ status: "start" | "success" | "error";
1195
+ data?: unknown;
1196
+ error?: Error;
1197
+ }
1198
+
1199
+ /**
1200
+ * TypeScript types for hypercert lexicon schemas.
1201
+ *
1202
+ * Re-exports generated types and validation from `@hypercerts-org/lexicon`.
1203
+ *
1204
+ * @packageDocumentation
1205
+ */
1206
+
1207
+ type HypercertClaim = OrgHypercertsClaim.Main;
1208
+ type HypercertRights = OrgHypercertsClaimRights.Main;
1209
+ type HypercertContribution = OrgHypercertsClaimContribution.Main;
1210
+ type HypercertMeasurement = OrgHypercertsClaimMeasurement.Main;
1211
+ type HypercertEvaluation = OrgHypercertsClaimEvaluation.Main;
1212
+ type HypercertCollection = OrgHypercertsCollection.Main;
1213
+ type HypercertCollectionClaimItem = OrgHypercertsCollection.ClaimItem;
1214
+ type HypercertLocation = AppCertifiedLocation.Main;
1215
+ /** Blob reference for uploaded files (images, GeoJSON, etc.) */
1216
+ interface BlobRef {
1217
+ $type: "blob";
1218
+ ref: {
1219
+ $link: string;
1220
+ };
1221
+ mimeType: string;
1222
+ size: number;
1223
+ }
1224
+ /** Evidence item for operations */
1225
+ interface HypercertEvidence {
1226
+ uri: string;
1227
+ title?: string;
1228
+ description?: string;
1229
+ }
1230
+ /** Image input for operations */
1231
+ type HypercertImage = {
1232
+ type: "uri";
1233
+ uri: string;
1234
+ } | {
1235
+ type: "blob";
1236
+ blob: Blob;
1237
+ };
1238
+ /** Hypercert with AT Protocol metadata */
1239
+ interface HypercertWithMetadata {
1240
+ uri: string;
1241
+ cid: string;
1242
+ record: HypercertClaim;
1243
+ }
1244
+
1245
+ /**
1246
+ * Repository interfaces - Operation contracts for repository functionality.
1247
+ *
1248
+ * This module defines the interfaces for all repository operations,
1249
+ * providing clear contracts for record management, blob handling,
1250
+ * profile management, and domain-specific operations.
1251
+ *
1252
+ * @packageDocumentation
1253
+ */
1254
+
1255
+ /**
1256
+ * Parameters for creating a new hypercert.
1257
+ *
1258
+ * This interface defines all the data needed to create a hypercert
1259
+ * along with optional related records (location, contributions, evidence).
1260
+ *
1261
+ * @example Minimal hypercert
1262
+ * ```typescript
1263
+ * const params: CreateHypercertParams = {
1264
+ * title: "Community Garden Project",
1265
+ * description: "Established a 1-acre community garden serving 50 families",
1266
+ * workScope: "Food Security",
1267
+ * workTimeframeFrom: "2024-01-01",
1268
+ * workTimeframeTo: "2024-06-30",
1269
+ * rights: {
1270
+ * name: "Attribution",
1271
+ * type: "license",
1272
+ * description: "CC-BY-4.0",
1273
+ * },
1274
+ * };
1275
+ * ```
1276
+ *
1277
+ * @example Full hypercert with all options
1278
+ * ```typescript
1279
+ * const params: CreateHypercertParams = {
1280
+ * title: "Reforestation Initiative",
1281
+ * description: "Planted 10,000 trees in deforested areas",
1282
+ * shortDescription: "10K trees planted",
1283
+ * workScope: "Environmental Restoration",
1284
+ * workTimeframeFrom: "2024-01-01",
1285
+ * workTimeframeTo: "2024-12-31",
1286
+ * rights: {
1287
+ * name: "Open Impact",
1288
+ * type: "impact-rights",
1289
+ * description: "Transferable impact rights",
1290
+ * },
1291
+ * image: coverImageBlob,
1292
+ * location: {
1293
+ * value: "Amazon Rainforest, Brazil",
1294
+ * name: "Amazon Basin",
1295
+ * description: "Southern Amazon region",
1296
+ * },
1297
+ * contributions: [
1298
+ * {
1299
+ * contributors: ["did:plc:lead-org"],
1300
+ * role: "coordinator",
1301
+ * description: "Project coordination and funding",
1302
+ * },
1303
+ * {
1304
+ * contributors: ["did:plc:local-partner"],
1305
+ * role: "implementer",
1306
+ * description: "On-ground planting and monitoring",
1307
+ * },
1308
+ * ],
1309
+ * evidence: [
1310
+ * {
1311
+ * uri: "https://example.com/satellite-data",
1312
+ * description: "Satellite imagery showing reforestation progress",
1313
+ * },
1314
+ * ],
1315
+ * onProgress: (step) => console.log(`${step.name}: ${step.status}`),
1316
+ * };
1317
+ * ```
1318
+ */
1319
+ interface CreateHypercertParams {
1320
+ /**
1321
+ * Title of the hypercert.
1322
+ *
1323
+ * Should be concise but descriptive of the impact claim.
1324
+ */
1325
+ title: string;
1326
+ /**
1327
+ * Detailed description of the impact.
1328
+ *
1329
+ * Can include methodology, outcomes, and other relevant details.
1330
+ * Supports markdown formatting.
1331
+ */
1332
+ description: string;
1333
+ /**
1334
+ * Scope of work or impact area.
1335
+ *
1336
+ * @example "Climate Action", "Education", "Healthcare"
1337
+ */
1338
+ workScope: string;
1339
+ /**
1340
+ * Start date of the work period.
1341
+ *
1342
+ * ISO 8601 date format (YYYY-MM-DD).
1343
+ */
1344
+ workTimeframeFrom: string;
1345
+ /**
1346
+ * End date of the work period.
1347
+ *
1348
+ * ISO 8601 date format (YYYY-MM-DD).
1349
+ */
1350
+ workTimeframeTo: string;
1351
+ /**
1352
+ * Rights associated with the hypercert.
1353
+ */
1354
+ rights: {
1355
+ /**
1356
+ * Name of the rights.
1357
+ *
1358
+ * @example "Attribution", "Impact Rights", "Public Domain"
1359
+ */
1360
+ name: string;
1361
+ /**
1362
+ * Type of rights.
1363
+ *
1364
+ * @example "license", "impact-rights", "ownership"
1365
+ */
1366
+ type: string;
1367
+ /**
1368
+ * Description of the rights terms.
1369
+ *
1370
+ * @example "CC-BY-4.0", "Transferable impact rights"
1371
+ */
1372
+ description: string;
1373
+ };
1374
+ /**
1375
+ * Optional short description for display in lists/cards.
1376
+ *
1377
+ * Should be under 200 characters.
1378
+ */
1379
+ shortDescription?: string;
1380
+ /**
1381
+ * Optional cover image for the hypercert.
1382
+ *
1383
+ * Recommended size: 1200x630 pixels (social media preview ratio).
1384
+ */
1385
+ image?: Blob;
1386
+ /**
1387
+ * Optional geographic location of the impact.
1388
+ */
1389
+ location?: {
1390
+ /**
1391
+ * Location value/address.
1392
+ *
1393
+ * @example "San Francisco, CA, USA"
1394
+ */
1395
+ value: string;
1396
+ /**
1397
+ * Human-readable location name.
1398
+ *
1399
+ * @example "SF Bay Area"
1400
+ */
1401
+ name?: string;
1402
+ /**
1403
+ * Description of the location scope.
1404
+ */
1405
+ description?: string;
1406
+ /**
1407
+ * Spatial Reference System identifier.
1408
+ *
1409
+ * @example "EPSG:4326" for WGS84
1410
+ */
1411
+ srs?: string;
1412
+ /**
1413
+ * GeoJSON file as a Blob for precise boundaries.
1414
+ */
1415
+ geojson?: Blob;
1416
+ };
1417
+ /**
1418
+ * Optional list of contributions to the impact.
1419
+ *
1420
+ * Use this to credit multiple contributors with different roles.
1421
+ */
1422
+ contributions?: Array<{
1423
+ /**
1424
+ * DIDs of the contributors.
1425
+ */
1426
+ contributors: string[];
1427
+ /**
1428
+ * Role in the contribution.
1429
+ *
1430
+ * @example "coordinator", "implementer", "funder", "volunteer"
1431
+ */
1432
+ role: string;
1433
+ /**
1434
+ * Description of the contribution.
1435
+ */
1436
+ description?: string;
1437
+ }>;
1438
+ /**
1439
+ * Optional evidence supporting the impact claim.
1440
+ */
1441
+ evidence?: HypercertEvidence[];
1442
+ /**
1443
+ * Optional callback for progress updates during creation.
1444
+ *
1445
+ * Called for each step of the creation process (image upload,
1446
+ * record creation, attachment linking, etc.).
1447
+ */
1448
+ onProgress?: (step: ProgressStep) => void;
1449
+ }
1450
+ /**
1451
+ * Result of creating a hypercert.
1452
+ *
1453
+ * Contains URIs and CIDs for all created records.
1454
+ */
1455
+ interface CreateHypercertResult {
1456
+ /**
1457
+ * AT-URI of the main hypercert record.
1458
+ */
1459
+ hypercertUri: string;
1460
+ /**
1461
+ * AT-URI of the associated rights record.
1462
+ */
1463
+ rightsUri: string;
1464
+ /**
1465
+ * CID of the hypercert record.
1466
+ */
1467
+ hypercertCid: string;
1468
+ /**
1469
+ * CID of the rights record.
1470
+ */
1471
+ rightsCid: string;
1472
+ /**
1473
+ * AT-URI of the location record, if location was provided.
1474
+ */
1475
+ locationUri?: string;
1476
+ /**
1477
+ * AT-URIs of contribution records, if contributions were provided.
1478
+ */
1479
+ contributionUris?: string[];
1480
+ }
1481
+ /**
1482
+ * Low-level record operations for AT Protocol CRUD.
1483
+ *
1484
+ * Use this interface for direct access to AT Protocol records when
1485
+ * the high-level APIs don't meet your needs.
1486
+ *
1487
+ * @example
1488
+ * ```typescript
1489
+ * // Create a record
1490
+ * const { uri, cid } = await repo.records.create({
1491
+ * collection: "org.example.mytype",
1492
+ * record: { foo: "bar", createdAt: new Date().toISOString() },
1493
+ * });
1494
+ *
1495
+ * // Get a record
1496
+ * const { value } = await repo.records.get({
1497
+ * collection: "org.example.mytype",
1498
+ * rkey: "abc123",
1499
+ * });
1500
+ *
1501
+ * // Update a record
1502
+ * await repo.records.update({
1503
+ * collection: "org.example.mytype",
1504
+ * rkey: "abc123",
1505
+ * record: { ...value, foo: "updated" },
1506
+ * });
1507
+ *
1508
+ * // List records
1509
+ * const { records, cursor } = await repo.records.list({
1510
+ * collection: "org.example.mytype",
1511
+ * limit: 50,
1512
+ * });
1513
+ *
1514
+ * // Delete a record
1515
+ * await repo.records.delete({
1516
+ * collection: "org.example.mytype",
1517
+ * rkey: "abc123",
1518
+ * });
1519
+ * ```
1520
+ */
1521
+ interface RecordOperations {
1522
+ /**
1523
+ * Creates a new record in a collection.
1524
+ *
1525
+ * @param params - Creation parameters
1526
+ * @param params.collection - NSID of the collection (e.g., "org.hypercerts.hypercert")
1527
+ * @param params.record - Record data (must conform to collection's lexicon)
1528
+ * @param params.rkey - Optional record key. Auto-generated if not provided.
1529
+ * @returns Promise resolving to the created record's URI and CID
1530
+ */
1531
+ create(params: {
1532
+ collection: string;
1533
+ record: unknown;
1534
+ rkey?: string;
1535
+ }): Promise<CreateResult>;
1536
+ /**
1537
+ * Updates an existing record.
1538
+ *
1539
+ * @param params - Update parameters
1540
+ * @param params.collection - NSID of the collection
1541
+ * @param params.rkey - Record key to update
1542
+ * @param params.record - New record data (replaces entire record)
1543
+ * @returns Promise resolving to the updated record's URI and CID
1544
+ */
1545
+ update(params: {
1546
+ collection: string;
1547
+ rkey: string;
1548
+ record: unknown;
1549
+ }): Promise<UpdateResult>;
1550
+ /**
1551
+ * Gets a single record by collection and key.
1552
+ *
1553
+ * @param params - Get parameters
1554
+ * @param params.collection - NSID of the collection
1555
+ * @param params.rkey - Record key
1556
+ * @returns Promise resolving to the record's URI, CID, and value
1557
+ */
1558
+ get(params: {
1559
+ collection: string;
1560
+ rkey: string;
1561
+ }): Promise<{
1562
+ uri: string;
1563
+ cid: string;
1564
+ value: unknown;
1565
+ }>;
1566
+ /**
1567
+ * Lists records in a collection with pagination.
1568
+ *
1569
+ * @param params - List parameters
1570
+ * @param params.collection - NSID of the collection
1571
+ * @param params.limit - Maximum records to return (default varies by server)
1572
+ * @param params.cursor - Pagination cursor from previous response
1573
+ * @returns Promise resolving to paginated list of records
1574
+ */
1575
+ list(params: {
1576
+ collection: string;
1577
+ limit?: number;
1578
+ cursor?: string;
1579
+ }): Promise<PaginatedList<{
1580
+ uri: string;
1581
+ cid: string;
1582
+ value: unknown;
1583
+ }>>;
1584
+ /**
1585
+ * Deletes a record.
1586
+ *
1587
+ * @param params - Delete parameters
1588
+ * @param params.collection - NSID of the collection
1589
+ * @param params.rkey - Record key to delete
1590
+ */
1591
+ delete(params: {
1592
+ collection: string;
1593
+ rkey: string;
1594
+ }): Promise<void>;
1595
+ }
1596
+ /**
1597
+ * Blob operations for binary data handling.
1598
+ *
1599
+ * Blobs are used for images, files, and other binary content.
1600
+ * They are referenced from records using blob references.
1601
+ *
1602
+ * @example
1603
+ * ```typescript
1604
+ * // Upload an image
1605
+ * const imageBlob = new Blob([imageData], { type: "image/jpeg" });
1606
+ * const { ref, mimeType, size } = await repo.blobs.upload(imageBlob);
1607
+ *
1608
+ * // Use the ref in a record
1609
+ * await repo.records.create({
1610
+ * collection: "org.example.post",
1611
+ * record: {
1612
+ * text: "Hello!",
1613
+ * image: ref, // { $link: "bafyrei..." }
1614
+ * },
1615
+ * });
1616
+ *
1617
+ * // Retrieve a blob
1618
+ * const { data, mimeType } = await repo.blobs.get(ref.$link);
1619
+ * ```
1620
+ */
1621
+ interface BlobOperations {
1622
+ /**
1623
+ * Uploads a blob to the server.
1624
+ *
1625
+ * @param blob - The blob to upload
1626
+ * @returns Promise resolving to blob reference and metadata
1627
+ */
1628
+ upload(blob: Blob): Promise<{
1629
+ /**
1630
+ * Blob reference to use in records.
1631
+ *
1632
+ * Contains `$link` property with the CID.
1633
+ */
1634
+ ref: {
1635
+ $link: string;
1636
+ };
1637
+ /**
1638
+ * MIME type of the uploaded blob.
1639
+ */
1640
+ mimeType: string;
1641
+ /**
1642
+ * Size of the blob in bytes.
1643
+ */
1644
+ size: number;
1645
+ }>;
1646
+ /**
1647
+ * Retrieves a blob by its CID.
1648
+ *
1649
+ * @param cid - Content Identifier of the blob
1650
+ * @returns Promise resolving to blob data and MIME type
1651
+ */
1652
+ get(cid: string): Promise<{
1653
+ /**
1654
+ * Raw blob data as Uint8Array.
1655
+ */
1656
+ data: Uint8Array;
1657
+ /**
1658
+ * MIME type of the blob.
1659
+ */
1660
+ mimeType: string;
1661
+ }>;
1662
+ }
1663
+ /**
1664
+ * Profile operations for user profile management.
1665
+ *
1666
+ * @example
1667
+ * ```typescript
1668
+ * // Get profile
1669
+ * const profile = await repo.profile.get();
1670
+ * console.log(profile.displayName);
1671
+ *
1672
+ * // Update profile
1673
+ * await repo.profile.update({
1674
+ * displayName: "New Name",
1675
+ * description: "Updated bio",
1676
+ * });
1677
+ *
1678
+ * // Update avatar
1679
+ * await repo.profile.update({
1680
+ * avatar: new Blob([avatarData], { type: "image/png" }),
1681
+ * });
1682
+ *
1683
+ * // Clear a field by passing null
1684
+ * await repo.profile.update({
1685
+ * website: null, // Removes website
1686
+ * });
1687
+ * ```
1688
+ */
1689
+ interface ProfileOperations {
1690
+ /**
1691
+ * Gets the repository's profile.
1692
+ *
1693
+ * @returns Promise resolving to profile data
1694
+ */
1695
+ get(): Promise<{
1696
+ /**
1697
+ * User's handle (e.g., "alice.bsky.social").
1698
+ */
1699
+ handle: string;
1700
+ /**
1701
+ * Display name.
1702
+ */
1703
+ displayName?: string;
1704
+ /**
1705
+ * Profile description/bio.
1706
+ */
1707
+ description?: string;
1708
+ /**
1709
+ * Avatar image URL or blob reference.
1710
+ */
1711
+ avatar?: string;
1712
+ /**
1713
+ * Banner image URL or blob reference.
1714
+ */
1715
+ banner?: string;
1716
+ /**
1717
+ * Website URL.
1718
+ */
1719
+ website?: string;
1720
+ }>;
1721
+ /**
1722
+ * Updates the repository's profile.
1723
+ *
1724
+ * Pass `null` to clear a field. Omitted fields are unchanged.
1725
+ *
1726
+ * @param params - Fields to update
1727
+ * @returns Promise resolving to update result
1728
+ */
1729
+ update(params: {
1730
+ displayName?: string | null;
1731
+ description?: string | null;
1732
+ avatar?: Blob | null;
1733
+ banner?: Blob | null;
1734
+ website?: string | null;
1735
+ }): Promise<UpdateResult>;
1736
+ }
1737
+ /**
1738
+ * Events emitted by hypercert operations.
1739
+ *
1740
+ * Use these to track progress of complex operations or react
1741
+ * to record changes.
1742
+ */
1743
+ interface HypercertEvents {
1744
+ /**
1745
+ * Emitted when a hypercert record is created.
1746
+ */
1747
+ recordCreated: {
1748
+ uri: string;
1749
+ cid: string;
1750
+ };
1751
+ /**
1752
+ * Emitted when a hypercert record is updated.
1753
+ */
1754
+ recordUpdated: {
1755
+ uri: string;
1756
+ cid: string;
1757
+ };
1758
+ /**
1759
+ * Emitted when a rights record is created.
1760
+ */
1761
+ rightsCreated: {
1762
+ uri: string;
1763
+ cid: string;
1764
+ };
1765
+ /**
1766
+ * Emitted when a location is attached to a hypercert.
1767
+ */
1768
+ locationAttached: {
1769
+ uri: string;
1770
+ cid: string;
1771
+ hypercertUri: string;
1772
+ };
1773
+ /**
1774
+ * Emitted when a contribution record is created.
1775
+ */
1776
+ contributionCreated: {
1777
+ uri: string;
1778
+ cid: string;
1779
+ };
1780
+ /**
1781
+ * Emitted when evidence is added to a hypercert.
1782
+ */
1783
+ evidenceAdded: {
1784
+ uri: string;
1785
+ cid: string;
1786
+ };
1787
+ /**
1788
+ * Emitted when a collection is created.
1789
+ */
1790
+ collectionCreated: {
1791
+ uri: string;
1792
+ cid: string;
1793
+ };
1794
+ }
1795
+ /**
1796
+ * High-level hypercert operations.
1797
+ *
1798
+ * Provides a convenient API for creating and managing hypercerts
1799
+ * with automatic handling of related records (rights, locations,
1800
+ * contributions, etc.).
1801
+ *
1802
+ * Extends EventEmitter to provide progress events.
1803
+ *
1804
+ * @example Basic usage
1805
+ * ```typescript
1806
+ * // Create a hypercert
1807
+ * const result = await repo.hypercerts.create({
1808
+ * title: "Impact Project",
1809
+ * description: "Description...",
1810
+ * workScope: "Climate",
1811
+ * workTimeframeFrom: "2024-01-01",
1812
+ * workTimeframeTo: "2024-12-31",
1813
+ * rights: { name: "CC-BY", type: "license", description: "..." },
1814
+ * });
1815
+ *
1816
+ * // List hypercerts
1817
+ * const { records } = await repo.hypercerts.list({ limit: 20 });
1818
+ *
1819
+ * // Get a specific hypercert
1820
+ * const hypercert = await repo.hypercerts.get(result.hypercertUri);
1821
+ * ```
1822
+ *
1823
+ * @example With events
1824
+ * ```typescript
1825
+ * repo.hypercerts.on("recordCreated", ({ uri }) => {
1826
+ * console.log(`Created: ${uri}`);
1827
+ * });
1828
+ * ```
1829
+ */
1830
+ interface HypercertOperations extends EventEmitter<HypercertEvents> {
1831
+ /**
1832
+ * Creates a new hypercert with all related records.
1833
+ *
1834
+ * @param params - Creation parameters
1835
+ * @returns Promise resolving to URIs and CIDs of created records
1836
+ */
1837
+ create(params: CreateHypercertParams): Promise<CreateHypercertResult>;
1838
+ /**
1839
+ * Updates an existing hypercert.
1840
+ *
1841
+ * @param params - Update parameters
1842
+ * @param params.uri - AT-URI of the hypercert to update
1843
+ * @param params.updates - Fields to update
1844
+ * @param params.image - New image, or `null` to remove
1845
+ * @returns Promise resolving to update result
1846
+ */
1847
+ update(params: {
1848
+ uri: string;
1849
+ updates: Partial<Omit<HypercertClaim, "$type" | "createdAt" | "rights">>;
1850
+ image?: Blob | null;
1851
+ }): Promise<UpdateResult>;
1852
+ /**
1853
+ * Gets a hypercert by URI.
1854
+ *
1855
+ * @param uri - AT-URI of the hypercert
1856
+ * @returns Promise resolving to hypercert data
1857
+ */
1858
+ get(uri: string): Promise<{
1859
+ uri: string;
1860
+ cid: string;
1861
+ record: HypercertClaim;
1862
+ }>;
1863
+ /**
1864
+ * Lists hypercerts with pagination.
1865
+ *
1866
+ * @param params - Optional pagination parameters
1867
+ * @returns Promise resolving to paginated list
1868
+ */
1869
+ list(params?: ListParams): Promise<PaginatedList<{
1870
+ uri: string;
1871
+ cid: string;
1872
+ record: HypercertClaim;
1873
+ }>>;
1874
+ /**
1875
+ * Deletes a hypercert.
1876
+ *
1877
+ * Note: This does not automatically delete related records
1878
+ * (rights, locations, contributions).
1879
+ *
1880
+ * @param uri - AT-URI of the hypercert to delete
1881
+ */
1882
+ delete(uri: string): Promise<void>;
1883
+ /**
1884
+ * Attaches a location to an existing hypercert.
1885
+ *
1886
+ * @param uri - AT-URI of the hypercert
1887
+ * @param location - Location data
1888
+ * @returns Promise resolving to location record result
1889
+ */
1890
+ attachLocation(uri: string, location: {
1891
+ value: string;
1892
+ name?: string;
1893
+ description?: string;
1894
+ srs?: string;
1895
+ geojson?: Blob;
1896
+ }): Promise<CreateResult>;
1897
+ /**
1898
+ * Adds evidence to an existing hypercert.
1899
+ *
1900
+ * @param uri - AT-URI of the hypercert
1901
+ * @param evidence - Array of evidence items to add
1902
+ * @returns Promise resolving to update result
1903
+ */
1904
+ addEvidence(uri: string, evidence: HypercertEvidence[]): Promise<UpdateResult>;
1905
+ /**
1906
+ * Creates a contribution record.
1907
+ *
1908
+ * @param params - Contribution parameters
1909
+ * @returns Promise resolving to contribution record result
1910
+ */
1911
+ addContribution(params: {
1912
+ hypercertUri?: string;
1913
+ contributors: string[];
1914
+ role: string;
1915
+ description?: string;
1916
+ }): Promise<CreateResult>;
1917
+ /**
1918
+ * Creates a measurement record for a hypercert.
1919
+ *
1920
+ * @param params - Measurement parameters
1921
+ * @returns Promise resolving to measurement record result
1922
+ */
1923
+ addMeasurement(params: {
1924
+ hypercertUri: string;
1925
+ measurers: string[];
1926
+ metric: string;
1927
+ value: string;
1928
+ methodUri?: string;
1929
+ evidenceUris?: string[];
1930
+ }): Promise<CreateResult>;
1931
+ /**
1932
+ * Creates an evaluation record.
1933
+ *
1934
+ * @param params - Evaluation parameters
1935
+ * @returns Promise resolving to evaluation record result
1936
+ */
1937
+ addEvaluation(params: {
1938
+ subjectUri: string;
1939
+ evaluators: string[];
1940
+ summary: string;
1941
+ }): Promise<CreateResult>;
1942
+ /**
1943
+ * Creates a collection of hypercerts.
1944
+ *
1945
+ * @param params - Collection parameters
1946
+ * @returns Promise resolving to collection record result
1947
+ */
1948
+ createCollection(params: {
1949
+ title: string;
1950
+ claims: Array<{
1951
+ uri: string;
1952
+ cid: string;
1953
+ weight: string;
1954
+ }>;
1955
+ shortDescription?: string;
1956
+ coverPhoto?: Blob;
1957
+ }): Promise<CreateResult>;
1958
+ /**
1959
+ * Gets a collection by URI.
1960
+ *
1961
+ * @param uri - AT-URI of the collection
1962
+ * @returns Promise resolving to collection data
1963
+ */
1964
+ getCollection(uri: string): Promise<{
1965
+ uri: string;
1966
+ cid: string;
1967
+ record: HypercertCollection;
1968
+ }>;
1969
+ /**
1970
+ * Lists collections with pagination.
1971
+ *
1972
+ * @param params - Optional pagination parameters
1973
+ * @returns Promise resolving to paginated list
1974
+ */
1975
+ listCollections(params?: ListParams): Promise<PaginatedList<{
1976
+ uri: string;
1977
+ cid: string;
1978
+ record: HypercertCollection;
1979
+ }>>;
1980
+ }
1981
+ /**
1982
+ * Collaborator operations for SDS access control.
1983
+ *
1984
+ * **SDS Only**: These operations are only available on Shared Data Servers.
1985
+ *
1986
+ * @example
1987
+ * ```typescript
1988
+ * // Grant access
1989
+ * await repo.collaborators.grant({
1990
+ * userDid: "did:plc:new-user",
1991
+ * role: "editor",
1992
+ * });
1993
+ *
1994
+ * // List collaborators
1995
+ * const collaborators = await repo.collaborators.list();
1996
+ *
1997
+ * // Check access
1998
+ * const hasAccess = await repo.collaborators.hasAccess("did:plc:someone");
1999
+ * const role = await repo.collaborators.getRole("did:plc:someone");
2000
+ *
2001
+ * // Revoke access
2002
+ * await repo.collaborators.revoke({ userDid: "did:plc:former-user" });
2003
+ * ```
2004
+ */
2005
+ interface CollaboratorOperations {
2006
+ /**
2007
+ * Grants repository access to a user.
2008
+ *
2009
+ * @param params - Grant parameters
2010
+ * @param params.userDid - DID of the user to grant access to
2011
+ * @param params.role - Role to assign
2012
+ */
2013
+ grant(params: {
2014
+ userDid: string;
2015
+ role: RepositoryRole;
2016
+ }): Promise<void>;
2017
+ /**
2018
+ * Revokes repository access from a user.
2019
+ *
2020
+ * @param params - Revoke parameters
2021
+ * @param params.userDid - DID of the user to revoke access from
2022
+ */
2023
+ revoke(params: {
2024
+ userDid: string;
2025
+ }): Promise<void>;
2026
+ /**
2027
+ * Lists all collaborators on the repository.
2028
+ *
2029
+ * @returns Promise resolving to array of access grants
2030
+ */
2031
+ list(): Promise<RepositoryAccessGrant[]>;
2032
+ /**
2033
+ * Checks if a user has any access to the repository.
2034
+ *
2035
+ * @param userDid - DID to check
2036
+ * @returns Promise resolving to boolean
2037
+ */
2038
+ hasAccess(userDid: string): Promise<boolean>;
2039
+ /**
2040
+ * Gets the role assigned to a user.
2041
+ *
2042
+ * @param userDid - DID to check
2043
+ * @returns Promise resolving to role, or `null` if no access
2044
+ */
2045
+ getRole(userDid: string): Promise<RepositoryRole | null>;
2046
+ }
2047
+ /**
2048
+ * Organization operations for SDS organization management.
2049
+ *
2050
+ * **SDS Only**: These operations are only available on Shared Data Servers.
2051
+ *
2052
+ * @example
2053
+ * ```typescript
2054
+ * // Create an organization
2055
+ * const org = await repo.organizations.create({
2056
+ * name: "My Team",
2057
+ * description: "A team for impact projects",
2058
+ * });
2059
+ *
2060
+ * // List organizations
2061
+ * const orgs = await repo.organizations.list();
2062
+ *
2063
+ * // Get organization details
2064
+ * const orgInfo = await repo.organizations.get(org.did);
2065
+ * ```
2066
+ */
2067
+ interface OrganizationOperations {
2068
+ /**
2069
+ * Creates a new organization.
2070
+ *
2071
+ * @param params - Organization parameters
2072
+ * @param params.name - Organization name
2073
+ * @param params.description - Optional description
2074
+ * @param params.handle - Optional custom handle
2075
+ * @returns Promise resolving to organization info
2076
+ */
2077
+ create(params: {
2078
+ name: string;
2079
+ description?: string;
2080
+ handle?: string;
2081
+ }): Promise<OrganizationInfo>;
2082
+ /**
2083
+ * Gets an organization by DID.
2084
+ *
2085
+ * @param did - Organization DID
2086
+ * @returns Promise resolving to organization info, or `null` if not found
2087
+ */
2088
+ get(did: string): Promise<OrganizationInfo | null>;
2089
+ /**
2090
+ * Lists organizations the current user has access to.
2091
+ *
2092
+ * @returns Promise resolving to array of organization info
2093
+ */
2094
+ list(): Promise<OrganizationInfo[]>;
2095
+ }
2096
+
2097
+ /**
2098
+ * Options for the OAuth authorization flow.
2099
+ */
2100
+ interface AuthorizeOptions {
2101
+ /**
2102
+ * OAuth scope string to request specific permissions.
2103
+ * Overrides the default scope configured in {@link ATProtoSDKConfig.oauth.scope}.
2104
+ *
2105
+ * @example
2106
+ * ```typescript
2107
+ * // Request read-only access
2108
+ * await sdk.authorize("user.bsky.social", { scope: "atproto" });
2109
+ *
2110
+ * // Request full access (default typically includes transition:generic)
2111
+ * await sdk.authorize("user.bsky.social", { scope: "atproto transition:generic" });
2112
+ * ```
2113
+ */
2114
+ scope?: string;
2115
+ }
2116
+
2117
+ export { ATProtoSDKConfigSchema, CollaboratorPermissionsSchema, CollaboratorSchema, OAuthConfigSchema, OrganizationSchema, ServerConfigSchema, TimeoutConfigSchema };
2118
+ export type { ATProtoSDKConfig, AuthorizeOptions, BlobOperations, BlobRef, CacheInterface, Collaborator, CollaboratorOperations, CollaboratorPermissions, CreateHypercertParams, CreateHypercertResult, CreateResult, DID, HypercertClaim, HypercertCollection, HypercertCollectionClaimItem, HypercertContribution, HypercertEvaluation, HypercertEvents, HypercertEvidence, HypercertImage, HypercertLocation, HypercertMeasurement, HypercertOperations, HypercertRights, HypercertWithMetadata, ListParams, LoggerInterface, Organization, OrganizationInfo, OrganizationOperations, PaginatedList, ProfileOperations, ProgressStep, RecordOperations, RepositoryAccessGrant, RepositoryOptions, RepositoryRole, Session, SessionStore, StateStore, UpdateResult, ValidationResult };