import { type SignedMandate } from "@aithos/protocol-client"; export interface AithosSchemaLite { readonly schema: string; readonly indexable: ReadonlySet; readonly encrypted: ReadonlySet; readonly auto: ReadonlySet; readonly defaults: Readonly>; } export interface CreateDataClientArgs { /** * PDS base URL. Defaults to `https://pds.aithos.be` (the production vanity * domain, CloudFront-fronted) when omitted. Override for self-hosting or * staging (e.g. a raw `execute-api` URL). */ readonly pdsUrl?: string; /** * Subject DID that owns the data. The canonical owner is a `did:aithos:…` * account signing under its dedicated `#data` sphere (see below). A * `did:key:…` is a throwaway identity for quick demos/tests only — it has no * sphere separation (every sphere collapses to the single embedded key). */ readonly did: string; /** * Ed25519 sphere seed (32 bytes) that signs every PDS envelope. For a * `did:aithos` account this MUST be the subject's dedicated **`#data`** sphere * seed — never the root key nor an Ethos sphere — so the root stays cold and * data operations are isolated to their own key. For a `did:key` it is the * single key embedded in the DID. */ readonly sphereSeed: Uint8Array; /** * The verification method URL within the DID document used to sign PDS * envelopes. For a `did:aithos` account this is **`#data`**. For a * `did:key` it is `#`. */ readonly verificationMethod: string; /** Optional fetch implementation. Defaults to globalThis.fetch. */ readonly fetch?: typeof fetch; /** * Optional list of app-defined schema definitions, in addition to * the SDK-bundled core schemas (currently `aithos.contacts.v1`). * * Apps in the vendor namespace (`aithos.x...v`) or * non-`aithos.*` namespaces MUST supply their schemas here so the * SDK can split records into indexable metadata vs encrypted payload. * * When the same schema id appears in both the bundled core registry * and this list, the app-supplied definition wins (intentional — * allows local overrides for testing, though immutability per spec * §3.5 means a published schema id should never change shape). * * Schemas are scoped to the {@link DataClient} instance — they don't * leak to other clients in the same process. */ readonly schemas?: readonly AithosSchemaLite[]; } export interface DataClient { /** Get / create a collection handle. */ collection(name: string): DataCollection; /** Initialize a new collection with an explicit schema. Throws * `-32073 AITHOS_DATA_COLLECTION_EXISTS` if it already exists. */ createCollection(args: { name: string; schema: string; forwardSecrecy?: "best_effort" | "strict"; }): Promise; /** * Get-or-create: create the collection if it doesn't exist, otherwise * succeed silently. Idempotent — safe to call on every app boot before * writing. Absorbs the `-32073 AITHOS_DATA_COLLECTION_EXISTS` conflict * (and the concurrent-create race) so callers don't have to special-case * "already there". Avoids the friction where `collection(name).insert(…)` * on a never-created collection fails with `-32020`. */ ensureCollection(args: { name: string; schema: string; forwardSecrecy?: "best_effort" | "strict"; }): Promise; /** List collections owned by this subject. */ listCollections(): Promise; /** List gamma audit entries. */ listGammaEntries(opts?: { limit?: number; opPrefix?: string; verify?: boolean; }): Promise; /** * Idempotently publish a vendor (`aithos.x...v`) * JSON Schema document to this subject's PDS. Once published, the * PDS validates record writes against the schema doc server-side, * closing the gap A2a left open (cf. Aithos-protocol/PLAN-A2b-…). * * Safe to call on every app boot — re-registering the same document * (same canonical hash) resolves to `{ created: false }`. A different * document for the same `aithos:schema` id is REJECTED with code * -32082 `AITHOS_DATA_SCHEMA_IMMUTABLE` ; the caller must bump the * version segment in `aithos:schema` and retry. * * Core schemas (`aithos..v` without `.x.`) cannot be * registered via this RPC ; they're bundled by the platform per spec * §3.7.2. * * @param schemaDoc Full JSON Schema 2020-12 document. MUST carry * `aithos:schema` and `aithos:version` top-level fields. */ registerSchema(schemaDoc: object): Promise<{ schemaId: string; docHash: string; created: boolean; createdAt?: string; }>; /** * Fetch a published schema document from the PDS. * * For core schemas (`aithos..v`) the lookup is global ; * `subjectDid` is ignored. For vendor schemas (`aithos.x.*`) the * `subjectDid` arg selects whose published registry to query and * defaults to this client's own DID. * * Returns null when the lookup misses (rather than throwing) so * call sites can branch on the result. */ getSchema(schemaId: string, opts?: { subjectDid?: string; }): Promise; /** * Grant a mandate-holding delegate read access to one of this owner's * collections, by re-wrapping the collection's CMK to the grantee's * key and posting `aithos.data.authorize_app`. * * Owner-only. The CMK is unwrapped locally (the owner holds it), then * re-wrapped X25519-HKDF-AEAD to the grantee's X25519 key (derived * from `mandate.grantee.pubkey`). The platform never sees the CMK in * clear — it only appends the wrap to the collection's envelope after * verifying the mandate (data spec §4.5). * * Idempotent at the server: re-authorizing the same grantee on the * same collection is a no-op. One wrap per grantee covers every record * in the collection (O(1) authorization — the CMK is stable). * * The mandate must carry a `data..{read|write|admin}` * or `data.*.*` scope and a `grantee.pubkey`. */ authorizeDelegate(args: { collectionName: string; mandate: SignedMandate; }): Promise; /** * Revoke a delegate's access to a collection (`aithos.data.revoke_app`). * Owner-only, forward-only: after revocation the PDS refuses the * delegate's reads (the mandate is marked revoked), and the delegate's * wrap is dropped from the collection's authorization index. Already-read * / cached plaintext on the delegate side is out of scope (a known limit * of any key-sharing scheme — revocation blocks FUTURE access). */ revokeDelegate(args: { collectionName: string; mandateId: string; reason?: string; }): Promise; /** Drop in-memory cache (CMK, collection metadata, …). */ reset(): void; } /** * Read-only view over a subject's data collections, driven by a mandate * the subject granted to a delegate (`data..read`). Built by * {@link createDelegateDataClient}. * * Mirror of {@link DataClient} minus every mutating verb: a delegate * holding a read mandate can `get`/`list` and enumerate collections, but * cannot insert, update, delete, create collections, register schemas, or * re-delegate. Those throw `-32042` client-side (and the PDS rejects them * server-side regardless). */ export interface ReadonlyDataClient { /** Get a read-only collection handle. */ collection(name: string): ReadonlyDataCollection; /** List the collections this delegate's mandate scopes cover (synthesized * from the scopes, since the server's list_collections is owner-only). * Throws if the mandate carries only a wildcard `data.*.*` scope, which * cannot be enumerated client-side. */ listCollections(): Promise; /** @deprecated Owner-only — the audit log belongs to the subject. On a * delegate client this throws (string code `data_delegate_owner_only`) * before any network call. Sign in as the owner to audit. */ listGammaEntries(opts?: { limit?: number; opPrefix?: string; verify?: boolean; }): Promise; /** Drop in-memory cache (CMK, collection metadata, …). */ reset(): void; } export interface ReadonlyDataCollection { readonly name: string; /** Fetch one record by id (decrypted client-side via the re-wrapped CMK). */ get(recordId: string): Promise | null>; /** List records, decrypted. Pagination via opaque cursor. */ list(opts?: ListOpts): Promise<{ items: Record[]; nextCursor?: string; }>; } export interface DataCollection { readonly name: string; /** * Insert a record. The object MAY contain both indexable and * encrypted fields per the schema; the SDK splits them. */ insert(record: Record): Promise; /** Fetch one record by id (decrypted client-side). */ get(recordId: string): Promise | null>; /** List records, decrypted. Pagination via opaque cursor. */ list(opts?: ListOpts): Promise<{ items: Record[]; nextCursor?: string; }>; /** * Replace a record. Same shape as insert; the SDK splits indexable * vs encrypted again per the schema. */ update(recordId: string, record: Record): Promise; /** Soft-delete a record. */ delete(recordId: string): Promise; } export interface ListOpts { readonly filter?: { readonly equals?: { field: string; value: unknown; }; readonly contains?: { field: string; value: string; }; readonly tagsAny?: readonly string[]; readonly tagsAll?: readonly string[]; readonly range?: { field: string; gte?: string; lte?: string; }; }; readonly order?: "newest" | "oldest"; readonly limit?: number; readonly cursor?: string; } export declare function createDataClient(args: CreateDataClientArgs): DataClient; export interface CreateDelegateDataClientArgs { /** PDS base URL (same endpoint the owner writes to). Defaults to * `https://pds.aithos.be` when omitted. */ readonly pdsUrl?: string; /** DID of the SUBJECT whose data is being read (the mandate issuer). */ readonly subjectDid: string; /** * The full signed mandate the subject granted to this delegate. Must * carry a `data..read` (or wider) scope and a * `grantee.pubkey` matching `delegateSeed`. */ readonly mandate: SignedMandate; /** The delegate's Ed25519 seed (32 bytes) — the grantee key the mandate * is bound to. Used to sign envelopes AND to derive the X25519 key that * unwraps the re-wrapped CMK. */ readonly delegateSeed: Uint8Array; /** * The delegate's Ed25519 public key, multibase-encoded. Defaults to * `mandate.grantee.pubkey`. This is the bare verificationMethod the PDS * binds the delegate envelope to. */ readonly granteePubkeyMultibase?: string; /** App-defined (vendor) schemas, as for {@link createDataClient}. */ readonly schemas?: readonly AithosSchemaLite[]; /** `fetch` override (tests). */ readonly fetch?: typeof fetch; } /** * Build a data client that operates on a subject's collections under a * mandate (delegate path). It signs every request as the delegate * (bare-multibase verificationMethod + the mandate attached to the * envelope) and decrypts/encrypts records using the CMK the owner * re-wrapped for this delegate via {@link DataClient.authorizeDelegate}. * * Record CRUD is bounded by the mandate scope: reads need * `data..read`, writes need `data..write` (or `.admin` / * wildcard) — enforced client-side and by the PDS. Owner-only operations * (createCollection, authorizeDelegate, revokeDelegate, registerSchema) * always throw `-32042`: the owner holds the CMK and controls access. * * @internal Prefer the session accessor `auth.data` (owner) / the delegate * session over hand-constructing this with a raw seed. */ export declare function createDelegateDataClient(args: CreateDelegateDataClientArgs): DataClient; /** An append-only handle on one collection: `insert` and nothing else. */ export interface AppendOnlyDataCollection { readonly name: string; /** * Deposit a record. The DEK is sealed to the owner's public key, so the * depositor cannot read this (or any) record back. Returns the record id. */ insert(record: Record): Promise; } /** A client holding a `data..append` mandate. Insert-only. */ export interface AppendOnlyDataClient { /** Get an append-only handle on a collection (schema supplied at * construction — append clients cannot read collection metadata). */ collection(name: string): AppendOnlyDataCollection; /** Drop in-memory cache. */ reset(): void; } export interface CreateAppendDataClientArgs { /** PDS base URL (same endpoint the owner writes to). Defaults to * `https://pds.aithos.be` when omitted. */ readonly pdsUrl?: string; /** DID of the SUBJECT who owns the target collection (the mandate issuer). */ readonly subjectDid: string; /** * The owner's `#data` Ed25519 public key (multibase z…). The depositor * derives the owner's X25519 wrap target from it and seals each DEK to it. * Source: the append mandate / invitation, or the owner's DID document. */ readonly ownerDataPubkeyMultibase: string; /** The signed mandate carrying `data..append`. */ readonly mandate: SignedMandate; /** The depositor's Ed25519 seed (32 bytes) — the grantee key the mandate is * bound to. Signs each insert envelope. NEVER used to read. */ readonly delegateSeed: Uint8Array; /** Defaults to `mandate.grantee.pubkey`. */ readonly granteePubkeyMultibase?: string; /** * Schema of the target collection(s). The append client builds records * locally (it cannot fetch collection metadata), so the caller MUST supply * the schema(s) used by the collection it deposits into. The first entry is * used as the default; multiple may be passed for multi-collection clients. */ readonly schema: AithosSchemaLite; /** Additional schemas (looked up by id alongside `schema`). */ readonly schemas?: readonly AithosSchemaLite[]; /** `fetch` override (tests). */ readonly fetch?: typeof fetch; } /** * Build an **append-only** data client from a `data..append` * mandate. The returned {@link AppendOnlyDataClient} can ONLY `insert`: it * seals each record's DEK to the owner's public key (never the CMK), so it * holds no read capability — it cannot decrypt anything in the collection, * not even its own deposit. The PDS additionally enforces the append scope * (insert allowed; get/list/update/delete refused). */ export declare function createAppendDataClient(args: CreateAppendDataClientArgs): AppendOnlyDataClient; /** * Derive an {@link AithosSchemaLite} from a PUBLISHED JSON Schema document (the * shape `aithos.data.get_schema` / `registerSchema` round-trip). The field * split is read from the per-property annotations: * - `aithos:indexable: true` → indexable (server-visible, filter/sort) * - `aithos:auto: …` → auto (server-populated, e.g. created_at) * - anything else → encrypted (AEAD'd client-side) * * These annotations are authoritative — by convention they mirror the writer's * own lite — so a reader that never bundled the schema can still split records * correctly. `defaults` is left empty (it only matters for inserts; the writer * supplies its own). */ export declare function liteFromPublishedSchema(doc: object): AithosSchemaLite; //# sourceMappingURL=data.d.ts.map