@noy-db/hub 0.1.0-pre.3 → 0.1.0-pre.5

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 (95) hide show
  1. package/dist/blobs/index.cjs.map +1 -1
  2. package/dist/blobs/index.d.cts +3 -3
  3. package/dist/blobs/index.d.ts +3 -3
  4. package/dist/blobs/index.js +2 -2
  5. package/dist/bundle/index.cjs +26 -3
  6. package/dist/bundle/index.cjs.map +1 -1
  7. package/dist/bundle/index.d.cts +3 -3
  8. package/dist/bundle/index.d.ts +3 -3
  9. package/dist/bundle/index.js +3 -1
  10. package/dist/{chunk-M2F2JAWB.js → chunk-6NPQTBZN.js} +103 -8
  11. package/dist/chunk-6NPQTBZN.js.map +1 -0
  12. package/dist/{chunk-UQFSPSWG.js → chunk-E4OOAPBZ.js} +2 -2
  13. package/dist/chunk-EMIGCR7X.js +39 -0
  14. package/dist/chunk-EMIGCR7X.js.map +1 -0
  15. package/dist/{chunk-EXQRC2L4.js → chunk-H3DV46AQ.js} +2 -2
  16. package/dist/{chunk-XHFOENR2.js → chunk-LMKOSLJY.js} +2 -2
  17. package/dist/{chunk-GJILMRPO.js → chunk-LRN3PNI6.js} +42 -4
  18. package/dist/chunk-LRN3PNI6.js.map +1 -0
  19. package/dist/{chunk-4OWFYIDQ.js → chunk-MIRZMUSQ.js} +3 -3
  20. package/dist/{chunk-ZRG4V3F5.js → chunk-NXUVITPB.js} +1 -1
  21. package/dist/chunk-NXUVITPB.js.map +1 -0
  22. package/dist/{chunk-5AATM2M2.js → chunk-QUDXYI4W.js} +2 -2
  23. package/dist/{chunk-ZLMV3TUA.js → chunk-QV4WLLKB.js} +3 -3
  24. package/dist/{chunk-E445ICYI.js → chunk-UFL4DUEV.js} +5 -3
  25. package/dist/chunk-UFL4DUEV.js.map +1 -0
  26. package/dist/chunk-UQQ2XFXI.js +155 -0
  27. package/dist/chunk-UQQ2XFXI.js.map +1 -0
  28. package/dist/consent/index.d.cts +3 -3
  29. package/dist/consent/index.d.ts +3 -3
  30. package/dist/{dev-unlock-KrKkcqD3.d.ts → dev-unlock-BgFqShBi.d.ts} +1 -1
  31. package/dist/{dev-unlock-CeXic1xC.d.cts → dev-unlock-qVMxG2Je.d.cts} +1 -1
  32. package/dist/{hash-ChfJjRjQ.d.ts → hash-BhoL7iUE.d.ts} +1 -1
  33. package/dist/{hash-9KO1BGxh.d.cts → hash-Bpvl2eSe.d.cts} +1 -1
  34. package/dist/history/index.cjs.map +1 -1
  35. package/dist/history/index.d.cts +4 -4
  36. package/dist/history/index.d.ts +4 -4
  37. package/dist/history/index.js +2 -2
  38. package/dist/i18n/index.cjs +3 -1
  39. package/dist/i18n/index.cjs.map +1 -1
  40. package/dist/i18n/index.d.cts +3 -3
  41. package/dist/i18n/index.d.ts +3 -3
  42. package/dist/i18n/index.js +3 -3
  43. package/dist/{index-DN-J-5wT.d.cts → index-6xNpPsxR.d.cts} +1 -1
  44. package/dist/{index-BRHBCmLt.d.ts → index-DJTf9yxn.d.ts} +1 -1
  45. package/dist/{index-DhjMjz7L.d.cts → index-DhK_zqOO.d.ts} +39 -5
  46. package/dist/{index-C8kQtmOk.d.ts → index-DyRt_5vM.d.cts} +39 -5
  47. package/dist/index.cjs +1501 -51
  48. package/dist/index.cjs.map +1 -1
  49. package/dist/index.d.cts +261 -19
  50. package/dist/index.d.ts +261 -19
  51. package/dist/index.js +1118 -44
  52. package/dist/index.js.map +1 -1
  53. package/dist/{ledger-2NX4L7PN.js → ledger-GA4DMJS6.js} +3 -3
  54. package/dist/periods/index.cjs.map +1 -1
  55. package/dist/periods/index.d.cts +3 -3
  56. package/dist/periods/index.d.ts +3 -3
  57. package/dist/periods/index.js +3 -3
  58. package/dist/public-envelope-R4EIEQE6.js +31 -0
  59. package/dist/public-envelope-R4EIEQE6.js.map +1 -0
  60. package/dist/query/index.d.cts +1 -1
  61. package/dist/query/index.d.ts +1 -1
  62. package/dist/session/index.cjs +4 -2
  63. package/dist/session/index.cjs.map +1 -1
  64. package/dist/session/index.d.cts +4 -4
  65. package/dist/session/index.d.ts +4 -4
  66. package/dist/session/index.js +1 -1
  67. package/dist/shadow/index.d.cts +3 -3
  68. package/dist/shadow/index.d.ts +3 -3
  69. package/dist/store/index.d.cts +3 -3
  70. package/dist/store/index.d.ts +3 -3
  71. package/dist/sync/index.cjs.map +1 -1
  72. package/dist/sync/index.d.cts +2 -2
  73. package/dist/sync/index.d.ts +2 -2
  74. package/dist/sync/index.js +2 -2
  75. package/dist/team/index.cjs +3 -1
  76. package/dist/team/index.cjs.map +1 -1
  77. package/dist/team/index.d.cts +3 -3
  78. package/dist/team/index.d.ts +3 -3
  79. package/dist/team/index.js +4 -4
  80. package/dist/tx/index.d.cts +3 -3
  81. package/dist/tx/index.d.ts +3 -3
  82. package/dist/{types-Bfs0qr5F.d.cts → types-BpyE4o_n.d.cts} +935 -4
  83. package/dist/{types-BZpCZB8N.d.ts → types-Df72wWCC.d.ts} +935 -4
  84. package/package.json +1 -1
  85. package/dist/chunk-E445ICYI.js.map +0 -1
  86. package/dist/chunk-GJILMRPO.js.map +0 -1
  87. package/dist/chunk-M2F2JAWB.js.map +0 -1
  88. package/dist/chunk-ZRG4V3F5.js.map +0 -1
  89. /package/dist/{chunk-UQFSPSWG.js.map → chunk-E4OOAPBZ.js.map} +0 -0
  90. /package/dist/{chunk-EXQRC2L4.js.map → chunk-H3DV46AQ.js.map} +0 -0
  91. /package/dist/{chunk-XHFOENR2.js.map → chunk-LMKOSLJY.js.map} +0 -0
  92. /package/dist/{chunk-4OWFYIDQ.js.map → chunk-MIRZMUSQ.js.map} +0 -0
  93. /package/dist/{chunk-5AATM2M2.js.map → chunk-QUDXYI4W.js.map} +0 -0
  94. /package/dist/{chunk-ZLMV3TUA.js.map → chunk-QV4WLLKB.js.map} +0 -0
  95. /package/dist/{ledger-2NX4L7PN.js.map → ledger-GA4DMJS6.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  import { I as IndexStrategy, d as LazyQuery } from './lazy-builder-CZVLKh0Z.cjs';
2
2
  import { A as AggregateStrategy } from './strategy-D-SrOLCl.cjs';
3
3
  import { C as CrdtStrategy, a as CrdtMode, b as CrdtState } from './strategy-BSxFXGzb.cjs';
4
- import { U as RefDescriptor, p as JoinableSource, Z as RefViolation, Q as Query, $ as ScanBuilder } from './index-DN-J-5wT.cjs';
4
+ import { N as NoydbError, U as RefDescriptor, p as JoinableSource, Z as RefViolation, Q as Query, $ as ScanBuilder } from './index-6xNpPsxR.cjs';
5
5
  import { I as IndexDef, C as CollectionIndexes } from './predicate-SBHmi6D0.cjs';
6
6
 
7
7
  /**
@@ -1739,6 +1739,86 @@ declare class NoydbEventEmitter {
1739
1739
  removeAllListeners(): void;
1740
1740
  }
1741
1741
 
1742
+ /**
1743
+ * Passphrase validation — phrase format (per the three-tier session-tiers
1744
+ * design, locked 2026-05-04).
1745
+ *
1746
+ * Passphrases are **phrases**: multiple simple words, easy to remember,
1747
+ * structurally constrained so a weak choice cannot silently collapse the
1748
+ * security floor. The format is intentionally narrow: lowercase letters
1749
+ * and single spaces only, no punctuation, no symbols, no digits.
1750
+ *
1751
+ * - Default minimum: 6 words (~77 bits with the 7,776-word EFF list).
1752
+ * - Strict minimum: 8 words (~103 bits).
1753
+ * - Per-word minimum: 3 characters (excludes "a", "is", "of").
1754
+ * - Adjacent repeats rejected ("the the").
1755
+ *
1756
+ * The hub runs validation default-on at every passphrase ingress
1757
+ * (`createOwnerKeyring`, `grant`, `rotatePassphrase`); test fixtures and
1758
+ * CLI scripts override via `{ allowWeakPassphrase: true }`.
1759
+ *
1760
+ * @module
1761
+ */
1762
+
1763
+ /** All reasons a phrase can be rejected. */
1764
+ type WeakPassphraseReason = 'empty' | 'invalid-chars' | 'leading-or-trailing-space' | 'double-space' | 'too-few-words' | 'word-too-short' | 'repeated-adjacent';
1765
+ /** Per-vault knobs. Aligns with `VaultPolicy.passphrase`. */
1766
+ interface PassphrasePolicy {
1767
+ /** Minimum number of words. Default 6. Strict policy uses 8. */
1768
+ readonly minWords?: number;
1769
+ /** Minimum characters per word. Default 3. */
1770
+ readonly minWordLength?: number;
1771
+ /** Reject adjacent identical words ("the the"). Default true. */
1772
+ readonly rejectRepeatedAdjacent?: boolean;
1773
+ }
1774
+ /** Result of a check. Discriminated union — compile-time exhaustive. */
1775
+ type PassphraseValidationResult = {
1776
+ readonly ok: true;
1777
+ readonly words: number;
1778
+ } | {
1779
+ readonly ok: false;
1780
+ readonly reason: WeakPassphraseReason;
1781
+ readonly minimum?: number;
1782
+ readonly got?: number;
1783
+ };
1784
+ /**
1785
+ * Thrown by `assertStrongPassphrase()` and by every hub ingress
1786
+ * point (`createOwnerKeyring`, `grant`, `rotatePassphrase`) when a
1787
+ * supplied phrase fails the structural rules above.
1788
+ */
1789
+ declare class WeakPassphraseError extends NoydbError {
1790
+ readonly reason: WeakPassphraseReason;
1791
+ readonly suggestion: string;
1792
+ constructor(reason: WeakPassphraseReason, suggestion: string);
1793
+ }
1794
+ /**
1795
+ * Inspect a phrase against the format rules and return a structured
1796
+ * verdict. Never throws — callers either branch on `ok` or pass the
1797
+ * result to {@link assertStrongPassphrase} for the throwing flavour.
1798
+ */
1799
+ declare function validatePassphrase(s: string, opts?: PassphrasePolicy): PassphraseValidationResult;
1800
+ /**
1801
+ * Throw {@link WeakPassphraseError} when the phrase fails. Used by
1802
+ * `createOwnerKeyring`, `grant`, and `rotatePassphrase` at ingress.
1803
+ *
1804
+ * Pass `{ allowWeakPassphrase: true }` to bypass — intended for test
1805
+ * fixtures, CLI scripts, and dev environments. The override never
1806
+ * loosens the cryptographic key derivation; it only relaxes the
1807
+ * structural-strength gate.
1808
+ */
1809
+ declare function assertStrongPassphrase(s: string, opts?: PassphrasePolicy & {
1810
+ allowWeakPassphrase?: boolean;
1811
+ }): void;
1812
+ /**
1813
+ * Estimate the entropy of a phrase, given the EFF 7,776-word list as
1814
+ * the assumed wordlist. ~12.9 bits per word.
1815
+ *
1816
+ * Returns 0 for any input that fails the phrase format — character-class
1817
+ * estimates aren't comparable to phrase entropy, and surfacing 0 makes
1818
+ * weak inputs visible in any UI that displays an entropy meter.
1819
+ */
1820
+ declare function estimateEntropy(passphrase: string): number;
1821
+
1742
1822
  /** In-memory representation of an unlocked keyring. */
1743
1823
  interface UnlockedKeyring {
1744
1824
  readonly userId: string;
@@ -1761,6 +1841,20 @@ interface UnlockedKeyring {
1761
1841
  * bundle import granted, regardless of role).
1762
1842
  */
1763
1843
  readonly importCapability?: ImportCapability;
1844
+ /**
1845
+ * Tier-2 authenticator slots — readonly snapshot loaded from the
1846
+ * keyring file. Mutations go through `enrollAuthenticator` /
1847
+ * `removeAuthenticator` (issue #11), which write back via
1848
+ * `persistKeyring`. Always defined; loads with an empty array for
1849
+ * keyrings written before the multi-slot extension landed.
1850
+ */
1851
+ readonly authenticators: readonly KeyringAuthenticator[];
1852
+ /**
1853
+ * Reserved per-keyring policy override (forward-compat for Option C
1854
+ * — see {@link VaultPolicyOnDisk}). v1.0 round-trips this field but
1855
+ * never enforces it; the gate engine uses `_meta/policy` only.
1856
+ */
1857
+ readonly policy?: VaultPolicyOnDisk;
1764
1858
  }
1765
1859
  /**
1766
1860
  * Recipient slot in a re-keyed `.noydb` bundle. Each slot becomes its
@@ -2715,6 +2809,347 @@ declare class SyncEngine {
2715
2809
  private persistMeta;
2716
2810
  }
2717
2811
 
2812
+ /**
2813
+ * Tier-1 change flows — `rotatePassphrase` (user remembers old) and
2814
+ * `recoverPassphrase` (user supplies a recovery proof). Issue #10.
2815
+ *
2816
+ * The two flows share the post-verification half — fresh salt, fresh
2817
+ * KEK, rewrap every DEK — and differ only in how they re-derive the
2818
+ * old KEK:
2819
+ *
2820
+ * - **Rotate**: derive from the supplied `oldPassphrase`.
2821
+ * - **Recover (paper)**: unwrap from a `RecoveryCodeEntry` using a
2822
+ * user-supplied recovery code. The entry is burned on success.
2823
+ *
2824
+ * The non-paper recovery profiles (Shamir, multi-channel,
2825
+ * admin-mediated) are not yet wired — calling them throws
2826
+ * {@link RecoveryProfileNotImplementedError} with a tracking link.
2827
+ *
2828
+ * @module
2829
+ */
2830
+
2831
+ /** Caller payload for {@link rotatePassphrase}. */
2832
+ interface RotatePassphraseInput {
2833
+ readonly oldPassphrase: string;
2834
+ readonly newPassphrase: string;
2835
+ readonly passphrasePolicy?: PassphrasePolicy;
2836
+ readonly allowWeakPassphrase?: boolean;
2837
+ }
2838
+ /**
2839
+ * Re-derive the user's KEK from `oldPassphrase`, rewrap every DEK
2840
+ * under a freshly-derived KEK from `newPassphrase`, and persist.
2841
+ *
2842
+ * Tier-2 authenticator slots are NOT preserved — each slot wraps the
2843
+ * old KEK and would need the user's per-slot derivation key to
2844
+ * re-wrap; the hub doesn't hold that. The user re-enrols any slots
2845
+ * after rotation. v0.1.0-pre.5 limitation.
2846
+ *
2847
+ * @throws `InvalidKeyError` if `oldPassphrase` does not unwrap the keyring.
2848
+ * @throws `WeakPassphraseError` if `newPassphrase` fails the strength rule.
2849
+ */
2850
+ declare function rotatePassphrase(store: NoydbStore, vault: string, userId: string, input: RotatePassphraseInput): Promise<UnlockedKeyring>;
2851
+ /** Caller payload for {@link recoverPassphrase}. */
2852
+ type RecoveryProof = {
2853
+ readonly profile: 'paper';
2854
+ readonly payload: {
2855
+ readonly code: string;
2856
+ };
2857
+ } | {
2858
+ readonly profile: 'shamir';
2859
+ readonly payload: {
2860
+ readonly shares: ReadonlyArray<string>;
2861
+ };
2862
+ } | {
2863
+ readonly profile: 'multi-channel';
2864
+ readonly payload: {
2865
+ readonly proofs: ReadonlyArray<unknown>;
2866
+ };
2867
+ } | {
2868
+ readonly profile: 'admin-mediated';
2869
+ readonly payload: {
2870
+ readonly token: string;
2871
+ readonly factor?: unknown;
2872
+ };
2873
+ };
2874
+ interface RecoverPassphraseInput {
2875
+ readonly newPassphrase: string;
2876
+ readonly recoveryProof: RecoveryProof;
2877
+ readonly passphrasePolicy?: PassphrasePolicy;
2878
+ readonly allowWeakPassphrase?: boolean;
2879
+ }
2880
+ /**
2881
+ * Reset the user's passphrase using a recovery proof. v0.1.0-pre.5
2882
+ * supports the `'paper'` profile via `@noy-db/on-recovery` entries
2883
+ * persisted in `_meta/recovery-paper`. The other three profiles throw
2884
+ * {@link RecoveryProfileNotImplementedError}.
2885
+ *
2886
+ * On success, the used recovery entry is burned (deleted from the
2887
+ * stored set).
2888
+ */
2889
+ declare function recoverPassphrase(store: NoydbStore, vault: string, userId: string, input: RecoverPassphraseInput): Promise<UnlockedKeyring>;
2890
+
2891
+ /**
2892
+ * Recovery profile persistence + dispatch — issue #10.
2893
+ *
2894
+ * v0.1.0-pre.5 wires the **paper** profile end-to-end through
2895
+ * `@noy-db/on-recovery`. The other three profiles (Shamir,
2896
+ * multi-channel, admin-mediated) ship the API surface and throw
2897
+ * {@link RecoveryProfileNotImplementedError} during use; per-profile
2898
+ * dispatch lands in follow-up issues.
2899
+ *
2900
+ * Storage layout:
2901
+ *
2902
+ * ```
2903
+ * _meta/recovery-paper — JSON { entries: RecoveryCodeEntry[] } produced by `on-recovery`.
2904
+ * _meta/recovery-shamir — reserved
2905
+ * _meta/recovery-multi — reserved
2906
+ * _meta/recovery-admin — reserved
2907
+ * ```
2908
+ *
2909
+ * Like `_meta/policy` and `_meta/handle`, the documents are plain JSON
2910
+ * with empty `_iv` — the recovery-code wrapping is what protects the
2911
+ * KEK; the entries themselves are inert without the user's code.
2912
+ *
2913
+ * @module
2914
+ */
2915
+
2916
+ /**
2917
+ * One paper recovery code as persisted in `_meta/recovery-paper`.
2918
+ *
2919
+ * The hub's KEK is intentionally non-extractable (see `crypto.ts`),
2920
+ * so the recovery entry can't AES-KW-wrap the KEK directly. Instead
2921
+ * we wrap a serialized DEK set: the entry holds the AES-GCM
2922
+ * ciphertext of `{ deks: { collection: rawDekBase64 } }`. Recovery
2923
+ * deserializes the DEK set, then mints a fresh KEK from the new
2924
+ * passphrase and rewraps the DEKs under it.
2925
+ *
2926
+ * This is the same pattern `@noy-db/on-pin` uses for tier-3 quick
2927
+ * resume — the cryptographic guarantee is identical (AES-GCM with a
2928
+ * PBKDF2-derived key), and it sidesteps the non-extractable-KEK
2929
+ * constraint cleanly.
2930
+ */
2931
+ interface PaperRecoveryEntry {
2932
+ readonly codeId: string;
2933
+ /** Base64 PBKDF2 salt. */
2934
+ readonly salt: string;
2935
+ /** Base64 AES-GCM IV used for the wrapped-DEK ciphertext. */
2936
+ readonly iv: string;
2937
+ /** Base64 AES-GCM ciphertext — JSON `{ deks: Record<string, base64> }`. */
2938
+ readonly wrappedDeks: string;
2939
+ readonly enrolledAt: string;
2940
+ }
2941
+ interface PaperRecoveryDoc {
2942
+ readonly _noydb_recovery: 1;
2943
+ readonly profile: 'paper';
2944
+ readonly entries: ReadonlyArray<PaperRecoveryEntry>;
2945
+ }
2946
+ /** Read the paper-recovery entries. Returns empty array when absent. */
2947
+ declare function loadPaperRecoveryEntries(store: NoydbStore, vault: string): Promise<ReadonlyArray<PaperRecoveryEntry>>;
2948
+ /** Replace the paper-recovery entries (used after burn-on-recovery). */
2949
+ declare function savePaperRecoveryEntries(store: NoydbStore, vault: string, entries: ReadonlyArray<PaperRecoveryEntry>): Promise<void>;
2950
+ /** Drop a single paper-recovery entry (burn-on-use). */
2951
+ declare function burnPaperRecoveryEntry(store: NoydbStore, vault: string, codeId: string): Promise<void>;
2952
+ /** Whether at least one recovery profile has any enrolled entries. */
2953
+ declare function hasRecoveryEnrolled(store: NoydbStore, vault: string): Promise<boolean>;
2954
+
2955
+ /**
2956
+ * Public envelope — owner-curated plaintext metadata, readable
2957
+ * before vault unlock or bundle decryption.
2958
+ *
2959
+ * @see docs/subsystems/public-envelope.md
2960
+ *
2961
+ * @module
2962
+ */
2963
+ /**
2964
+ * Either a single string (used when the developer's app is
2965
+ * single-locale) or a locale → string map for i18n. Mirrors the
2966
+ * shape `@noy-db/hub/i18n` already uses for record fields, so the
2967
+ * existing `resolveI18nText` resolver applies.
2968
+ */
2969
+ type PublicEnvelopeText = string | Record<string, string>;
2970
+ /**
2971
+ * Persisted shape — both `_meta/public-envelope` and the bundle
2972
+ * header carry this. The version number is monotonic per vault and
2973
+ * helps cache invalidators detect change without hashing the JSON.
2974
+ */
2975
+ interface PublicEnvelope {
2976
+ readonly _noydb_public: 1;
2977
+ readonly version: number;
2978
+ readonly name?: PublicEnvelopeText;
2979
+ readonly description?: PublicEnvelopeText;
2980
+ /** Inline `data:` URL (`data:image/png;base64,…` or `data:image/svg+xml;base64,…`). */
2981
+ readonly icon?: string;
2982
+ /** ISO-8601 timestamp; auto-set on first envelope write, immutable thereafter. */
2983
+ readonly createdAt?: string;
2984
+ /** ISO-8601 timestamp; auto-updated on every `setPublicEnvelope` call. */
2985
+ readonly updatedAt?: string;
2986
+ /** BCP-47 fallback locale for renderers when the user's locale isn't covered. */
2987
+ readonly defaultLocale?: string;
2988
+ }
2989
+ /** Field names the developer can allow in `PublicEnvelopeSchema.fields`. */
2990
+ declare const PUBLIC_ENVELOPE_FIELDS: readonly ["name", "description", "icon", "createdAt", "updatedAt", "defaultLocale"];
2991
+ type PublicEnvelopeField = (typeof PUBLIC_ENVELOPE_FIELDS)[number];
2992
+ /**
2993
+ * Build-time schema. The developer enables the feature and bounds
2994
+ * what the owner can set. `true` is shorthand for "all defaults" —
2995
+ * gives the owner the full field set with the standard caps.
2996
+ */
2997
+ interface PublicEnvelopeSchema {
2998
+ /**
2999
+ * Allowed field names. Setting `name`/`description`/`icon`/`defaultLocale` is
3000
+ * gated on the field being listed here. `createdAt` / `updatedAt` are managed
3001
+ * by the hub; including them is a no-op (the owner cannot set them
3002
+ * directly). Default: every field above.
3003
+ */
3004
+ readonly fields?: ReadonlyArray<PublicEnvelopeField>;
3005
+ /**
3006
+ * Maximum icon size — measured as the length of the data-URL
3007
+ * string. Default 256 KB.
3008
+ */
3009
+ readonly maxIconBytes?: number;
3010
+ /** Allowed icon MIME types. Default ['image/png', 'image/svg+xml']. */
3011
+ readonly iconMimeTypes?: ReadonlyArray<string>;
3012
+ /** Maximum length of `name` / `description` per locale. Default 200. */
3013
+ readonly maxStringChars?: number;
3014
+ }
3015
+ /** Default schema values; merged onto every developer-supplied schema. */
3016
+ declare const DEFAULT_PUBLIC_ENVELOPE_SCHEMA: {
3017
+ readonly fields: readonly ["name", "description", "icon", "createdAt", "updatedAt", "defaultLocale"];
3018
+ readonly maxIconBytes: number;
3019
+ readonly iconMimeTypes: readonly ["image/png", "image/svg+xml"];
3020
+ readonly maxStringChars: 200;
3021
+ };
3022
+ /** Resolved schema after merging developer override onto defaults. */
3023
+ interface ResolvedPublicEnvelopeSchema {
3024
+ readonly fields: ReadonlyArray<PublicEnvelopeField>;
3025
+ readonly maxIconBytes: number;
3026
+ readonly iconMimeTypes: ReadonlyArray<string>;
3027
+ readonly maxStringChars: number;
3028
+ }
3029
+ /**
3030
+ * Merge developer schema onto the defaults. The shorthand `true`
3031
+ * resolves to the full default schema; an explicit object only
3032
+ * overrides the keys it provides.
3033
+ */
3034
+ declare function resolveSchema(schema: true | PublicEnvelopeSchema | undefined): ResolvedPublicEnvelopeSchema | undefined;
3035
+
3036
+ /** Owner-supplied input — the subset of {@link PublicEnvelope} the owner can set. */
3037
+ interface SetPublicEnvelopeInput {
3038
+ readonly name?: PublicEnvelopeText;
3039
+ readonly description?: PublicEnvelopeText;
3040
+ readonly icon?: string;
3041
+ readonly defaultLocale?: string;
3042
+ }
3043
+ /**
3044
+ * Validate an owner-supplied envelope input against the developer's
3045
+ * resolved schema. Throws `ValidationError` on the first violation;
3046
+ * returns void on success.
3047
+ *
3048
+ * The validator is deliberately strict: every fail mode is a hard
3049
+ * error rather than a silent drop, so the owner finds out immediately
3050
+ * which field they oversized rather than discovering a truncated
3051
+ * label months later.
3052
+ */
3053
+ declare function validatePublicEnvelopeInput(input: SetPublicEnvelopeInput, schema: ResolvedPublicEnvelopeSchema): void;
3054
+ /**
3055
+ * Lightweight runtime predicate — used by the bundle header
3056
+ * validator to recognise a public envelope without requiring it.
3057
+ */
3058
+ declare function isPublicEnvelope(x: unknown): x is PublicEnvelope;
3059
+
3060
+ /**
3061
+ * Tier-2 authenticator slot management — issue #11.
3062
+ *
3063
+ * Each slot independently wraps the SAME KEK under a method-specific
3064
+ * derived key (LUKS pattern). Enrolling adds a slot; removing drops
3065
+ * one. Both are constant-time keyring writes — no DEK re-keying.
3066
+ *
3067
+ * The crypto for each method lives in its `@noy-db/on-*` package
3068
+ * (`on-webauthn`, `on-oidc`, `on-password`); this module accepts the
3069
+ * package's `wrapped_kek` ciphertext + `meta` payload and persists it.
3070
+ *
3071
+ * @see docs/subsystems/session-tiers.md → Tier 2 — Authenticate
3072
+ *
3073
+ * @module
3074
+ */
3075
+
3076
+ /** Input shape for `enrollAuthenticator`. */
3077
+ interface EnrollAuthenticatorOptions {
3078
+ readonly id: string;
3079
+ readonly method: KeyringAuthenticator['method'];
3080
+ /** Already-wrapped KEK ciphertext (base64) — produced by the on-* package. */
3081
+ readonly wrapped_kek: string;
3082
+ /** Method-specific metadata (cred id, salt, …). */
3083
+ readonly meta: Record<string, unknown>;
3084
+ /** Tier the active session held when enrolling. Defaults to 1. */
3085
+ readonly enrolled_via_tier?: 1 | 2;
3086
+ }
3087
+ /**
3088
+ * Append a new authenticator slot to the keyring file. Throws
3089
+ * `ValidationError` if a slot with the same id already exists — the
3090
+ * caller decides whether to remove + re-enroll.
3091
+ */
3092
+ declare function enrollAuthenticator(store: NoydbStore, vault: string, keyring: UnlockedKeyring, options: EnrollAuthenticatorOptions): Promise<UnlockedKeyring>;
3093
+ /**
3094
+ * Drop a slot by id. No-op if the slot doesn't exist (idempotent —
3095
+ * removing a non-existent slot is a recoverable retry, not an error).
3096
+ */
3097
+ declare function removeAuthenticator(store: NoydbStore, vault: string, keyring: UnlockedKeyring, slotId: string): Promise<UnlockedKeyring>;
3098
+ /**
3099
+ * Look up a slot by id. Returns `undefined` when no slot matches.
3100
+ * Used by tier-2 unlock dispatchers to fetch the wrapped KEK + meta
3101
+ * before invoking the method-specific verifier.
3102
+ */
3103
+ declare function findAuthenticator(keyring: UnlockedKeyring, slotId: string): KeyringAuthenticator | undefined;
3104
+
3105
+ /**
3106
+ * Per-vault tier-3 (PIN / quick-resume) state — issue #11.
3107
+ *
3108
+ * The hub holds a `PinResumeState`-shaped record in memory, keyed by
3109
+ * vault. `enrollUnlock` populates it; `unlockViaPin` consumes it via
3110
+ * `@noy-db/on-pin`'s `resumePin`. The cached state is wiped when the
3111
+ * idle timer fires or `db.close()` is called.
3112
+ *
3113
+ * Importantly, this module does NOT depend on `@noy-db/on-pin` — the
3114
+ * caller passes the already-built state in. That keeps the hub's
3115
+ * `peerDependencies` empty for tier-3 and lets developers swap the
3116
+ * primitive (e.g. an OS biometric in place of a PIN).
3117
+ *
3118
+ * @module
3119
+ */
3120
+ /**
3121
+ * Opaque `PinResumeState`-compatible record. Mirrored from
3122
+ * `@noy-db/on-pin/PinResumeState`. The hub treats the contents as
3123
+ * a black box.
3124
+ */
3125
+ interface QuickUnlockState {
3126
+ readonly _noydb_on_pin: 1;
3127
+ readonly salt: string;
3128
+ readonly iv: string;
3129
+ readonly wrappedKeyring: string;
3130
+ readonly expiresAt: string;
3131
+ readonly maxAttempts: number;
3132
+ attempts: number;
3133
+ }
3134
+ /** In-memory store for tier-3 unlock state, keyed by vault. */
3135
+ declare class QuickUnlockStore {
3136
+ private readonly states;
3137
+ private readonly timers;
3138
+ /**
3139
+ * Register a quick-unlock state for a vault. Replaces any existing
3140
+ * state. Schedules an automatic clear when the state's `expiresAt`
3141
+ * elapses.
3142
+ */
3143
+ set(vault: string, state: QuickUnlockState): void;
3144
+ /** Read the state for a vault. Returns undefined when none is registered. */
3145
+ get(vault: string): QuickUnlockState | undefined;
3146
+ /** Drop the state for a vault. Cancels the auto-clear timer. */
3147
+ delete(vault: string): void;
3148
+ /** Drop every cached state. Called on `db.close()`. */
3149
+ clear(): void;
3150
+ private clearTimer;
3151
+ }
3152
+
2718
3153
  /**
2719
3154
  * Multi-record atomic transactions.
2720
3155
  *
@@ -2853,6 +3288,84 @@ declare class TxCollection<T> {
2853
3288
  */
2854
3289
  declare function runTransaction<T>(db: Noydb, fn: (tx: TxContext) => Promise<T> | T): Promise<T>;
2855
3290
 
3291
+ /**
3292
+ * Policy gate DSL types — issue #9.
3293
+ *
3294
+ * Sensitive operations (rotate the passphrase, enroll an authenticator,
3295
+ * export plaintext, grant a user, …) are gated by a typed policy
3296
+ * object. The developer supplies a {@link VaultPolicy} at vault
3297
+ * creation; the hub merges it onto a built-in preset and persists the
3298
+ * merged document at `_meta/policy`.
3299
+ *
3300
+ * @see docs/subsystems/session-tiers.md → Policy gates DSL
3301
+ *
3302
+ * @module
3303
+ */
3304
+
3305
+ /** A single off-device factor surface — the proof an actor presents at gate time. */
3306
+ type FactorKind = 'totp' | 'email-otp' | 'recovery' | 'shamir' | 'webauthn-roaming';
3307
+ /**
3308
+ * One factor requirement entry. The default is "any one of the listed
3309
+ * factors, fresh within the last 5 minutes". Bumping `count` requires N
3310
+ * distinct fresh proofs; bumping `freshnessMs` widens the acceptance
3311
+ * window.
3312
+ */
3313
+ interface FactorRequirement {
3314
+ readonly anyOf: ReadonlyArray<FactorKind>;
3315
+ /** Number of distinct factors required. Default 1. */
3316
+ readonly count?: number;
3317
+ /** How recent each proof must be. Default 5 minutes. */
3318
+ readonly freshnessMs?: number;
3319
+ }
3320
+ /** Soft signals layered on top of the gate verdict — never block on their own. */
3321
+ interface WarningRules {
3322
+ /** Behavior on shared-device tier-1 ops. `'block'` raises a `PolicyDeniedError`. */
3323
+ readonly sharedDevice?: 'warn' | 'block';
3324
+ /** Behavior on weak tier-2 (e.g. password-only) for sensitive ops. */
3325
+ readonly weakAuthenticator?: 'warn' | 'block';
3326
+ }
3327
+ /**
3328
+ * Policy applied to one named gate. `enabled: false` disables the
3329
+ * action entirely (useful in managed-passphrase mode where rotation is
3330
+ * impossible by construction).
3331
+ */
3332
+ interface GatePolicy {
3333
+ /** Minimum tier the active session must hold. */
3334
+ readonly minTier: 1 | 2 | 3;
3335
+ /** Extra freshness-bound proofs required at gate time. */
3336
+ readonly factors?: ReadonlyArray<FactorRequirement>;
3337
+ readonly warn?: WarningRules;
3338
+ readonly enabled?: boolean;
3339
+ }
3340
+ /**
3341
+ * Built-in gate names. App-defined gates live in the `app:*` namespace
3342
+ * and use the same engine; the engine treats unknown names with no
3343
+ * configured policy as "no gate" (no-op).
3344
+ */
3345
+ type BuiltInGateName = 'rotate-passphrase' | 'recover-passphrase' | 'enroll-authenticator' | 'remove-authenticator' | 'rotate-unlock' | 'enroll-user' | 'revoke-user' | 'export-bundle' | 'export-plaintext' | 'view-user-auth';
3346
+ /** Either a built-in gate name or an `app:*` custom gate. */
3347
+ type GateName = BuiltInGateName | `app:${string}`;
3348
+ /**
3349
+ * Top-level policy object. Persisted at `_meta/policy` once at vault
3350
+ * creation. The `passphrase` block configures the strength rules
3351
+ * applied at every passphrase ingress (issue #7); `gates` configures
3352
+ * the action-level requirements.
3353
+ */
3354
+ interface VaultPolicy {
3355
+ readonly passphrase?: PassphrasePolicy;
3356
+ readonly gates: Partial<Record<GateName, GatePolicy>>;
3357
+ }
3358
+ /** Concrete proof an actor presents to {@link checkGate}. */
3359
+ interface FactorProof {
3360
+ readonly kind: FactorKind;
3361
+ /** ISO-8601 timestamp the proof was minted at. Compared against `freshnessMs`. */
3362
+ readonly mintedAt?: string;
3363
+ /** Method-specific payload. The engine treats it as opaque — verification is delegated. */
3364
+ readonly payload?: unknown;
3365
+ }
3366
+ /** Active session tier — what the engine compares against `gate.minTier`. */
3367
+ type ActiveTier = 1 | 2 | 3;
3368
+
2856
3369
  /** The top-level NOYDB instance. */
2857
3370
  declare class Noydb {
2858
3371
  private readonly options;
@@ -2860,6 +3373,25 @@ declare class Noydb {
2860
3373
  private readonly vaultCache;
2861
3374
  private readonly keyringCache;
2862
3375
  private readonly syncEngines;
3376
+ /**
3377
+ * Per-vault active session tier — defaults to `1` after a passphrase
3378
+ * unlock; tier-2 / tier-3 unlocks (issue #11) downgrade it. Used by
3379
+ * {@link checkGate} to evaluate `gate.minTier`.
3380
+ */
3381
+ private readonly activeTier;
3382
+ /**
3383
+ * Per-vault loaded policy. Cached after the first
3384
+ * `_meta/policy` load; replaced by `db.updatePolicy()`.
3385
+ */
3386
+ private readonly policyCache;
3387
+ /** Per-vault tier-3 (PIN / quick-resume) state — issue #11. */
3388
+ private readonly quickUnlock;
3389
+ /**
3390
+ * Resolved public-envelope schema. Lazily computed once from
3391
+ * `NoydbOptions.publicEnvelope`; `undefined` when the developer
3392
+ * didn't opt in.
3393
+ */
3394
+ private readonly publicEnvelopeSchema;
2863
3395
  private closed;
2864
3396
  private sessionTimer;
2865
3397
  /** Per-vault policy enforcers. */
@@ -3113,6 +3645,211 @@ declare class Noydb {
3113
3645
  * @internal — not part of the public API surface
3114
3646
  */
3115
3647
  invokeTranslator(text: string, from: string, to: string, field: string, collection: string): Promise<string>;
3648
+ /**
3649
+ * Read the active policy for a vault. Loads from `_meta/policy` on
3650
+ * first call; subsequent calls hit the in-memory cache. Throws
3651
+ * `ValidationError` if the vault has not been opened.
3652
+ */
3653
+ getPolicy(vault: string): Promise<VaultPolicy>;
3654
+ /**
3655
+ * Replace the policy document at `_meta/policy` and update the
3656
+ * in-memory cache. Gated by the `enroll-user` policy (a policy
3657
+ * change is fundamentally a privilege-management action).
3658
+ */
3659
+ updatePolicy(vault: string, override: Partial<VaultPolicy>): Promise<VaultPolicy>;
3660
+ /**
3661
+ * Evaluate a policy gate against the active session tier and the
3662
+ * presented factor proofs. Throws {@link PolicyDeniedError} on
3663
+ * denial; resolves with `void` on success.
3664
+ *
3665
+ * @param vault The vault whose policy applies.
3666
+ * @param gate Gate name — built-in (e.g. `'rotate-passphrase'`)
3667
+ * or app-defined (`app:*`).
3668
+ * @param presented Caller-supplied factor proofs.
3669
+ */
3670
+ checkGate(vault: string, gate: GateName, presented?: {
3671
+ factors?: ReadonlyArray<FactorProof>;
3672
+ sharedDevice?: boolean;
3673
+ }): Promise<void>;
3674
+ /** Read or persist the vault policy at `_meta/policy` on first open. */
3675
+ private bootstrapPolicy;
3676
+ /**
3677
+ * Throw {@link RecoveryNotEnrolledError} when the developer
3678
+ * explicitly opts into strict mandatory-recovery enforcement
3679
+ * (`createNoydb({ requireRecovery: true })`) and no recovery
3680
+ * entries are persisted.
3681
+ *
3682
+ * The default behavior is lenient — `recover-passphrase` is enabled
3683
+ * in `PERSONAL_POLICY` but the hub does not block vault open on
3684
+ * missing enrollment. v1.0 will flip the default to strict; for now,
3685
+ * apps that want the spec-mandated check turn it on per-vault.
3686
+ */
3687
+ private assertRecoveryEnrolled;
3688
+ /**
3689
+ * Internal accessor used by tier-2/tier-3 unlock paths (issue #11)
3690
+ * to mark the active session tier.
3691
+ * @internal
3692
+ */
3693
+ _setActiveTier(vault: string, tier: ActiveTier): void;
3694
+ /**
3695
+ * Add a tier-2 authenticator slot to the calling user's keyring.
3696
+ * Each slot independently wraps the SAME KEK under a method-specific
3697
+ * key — adding a slot is a constant-time keyring write.
3698
+ *
3699
+ * The wrapping ciphertext is produced by the corresponding
3700
+ * `@noy-db/on-*` package (e.g. `enrollPasswordAuthenticator` from
3701
+ * `@noy-db/on-password`); the hub persists the result.
3702
+ *
3703
+ * Gated by `enroll-authenticator`; `presented` carries any factor
3704
+ * proofs the active policy demands.
3705
+ */
3706
+ enrollAuthenticator(vault: string, options: EnrollAuthenticatorOptions, presented?: {
3707
+ factors?: ReadonlyArray<FactorProof>;
3708
+ sharedDevice?: boolean;
3709
+ }): Promise<void>;
3710
+ /**
3711
+ * Remove a tier-2 authenticator slot. Idempotent — removing a
3712
+ * non-existent slot is a successful no-op. Gated by
3713
+ * `remove-authenticator`.
3714
+ */
3715
+ removeAuthenticator(vault: string, slotId: string, presented?: {
3716
+ factors?: ReadonlyArray<FactorProof>;
3717
+ sharedDevice?: boolean;
3718
+ }): Promise<void>;
3719
+ /** Read the slot list for a vault. Internal — `describeAuthConfig` (#13) consumes this. */
3720
+ listAuthenticators(vault: string): Promise<ReadonlyArray<KeyringAuthenticator>>;
3721
+ /**
3722
+ * Resolve a slot by id, then hand the wrapped-KEK ciphertext + meta
3723
+ * to the caller-supplied verifier. The verifier is the
3724
+ * `unlockWith*` function from the corresponding `@noy-db/on-*`
3725
+ * package, e.g. `unlockWithPassword(slot, password)`.
3726
+ *
3727
+ * On success, mark the active session tier as 2 — subsequent
3728
+ * `checkGate` calls see a tier-2 unlock.
3729
+ */
3730
+ unlockViaAuthenticator(vault: string, slotId: string, verify: (slot: KeyringAuthenticator) => Promise<UnlockedKeyring>): Promise<UnlockedKeyring>;
3731
+ /**
3732
+ * Set the owner-curated public envelope for a vault. Throws
3733
+ * `ValidationError` if the developer did not opt the hub into
3734
+ * `publicEnvelope` via `NoydbOptions`, or if the input violates
3735
+ * the resolved schema (oversized icon, disallowed MIME, oversized
3736
+ * string, unknown field).
3737
+ *
3738
+ * `createdAt` is set on the first write and preserved on every
3739
+ * subsequent write. `updatedAt` is refreshed on every write.
3740
+ * `version` is monotonic — increments on every successful write.
3741
+ */
3742
+ setPublicEnvelope(vault: string, input: SetPublicEnvelopeInput): Promise<PublicEnvelope>;
3743
+ /**
3744
+ * Read the public envelope for a vault. Returns `undefined` when
3745
+ * none has been written. Pass `locale` to resolve any locale-map
3746
+ * fields to plain strings; omitting `locale` returns the raw map.
3747
+ *
3748
+ * Works even when the developer didn't enable
3749
+ * `publicEnvelope` — reads are passive and never throw on a
3750
+ * missing schema (the envelope is plaintext and exists on disk
3751
+ * regardless).
3752
+ */
3753
+ getPublicEnvelope(vault: string, opts?: {
3754
+ readonly locale?: string;
3755
+ }): Promise<PublicEnvelope | undefined>;
3756
+ /** English summary of the configured auth model. */
3757
+ describeAuthConfig(vault: string): Promise<string>;
3758
+ /** Mermaid `flowchart TB` source for the auth graph. */
3759
+ diagramAuthConfig(vault: string): Promise<string>;
3760
+ /**
3761
+ * Per-user enrollment summary. Gated by `view-user-auth` (default:
3762
+ * disabled). Sanitization is allowlist-based — never renders cred
3763
+ * ids, password hashes, secrets, or any field outside the allowlist.
3764
+ */
3765
+ describeUserAuth(vault: string, userId: string, factors?: {
3766
+ factors?: ReadonlyArray<FactorProof>;
3767
+ sharedDevice?: boolean;
3768
+ }): Promise<string>;
3769
+ /** Bulk variant for owner dashboards. Gated by `view-user-auth`. */
3770
+ describeAllUsersAuth(vault: string, factors?: {
3771
+ factors?: ReadonlyArray<FactorProof>;
3772
+ sharedDevice?: boolean;
3773
+ }): Promise<Array<{
3774
+ userId: string;
3775
+ description: string;
3776
+ }>>;
3777
+ /**
3778
+ * Rotate the user's passphrase (user remembers old). Validates the
3779
+ * new phrase against the configured `passphrase` policy, runs the
3780
+ * `rotate-passphrase` gate, then re-derives + re-wraps every DEK.
3781
+ *
3782
+ * Tier-2 authenticator slots are dropped — each slot wraps the old
3783
+ * KEK and would need its derivation key to be re-presented. Re-enrol
3784
+ * via `db.enrollAuthenticator` after rotation. Tracked as a
3785
+ * v0.1.0-pre.5 limitation.
3786
+ *
3787
+ * @throws `WeakPassphraseError` on a weak new phrase.
3788
+ * @throws `PolicyDeniedError` when the gate denies (missing factor, …).
3789
+ * @throws `InvalidKeyError` when `oldPassphrase` is wrong.
3790
+ */
3791
+ rotatePassphrase(vault: string, input: RotatePassphraseInput, factors?: {
3792
+ factors?: ReadonlyArray<FactorProof>;
3793
+ sharedDevice?: boolean;
3794
+ }): Promise<void>;
3795
+ /**
3796
+ * Reset the passphrase using a recovery proof (user forgot the old).
3797
+ * v0.1.0-pre.5 supports the `'paper'` profile end-to-end; the
3798
+ * other three profiles throw {@link RecoveryProfileNotImplementedError}.
3799
+ *
3800
+ * Burns the used recovery entry on success.
3801
+ */
3802
+ recoverPassphrase(vault: string, input: RecoverPassphraseInput, factors?: {
3803
+ factors?: ReadonlyArray<FactorProof>;
3804
+ sharedDevice?: boolean;
3805
+ }): Promise<void>;
3806
+ /**
3807
+ * Persist a recovery enrollment. v0.1.0-pre.5 accepts the `'paper'`
3808
+ * profile — the developer first calls
3809
+ * `@noy-db/on-recovery/generateRecoveryCodeSet` to mint codes +
3810
+ * entries, shows the codes to the user once, then hands the entries
3811
+ * here.
3812
+ *
3813
+ * ```ts
3814
+ * import { generateRecoveryCodeSet } from '@noy-db/on-recovery'
3815
+ * const { codes, entries } = await generateRecoveryCodeSet({ kek, count: 10 })
3816
+ * await db.enrollRecovery('acme', { profile: 'paper', entries })
3817
+ * showCodesToUser(codes)
3818
+ * ```
3819
+ */
3820
+ enrollRecovery(vault: string, enrollment: {
3821
+ profile: 'paper';
3822
+ entries: ReadonlyArray<PaperRecoveryEntry>;
3823
+ }): Promise<void>;
3824
+ /** Read the persisted paper-recovery entries. Used by `describeAuthConfig` (#13). */
3825
+ listRecoveryEntries(vault: string): Promise<{
3826
+ paper: ReadonlyArray<PaperRecoveryEntry>;
3827
+ }>;
3828
+ /**
3829
+ * Register a tier-3 quick-unlock state for the vault. The state is
3830
+ * an opaque blob produced by `@noy-db/on-pin/enrollPin` (or any
3831
+ * compatible primitive). It is held in memory only — never persisted
3832
+ * — and auto-clears when its `expiresAt` elapses.
3833
+ *
3834
+ * Gated by `rotate-unlock` (the same gate covers "set" and "rotate"
3835
+ * because tier-3 is a single-slot rolling secret).
3836
+ */
3837
+ enrollUnlock(vault: string, state: QuickUnlockState, presented?: {
3838
+ factors?: ReadonlyArray<FactorProof>;
3839
+ sharedDevice?: boolean;
3840
+ }): Promise<void>;
3841
+ /**
3842
+ * Resume a session via the registered tier-3 state. The verifier is
3843
+ * `@noy-db/on-pin/resumePin` (or compatible). On success, mark the
3844
+ * active session tier as 3 — every operation must re-authenticate at
3845
+ * tier 2 to elevate.
3846
+ *
3847
+ * Returns `undefined` (caller should fall back to tier 2) when no
3848
+ * tier-3 state is registered.
3849
+ */
3850
+ unlockViaPin(vault: string, resume: (state: QuickUnlockState) => Promise<UnlockedKeyring>): Promise<UnlockedKeyring | undefined>;
3851
+ /** Drop the tier-3 state for a vault — explicit logout. */
3852
+ clearQuickUnlock(vault: string): void;
3116
3853
  /** Get or load the keyring for a vault. */
3117
3854
  private getKeyring;
3118
3855
  }
@@ -4368,6 +5105,22 @@ declare class Vault {
4368
5105
  * separate vault instances now.
4369
5106
  */
4370
5107
  getBundleHandle(): Promise<string>;
5108
+ /**
5109
+ * Read the owner-curated public envelope for this vault (or
5110
+ * `undefined` if none is persisted). The envelope lives in
5111
+ * `_meta/public-envelope` as plaintext — readable without any KEK
5112
+ * — so `getBundleHandle`-style callers can label a vault before
5113
+ * unlock.
5114
+ *
5115
+ * Mirrors `Noydb.getPublicEnvelope(vault, opts)` but scoped to a
5116
+ * single, already-opened `Vault` instance so the
5117
+ * bundle writer can snapshot it without holding a `Noydb` reference.
5118
+ *
5119
+ * @see docs/subsystems/public-envelope.md
5120
+ */
5121
+ getPublicEnvelope(opts?: {
5122
+ readonly locale?: string;
5123
+ }): Promise<PublicEnvelope | undefined>;
4371
5124
  /**
4372
5125
  * Dump vault as a verifiable encrypted JSON backup string.
4373
5126
  *
@@ -6448,6 +7201,71 @@ interface ImportCapability {
6448
7201
  readonly plaintext?: readonly ExportFormat[];
6449
7202
  readonly bundle?: boolean;
6450
7203
  }
7204
+ /**
7205
+ * Forward-declared on-disk shape for `VaultPolicy` — the actual policy
7206
+ * model lives in `policy/types.ts` (#9). Declared here as `unknown`-typed
7207
+ * map so types.ts has no dependency on the policy module while the
7208
+ * `KeyringFile.policy` field can still round-trip foreign documents.
7209
+ *
7210
+ * @internal
7211
+ */
7212
+ type VaultPolicyOnDisk = Record<string, unknown>;
7213
+ /**
7214
+ * Recovery profile enrolled at vault creation (issue #10).
7215
+ *
7216
+ * - `paper` — `on-recovery` codes (the only end-to-end profile in v0.1.0-pre.5).
7217
+ * - `shamir` / `multi-channel` / `admin-mediated` — API surface ships;
7218
+ * per-profile dispatch lands in follow-up issues. Calling
7219
+ * `db.recoverPassphrase` against these throws
7220
+ * {@link RecoveryProfileNotImplementedError}.
7221
+ */
7222
+ type RecoveryEnrollment = {
7223
+ readonly profile: 'paper';
7224
+ /** Number of single-use codes to print at enrollment. */
7225
+ readonly codes: number;
7226
+ } | {
7227
+ readonly profile: 'shamir';
7228
+ readonly k: number;
7229
+ readonly n: number;
7230
+ readonly trustees: ReadonlyArray<string>;
7231
+ } | {
7232
+ readonly profile: 'multi-channel';
7233
+ readonly email?: string;
7234
+ readonly pin?: boolean;
7235
+ readonly paperCodes?: number;
7236
+ } | {
7237
+ readonly profile: 'admin-mediated';
7238
+ readonly grantorUserId: string;
7239
+ };
7240
+ /**
7241
+ * One tier-2 authenticator slot inside a keyring file. Each slot
7242
+ * independently wraps the SAME KEK under a method-specific derived key
7243
+ * (LUKS pattern). Adding or removing a slot is a constant-time keyring
7244
+ * write — no DEK re-keying required.
7245
+ *
7246
+ * @see docs/subsystems/session-tiers.md → Tier 2 — Authenticate (multi-slot)
7247
+ */
7248
+ interface KeyringAuthenticator {
7249
+ /** Caller-chosen identifier — e.g. `'webauthn-yubikey-blue'`, `'oidc-google'`, `'password-daily'`. */
7250
+ readonly id: string;
7251
+ /** Method family — selects which `@noy-db/on-*` package handles unlock. */
7252
+ readonly method: 'webauthn' | 'oidc' | 'password';
7253
+ /** ISO-8601 timestamp at which the slot was added. */
7254
+ readonly enrolled_at: string;
7255
+ /**
7256
+ * Which session tier ENROLLED this slot. Tier 1 enrolls a fresh slot;
7257
+ * tier 2 may add a sibling slot when the active policy permits.
7258
+ */
7259
+ readonly enrolled_via_tier: 1 | 2;
7260
+ /** Base64 wrapped-KEK ciphertext under the method-derived key. */
7261
+ readonly wrapped_kek: string;
7262
+ /**
7263
+ * Method-specific metadata: WebAuthn cred id, OIDC issuer/sub, PBKDF2
7264
+ * salt for `on-password`, etc. The schema is open by design — the
7265
+ * `@noy-db/on-*` package owns the contents.
7266
+ */
7267
+ readonly meta: Record<string, unknown>;
7268
+ }
6451
7269
  interface KeyringFile {
6452
7270
  readonly _noydb_keyring: typeof NOYDB_KEYRING_VERSION;
6453
7271
  readonly user_id: string;
@@ -6458,6 +7276,23 @@ interface KeyringFile {
6458
7276
  readonly salt: string;
6459
7277
  readonly created_at: string;
6460
7278
  readonly granted_by: string;
7279
+ /**
7280
+ * Tier-2 authenticator slots (multi-slot keyring extension).
7281
+ * Optional / append-only: keyring files written before the
7282
+ * extension load with an empty list. Each slot independently wraps
7283
+ * the same KEK; any one of them unlocks.
7284
+ *
7285
+ * @see KeyringAuthenticator
7286
+ */
7287
+ readonly authenticators?: readonly KeyringAuthenticator[];
7288
+ /**
7289
+ * Per-keyring policy override (reserved). The on-disk format
7290
+ * accepts the field for forward compatibility with the Option C
7291
+ * merge engine deferred to a later release; v1.0 reads only the
7292
+ * vault-level `_meta/policy` document, so this field is parsed and
7293
+ * round-tripped but never enforced.
7294
+ */
7295
+ readonly policy?: VaultPolicyOnDisk;
6461
7296
  /**
6462
7297
  * Optional — authorization spec capability bits. Absent on keyrings written
6463
7298
  * before the RFC implementation. Loading falls back to role-based
@@ -6812,6 +7647,12 @@ interface GrantOptions {
6812
7647
  * is grantable until positively listed; bundle import is denied.
6813
7648
  */
6814
7649
  readonly importCapability?: ImportCapability;
7650
+ /**
7651
+ * Skip phrase-format strength validation (issue #7). Defaults to
7652
+ * false — `grant()` rejects phrases that don't meet the configured
7653
+ * `PassphrasePolicy`. Test fixtures and CLI scripts pass `true`.
7654
+ */
7655
+ readonly allowWeakPassphrase?: boolean;
6815
7656
  }
6816
7657
  interface RevokeOptions {
6817
7658
  readonly userId: string;
@@ -7385,8 +8226,47 @@ interface NoydbOptions {
7385
8226
  readonly sync?: NoydbStore | SyncTarget | SyncTarget[];
7386
8227
  /** User identifier. */
7387
8228
  readonly user: string;
7388
- /** Passphrase for key derivation. Required unless encrypt is false. */
8229
+ /** Passphrase for key derivation. Required unless encrypt is false or `getKeyring` is provided. */
7389
8230
  readonly secret?: string;
8231
+ /**
8232
+ * Optional callback that returns an unlocked keyring for a given vault.
8233
+ * Use this to plug in WebAuthn / OIDC / Shamir / any unlock path that
8234
+ * produces an `UnlockedKeyring` outside the passphrase model.
8235
+ *
8236
+ * When set, `secret` MUST NOT also be set — `createNoydb` throws if both
8237
+ * are supplied. When neither is set (and `encrypt !== false`), `createNoydb`
8238
+ * also throws.
8239
+ *
8240
+ * The callback is called lazily, on the first operation that needs the
8241
+ * keyring for a given vault. Noydb caches the returned keyring per-vault
8242
+ * for the lifetime of the instance, so the callback is invoked at most
8243
+ * once per `(instance, vault)` pair (assuming the callback resolves
8244
+ * successfully). If the callback rejects, the rejection surfaces from the
8245
+ * first vault operation that triggered the unlock; subsequent operations
8246
+ * will retry the callback.
8247
+ *
8248
+ * @example
8249
+ * ```ts
8250
+ * import { createNoydb } from '@noy-db/hub'
8251
+ * import { unlockWebAuthn } from '@noy-db/on-webauthn'
8252
+ *
8253
+ * const enrollment = await loadEnrollment()
8254
+ * const db = await createNoydb({
8255
+ * store,
8256
+ * user: 'alice',
8257
+ * getKeyring: (vault) => unlockWebAuthn(enrollment),
8258
+ * })
8259
+ * ```
8260
+ *
8261
+ * Note: this callback is responsible for both the "open existing vault"
8262
+ * and the "create new vault" cases. Unlike the passphrase path, there is
8263
+ * no automatic `NoAccessError` → `createOwnerKeyring` fallback, because
8264
+ * the callback owner has the UI context to decide which path to run.
8265
+ * For first-time bootstrap, use a passphrase or recovery code, enroll
8266
+ * WebAuthn from the unlocked keyring, then swap to `getKeyring` on
8267
+ * subsequent sessions.
8268
+ */
8269
+ readonly getKeyring?: (vault: string) => Promise<UnlockedKeyring>;
7390
8270
  /** Auth method. Default: 'passphrase'. */
7391
8271
  readonly auth?: 'passphrase' | 'biometric';
7392
8272
  /** Enable encryption. Default: true. */
@@ -7421,8 +8301,59 @@ interface NoydbOptions {
7421
8301
  * legacy `sessionTimeout` field.
7422
8302
  */
7423
8303
  readonly sessionPolicy?: SessionPolicy;
7424
- /** Validate passphrase strength on creation. Default: true. */
8304
+ /**
8305
+ * Validate passphrase strength against the phrase format
8306
+ * (`@noy-db/hub` issue #7) on first-time keyring creation. When
8307
+ * `true`, weak phrases throw {@link WeakPassphraseError} from
8308
+ * `createNoydb()` / `db.rotatePassphrase()`. Default: `false` for
8309
+ * back-compat in v0.1.x; planned to flip to `true` at v1.0.
8310
+ */
7425
8311
  readonly validatePassphrase?: boolean;
8312
+ /**
8313
+ * Vault-level policy gate document (issue #9). When present, the hub
8314
+ * persists the merged policy at `_meta/policy` on first-time vault
8315
+ * creation and gates sensitive operations (`db.rotatePassphrase`,
8316
+ * `db.export*`, …) against it. Omitted ⇒ the engine uses
8317
+ * {@link PERSONAL_POLICY}. Use {@link STRICT_POLICY} for regulated
8318
+ * deployments.
8319
+ *
8320
+ * The on-disk document is the source of truth — the policy field
8321
+ * is only honored at vault creation; subsequent runs read from
8322
+ * `_meta/policy`. Use `db.updatePolicy()` to change it deliberately.
8323
+ *
8324
+ * Imported from `@noy-db/hub` as a type-only reference; the runtime
8325
+ * import lives in `policy/index.ts`.
8326
+ */
8327
+ readonly policy?: VaultPolicy;
8328
+ /**
8329
+ * Mandatory recovery profile enrollment (issue #10). Vaults with
8330
+ * `recover-passphrase` enabled MUST register at least one profile
8331
+ * before being production-ready, otherwise `createNoydb()` throws
8332
+ * {@link RecoveryNotEnrolledError}. Set
8333
+ * `policy.gates['recover-passphrase'].enabled = false` to
8334
+ * deliberately opt out of recovery (passphrase loss = data loss).
8335
+ *
8336
+ * v0.1.0-pre.5 supports the `'paper'` profile end-to-end. Other
8337
+ * profiles ship the API shape and throw
8338
+ * {@link RecoveryProfileNotImplementedError} during use.
8339
+ */
8340
+ readonly recovery?: ReadonlyArray<RecoveryEnrollment>;
8341
+ /**
8342
+ * When `true`, `createNoydb` rejects vaults with no recovery
8343
+ * entries persisted (per the spec's mandatory-enrollment
8344
+ * requirement). Default `false` for v0.1.x back-compat; planned to
8345
+ * flip to `true` at v1.0. Apps in regulated environments should
8346
+ * turn this on now.
8347
+ */
8348
+ readonly requireRecovery?: boolean;
8349
+ /**
8350
+ * Enable the public envelope subsystem (`docs/subsystems/public-envelope.md`).
8351
+ * Pass `true` for the default schema (every standard field, 256 KB
8352
+ * icon cap, 200-char text cap), or a `PublicEnvelopeSchema` to
8353
+ * narrow what the owner can set. Off by default — vaults written
8354
+ * by hubs without this option carry no envelope, full stop.
8355
+ */
8356
+ readonly publicEnvelope?: true | PublicEnvelopeSchema;
7426
8357
  /** Audit history configuration. */
7427
8358
  readonly history?: HistoryConfig;
7428
8359
  /**
@@ -7523,4 +8454,4 @@ interface DeleteManyResult {
7523
8454
  }>;
7524
8455
  }
7525
8456
 
7526
- export { type ConsentAuditEntry as $, type BlobObject as A, type BlobStrategy as B, type BlobPutOptions as C, DICT_COLLECTION_PREFIX as D, type BlobResponseOptions as E, BlobSet as F, type BlobStrategyOpenArgs as G, type CompactRunOptions as H, type I18nStrategy as I, type CompactionContext as J, type CompactionResult as K, DEFAULT_CHUNK_SIZE as L, EXPORT_AUDIT_COLLECTION as M, ExportBlobsAbortedError as N, type ExportBlobsAuditEntry as O, PolicyEnforcer as P, type ExportBlobsHandle as Q, type ExportBlobsOptions as R, type SessionStrategy as S, type ExportedBlob as T, type SlotInfo as U, type SlotRecord as V, type VersionRecord as W, createExportBlobsHandle as X, runCompaction as Y, type ConsentStrategy as Z, CONSENT_AUDIT_COLLECTION as _, type DictEntry as a, type Conflict as a$, type ConsentAuditFilter as a0, type ConsentContext as a1, type ConsentOp as a2, loadConsentEntries as a3, writeConsentEntry as a4, type PeriodsStrategy as a5, type CarryForwardContext as a6, type ClosePeriodOptions as a7, type OpenPeriodOptions as a8, PERIODS_COLLECTION as a9, type DiffEntry as aA, type JsonPatch as aB, type JsonPatchOp as aC, type LedgerEntry as aD, LedgerStore as aE, type VaultEngine as aF, VaultInstant as aG, type VerifyResult as aH, applyPatch as aI, canonicalJson as aJ, computePatch as aK, diff as aL, formatDiff as aM, hashEntry as aN, paddedIndex as aO, parseIndex as aP, sha256Hex as aQ, Vault as aR, type AccessibleVault as aS, BUNDLE_STORE_POLICY as aT, type BundleRecipient as aU, type CacheOptions as aV, type CacheStats as aW, type ChangeEvent as aX, Collection as aY, type CollectionChangeEvent as aZ, type CollectionConflictResolver as a_, type PeriodRecord as aa, type ReadOnlyCollection as ab, appendPeriodLedgerEntry as ac, assertTsWritable as ad, chainAnchor as ae, loadPeriods as af, validatePeriodName as ag, type ShadowStrategy as ah, CollectionFrame as ai, VaultFrame as aj, type TxStrategy as ak, TxCollection as al, TxContext as am, TxVault as an, runTransaction as ao, type SyncStrategy as ap, type Role as aq, type UnlockedKeyring as ar, type HistoryStrategy as as, type NoydbStore as at, type HistoryOptions as au, type EncryptedEnvelope as av, type PruneOptions as aw, type AppendInput as ax, type ChangeType as ay, CollectionInstant as az, type DictKeyDescriptor as b, type SessionPolicy as b$, type ConflictPolicy as b0, type ConflictStrategy as b1, type CrossTierAccessEvent as b2, DELEGATIONS_COLLECTION as b3, type DelegationToken as b4, type DeleteManyResult as b5, type DirtyEntry as b6, ELEVATION_AUDIT_COLLECTION as b7, ElevatedHandle as b8, type ExportCapability as b9, NOYDB_KEYRING_VERSION as bA, NOYDB_SYNC_VERSION as bB, Noydb as bC, type NoydbBundleStore as bD, type NoydbEventMap as bE, type NoydbOptions as bF, type Permission as bG, type Permissions as bH, type PlaintextTranslatorContext as bI, type PlaintextTranslatorFn as bJ, PresenceHandle as bK, type PresencePeer as bL, type PullMode as bM, type PullOptions as bN, type PullPolicy as bO, type PullResult as bP, type PushMode as bQ, type PushOptions as bR, type PushPolicy as bS, type PushResult as bT, type PutManyItemOptions as bU, type PutManyOptions as bV, type PutManyResult as bW, type QueryAcrossOptions as bX, type QueryAcrossResult as bY, type ReAuthOperation as bZ, type RevokeOptions as b_, type ExportChunk as ba, type ExportFormat as bb, type ExportStreamOptions as bc, type GhostRecord as bd, type GrantOptions as be, type HistoryConfig as bf, type HistoryEntry as bg, INDEXED_STORE_POLICY as bh, type ImportCapability as bi, type InferOutput as bj, type IssueDelegationOptions as bk, type IssueMagicLinkGrantOptions as bl, type KeyringFile as bm, type ListAccessibleVaultsOptions as bn, type ListPageResult as bo, type LocaleReadOptions as bp, Lru as bq, type LruOptions as br, type LruStats as bs, MAGIC_LINK_CONTENT_INFO_PREFIX as bt, MAGIC_LINK_GRANTS_COLLECTION as bu, MAGIC_LINK_KEK_INFO_PREFIX as bv, type MagicLinkGrantPayload as bw, type MagicLinkGrantRecord as bx, NOYDB_BACKUP_VERSION as by, NOYDB_FORMAT_VERSION as bz, DictionaryHandle as c, type StandardSchemaV1 as c0, type StandardSchemaV1Issue as c1, type StandardSchemaV1SyncResult as c2, type StoreAuth as c3, type StoreAuthKind as c4, type StoreCapabilities as c5, SyncEngine as c6, type SyncMetadata as c7, type SyncPolicy as c8, SyncScheduler as c9, revokeDelegation as cA, revokeMagicLinkGrant as cB, unwrapMagicLinkGrant as cC, validateSchemaInput as cD, validateSchemaOutput as cE, writeMagicLinkGrant as cF, type SyncSchedulerStatus as ca, type SyncStatus as cb, type SyncTarget as cc, type SyncTargetRole as cd, SyncTransaction as ce, type SyncTransactionResult as cf, type TierMode as cg, type TranslatorAuditEntry as ch, type TxOp as ci, type UserInfo as cj, type VaultBackup as ck, type VaultSnapshot as cl, buildRecipientKeyringFile as cm, createNoydb as cn, createStore as co, deriveMagicLinkContentKey as cp, evaluateExportCapability as cq, evaluateImportCapability as cr, hasExportCapability as cs, hasImportCapability as ct, isMagicLinkGrantExpired as cu, issueDelegation as cv, listMagicLinkGrants as cw, loadActiveDelegations as cx, magicLinkGrantRecordId as cy, readMagicLinkGrantRecord as cz, type DictionaryOptions as d, type I18nTextDescriptor as e, type I18nTextOptions as f, applyI18nLocale as g, dictCollectionName as h, dictKey as i, i18nText as j, isDictCollectionName as k, isDictKeyDescriptor as l, isI18nTextDescriptor as m, createEnforcer as n, validateSessionPolicy as o, BLOB_CHUNKS_COLLECTION as p, BLOB_COLLECTION as q, resolveI18nText as r, BLOB_EVICTION_AUDIT_COLLECTION as s, BLOB_INDEX_COLLECTION as t, BLOB_SLOTS_PREFIX as u, validateI18nTextValue as v, BLOB_VERSIONS_PREFIX as w, type BlobEvictionEntry as x, type BlobFieldPolicy as y, type BlobFieldsConfig as z };
8457
+ export { type ConsentAuditEntry as $, type BlobObject as A, type BlobStrategy as B, type BlobPutOptions as C, DICT_COLLECTION_PREFIX as D, type BlobResponseOptions as E, BlobSet as F, type BlobStrategyOpenArgs as G, type CompactRunOptions as H, type I18nStrategy as I, type CompactionContext as J, type CompactionResult as K, DEFAULT_CHUNK_SIZE as L, EXPORT_AUDIT_COLLECTION as M, ExportBlobsAbortedError as N, type ExportBlobsAuditEntry as O, PolicyEnforcer as P, type ExportBlobsHandle as Q, type ExportBlobsOptions as R, type SessionStrategy as S, type ExportedBlob as T, type SlotInfo as U, type SlotRecord as V, type VersionRecord as W, createExportBlobsHandle as X, runCompaction as Y, type ConsentStrategy as Z, CONSENT_AUDIT_COLLECTION as _, type DictEntry as a, type BundleRecipient as a$, type ConsentAuditFilter as a0, type ConsentContext as a1, type ConsentOp as a2, loadConsentEntries as a3, writeConsentEntry as a4, type PeriodsStrategy as a5, type CarryForwardContext as a6, type ClosePeriodOptions as a7, type OpenPeriodOptions as a8, PERIODS_COLLECTION as a9, type DiffEntry as aA, type JsonPatch as aB, type JsonPatchOp as aC, type LedgerEntry as aD, LedgerStore as aE, type VaultEngine as aF, VaultInstant as aG, type VerifyResult as aH, applyPatch as aI, canonicalJson as aJ, computePatch as aK, diff as aL, formatDiff as aM, hashEntry as aN, paddedIndex as aO, parseIndex as aP, sha256Hex as aQ, type PublicEnvelope as aR, type GateName as aS, type GatePolicy as aT, type VaultPolicy as aU, type ActiveTier as aV, type FactorProof as aW, Vault as aX, type AccessibleVault as aY, BUNDLE_STORE_POLICY as aZ, type BuiltInGateName as a_, type PeriodRecord as aa, type ReadOnlyCollection as ab, appendPeriodLedgerEntry as ac, assertTsWritable as ad, chainAnchor as ae, loadPeriods as af, validatePeriodName as ag, type ShadowStrategy as ah, CollectionFrame as ai, VaultFrame as aj, type TxStrategy as ak, TxCollection as al, TxContext as am, TxVault as an, runTransaction as ao, type SyncStrategy as ap, type Role as aq, type UnlockedKeyring as ar, type HistoryStrategy as as, type NoydbStore as at, type HistoryOptions as au, type EncryptedEnvelope as av, type PruneOptions as aw, type AppendInput as ax, type ChangeType as ay, CollectionInstant as az, type DictKeyDescriptor as b, PresenceHandle as b$, type CacheOptions as b0, type CacheStats as b1, type ChangeEvent as b2, Collection as b3, type CollectionChangeEvent as b4, type CollectionConflictResolver as b5, type Conflict as b6, type ConflictPolicy as b7, type ConflictStrategy as b8, type CrossTierAccessEvent as b9, type ListPageResult as bA, type LocaleReadOptions as bB, Lru as bC, type LruOptions as bD, type LruStats as bE, MAGIC_LINK_CONTENT_INFO_PREFIX as bF, MAGIC_LINK_GRANTS_COLLECTION as bG, MAGIC_LINK_KEK_INFO_PREFIX as bH, type MagicLinkGrantPayload as bI, type MagicLinkGrantRecord as bJ, NOYDB_BACKUP_VERSION as bK, NOYDB_FORMAT_VERSION as bL, NOYDB_KEYRING_VERSION as bM, NOYDB_SYNC_VERSION as bN, Noydb as bO, type NoydbBundleStore as bP, type NoydbEventMap as bQ, type NoydbOptions as bR, PUBLIC_ENVELOPE_FIELDS as bS, type PaperRecoveryDoc as bT, type PaperRecoveryEntry as bU, type PassphrasePolicy as bV, type PassphraseValidationResult as bW, type Permission as bX, type Permissions as bY, type PlaintextTranslatorContext as bZ, type PlaintextTranslatorFn as b_, DEFAULT_PUBLIC_ENVELOPE_SCHEMA as ba, DELEGATIONS_COLLECTION as bb, type DelegationToken as bc, type DeleteManyResult as bd, type DirtyEntry as be, ELEVATION_AUDIT_COLLECTION as bf, ElevatedHandle as bg, type EnrollAuthenticatorOptions as bh, type ExportCapability as bi, type ExportChunk as bj, type ExportFormat as bk, type ExportStreamOptions as bl, type FactorKind as bm, type FactorRequirement as bn, type GhostRecord as bo, type GrantOptions as bp, type HistoryConfig as bq, type HistoryEntry as br, INDEXED_STORE_POLICY as bs, type ImportCapability as bt, type InferOutput as bu, type IssueDelegationOptions as bv, type IssueMagicLinkGrantOptions as bw, type KeyringAuthenticator as bx, type KeyringFile as by, type ListAccessibleVaultsOptions as bz, DictionaryHandle as c, findAuthenticator as c$, type PresencePeer as c0, type PublicEnvelopeField as c1, type PublicEnvelopeSchema as c2, type PublicEnvelopeText as c3, type PullMode as c4, type PullOptions as c5, type PullPolicy as c6, type PullResult as c7, type PushMode as c8, type PushOptions as c9, SyncScheduler as cA, type SyncSchedulerStatus as cB, type SyncStatus as cC, type SyncTarget as cD, type SyncTargetRole as cE, SyncTransaction as cF, type SyncTransactionResult as cG, type TierMode as cH, type TranslatorAuditEntry as cI, type TxOp as cJ, type UserInfo as cK, type VaultBackup as cL, type VaultPolicyOnDisk as cM, type VaultSnapshot as cN, type WarningRules as cO, WeakPassphraseError as cP, type WeakPassphraseReason as cQ, assertStrongPassphrase as cR, buildRecipientKeyringFile as cS, burnPaperRecoveryEntry as cT, createNoydb as cU, createStore as cV, deriveMagicLinkContentKey as cW, enrollAuthenticator as cX, estimateEntropy as cY, evaluateExportCapability as cZ, evaluateImportCapability as c_, type PushPolicy as ca, type PushResult as cb, type PutManyItemOptions as cc, type PutManyOptions as cd, type PutManyResult as ce, type QueryAcrossOptions as cf, type QueryAcrossResult as cg, type QuickUnlockState as ch, QuickUnlockStore as ci, type ReAuthOperation as cj, type RecoverPassphraseInput as ck, type RecoveryProof as cl, type ResolvedPublicEnvelopeSchema as cm, type RevokeOptions as cn, type RotatePassphraseInput as co, type SessionPolicy as cp, type SetPublicEnvelopeInput as cq, type StandardSchemaV1 as cr, type StandardSchemaV1Issue as cs, type StandardSchemaV1SyncResult as ct, type StoreAuth as cu, type StoreAuthKind as cv, type StoreCapabilities as cw, SyncEngine as cx, type SyncMetadata as cy, type SyncPolicy as cz, type DictionaryOptions as d, hasExportCapability as d0, hasImportCapability as d1, hasRecoveryEnrolled as d2, isMagicLinkGrantExpired as d3, isPublicEnvelope as d4, issueDelegation as d5, recoverPassphrase as d6, rotatePassphrase as d7, listMagicLinkGrants as d8, loadActiveDelegations as d9, loadPaperRecoveryEntries as da, magicLinkGrantRecordId as db, readMagicLinkGrantRecord as dc, removeAuthenticator as dd, resolveSchema as de, revokeDelegation as df, revokeMagicLinkGrant as dg, savePaperRecoveryEntries as dh, unwrapMagicLinkGrant as di, validatePassphrase as dj, validatePublicEnvelopeInput as dk, validateSchemaInput as dl, validateSchemaOutput as dm, writeMagicLinkGrant as dn, type I18nTextDescriptor as e, type I18nTextOptions as f, applyI18nLocale as g, dictCollectionName as h, dictKey as i, i18nText as j, isDictCollectionName as k, isDictKeyDescriptor as l, isI18nTextDescriptor as m, createEnforcer as n, validateSessionPolicy as o, BLOB_CHUNKS_COLLECTION as p, BLOB_COLLECTION as q, resolveI18nText as r, BLOB_EVICTION_AUDIT_COLLECTION as s, BLOB_INDEX_COLLECTION as t, BLOB_SLOTS_PREFIX as u, validateI18nTextValue as v, BLOB_VERSIONS_PREFIX as w, type BlobEvictionEntry as x, type BlobFieldPolicy as y, type BlobFieldsConfig as z };