@hypercerts-org/sdk-core 0.4.0-beta.0 → 0.5.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.
package/dist/types.cjs CHANGED
@@ -173,9 +173,10 @@ const OrganizationSchema = zod.z.object({
173
173
  /**
174
174
  * How the current user relates to this organization.
175
175
  * - `"owner"`: User created or owns the organization
176
- * - `"collaborator"`: User was invited to collaborate
176
+ * - `"shared"`: User was invited to collaborate (has permissions)
177
+ * - `"none"`: User has no access to this organization
177
178
  */
178
- accessType: zod.z.enum(["owner", "collaborator"]),
179
+ accessType: zod.z.enum(["owner", "shared", "none"]),
179
180
  });
180
181
  /**
181
182
  * Zod schema for collaborator data.
@@ -1 +1 @@
1
- {"version":3,"file":"types.cjs","sources":["../src/core/config.ts","../src/core/types.ts"],"sourcesContent":["import { z } from \"zod\";\nimport type { SessionStore, StateStore, CacheInterface, LoggerInterface } from \"./interfaces.js\";\n\n/**\n * Zod schema for OAuth configuration validation.\n *\n * @remarks\n * All URLs must be valid and use HTTPS in production. The `jwkPrivate` field\n * should contain the private key in JWK (JSON Web Key) format as a string.\n */\nexport const OAuthConfigSchema = z.object({\n /**\n * URL to the OAuth client metadata JSON document.\n * This document describes your application to the authorization server.\n *\n * @see https://atproto.com/specs/oauth#client-metadata\n */\n clientId: z.string().url(),\n\n /**\n * URL where users are redirected after authentication.\n * Must match one of the redirect URIs in your client metadata.\n */\n redirectUri: z.string().url(),\n\n /**\n * OAuth scopes to request, space-separated.\n * Common scopes: \"atproto\", \"transition:generic\"\n */\n scope: z.string(),\n\n /**\n * URL to your public JWKS (JSON Web Key Set) endpoint.\n * Used by the authorization server to verify your client's signatures.\n */\n jwksUri: z.string().url(),\n\n /**\n * Private JWK (JSON Web Key) as a JSON string.\n * Used for signing DPoP proofs and client assertions.\n *\n * @remarks\n * This should be kept secret and never exposed to clients.\n * Typically loaded from environment variables or a secrets manager.\n */\n jwkPrivate: z.string(),\n});\n\n/**\n * Zod schema for server URL configuration.\n *\n * @remarks\n * At least one server (PDS or SDS) should be configured for the SDK to be useful.\n */\nexport const ServerConfigSchema = z.object({\n /**\n * Personal Data Server URL - the user's own AT Protocol server.\n * This is the primary server for user data operations.\n *\n * @example \"https://bsky.social\"\n */\n pds: z.string().url().optional(),\n\n /**\n * Shared Data Server URL - for collaborative data storage.\n * Required for collaborator and organization operations.\n *\n * @example \"https://sds.hypercerts.org\"\n */\n sds: z.string().url().optional(),\n});\n\n/**\n * Zod schema for timeout configuration.\n *\n * @remarks\n * All timeout values are in milliseconds.\n */\nexport const TimeoutConfigSchema = z.object({\n /**\n * Timeout for fetching PDS metadata during identity resolution.\n * @default 5000 (5 seconds, set by OAuthClient)\n */\n pdsMetadata: z.number().positive().optional(),\n\n /**\n * Timeout for general API requests to PDS/SDS.\n * @default 30000 (30 seconds)\n */\n apiRequests: z.number().positive().optional(),\n});\n\n/**\n * Zod schema for SDK configuration validation.\n *\n * @remarks\n * This schema validates only the primitive/serializable parts of the configuration.\n * Storage interfaces ({@link SessionStore}, {@link StateStore}) cannot be validated\n * with Zod as they are runtime objects.\n */\nexport const ATProtoSDKConfigSchema = z.object({\n oauth: OAuthConfigSchema,\n servers: ServerConfigSchema.optional(),\n timeouts: TimeoutConfigSchema.optional(),\n});\n\n/**\n * Configuration options for the ATProto SDK.\n *\n * This interface defines all configuration needed to initialize the SDK,\n * including OAuth credentials, server endpoints, and optional customizations.\n *\n * @example Minimal configuration\n * ```typescript\n * const config: ATProtoSDKConfig = {\n * oauth: {\n * clientId: \"https://my-app.com/client-metadata.json\",\n * redirectUri: \"https://my-app.com/callback\",\n * scope: \"atproto transition:generic\",\n * jwksUri: \"https://my-app.com/.well-known/jwks.json\",\n * jwkPrivate: process.env.JWK_PRIVATE_KEY!,\n * },\n * servers: {\n * pds: \"https://bsky.social\",\n * },\n * };\n * ```\n *\n * @example Full configuration with custom storage\n * ```typescript\n * const config: ATProtoSDKConfig = {\n * oauth: { ... },\n * servers: {\n * pds: \"https://bsky.social\",\n * sds: \"https://sds.hypercerts.org\",\n * },\n * storage: {\n * sessionStore: new RedisSessionStore(redisClient),\n * stateStore: new RedisStateStore(redisClient),\n * },\n * timeouts: {\n * pdsMetadata: 5000,\n * apiRequests: 30000,\n * },\n * logger: console,\n * };\n * ```\n */\nexport interface ATProtoSDKConfig {\n /**\n * OAuth 2.0 configuration for authentication.\n *\n * Required fields for the OAuth flow with DPoP (Demonstrating Proof of Possession).\n * Your application must host the client metadata and JWKS endpoints.\n *\n * @see https://atproto.com/specs/oauth for AT Protocol OAuth specification\n */\n oauth: z.infer<typeof OAuthConfigSchema>;\n\n /**\n * Server URLs for PDS and SDS connections.\n *\n * - **PDS**: Personal Data Server - user's own data storage\n * - **SDS**: Shared Data Server - collaborative storage with access control\n */\n servers?: z.infer<typeof ServerConfigSchema>;\n\n /**\n * Storage adapters for persisting OAuth sessions and state.\n *\n * If not provided, in-memory implementations are used automatically.\n * **Warning**: In-memory storage is lost on process restart - use persistent\n * storage (Redis, database, etc.) in production.\n *\n * @example\n * ```typescript\n * storage: {\n * sessionStore: new RedisSessionStore(redis),\n * stateStore: new RedisStateStore(redis),\n * }\n * ```\n */\n storage?: {\n /**\n * Persistent storage for OAuth sessions.\n * Sessions contain access tokens, refresh tokens, and DPoP keys.\n */\n sessionStore?: SessionStore;\n\n /**\n * Temporary storage for OAuth state during the authorization flow.\n * State is short-lived and used for PKCE and CSRF protection.\n */\n stateStore?: StateStore;\n };\n\n /**\n * Custom fetch implementation for HTTP requests.\n *\n * Use this to add custom headers, logging, or to use a different HTTP client.\n * Must be compatible with the standard Fetch API.\n *\n * @example\n * ```typescript\n * fetch: async (url, init) => {\n * console.log(`Fetching: ${url}`);\n * return globalThis.fetch(url, init);\n * }\n * ```\n */\n fetch?: typeof fetch;\n\n /**\n * Timeout configuration for network requests.\n * Values are in milliseconds.\n */\n timeouts?: z.infer<typeof TimeoutConfigSchema>;\n\n /**\n * Cache for profiles, metadata, and other frequently accessed data.\n *\n * Implementing caching can significantly reduce API calls and improve performance.\n * The SDK does not provide a default cache - you must implement {@link CacheInterface}.\n */\n cache?: CacheInterface;\n\n /**\n * Logger for debugging and observability.\n *\n * The logger receives debug, info, warn, and error messages from the SDK.\n * Compatible with `console` or any logger implementing {@link LoggerInterface}.\n *\n * @example\n * ```typescript\n * logger: console\n * // or\n * logger: pino()\n * // or\n * logger: winston.createLogger({ ... })\n * ```\n */\n logger?: LoggerInterface;\n}\n","import type { OAuthSession } from \"@atproto/oauth-client-node\";\nimport { z } from \"zod\";\n\n/**\n * Decentralized Identifier (DID) - a unique, persistent identifier for AT Protocol users.\n *\n * DIDs are the canonical identifier for users in the AT Protocol ecosystem.\n * Unlike handles which can change, DIDs remain constant for the lifetime of an account.\n *\n * @remarks\n * AT Protocol supports multiple DID methods:\n * - `did:plc:` - PLC (Public Ledger of Credentials) DIDs, most common for Bluesky users\n * - `did:web:` - Web DIDs, resolved via HTTPS\n *\n * @example\n * ```typescript\n * const did: DID = \"did:plc:ewvi7nxzyoun6zhxrhs64oiz\";\n * const webDid: DID = \"did:web:example.com\";\n * ```\n *\n * @see https://atproto.com/specs/did for DID specification\n */\nexport type DID = string;\n\n/**\n * OAuth session with DPoP (Demonstrating Proof of Possession) support.\n *\n * This type represents an authenticated user session. It wraps the\n * `@atproto/oauth-client-node` OAuthSession and contains:\n * - Access token for API requests\n * - Refresh token for obtaining new access tokens\n * - DPoP key pair for proof-of-possession\n * - User's DID and other identity information\n *\n * @remarks\n * Sessions are managed by the SDK and automatically refresh when tokens expire.\n * Store the user's DID to restore sessions later with {@link ATProtoSDK.restoreSession}.\n *\n * Key properties from OAuthSession:\n * - `did` or `sub`: The user's DID\n * - `handle`: The user's handle (e.g., \"user.bsky.social\")\n *\n * @example\n * ```typescript\n * const session = await sdk.callback(params);\n *\n * // Access user identity\n * console.log(`Logged in as: ${session.did}`);\n *\n * // Use session for repository operations\n * const repo = sdk.repository(session);\n * ```\n *\n * @see https://atproto.com/specs/oauth for OAuth specification\n */\nexport type Session = OAuthSession;\n\n/**\n * Zod schema for collaborator permissions in SDS repositories.\n *\n * Defines the granular permissions a collaborator can have on a shared repository.\n * Permissions follow a hierarchical model where higher-level permissions\n * typically imply lower-level ones.\n */\nexport const CollaboratorPermissionsSchema = z.object({\n /**\n * Can read/view records in the repository.\n * This is the most basic permission level.\n */\n read: z.boolean(),\n\n /**\n * Can create new records in the repository.\n * Typically implies `read` permission.\n */\n create: z.boolean(),\n\n /**\n * Can modify existing records in the repository.\n * Typically implies `read` and `create` permissions.\n */\n update: z.boolean(),\n\n /**\n * Can delete records from the repository.\n * Typically implies `read`, `create`, and `update` permissions.\n */\n delete: z.boolean(),\n\n /**\n * Can manage collaborators and their permissions.\n * Administrative permission that allows inviting/removing collaborators.\n */\n admin: z.boolean(),\n\n /**\n * Full ownership of the repository.\n * Owners have all permissions and cannot be removed by other admins.\n * There must always be at least one owner.\n */\n owner: z.boolean(),\n});\n\n/**\n * Collaborator permissions for SDS (Shared Data Server) repositories.\n *\n * These permissions control what actions a collaborator can perform\n * on records within a shared repository.\n *\n * @example\n * ```typescript\n * // Read-only collaborator\n * const readOnlyPerms: CollaboratorPermissions = {\n * read: true,\n * create: false,\n * update: false,\n * delete: false,\n * admin: false,\n * owner: false,\n * };\n *\n * // Editor collaborator\n * const editorPerms: CollaboratorPermissions = {\n * read: true,\n * create: true,\n * update: true,\n * delete: false,\n * admin: false,\n * owner: false,\n * };\n *\n * // Admin collaborator\n * const adminPerms: CollaboratorPermissions = {\n * read: true,\n * create: true,\n * update: true,\n * delete: true,\n * admin: true,\n * owner: false,\n * };\n * ```\n */\nexport type CollaboratorPermissions = z.infer<typeof CollaboratorPermissionsSchema>;\n\n/**\n * Zod schema for SDS organization data.\n *\n * Organizations are top-level entities in SDS that can own repositories\n * and have multiple collaborators with different permission levels.\n */\nexport const OrganizationSchema = z.object({\n /**\n * The organization's DID - unique identifier.\n * Format: \"did:plc:...\" or \"did:web:...\"\n */\n did: z.string(),\n\n /**\n * The organization's handle - human-readable identifier.\n * Format: \"orgname.sds.hypercerts.org\" or similar\n */\n handle: z.string(),\n\n /**\n * Display name for the organization.\n */\n name: z.string(),\n\n /**\n * Optional description of the organization's purpose.\n */\n description: z.string().optional(),\n\n /**\n * ISO 8601 timestamp when the organization was created.\n * Format: \"2024-01-15T10:30:00.000Z\"\n */\n createdAt: z.string(),\n\n /**\n * The current user's permissions within this organization.\n */\n permissions: CollaboratorPermissionsSchema,\n\n /**\n * How the current user relates to this organization.\n * - `\"owner\"`: User created or owns the organization\n * - `\"collaborator\"`: User was invited to collaborate\n */\n accessType: z.enum([\"owner\", \"collaborator\"]),\n});\n\n/**\n * SDS Organization entity.\n *\n * Represents an organization on a Shared Data Server. Organizations\n * provide a way to group repositories and manage access for teams.\n *\n * @example\n * ```typescript\n * const org: Organization = {\n * did: \"did:plc:org123abc\",\n * handle: \"my-team.sds.hypercerts.org\",\n * name: \"My Team\",\n * description: \"A team working on impact certificates\",\n * createdAt: \"2024-01-15T10:30:00.000Z\",\n * permissions: {\n * read: true,\n * create: true,\n * update: true,\n * delete: true,\n * admin: true,\n * owner: true,\n * },\n * accessType: \"owner\",\n * };\n * ```\n */\nexport type Organization = z.infer<typeof OrganizationSchema>;\n\n/**\n * Zod schema for collaborator data.\n *\n * Represents a user who has been granted access to a shared repository\n * or organization with specific permissions.\n */\nexport const CollaboratorSchema = z.object({\n /**\n * The collaborator's DID - their unique identifier.\n * Format: \"did:plc:...\" or \"did:web:...\"\n */\n userDid: z.string(),\n\n /**\n * The permissions granted to this collaborator.\n */\n permissions: CollaboratorPermissionsSchema,\n\n /**\n * DID of the user who granted these permissions.\n * Useful for audit trails.\n */\n grantedBy: z.string(),\n\n /**\n * ISO 8601 timestamp when permissions were granted.\n * Format: \"2024-01-15T10:30:00.000Z\"\n */\n grantedAt: z.string(),\n\n /**\n * ISO 8601 timestamp when permissions were revoked, if applicable.\n * Undefined if the collaborator is still active.\n */\n revokedAt: z.string().optional(),\n});\n\n/**\n * Collaborator information for SDS repositories.\n *\n * Represents a user who has been granted access to collaborate on\n * a shared repository or organization.\n *\n * @example\n * ```typescript\n * const collaborator: Collaborator = {\n * userDid: \"did:plc:user456def\",\n * permissions: {\n * read: true,\n * create: true,\n * update: true,\n * delete: false,\n * admin: false,\n * owner: false,\n * },\n * grantedBy: \"did:plc:owner123abc\",\n * grantedAt: \"2024-02-01T14:00:00.000Z\",\n * };\n * ```\n */\nexport type Collaborator = z.infer<typeof CollaboratorSchema>;\n"],"names":["z"],"mappings":"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"}
1
+ {"version":3,"file":"types.cjs","sources":["../src/core/config.ts","../src/core/types.ts"],"sourcesContent":["import { z } from \"zod\";\nimport type { SessionStore, StateStore, CacheInterface, LoggerInterface } from \"./interfaces.js\";\n\n/**\n * Zod schema for OAuth configuration validation.\n *\n * @remarks\n * All URLs must be valid and use HTTPS in production. The `jwkPrivate` field\n * should contain the private key in JWK (JSON Web Key) format as a string.\n */\nexport const OAuthConfigSchema = z.object({\n /**\n * URL to the OAuth client metadata JSON document.\n * This document describes your application to the authorization server.\n *\n * @see https://atproto.com/specs/oauth#client-metadata\n */\n clientId: z.string().url(),\n\n /**\n * URL where users are redirected after authentication.\n * Must match one of the redirect URIs in your client metadata.\n */\n redirectUri: z.string().url(),\n\n /**\n * OAuth scopes to request, space-separated.\n * Common scopes: \"atproto\", \"transition:generic\"\n */\n scope: z.string(),\n\n /**\n * URL to your public JWKS (JSON Web Key Set) endpoint.\n * Used by the authorization server to verify your client's signatures.\n */\n jwksUri: z.string().url(),\n\n /**\n * Private JWK (JSON Web Key) as a JSON string.\n * Used for signing DPoP proofs and client assertions.\n *\n * @remarks\n * This should be kept secret and never exposed to clients.\n * Typically loaded from environment variables or a secrets manager.\n */\n jwkPrivate: z.string(),\n});\n\n/**\n * Zod schema for server URL configuration.\n *\n * @remarks\n * At least one server (PDS or SDS) should be configured for the SDK to be useful.\n */\nexport const ServerConfigSchema = z.object({\n /**\n * Personal Data Server URL - the user's own AT Protocol server.\n * This is the primary server for user data operations.\n *\n * @example \"https://bsky.social\"\n */\n pds: z.string().url().optional(),\n\n /**\n * Shared Data Server URL - for collaborative data storage.\n * Required for collaborator and organization operations.\n *\n * @example \"https://sds.hypercerts.org\"\n */\n sds: z.string().url().optional(),\n});\n\n/**\n * Zod schema for timeout configuration.\n *\n * @remarks\n * All timeout values are in milliseconds.\n */\nexport const TimeoutConfigSchema = z.object({\n /**\n * Timeout for fetching PDS metadata during identity resolution.\n * @default 5000 (5 seconds, set by OAuthClient)\n */\n pdsMetadata: z.number().positive().optional(),\n\n /**\n * Timeout for general API requests to PDS/SDS.\n * @default 30000 (30 seconds)\n */\n apiRequests: z.number().positive().optional(),\n});\n\n/**\n * Zod schema for SDK configuration validation.\n *\n * @remarks\n * This schema validates only the primitive/serializable parts of the configuration.\n * Storage interfaces ({@link SessionStore}, {@link StateStore}) cannot be validated\n * with Zod as they are runtime objects.\n */\nexport const ATProtoSDKConfigSchema = z.object({\n oauth: OAuthConfigSchema,\n servers: ServerConfigSchema.optional(),\n timeouts: TimeoutConfigSchema.optional(),\n});\n\n/**\n * Configuration options for the ATProto SDK.\n *\n * This interface defines all configuration needed to initialize the SDK,\n * including OAuth credentials, server endpoints, and optional customizations.\n *\n * @example Minimal configuration\n * ```typescript\n * const config: ATProtoSDKConfig = {\n * oauth: {\n * clientId: \"https://my-app.com/client-metadata.json\",\n * redirectUri: \"https://my-app.com/callback\",\n * scope: \"atproto transition:generic\",\n * jwksUri: \"https://my-app.com/.well-known/jwks.json\",\n * jwkPrivate: process.env.JWK_PRIVATE_KEY!,\n * },\n * servers: {\n * pds: \"https://bsky.social\",\n * },\n * };\n * ```\n *\n * @example Full configuration with custom storage\n * ```typescript\n * const config: ATProtoSDKConfig = {\n * oauth: { ... },\n * servers: {\n * pds: \"https://bsky.social\",\n * sds: \"https://sds.hypercerts.org\",\n * },\n * storage: {\n * sessionStore: new RedisSessionStore(redisClient),\n * stateStore: new RedisStateStore(redisClient),\n * },\n * timeouts: {\n * pdsMetadata: 5000,\n * apiRequests: 30000,\n * },\n * logger: console,\n * };\n * ```\n */\nexport interface ATProtoSDKConfig {\n /**\n * OAuth 2.0 configuration for authentication.\n *\n * Required fields for the OAuth flow with DPoP (Demonstrating Proof of Possession).\n * Your application must host the client metadata and JWKS endpoints.\n *\n * @see https://atproto.com/specs/oauth for AT Protocol OAuth specification\n */\n oauth: z.infer<typeof OAuthConfigSchema>;\n\n /**\n * Server URLs for PDS and SDS connections.\n *\n * - **PDS**: Personal Data Server - user's own data storage\n * - **SDS**: Shared Data Server - collaborative storage with access control\n */\n servers?: z.infer<typeof ServerConfigSchema>;\n\n /**\n * Storage adapters for persisting OAuth sessions and state.\n *\n * If not provided, in-memory implementations are used automatically.\n * **Warning**: In-memory storage is lost on process restart - use persistent\n * storage (Redis, database, etc.) in production.\n *\n * @example\n * ```typescript\n * storage: {\n * sessionStore: new RedisSessionStore(redis),\n * stateStore: new RedisStateStore(redis),\n * }\n * ```\n */\n storage?: {\n /**\n * Persistent storage for OAuth sessions.\n * Sessions contain access tokens, refresh tokens, and DPoP keys.\n */\n sessionStore?: SessionStore;\n\n /**\n * Temporary storage for OAuth state during the authorization flow.\n * State is short-lived and used for PKCE and CSRF protection.\n */\n stateStore?: StateStore;\n };\n\n /**\n * Custom fetch implementation for HTTP requests.\n *\n * Use this to add custom headers, logging, or to use a different HTTP client.\n * Must be compatible with the standard Fetch API.\n *\n * @example\n * ```typescript\n * fetch: async (url, init) => {\n * console.log(`Fetching: ${url}`);\n * return globalThis.fetch(url, init);\n * }\n * ```\n */\n fetch?: typeof fetch;\n\n /**\n * Timeout configuration for network requests.\n * Values are in milliseconds.\n */\n timeouts?: z.infer<typeof TimeoutConfigSchema>;\n\n /**\n * Cache for profiles, metadata, and other frequently accessed data.\n *\n * Implementing caching can significantly reduce API calls and improve performance.\n * The SDK does not provide a default cache - you must implement {@link CacheInterface}.\n */\n cache?: CacheInterface;\n\n /**\n * Logger for debugging and observability.\n *\n * The logger receives debug, info, warn, and error messages from the SDK.\n * Compatible with `console` or any logger implementing {@link LoggerInterface}.\n *\n * @example\n * ```typescript\n * logger: console\n * // or\n * logger: pino()\n * // or\n * logger: winston.createLogger({ ... })\n * ```\n */\n logger?: LoggerInterface;\n}\n","import type { OAuthSession } from \"@atproto/oauth-client-node\";\nimport { z } from \"zod\";\n\n/**\n * Decentralized Identifier (DID) - a unique, persistent identifier for AT Protocol users.\n *\n * DIDs are the canonical identifier for users in the AT Protocol ecosystem.\n * Unlike handles which can change, DIDs remain constant for the lifetime of an account.\n *\n * @remarks\n * AT Protocol supports multiple DID methods:\n * - `did:plc:` - PLC (Public Ledger of Credentials) DIDs, most common for Bluesky users\n * - `did:web:` - Web DIDs, resolved via HTTPS\n *\n * @example\n * ```typescript\n * const did: DID = \"did:plc:ewvi7nxzyoun6zhxrhs64oiz\";\n * const webDid: DID = \"did:web:example.com\";\n * ```\n *\n * @see https://atproto.com/specs/did for DID specification\n */\nexport type DID = string;\n\n/**\n * OAuth session with DPoP (Demonstrating Proof of Possession) support.\n *\n * This type represents an authenticated user session. It wraps the\n * `@atproto/oauth-client-node` OAuthSession and contains:\n * - Access token for API requests\n * - Refresh token for obtaining new access tokens\n * - DPoP key pair for proof-of-possession\n * - User's DID and other identity information\n *\n * @remarks\n * Sessions are managed by the SDK and automatically refresh when tokens expire.\n * Store the user's DID to restore sessions later with {@link ATProtoSDK.restoreSession}.\n *\n * Key properties from OAuthSession:\n * - `did` or `sub`: The user's DID\n * - `handle`: The user's handle (e.g., \"user.bsky.social\")\n *\n * @example\n * ```typescript\n * const session = await sdk.callback(params);\n *\n * // Access user identity\n * console.log(`Logged in as: ${session.did}`);\n *\n * // Use session for repository operations\n * const repo = sdk.repository(session);\n * ```\n *\n * @see https://atproto.com/specs/oauth for OAuth specification\n */\nexport type Session = OAuthSession;\n\n/**\n * Zod schema for collaborator permissions in SDS repositories.\n *\n * Defines the granular permissions a collaborator can have on a shared repository.\n * Permissions follow a hierarchical model where higher-level permissions\n * typically imply lower-level ones.\n */\nexport const CollaboratorPermissionsSchema = z.object({\n /**\n * Can read/view records in the repository.\n * This is the most basic permission level.\n */\n read: z.boolean(),\n\n /**\n * Can create new records in the repository.\n * Typically implies `read` permission.\n */\n create: z.boolean(),\n\n /**\n * Can modify existing records in the repository.\n * Typically implies `read` and `create` permissions.\n */\n update: z.boolean(),\n\n /**\n * Can delete records from the repository.\n * Typically implies `read`, `create`, and `update` permissions.\n */\n delete: z.boolean(),\n\n /**\n * Can manage collaborators and their permissions.\n * Administrative permission that allows inviting/removing collaborators.\n */\n admin: z.boolean(),\n\n /**\n * Full ownership of the repository.\n * Owners have all permissions and cannot be removed by other admins.\n * There must always be at least one owner.\n */\n owner: z.boolean(),\n});\n\n/**\n * Collaborator permissions for SDS (Shared Data Server) repositories.\n *\n * These permissions control what actions a collaborator can perform\n * on records within a shared repository.\n *\n * @example\n * ```typescript\n * // Read-only collaborator\n * const readOnlyPerms: CollaboratorPermissions = {\n * read: true,\n * create: false,\n * update: false,\n * delete: false,\n * admin: false,\n * owner: false,\n * };\n *\n * // Editor collaborator\n * const editorPerms: CollaboratorPermissions = {\n * read: true,\n * create: true,\n * update: true,\n * delete: false,\n * admin: false,\n * owner: false,\n * };\n *\n * // Admin collaborator\n * const adminPerms: CollaboratorPermissions = {\n * read: true,\n * create: true,\n * update: true,\n * delete: true,\n * admin: true,\n * owner: false,\n * };\n * ```\n */\nexport type CollaboratorPermissions = z.infer<typeof CollaboratorPermissionsSchema>;\n\n/**\n * Zod schema for SDS organization data.\n *\n * Organizations are top-level entities in SDS that can own repositories\n * and have multiple collaborators with different permission levels.\n */\nexport const OrganizationSchema = z.object({\n /**\n * The organization's DID - unique identifier.\n * Format: \"did:plc:...\" or \"did:web:...\"\n */\n did: z.string(),\n\n /**\n * The organization's handle - human-readable identifier.\n * Format: \"orgname.sds.hypercerts.org\" or similar\n */\n handle: z.string(),\n\n /**\n * Display name for the organization.\n */\n name: z.string(),\n\n /**\n * Optional description of the organization's purpose.\n */\n description: z.string().optional(),\n\n /**\n * ISO 8601 timestamp when the organization was created.\n * Format: \"2024-01-15T10:30:00.000Z\"\n */\n createdAt: z.string(),\n\n /**\n * The current user's permissions within this organization.\n */\n permissions: CollaboratorPermissionsSchema,\n\n /**\n * How the current user relates to this organization.\n * - `\"owner\"`: User created or owns the organization\n * - `\"shared\"`: User was invited to collaborate (has permissions)\n * - `\"none\"`: User has no access to this organization\n */\n accessType: z.enum([\"owner\", \"shared\", \"none\"]),\n});\n\n/**\n * SDS Organization entity.\n *\n * Represents an organization on a Shared Data Server. Organizations\n * provide a way to group repositories and manage access for teams.\n *\n * @example\n * ```typescript\n * const org: Organization = {\n * did: \"did:plc:org123abc\",\n * handle: \"my-team.sds.hypercerts.org\",\n * name: \"My Team\",\n * description: \"A team working on impact certificates\",\n * createdAt: \"2024-01-15T10:30:00.000Z\",\n * permissions: {\n * read: true,\n * create: true,\n * update: true,\n * delete: true,\n * admin: true,\n * owner: true,\n * },\n * accessType: \"owner\",\n * };\n * ```\n */\nexport type Organization = z.infer<typeof OrganizationSchema>;\n\n/**\n * Zod schema for collaborator data.\n *\n * Represents a user who has been granted access to a shared repository\n * or organization with specific permissions.\n */\nexport const CollaboratorSchema = z.object({\n /**\n * The collaborator's DID - their unique identifier.\n * Format: \"did:plc:...\" or \"did:web:...\"\n */\n userDid: z.string(),\n\n /**\n * The permissions granted to this collaborator.\n */\n permissions: CollaboratorPermissionsSchema,\n\n /**\n * DID of the user who granted these permissions.\n * Useful for audit trails.\n */\n grantedBy: z.string(),\n\n /**\n * ISO 8601 timestamp when permissions were granted.\n * Format: \"2024-01-15T10:30:00.000Z\"\n */\n grantedAt: z.string(),\n\n /**\n * ISO 8601 timestamp when permissions were revoked, if applicable.\n * Undefined if the collaborator is still active.\n */\n revokedAt: z.string().optional(),\n});\n\n/**\n * Collaborator information for SDS repositories.\n *\n * Represents a user who has been granted access to collaborate on\n * a shared repository or organization.\n *\n * @example\n * ```typescript\n * const collaborator: Collaborator = {\n * userDid: \"did:plc:user456def\",\n * permissions: {\n * read: true,\n * create: true,\n * update: true,\n * delete: false,\n * admin: false,\n * owner: false,\n * },\n * grantedBy: \"did:plc:owner123abc\",\n * grantedAt: \"2024-02-01T14:00:00.000Z\",\n * };\n * ```\n */\nexport type Collaborator = z.infer<typeof CollaboratorSchema>;\n"],"names":["z"],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -232,9 +232,10 @@ declare const OrganizationSchema: z.ZodObject<{
232
232
  /**
233
233
  * How the current user relates to this organization.
234
234
  * - `"owner"`: User created or owns the organization
235
- * - `"collaborator"`: User was invited to collaborate
235
+ * - `"shared"`: User was invited to collaborate (has permissions)
236
+ * - `"none"`: User has no access to this organization
236
237
  */
237
- accessType: z.ZodEnum<["owner", "collaborator"]>;
238
+ accessType: z.ZodEnum<["owner", "shared", "none"]>;
238
239
  }, "strip", z.ZodTypeAny, {
239
240
  did: string;
240
241
  handle: string;
@@ -248,7 +249,7 @@ declare const OrganizationSchema: z.ZodObject<{
248
249
  admin: boolean;
249
250
  owner: boolean;
250
251
  };
251
- accessType: "owner" | "collaborator";
252
+ accessType: "owner" | "shared" | "none";
252
253
  description?: string | undefined;
253
254
  }, {
254
255
  did: string;
@@ -263,7 +264,7 @@ declare const OrganizationSchema: z.ZodObject<{
263
264
  admin: boolean;
264
265
  owner: boolean;
265
266
  };
266
- accessType: "owner" | "collaborator";
267
+ accessType: "owner" | "shared" | "none";
267
268
  description?: string | undefined;
268
269
  }>;
269
270
  /**
@@ -1176,7 +1177,7 @@ interface OrganizationInfo {
1176
1177
  name: string;
1177
1178
  description?: string;
1178
1179
  createdAt: string;
1179
- accessType: "owner" | "collaborator";
1180
+ accessType: "owner" | "shared" | "none";
1180
1181
  permissions: CollaboratorPermissions;
1181
1182
  collaboratorCount?: number;
1182
1183
  profile?: {
@@ -2027,9 +2028,18 @@ interface CollaboratorOperations {
2027
2028
  /**
2028
2029
  * Lists all collaborators on the repository.
2029
2030
  *
2030
- * @returns Promise resolving to array of access grants
2031
+ * @param params - Optional pagination parameters
2032
+ * @param params.limit - Maximum number of results (1-100, default 50)
2033
+ * @param params.cursor - Pagination cursor from previous response
2034
+ * @returns Promise resolving to collaborators and optional cursor
2031
2035
  */
2032
- list(): Promise<RepositoryAccessGrant[]>;
2036
+ list(params?: {
2037
+ limit?: number;
2038
+ cursor?: string;
2039
+ }): Promise<{
2040
+ collaborators: RepositoryAccessGrant[];
2041
+ cursor?: string;
2042
+ }>;
2033
2043
  /**
2034
2044
  * Checks if a user has any access to the repository.
2035
2045
  *
@@ -2108,9 +2118,18 @@ interface OrganizationOperations {
2108
2118
  /**
2109
2119
  * Lists organizations the current user has access to.
2110
2120
  *
2111
- * @returns Promise resolving to array of organization info
2121
+ * @param params - Optional pagination parameters
2122
+ * @param params.limit - Maximum number of results (1-100, default 50)
2123
+ * @param params.cursor - Pagination cursor from previous response
2124
+ * @returns Promise resolving to organizations and optional cursor
2112
2125
  */
2113
- list(): Promise<OrganizationInfo[]>;
2126
+ list(params?: {
2127
+ limit?: number;
2128
+ cursor?: string;
2129
+ }): Promise<{
2130
+ organizations: OrganizationInfo[];
2131
+ cursor?: string;
2132
+ }>;
2114
2133
  }
