import { Effect } from "effect";
import { StorageError, type IFumaClient } from "./fuma-runtime";
import type { Owner } from "./ids";
export interface BlobStore {
    readonly get: (namespace: string, key: string) => Effect.Effect<string | null, StorageError>;
    /** Multi-namespace lookup for a single key. Backends issue one query
     *  (`WHERE namespace IN (...) AND key = ?`) and return the hits keyed
     *  by namespace — the caller applies its own precedence. Lets
     *  `pluginBlobStore` walk the scope stack in O(1) round-trips instead
     *  of one per scope. */
    readonly getMany: (namespaces: readonly string[], key: string) => Effect.Effect<ReadonlyMap<string, string>, StorageError>;
    readonly put: (namespace: string, key: string, value: string) => Effect.Effect<void, StorageError>;
    readonly delete: (namespace: string, key: string) => Effect.Effect<void, StorageError>;
    readonly has: (namespace: string, key: string) => Effect.Effect<boolean, StorageError>;
}
export interface PluginBlobStore {
    /** Read precedence: this subject's own (`user`) value first, then the
     *  org-shared value. Returns the first non-null. */
    readonly get: (key: string) => Effect.Effect<string | null, StorageError>;
    /** Write `value` under `key` for the named owner (`"org"` shared, `"user"`
     *  private). `"user"` requires the executor to be bound to a subject. */
    readonly put: (key: string, value: string, options: {
        readonly owner: Owner;
    }) => Effect.Effect<void, StorageError>;
    /** Delete `key` for the named owner. */
    readonly delete: (key: string, options: {
        readonly owner: Owner;
    }) => Effect.Effect<void, StorageError>;
    /** True if either the user or org partition has a value for `key`. */
    readonly has: (key: string) => Effect.Effect<boolean, StorageError>;
}
/** The owner partition strings an executor binding resolves to: the org
 *  partition (always present) and this subject's user partition (null for a
 *  pure-org executor). Reads walk `[user, org]`; writes target one. */
export interface OwnerPartitions {
    readonly org: string;
    readonly user: string | null;
}
/**
 * Bind a `BlobStore` to an owner partitioning + plugin id. Reads fall through
 * `[user, org]` (user first); writes target an explicit owner. Used by the
 * executor to build the `blobs` field handed to each plugin's `storage` factory.
 */
export declare const pluginBlobStore: (store: BlobStore, partitions: OwnerPartitions, pluginId: string) => PluginBlobStore;
/**
 * Minimal in-memory BlobStore — good for tests and trivial hosts. Real
 * backends (filesystem, S3/R2, SQLite-table-backed) implement the same
 * interface.
 *
 * Every method is `Effect<_, never>` — a pure in-memory Map can't fail.
 * `never` is assignable to `StorageError`, so the result still fits the
 * `BlobStore` interface.
 */
export declare const makeInMemoryBlobStore: () => BlobStore;
/** Hex SHA-256 of a UTF-8 string — the content-address key plugins use for
 *  write-once blobs (`put(key(hash), …)` is then idempotent and orphaned
 *  writes are harmless). Web Crypto, so it runs on Workers/Bun/Node alike. */
export declare const sha256Hex: (text: string) => Effect.Effect<string>;
export declare const makeFumaBlobStore: (fuma: IFumaClient) => BlobStore;
//# sourceMappingURL=blob.d.ts.map