···3434// Domain types
3535export {
3636 type OpakeInitOptions,
3737+ type AccountConfig,
3738 type MutationResult,
3839 type UploadResult,
3940 type DownloadResult,
+41
packages/opake-sdk/src/opake.ts
···11111212import type { Storage } from "./storage";
1313import type {
1414+ AccountConfig,
1415 MutationResult,
1516 OpakeInitOptions,
1617 ResolvedIdentity,
···675676 @withTokenGuard
676677 publishPublicKey(): Promise<string> {
677678 return this.requireContext().publishPublicKey();
679679+ }
680680+681681+ // ---------------------------------------------------------------------------
682682+ // Account config (per-account preferences synced to PDS)
683683+ // ---------------------------------------------------------------------------
684684+685685+ /**
686686+ * Fetch the account config record (`app.opake.accountConfig/self`), if
687687+ * one exists on the PDS. Returns null when the account has never
688688+ * written a config.
689689+ */
690690+ @wrapWasmErrors
691691+ @withTokenGuard
692692+ getAccountConfig(): Promise<AccountConfig | null> {
693693+ return this.requireContext().getAccountConfig() as Promise<AccountConfig | null>;
694694+ }
695695+696696+ /**
697697+ * Write (upsert) the account config record. Merges with whatever the
698698+ * caller passes — if a field is omitted from `updates`, the current
699699+ * stored value is preserved.
700700+ *
701701+ * @returns The updated config.
702702+ */
703703+ @wrapWasmErrors
704704+ @withTokenGuard
705705+ async updateAccountConfig(updates: Partial<AccountConfig>): Promise<AccountConfig> {
706706+ const ctx = this.requireContext();
707707+ const current = ((await ctx.getAccountConfig()) as AccountConfig | null) ?? {
708708+ opakeVersion: 1,
709709+ telemetryEnabled: false,
710710+ modifiedAt: new Date().toISOString(),
711711+ };
712712+ const next: AccountConfig = {
713713+ ...current,
714714+ ...updates,
715715+ modifiedAt: new Date().toISOString(),
716716+ };
717717+ await ctx.setAccountConfig(next);
718718+ return next;
678719 }
679720680721 // ---------------------------------------------------------------------------
+14
packages/opake-sdk/src/types.ts
···44// TypeScript interfaces. The SDK validates WASM output and returns
55// these typed values — consumers never see raw JsValue.
6677+/**
88+ * Per-account config synced to the user's PDS as a singleton record
99+ * under `app.opake.accountConfig/self`. Holds non-sensitive preferences
1010+ * that should follow the account across devices.
1111+ */
1212+export interface AccountConfig {
1313+ readonly opakeVersion: number;
1414+ readonly telemetryEnabled: boolean;
1515+ /** Override the default appview. Leave undefined to use the built-in default. */
1616+ readonly appviewUrl?: string;
1717+ /** ISO-8601 timestamp of last write. */
1818+ readonly modifiedAt: string;
1919+}
2020+721/** Result of a mutation that may be applied directly or proposed for owner approval. */
822export interface MutationResult {
923 /** URI of the created/updated record (null for proposals on other owners' PDS). */