2115
2134
 
2116
2135
  /**
package/dist/types.mjs CHANGED
@@ -171,9 +171,10 @@ const OrganizationSchema = z.object({
171
171
  /**
172
172
  * How the current user relates to this organization.
173
173
  * - `"owner"`: User created or owns the organization
174
- * - `"collaborator"`: User was invited to collaborate
174
+ * - `"shared"`: User was invited to collaborate (has permissions)
175
+ * - `"none"`: User has no access to this organization
175
176
  */
176
- accessType: z.enum(["owner", "collaborator"]),
177
+ accessType: z.enum(["owner", "shared", "none"]),
177
178
  });
178
179
  /**
179
180
  * Zod schema for collaborator data.
@@ -1 +1 @@
1
- {"version":3,"file":"types.mjs","sources":["../src/core/config.ts","../src/core/types.ts"],"sourcesContent":["import { z } from \"zod\";\nimport type { SessionStore, StateStore, CacheInterface, LoggerInterface } from \"./interfaces.js\";\n\n/**\n * Zod schema for OAuth configuration validation.\n *\n * @remarks\n * All URLs must be valid and use HTTPS in production. The `jwkPrivate` field\n * should contain the private key in JWK (JSON Web Key) format as a string.\n */\nexport const OAuthConfigSchema = z.object({\n /**\n * URL to the OAuth client metadata JSON document.\n * This document describes your application to the authorization server.\n *\n * @see https://atproto.com/specs/oauth#client-metadata\n */\n clientId: z.string().url(),\n\n /**\n * URL where users are redirected after authentication.\n * Must match one of the redirect URIs in your client metadata.\n */\n redirectUri: z.string().url(),\n\n /**\n * OAuth scopes to request, space-separated.\n * Common scopes: \"atproto\", \"transition:generic\"\n */\n scope: z.string(),\n\n /**\n * URL to your public JWKS (JSON Web Key Set) endpoint.\n * Used by the authorization server to verify your client's signatures.\n */\n jwksUri: z.string().url(),\n\n /**\n * Private JWK (JSON Web Key) as a JSON string.\n * Used for signing DPoP proofs and client assertions.\n *\n * @remarks\n * This should be kept secret and never exposed to clients.\n * Typically loaded from environment variables or a secrets manager.\n */\n jwkPrivate: z.string(),\n});\n\n/**\n * Zod schema for server URL configuration.\n *\n * @remarks\n * At least one server (PDS or SDS) should be configured for the SDK to be useful.\n */\nexport const ServerConfigSchema = z.object({\n /**\n * Personal Data Server URL - the user's own AT Protocol server.\n * This is the primary server for user data operations.\n *\n * @example \"https://bsky.social\"\n */\n pds: z.string().url().optional(),\n\n /**\n * Shared Data Server URL - for collaborative data storage.\n * Required for collaborator and organization operations.\n *\n * @example \"https://sds.hypercerts.org\"\n */\n sds: z.string().url().optional(),\n});\n\n/**\n * Zod schema for timeout configuration.\n *\n * @remarks\n * All timeout values are in milliseconds.\n */\nexport const TimeoutConfigSchema = z.object({\n /**\n * Timeout for fetching PDS metadata during identity resolution.\n * @default 5000 (5 seconds, set by OAuthClient)\n */\n pdsMetadata: z.number().positive().optional(),\n\n /**\n * Timeout for general API requests to PDS/SDS.\n * @default 30000 (30 seconds)\n */\n apiRequests: z.number().positive().optional(),\n});\n\n/**\n * Zod schema for SDK configuration validation.\n *\n * @remarks\n * This schema validates only the primitive/serializable parts of the configuration.\n * Storage interfaces ({@link SessionStore}, {@link StateStore}) cannot be validated\n * with Zod as they are runtime objects.\n */\nexport const ATProtoSDKConfigSchema = z.object({\n oauth: OAuthConfigSchema,\n servers: ServerConfigSchema.optional(),\n timeouts: TimeoutConfigSchema.optional(),\n});\n\n/**\n * Configuration options for the ATProto SDK.\n *\n * This interface defines all configuration needed to initialize the SDK,\n * including OAuth credentials, server endpoints, and optional customizations.\n *\n * @example Minimal configuration\n * ```typescript\n * const config: ATProtoSDKConfig = {\n * oauth: {\n * clientId: \"https://my-app.com/client-metadata.json\",\n * redirectUri: \"https://my-app.com/callback\",\n * scope: \"atproto transition:generic\",\n * jwksUri: \"https://my-app.com/.well-known/jwks.json\",\n * jwkPrivate: process.env.JWK_PRIVATE_KEY!,\n * },\n * servers: {\n * pds: \"https://bsky.social\",\n * },\n * };\n * ```\n *\n * @example Full configuration with custom storage\n * ```typescript\n * const config: ATProtoSDKConfig = {\n * oauth: { ... },\n * servers: {\n * pds: \"https://bsky.social\",\n * sds: \"https://sds.hypercerts.org\",\n * },\n * storage: {\n * sessionStore: new RedisSessionStore(redisClient),\n * stateStore: new RedisStateStore(redisClient),\n * },\n * timeouts: {\n * pdsMetadata: 5000,\n * apiRequests: 30000,\n * },\n * logger: console,\n * };\n * ```\n */\nexport interface ATProtoSDKConfig {\n /**\n * OAuth 2.0 configuration for authentication.\n *\n * Required fields for the OAuth flow with DPoP (Demonstrating Proof of Possession).\n * Your application must host the client metadata and JWKS endpoints.\n *\n * @see https://atproto.com/specs/oauth for AT Protocol OAuth specification\n */\n oauth: z.infer<typeof OAuthConfigSchema>;\n\n /**\n * Server URLs for PDS and SDS connections.\n *\n * - **PDS**: Personal Data Server - user's own data storage\n * - **SDS**: Shared Data Server - collaborative storage with access control\n */\n servers?: z.infer<typeof ServerConfigSchema>;\n\n /**\n * Storage adapters for persisting OAuth sessions and state.\n *\n * If not provided, in-memory implementations are used automatically.\n * **Warning**: In-memory storage is lost on process restart - use persistent\n * storage (Redis, database, etc.) in production.\n *\n * @example\n * ```typescript\n * storage: {\n * sessionStore: new RedisSessionStore(redis),\n * stateStore: new RedisStateStore(redis),\n * }\n * ```\n */\n storage?: {\n /**\n * Persistent storage for OAuth sessions.\n * Sessions contain access tokens, refresh tokens, and DPoP keys.\n */\n sessionStore?: SessionStore;\n\n /**\n * Temporary storage for OAuth state during the authorization flow.\n * State is short-lived and used for PKCE and CSRF protection.\n */\n stateStore?: StateStore;\n };\n\n /**\n * Custom fetch implementation for HTTP requests.\n *\n * Use this to add custom headers, logging, or to use a different HTTP client.\n * Must be compatible with the standard Fetch API.\n *\n * @example\n * ```typescript\n * fetch: async (url, init) => {\n * console.log(`Fetching: ${url}`);\n * return globalThis.fetch(url, init);\n * }\n * ```\n */\n fetch?: typeof fetch;\n\n /**\n * Timeout configuration for network requests.\n * Values are in milliseconds.\n */\n timeouts?: z.infer<typeof TimeoutConfigSchema>;\n\n /**\n * Cache for profiles, metadata, and other frequently accessed data.\n *\n * Implementing caching can significantly reduce API calls and improve performance.\n * The SDK does not provide a default cache - you must implement {@link CacheInterface}.\n */\n cache?: CacheInterface;\n\n /**\n * Logger for debugging and observability.\n *\n * The logger receives debug, info, warn, and error messages from the SDK.\n * Compatible with `console` or any logger implementing {@link LoggerInterface}.\n *\n * @example\n * ```typescript\n * logger: console\n * // or\n * logger: pino()\n * // or\n * logger: winston.createLogger({ ... })\n * ```\n */\n logger?: LoggerInterface;\n}\n","import type { OAuthSession } from \"@atproto/oauth-client-node\";\nimport { z } from \"zod\";\n\n/**\n * Decentralized Identifier (DID) - a unique, persistent identifier for AT Protocol users.\n *\n * DIDs are the canonical identifier for users in the AT Protocol ecosystem.\n * Unlike handles which can change, DIDs remain constant for the lifetime of an account.\n *\n * @remarks\n * AT Protocol supports multiple DID methods:\n * - `did:plc:` - PLC (Public Ledger of Credentials) DIDs, most common for Bluesky users\n * - `did:web:` - Web DIDs, resolved via HTTPS\n *\n * @example\n * ```typescript\n * const did: DID = \"did:plc:ewvi7nxzyoun6zhxrhs64oiz\";\n * const webDid: DID = \"did:web:example.com\";\n * ```\n *\n * @see https://atproto.com/specs/did for DID specification\n */\nexport type DID = string;\n\n/**\n * OAuth session with DPoP (Demonstrating Proof of Possession) support.\n *\n * This type represents an authenticated user session. It wraps the\n * `@atproto/oauth-client-node` OAuthSession and contains:\n * - Access token for API requests\n * - Refresh token for obtaining new access tokens\n * - DPoP key pair for proof-of-possession\n * - User's DID and other identity information\n *\n * @remarks\n * Sessions are managed by the SDK and automatically refresh when tokens expire.\n * Store the user's DID to restore sessions later with {@link ATProtoSDK.restoreSession}.\n *\n * Key properties from OAuthSession:\n * - `did` or `sub`: The user's DID\n * - `handle`: The user's handle (e.g., \"user.bsky.social\")\n *\n * @example\n * ```typescript\n * const session = await sdk.callback(params);\n *\n * // Access user identity\n * console.log(`Logged in as: ${session.did}`);\n *\n * // Use session for repository operations\n * const repo = sdk.repository(session);\n * ```\n *\n * @see https://atproto.com/specs/oauth for OAuth specification\n */\nexport type Session = OAuthSession;\n\n/**\n * Zod schema for collaborator permissions in SDS repositories.\n *\n * Defines the granular permissions a collaborator can have on a shared repository.\n * Permissions follow a hierarchical model where higher-level permissions\n * typically imply lower-level ones.\n */\nexport const CollaboratorPermissionsSchema = z.object({\n /**\n * Can read/view records in the repository.\n * This is the most basic permission level.\n */\n read: z.boolean(),\n\n /**\n * Can create new records in the repository.\n * Typically implies `read` permission.\n */\n create: z.boolean(),\n\n /**\n * Can modify existing records in the repository.\n * Typically implies `read` and `create` permissions.\n */\n update: z.boolean(),\n\n /**\n * Can delete records from the repository.\n * Typically implies `read`, `create`, and `update` permissions.\n */\n delete: z.boolean(),\n\n /**\n * Can manage collaborators and their permissions.\n * Administrative permission that allows inviting/removing collaborators.\n */\n admin: z.boolean(),\n\n /**\n * Full ownership of the repository.\n * Owners have all permissions and cannot be removed by other admins.\n * There must always be at least one owner.\n */\n owner: z.boolean(),\n});\n\n/**\n * Collaborator permissions for SDS (Shared Data Server) repositories.\n *\n * These permissions control what actions a collaborator can perform\n * on records within a shared repository.\n *\n * @example\n * ```typescript\n * // Read-only collaborator\n * const readOnlyPerms: CollaboratorPermissions = {\n * read: true,\n * create: false,\n * update: false,\n * delete: false,\n * admin: false,\n * owner: false,\n * };\n *\n * // Editor collaborator\n * const editorPerms: CollaboratorPermissions = {\n * read: true,\n * create: true,\n * update: true,\n * delete: false,\n * admin: false,\n * owner: false,\n * };\n *\n * // Admin collaborator\n * const adminPerms: CollaboratorPermissions = {\n * read: true,\n * create: true,\n * update: true,\n * delete: true,\n * admin: true,\n * owner: false,\n * };\n * ```\n */\nexport type CollaboratorPermissions = z.infer<typeof CollaboratorPermissionsSchema>;\n\n/**\n * Zod schema for SDS organization data.\n *\n * Organizations are top-level entities in SDS that can own repositories\n * and have multiple collaborators with different permission levels.\n */\nexport const OrganizationSchema = z.object({\n /**\n * The organization's DID - unique identifier.\n * Format: \"did:plc:...\" or \"did:web:...\"\n */\n did: z.string(),\n\n /**\n * The organization's handle - human-readable identifier.\n * Format: \"orgname.sds.hypercerts.org\" or similar\n */\n handle: z.string(),\n\n /**\n * Display name for the organization.\n */\n name: z.string(),\n\n /**\n * Optional description of the organization's purpose.\n */\n description: z.string().optional(),\n\n /**\n * ISO 8601 timestamp when the organization was created.\n * Format: \"2024-01-15T10:30:00.000Z\"\n */\n createdAt: z.string(),\n\n /**\n * The current user's permissions within this organization.\n */\n permissions: CollaboratorPermissionsSchema,\n\n /**\n * How the current user relates to this organization.\n * - `\"owner\"`: User created or owns the organization\n * - `\"collaborator\"`: User was invited to collaborate\n */\n accessType: z.enum([\"owner\", \"collaborator\"]),\n});\n\n/**\n * SDS Organization entity.\n *\n * Represents an organization on a Shared Data Server. Organizations\n * provide a way to group repositories and manage access for teams.\n *\n * @example\n * ```typescript\n * const org: Organization = {\n * did: \"did:plc:org123abc\",\n * handle: \"my-team.sds.hypercerts.org\",\n * name: \"My Team\",\n * description: \"A team working on impact certificates\",\n * createdAt: \"2024-01-15T10:30:00.000Z\",\n * permissions: {\n * read: true,\n * create: true,\n * update: true,\n * delete: true,\n * admin: true,\n * owner: true,\n * },\n * accessType: \"owner\",\n * };\n * ```\n */\nexport type Organization = z.infer<typeof OrganizationSchema>;\n\n/**\n * Zod schema for collaborator data.\n *\n * Represents a user who has been granted access to a shared repository\n * or organization with specific permissions.\n */\nexport const CollaboratorSchema = z.object({\n /**\n * The collaborator's DID - their unique identifier.\n * Format: \"did:plc:...\" or \"did:web:...\"\n */\n userDid: z.string(),\n\n /**\n * The permissions granted to this collaborator.\n */\n permissions: CollaboratorPermissionsSchema,\n\n /**\n * DID of the user who granted these permissions.\n * Useful for audit trails.\n */\n grantedBy: z.string(),\n\n /**\n * ISO 8601 timestamp when permissions were granted.\n * Format: \"2024-01-15T10:30:00.000Z\"\n */\n grantedAt: z.string(),\n\n /**\n * ISO 8601 timestamp when permissions were revoked, if applicable.\n * Undefined if the collaborator is still active.\n */\n revokedAt: z.string().optional(),\n});\n\n/**\n * Collaborator information for SDS repositories.\n *\n * Represents a user who has been granted access to collaborate on\n * a shared repository or organization.\n *\n * @example\n * ```typescript\n * const collaborator: Collaborator = {\n * userDid: \"did:plc:user456def\",\n * permissions: {\n * read: true,\n * create: true,\n * update: true,\n * delete: false,\n * admin: false,\n * owner: false,\n * },\n * grantedBy: \"did:plc:owner123abc\",\n * grantedAt: \"2024-02-01T14:00:00.000Z\",\n * };\n * ```\n */\nexport type Collaborator = z.infer<typeof CollaboratorSchema>;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.mjs","sources":["../src/core/config.ts","../src/core/types.ts"],"sourcesContent":["import { z } from \"zod\";\nimport type { SessionStore, StateStore, CacheInterface, LoggerInterface } from \"./interfaces.js\";\n\n/**\n * Zod schema for OAuth configuration validation.\n *\n * @remarks\n * All URLs must be valid and use HTTPS in production. The `jwkPrivate` field\n * should contain the private key in JWK (JSON Web Key) format as a string.\n */\nexport const OAuthConfigSchema = z.object({\n /**\n * URL to the OAuth client metadata JSON document.\n * This document describes your application to the authorization server.\n *\n * @see https://atproto.com/specs/oauth#client-metadata\n */\n clientId: z.string().url(),\n\n /**\n * URL where users are redirected after authentication.\n * Must match one of the redirect URIs in your client metadata.\n */\n redirectUri: z.string().url(),\n\n /**\n * OAuth scopes to request, space-separated.\n * Common scopes: \"atproto\", \"transition:generic\"\n */\n scope: z.string(),\n\n /**\n * URL to your public JWKS (JSON Web Key Set) endpoint.\n * Used by the authorization server to verify your client's signatures.\n */\n jwksUri: z.string().url(),\n\n /**\n * Private JWK (JSON Web Key) as a JSON string.\n * Used for signing DPoP proofs and client assertions.\n *\n * @remarks\n * This should be kept secret and never exposed to clients.\n * Typically loaded from environment variables or a secrets manager.\n */\n jwkPrivate: z.string(),\n});\n\n/**\n * Zod schema for server URL configuration.\n *\n * @remarks\n * At least one server (PDS or SDS) should be configured for the SDK to be useful.\n */\nexport const ServerConfigSchema = z.object({\n /**\n * Personal Data Server URL - the user's own AT Protocol server.\n * This is the primary server for user data operations.\n *\n * @example \"https://bsky.social\"\n */\n pds: z.string().url().optional(),\n\n /**\n * Shared Data Server URL - for collaborative data storage.\n * Required for collaborator and organization operations.\n *\n * @example \"https://sds.hypercerts.org\"\n */\n sds: z.string().url().optional(),\n});\n\n/**\n * Zod schema for timeout configuration.\n *\n * @remarks\n * All timeout values are in milliseconds.\n */\nexport const TimeoutConfigSchema = z.object({\n /**\n * Timeout for fetching PDS metadata during identity resolution.\n * @default 5000 (5 seconds, set by OAuthClient)\n */\n pdsMetadata: z.number().positive().optional(),\n\n /**\n * Timeout for general API requests to PDS/SDS.\n * @default 30000 (30 seconds)\n */\n apiRequests: z.number().positive().optional(),\n});\n\n/**\n * Zod schema for SDK configuration validation.\n *\n * @remarks\n * This schema validates only the primitive/serializable parts of the configuration.\n * Storage interfaces ({@link SessionStore}, {@link StateStore}) cannot be validated\n * with Zod as they are runtime objects.\n */\nexport const ATProtoSDKConfigSchema = z.object({\n oauth: OAuthConfigSchema,\n servers: ServerConfigSchema.optional(),\n timeouts: TimeoutConfigSchema.optional(),\n});\n\n/**\n * Configuration options for the ATProto SDK.\n *\n * This interface defines all configuration needed to initialize the SDK,\n * including OAuth credentials, server endpoints, and optional customizations.\n *\n * @example Minimal configuration\n * ```typescript\n * const config: ATProtoSDKConfig = {\n * oauth: {\n * clientId: \"https://my-app.com/client-metadata.json\",\n * redirectUri: \"https://my-app.com/callback\",\n * scope: \"atproto transition:generic\",\n * jwksUri: \"https://my-app.com/.well-known/jwks.json\",\n * jwkPrivate: process.env.JWK_PRIVATE_KEY!,\n * },\n * servers: {\n * pds: \"https://bsky.social\",\n * },\n * };\n * ```\n *\n * @example Full configuration with custom storage\n * ```typescript\n * const config: ATProtoSDKConfig = {\n * oauth: { ... },\n * servers: {\n * pds: \"https://bsky.social\",\n * sds: \"https://sds.hypercerts.org\",\n * },\n * storage: {\n * sessionStore: new RedisSessionStore(redisClient),\n * stateStore: new RedisStateStore(redisClient),\n * },\n * timeouts: {\n * pdsMetadata: 5000,\n * apiRequests: 30000,\n * },\n * logger: console,\n * };\n * ```\n */\nexport interface ATProtoSDKConfig {\n /**\n * OAuth 2.0 configuration for authentication.\n *\n * Required fields for the OAuth flow with DPoP (Demonstrating Proof of Possession).\n * Your application must host the client metadata and JWKS endpoints.\n *\n * @see https://atproto.com/specs/oauth for AT Protocol OAuth specification\n */\n oauth: z.infer<typeof OAuthConfigSchema>;\n\n /**\n * Server URLs for PDS and SDS connections.\n *\n * - **PDS**: Personal Data Server - user's own data storage\n * - **SDS**: Shared Data Server - collaborative storage with access control\n */\n servers?: z.infer<typeof ServerConfigSchema>;\n\n /**\n * Storage adapters for persisting OAuth sessions and state.\n *\n * If not provided, in-memory implementations are used automatically.\n * **Warning**: In-memory storage is lost on process restart - use persistent\n * storage (Redis, database, etc.) in production.\n *\n * @example\n * ```typescript\n * storage: {\n * sessionStore: new RedisSessionStore(redis),\n * stateStore: new RedisStateStore(redis),\n * }\n * ```\n */\n storage?: {\n /**\n * Persistent storage for OAuth sessions.\n * Sessions contain access tokens, refresh tokens, and DPoP keys.\n */\n sessionStore?: SessionStore;\n\n /**\n * Temporary storage for OAuth state during the authorization flow.\n * State is short-lived and used for PKCE and CSRF protection.\n */\n stateStore?: StateStore;\n };\n\n /**\n * Custom fetch implementation for HTTP requests.\n *\n * Use this to add custom headers, logging, or to use a different HTTP client.\n * Must be compatible with the standard Fetch API.\n *\n * @example\n * ```typescript\n * fetch: async (url, init) => {\n * console.log(`Fetching: ${url}`);\n * return globalThis.fetch(url, init);\n * }\n * ```\n */\n fetch?: typeof fetch;\n\n /**\n * Timeout configuration for network requests.\n * Values are in milliseconds.\n */\n timeouts?: z.infer<typeof TimeoutConfigSchema>;\n\n /**\n * Cache for profiles, metadata, and other frequently accessed data.\n *\n * Implementing caching can significantly reduce API calls and improve performance.\n * The SDK does not provide a default cache - you must implement {@link CacheInterface}.\n */\n cache?: CacheInterface;\n\n /**\n * Logger for debugging and observability.\n *\n * The logger receives debug, info, warn, and error messages from the SDK.\n * Compatible with `console` or any logger implementing {@link LoggerInterface}.\n *\n * @example\n * ```typescript\n * logger: console\n * // or\n * logger: pino()\n * // or\n * logger: winston.createLogger({ ... })\n * ```\n */\n logger?: LoggerInterface;\n}\n","import type { OAuthSession } from \"@atproto/oauth-client-node\";\nimport { z } from \"zod\";\n\n/**\n * Decentralized Identifier (DID) - a unique, persistent identifier for AT Protocol users.\n *\n * DIDs are the canonical identifier for users in the AT Protocol ecosystem.\n * Unlike handles which can change, DIDs remain constant for the lifetime of an account.\n *\n * @remarks\n * AT Protocol supports multiple DID methods:\n * - `did:plc:` - PLC (Public Ledger of Credentials) DIDs, most common for Bluesky users\n * - `did:web:` - Web DIDs, resolved via HTTPS\n *\n * @example\n * ```typescript\n * const did: DID = \"did:plc:ewvi7nxzyoun6zhxrhs64oiz\";\n * const webDid: DID = \"did:web:example.com\";\n * ```\n *\n * @see https://atproto.com/specs/did for DID specification\n */\nexport type DID = string;\n\n/**\n * OAuth session with DPoP (Demonstrating Proof of Possession) support.\n *\n * This type represents an authenticated user session. It wraps the\n * `@atproto/oauth-client-node` OAuthSession and contains:\n * - Access token for API requests\n * - Refresh token for obtaining new access tokens\n * - DPoP key pair for proof-of-possession\n * - User's DID and other identity information\n *\n * @remarks\n * Sessions are managed by the SDK and automatically refresh when tokens expire.\n * Store the user's DID to restore sessions later with {@link ATProtoSDK.restoreSession}.\n *\n * Key properties from OAuthSession:\n * - `did` or `sub`: The user's DID\n * - `handle`: The user's handle (e.g., \"user.bsky.social\")\n *\n * @example\n * ```typescript\n * const session = await sdk.callback(params);\n *\n * // Access user identity\n * console.log(`Logged in as: ${session.did}`);\n *\n * // Use session for repository operations\n * const repo = sdk.repository(session);\n * ```\n *\n * @see https://atproto.com/specs/oauth for OAuth specification\n */\nexport type Session = OAuthSession;\n\n/**\n * Zod schema for collaborator permissions in SDS repositories.\n *\n * Defines the granular permissions a collaborator can have on a shared repository.\n * Permissions follow a hierarchical model where higher-level permissions\n * typically imply lower-level ones.\n */\nexport const CollaboratorPermissionsSchema = z.object({\n /**\n * Can read/view records in the repository.\n * This is the most basic permission level.\n */\n read: z.boolean(),\n\n /**\n * Can create new records in the repository.\n * Typically implies `read` permission.\n */\n create: z.boolean(),\n\n /**\n * Can modify existing records in the repository.\n * Typically implies `read` and `create` permissions.\n */\n update: z.boolean(),\n\n /**\n * Can delete records from the repository.\n * Typically implies `read`, `create`, and `update` permissions.\n */\n delete: z.boolean(),\n\n /**\n * Can manage collaborators and their permissions.\n * Administrative permission that allows inviting/removing collaborators.\n */\n admin: z.boolean(),\n\n /**\n * Full ownership of the repository.\n * Owners have all permissions and cannot be removed by other admins.\n * There must always be at least one owner.\n */\n owner: z.boolean(),\n});\n\n/**\n * Collaborator permissions for SDS (Shared Data Server) repositories.\n *\n * These permissions control what actions a collaborator can perform\n * on records within a shared repository.\n *\n * @example\n * ```typescript\n * // Read-only collaborator\n * const readOnlyPerms: CollaboratorPermissions = {\n * read: true,\n * create: false,\n * update: false,\n * delete: false,\n * admin: false,\n * owner: false,\n * };\n *\n * // Editor collaborator\n * const editorPerms: CollaboratorPermissions = {\n * read: true,\n * create: true,\n * update: true,\n * delete: false,\n * admin: false,\n * owner: false,\n * };\n *\n * // Admin collaborator\n * const adminPerms: CollaboratorPermissions = {\n * read: true,\n * create: true,\n * update: true,\n * delete: true,\n * admin: true,\n * owner: false,\n * };\n * ```\n */\nexport type CollaboratorPermissions = z.infer<typeof CollaboratorPermissionsSchema>;\n\n/**\n * Zod schema for SDS organization data.\n *\n * Organizations are top-level entities in SDS that can own repositories\n * and have multiple collaborators with different permission levels.\n */\nexport const OrganizationSchema = z.object({\n /**\n * The organization's DID - unique identifier.\n * Format: \"did:plc:...\" or \"did:web:...\"\n */\n did: z.string(),\n\n /**\n * The organization's handle - human-readable identifier.\n * Format: \"orgname.sds.hypercerts.org\" or similar\n */\n handle: z.string(),\n\n /**\n * Display name for the organization.\n */\n name: z.string(),\n\n /**\n * Optional description of the organization's purpose.\n */\n description: z.string().optional(),\n\n /**\n * ISO 8601 timestamp when the organization was created.\n * Format: \"2024-01-15T10:30:00.000Z\"\n */\n createdAt: z.string(),\n\n /**\n * The current user's permissions within this organization.\n */\n permissions: CollaboratorPermissionsSchema,\n\n /**\n * How the current user relates to this organization.\n * - `\"owner\"`: User created or owns the organization\n * - `\"shared\"`: User was invited to collaborate (has permissions)\n * - `\"none\"`: User has no access to this organization\n */\n accessType: z.enum([\"owner\", \"shared\", \"none\"]),\n});\n\n/**\n * SDS Organization entity.\n *\n * Represents an organization on a Shared Data Server. Organizations\n * provide a way to group repositories and manage access for teams.\n *\n * @example\n * ```typescript\n * const org: Organization = {\n * did: \"did:plc:org123abc\",\n * handle: \"my-team.sds.hypercerts.org\",\n * name: \"My Team\",\n * description: \"A team working on impact certificates\",\n * createdAt: \"2024-01-15T10:30:00.000Z\",\n * permissions: {\n * read: true,\n * create: true,\n * update: true,\n * delete: true,\n * admin: true,\n * owner: true,\n * },\n * accessType: \"owner\",\n * };\n * ```\n */\nexport type Organization = z.infer<typeof OrganizationSchema>;\n\n/**\n * Zod schema for collaborator data.\n *\n * Represents a user who has been granted access to a shared repository\n * or organization with specific permissions.\n */\nexport const CollaboratorSchema = z.object({\n /**\n * The collaborator's DID - their unique identifier.\n * Format: \"did:plc:...\" or \"did:web:...\"\n */\n userDid: z.string(),\n\n /**\n * The permissions granted to this collaborator.\n */\n permissions: CollaboratorPermissionsSchema,\n\n /**\n * DID of the user who granted these permissions.\n * Useful for audit trails.\n */\n grantedBy: z.string(),\n\n /**\n * ISO 8601 timestamp when permissions were granted.\n * Format: \"2024-01-15T10:30:00.000Z\"\n */\n grantedAt: z.string(),\n\n /**\n * ISO 8601 timestamp when permissions were revoked, if applicable.\n * Undefined if the collaborator is still active.\n */\n revokedAt: z.string().optional(),\n});\n\n/**\n * Collaborator information for SDS repositories.\n *\n * Represents a user who has been granted access to collaborate on\n * a shared repository or organization.\n *\n * @example\n * ```typescript\n * const collaborator: Collaborator = {\n * userDid: \"did:plc:user456def\",\n * permissions: {\n * read: true,\n * create: true,\n * update: true,\n * delete: false,\n * admin: false,\n * owner: false,\n * },\n * grantedBy: \"did:plc:owner123abc\",\n * grantedAt: \"2024-02-01T14:00:00.000Z\",\n * };\n * ```\n */\nexport type Collaborator = z.infer<typeof CollaboratorSchema>;\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hypercerts-org/sdk-core",
3
- "version": "0.4.0-beta.0",
3
+ "version": "0.5.0-beta.0",
4
4
  "description": "Framework-agnostic ATProto SDK core for authentication, repository operations, and lexicon management",
5
5
  "main": "dist/index.cjs",
6
6
  "repository": {
@@ -75,7 +75,7 @@
75
75
  "@atproto/oauth-client-node": "^0.3.10",
76
76
  "eventemitter3": "^5.0.1",
77
77
  "zod": "^3.24.4",
78
- "@hypercerts-org/lexicon": "0.4.0-beta.0"
78
+ "@hypercerts-org/lexicon": "0.5.0-beta.0"
79
79
  },
80
80
  "scripts": {
81
81
  "test": "vitest",
package/src/core/types.ts CHANGED
@@ -185,9 +185,10 @@ export const OrganizationSchema = z.object({
185
185
  /**
186
186
  * How the current user relates to this organization.
187
187
  * - `"owner"`: User created or owns the organization
188
- * - `"collaborator"`: User was invited to collaborate
188
+ * - `"shared"`: User was invited to collaborate (has permissions)
189
+ * - `"none"`: User has no access to this organization
189
190
  */
190
- accessType: z.enum(["owner", "collaborator"]),
191
+ accessType: z.enum(["owner", "shared", "none"]),
191
192
  });
192
193
 
193
194
  /**
@@ -122,7 +122,7 @@ export class BlobOperationsImpl implements BlobOperations {
122
122
  }
123
123
 
124
124
  return {
125
- ref: result.data.blob.ref,
125
+ ref: { $link: result.data.blob.ref.toString() },
126
126
  mimeType: result.data.blob.mimeType,
127
127
  size: result.data.blob.size,
128
128
  };
@@ -107,6 +107,27 @@ export class CollaboratorOperationsImpl implements CollaboratorOperations {
107
107
  return "viewer";
108
108
  }
109
109
 
110
+ /**
111
+ * Converts a permission string array to a permissions object.
112
+ *
113
+ * The SDS API returns permissions as an array of strings (e.g., ["read", "create"]).
114
+ * This method converts them to the boolean flag format used by the SDK.
115
+ *
116
+ * @param permissionArray - Array of permission strings from SDS API
117
+ * @returns Permission flags object
118
+ * @internal
119
+ */
120
+ private parsePermissions(permissionArray: string[]): CollaboratorPermissions {
121
+ return {
122
+ read: permissionArray.includes("read"),
123
+ create: permissionArray.includes("create"),
124
+ update: permissionArray.includes("update"),
125
+ delete: permissionArray.includes("delete"),
126
+ admin: permissionArray.includes("admin"),
127
+ owner: permissionArray.includes("owner"),
128
+ };
129
+ }
130
+
110
131
  /**
111
132
  * Grants repository access to a user.
112
133
  *
@@ -188,7 +209,10 @@ export class CollaboratorOperationsImpl implements CollaboratorOperations {
188
209
  /**
189
210
  * Lists all collaborators on the repository.
190
211
  *
191
- * @returns Promise resolving to array of access grants
212
+ * @param params - Optional pagination parameters
213
+ * @param params.limit - Maximum number of results (1-100, default 50)
214
+ * @param params.cursor - Pagination cursor from previous response
215
+ * @returns Promise resolving to collaborators and optional cursor
192
216
  * @throws {@link NetworkError} if the list operation fails
193
217
  *
194
218
  * @remarks
@@ -197,23 +221,37 @@ export class CollaboratorOperationsImpl implements CollaboratorOperations {
197
221
  *
198
222
  * @example
199
223
  * ```typescript
200
- * const collaborators = await repo.collaborators.list();
224
+ * // Get first page
225
+ * const page1 = await repo.collaborators.list({ limit: 10 });
226
+ * console.log(`Found ${page1.collaborators.length} collaborators`);
227
+ *
228
+ * // Get next page if available
229
+ * if (page1.cursor) {
230
+ * const page2 = await repo.collaborators.list({ limit: 10, cursor: page1.cursor });
231
+ * }
201
232
  *
202
233
  * // Filter active collaborators
203
- * const active = collaborators.filter(c => !c.revokedAt);
204
- *
205
- * // Group by role
206
- * const byRole = {
207
- * owners: active.filter(c => c.role === "owner"),
208
- * admins: active.filter(c => c.role === "admin"),
209
- * editors: active.filter(c => c.role === "editor"),
210
- * viewers: active.filter(c => c.role === "viewer"),
211
- * };
234
+ * const active = page1.collaborators.filter(c => !c.revokedAt);
212
235
  * ```
213
236
  */
214
- async list(): Promise<RepositoryAccessGrant[]> {
237
+ async list(params?: { limit?: number; cursor?: string }): Promise<{
238
+ collaborators: RepositoryAccessGrant[];
239
+ cursor?: string;
240
+ }> {
241
+ const queryParams = new URLSearchParams({
242
+ repo: this.repoDid,
243
+ });
244
+
245
+ if (params?.limit !== undefined) {
246
+ queryParams.set("limit", params.limit.toString());
247
+ }
248
+
249
+ if (params?.cursor) {
250
+ queryParams.set("cursor", params.cursor);
251
+ }
252
+
215
253
  const response = await this.session.fetchHandler(
216
- `${this.serverUrl}/xrpc/com.sds.repo.listCollaborators?repo=${encodeURIComponent(this.repoDid)}`,
254
+ `${this.serverUrl}/xrpc/com.sds.repo.listCollaborators?${queryParams.toString()}`,
217
255
  { method: "GET" },
218
256
  );
219
257
 
@@ -222,22 +260,30 @@ export class CollaboratorOperationsImpl implements CollaboratorOperations {
222
260
  }
223
261
 
224
262
  const data = await response.json();
225
- return (data.collaborators || []).map(
263
+ const collaborators = (data.collaborators || []).map(
226
264
  (c: {
227
265
  userDid: string;
228
- permissions: CollaboratorPermissions;
266
+ permissions: string[]; // SDS API returns string array
229
267
  grantedBy: string;
230
268
  grantedAt: string;
231
269
  revokedAt?: string;
232
- }) => ({
233
- userDid: c.userDid,
234
- role: this.permissionsToRole(c.permissions),
235
- permissions: c.permissions,
236
- grantedBy: c.grantedBy,
237
- grantedAt: c.grantedAt,
238
- revokedAt: c.revokedAt,
239
- }),
270
+ }) => {
271
+ const permissions = this.parsePermissions(c.permissions);
272
+ return {
273
+ userDid: c.userDid,
274
+ role: this.permissionsToRole(permissions),
275
+ permissions: permissions,
276
+ grantedBy: c.grantedBy,
277
+ grantedAt: c.grantedAt,
278
+ revokedAt: c.revokedAt,
279
+ };
280
+ },
240
281
  );
282
+
283
+ return {
284
+ collaborators,
285
+ cursor: data.cursor,
286
+ };
241
287
  }
242
288
 
243
289
  /**
@@ -261,7 +307,7 @@ export class CollaboratorOperationsImpl implements CollaboratorOperations {
261
307
  */
262
308
  async hasAccess(userDid: string): Promise<boolean> {
263
309
  try {
264
- const collaborators = await this.list();
310
+ const { collaborators } = await this.list();
265
311
  return collaborators.some((c) => c.userDid === userDid && !c.revokedAt);
266
312
  } catch {
267
313
  return false;
@@ -283,7 +329,7 @@ export class CollaboratorOperationsImpl implements CollaboratorOperations {
283
329
  * ```
284
330
  */
285
331
  async getRole(userDid: string): Promise<RepositoryRole | null> {
286
- const collaborators = await this.list();
332
+ const { collaborators } = await this.list();
287
333
  const collab = collaborators.find((c) => c.userDid === userDid && !c.revokedAt);
288
334
  return collab?.role ?? null;
289
335
  }
@@ -208,7 +208,7 @@ export class HypercertOperationsImpl extends EventEmitter<HypercertEvents> imple
208
208
  if (uploadResult.success) {
209
209
  imageBlobRef = {
210
210
  $type: "blob",
211
- ref: uploadResult.data.blob.ref,
211
+ ref: { $link: uploadResult.data.blob.ref.toString() },
212
212
  mimeType: uploadResult.data.blob.mimeType,
213
213
  size: uploadResult.data.blob.size,
214
214
  };
@@ -676,7 +676,7 @@ export class HypercertOperationsImpl extends EventEmitter<HypercertEvents> imple
676
676
  if (uploadResult.success) {
677
677
  locationValue = {
678
678
  $type: "blob",
679
- ref: uploadResult.data.blob.ref,
679
+ ref: { $link: uploadResult.data.blob.ref.toString() },
680
680
  mimeType: uploadResult.data.blob.mimeType,
681
681
  size: uploadResult.data.blob.size,
682
682
  };
@@ -999,7 +999,7 @@ export class HypercertOperationsImpl extends EventEmitter<HypercertEvents> imple
999
999
  if (uploadResult.success) {
1000
1000
  coverPhotoRef = {
1001
1001
  $type: "blob",
1002
- ref: uploadResult.data.blob.ref,
1002
+ ref: { $link: uploadResult.data.blob.ref.toString() },
1003
1003
  mimeType: uploadResult.data.blob.mimeType,
1004
1004
  size: uploadResult.data.blob.size,
1005
1005
  };