@noy-db/hub 0.1.0-pre.10
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/LICENSE +21 -0
- package/README.md +197 -0
- package/dist/aggregate/index.cjs +476 -0
- package/dist/aggregate/index.cjs.map +1 -0
- package/dist/aggregate/index.d.cts +38 -0
- package/dist/aggregate/index.d.ts +38 -0
- package/dist/aggregate/index.js +53 -0
- package/dist/aggregate/index.js.map +1 -0
- package/dist/blobs/index.cjs +1480 -0
- package/dist/blobs/index.cjs.map +1 -0
- package/dist/blobs/index.d.cts +45 -0
- package/dist/blobs/index.d.ts +45 -0
- package/dist/blobs/index.js +48 -0
- package/dist/blobs/index.js.map +1 -0
- package/dist/bundle/index.cjs +496 -0
- package/dist/bundle/index.cjs.map +1 -0
- package/dist/bundle/index.d.cts +7 -0
- package/dist/bundle/index.d.ts +7 -0
- package/dist/bundle/index.js +51 -0
- package/dist/bundle/index.js.map +1 -0
- package/dist/chunk-2QR2PQTT.js +217 -0
- package/dist/chunk-2QR2PQTT.js.map +1 -0
- package/dist/chunk-72UIIX3E.js +1109 -0
- package/dist/chunk-72UIIX3E.js.map +1 -0
- package/dist/chunk-A4NFZKRW.js +722 -0
- package/dist/chunk-A4NFZKRW.js.map +1 -0
- package/dist/chunk-AOYCZP2H.js +793 -0
- package/dist/chunk-AOYCZP2H.js.map +1 -0
- package/dist/chunk-CIMZBAZB.js +72 -0
- package/dist/chunk-CIMZBAZB.js.map +1 -0
- package/dist/chunk-E3AGCGJ4.js +160 -0
- package/dist/chunk-E3AGCGJ4.js.map +1 -0
- package/dist/chunk-EKX3YVCI.js +97 -0
- package/dist/chunk-EKX3YVCI.js.map +1 -0
- package/dist/chunk-EMIGCR7X.js +39 -0
- package/dist/chunk-EMIGCR7X.js.map +1 -0
- package/dist/chunk-EMMRIE3C.js +72 -0
- package/dist/chunk-EMMRIE3C.js.map +1 -0
- package/dist/chunk-EUNIORPU.js +680 -0
- package/dist/chunk-EUNIORPU.js.map +1 -0
- package/dist/chunk-FZU343FL.js +32 -0
- package/dist/chunk-FZU343FL.js.map +1 -0
- package/dist/chunk-GHGXG53C.js +795 -0
- package/dist/chunk-GHGXG53C.js.map +1 -0
- package/dist/chunk-GKA4BGJN.js +79 -0
- package/dist/chunk-GKA4BGJN.js.map +1 -0
- package/dist/chunk-HG2OWBLX.js +430 -0
- package/dist/chunk-HG2OWBLX.js.map +1 -0
- package/dist/chunk-IGAROPKM.js +34 -0
- package/dist/chunk-IGAROPKM.js.map +1 -0
- package/dist/chunk-J66GRPNH.js +111 -0
- package/dist/chunk-J66GRPNH.js.map +1 -0
- package/dist/chunk-LVMMDXFT.js +275 -0
- package/dist/chunk-LVMMDXFT.js.map +1 -0
- package/dist/chunk-M5INGEFC.js +84 -0
- package/dist/chunk-M5INGEFC.js.map +1 -0
- package/dist/chunk-NBYQNDXA.js +557 -0
- package/dist/chunk-NBYQNDXA.js.map +1 -0
- package/dist/chunk-NPC4LFV5.js +132 -0
- package/dist/chunk-NPC4LFV5.js.map +1 -0
- package/dist/chunk-NSWHB5VQ.js +1285 -0
- package/dist/chunk-NSWHB5VQ.js.map +1 -0
- package/dist/chunk-OLM4LA6K.js +392 -0
- package/dist/chunk-OLM4LA6K.js.map +1 -0
- package/dist/chunk-UAFBZWFB.js +155 -0
- package/dist/chunk-UAFBZWFB.js.map +1 -0
- package/dist/chunk-UF3BUNQZ.js +1 -0
- package/dist/chunk-UF3BUNQZ.js.map +1 -0
- package/dist/chunk-UMMAVAYW.js +17 -0
- package/dist/chunk-UMMAVAYW.js.map +1 -0
- package/dist/chunk-UPY7WLBH.js +381 -0
- package/dist/chunk-UPY7WLBH.js.map +1 -0
- package/dist/chunk-W63BWEJH.js +311 -0
- package/dist/chunk-W63BWEJH.js.map +1 -0
- package/dist/chunk-WIGI5OJK.js +90 -0
- package/dist/chunk-WIGI5OJK.js.map +1 -0
- package/dist/chunk-XNL2TKKR.js +490 -0
- package/dist/chunk-XNL2TKKR.js.map +1 -0
- package/dist/chunk-XWNUJPIS.js +367 -0
- package/dist/chunk-XWNUJPIS.js.map +1 -0
- package/dist/chunk-YWKJZZGV.js +715 -0
- package/dist/chunk-YWKJZZGV.js.map +1 -0
- package/dist/consent/index.cjs +204 -0
- package/dist/consent/index.cjs.map +1 -0
- package/dist/consent/index.d.cts +24 -0
- package/dist/consent/index.d.ts +24 -0
- package/dist/consent/index.js +23 -0
- package/dist/consent/index.js.map +1 -0
- package/dist/crdt/index.cjs +152 -0
- package/dist/crdt/index.cjs.map +1 -0
- package/dist/crdt/index.d.cts +30 -0
- package/dist/crdt/index.d.ts +30 -0
- package/dist/crdt/index.js +24 -0
- package/dist/crdt/index.js.map +1 -0
- package/dist/crypto-6PNIHP7W.js +44 -0
- package/dist/crypto-6PNIHP7W.js.map +1 -0
- package/dist/delegation-WVIVMF73.js +17 -0
- package/dist/delegation-WVIVMF73.js.map +1 -0
- package/dist/dev-unlock-D4xB0_gs.d.cts +263 -0
- package/dist/dev-unlock-Dz8GEbd3.d.ts +263 -0
- package/dist/hash--EflSV65.d.cts +63 -0
- package/dist/hash-CRdXYnv3.d.ts +63 -0
- package/dist/history/index.cjs +1215 -0
- package/dist/history/index.cjs.map +1 -0
- package/dist/history/index.d.cts +62 -0
- package/dist/history/index.d.ts +62 -0
- package/dist/history/index.js +79 -0
- package/dist/history/index.js.map +1 -0
- package/dist/i18n/index.cjs +840 -0
- package/dist/i18n/index.cjs.map +1 -0
- package/dist/i18n/index.d.cts +38 -0
- package/dist/i18n/index.d.ts +38 -0
- package/dist/i18n/index.js +68 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/index-CD1VnONm.d.cts +415 -0
- package/dist/index-CLRxPs-W.d.cts +1960 -0
- package/dist/index-CUi9wfss.d.ts +415 -0
- package/dist/index-DtV93TMP.d.ts +1960 -0
- package/dist/index.cjs +17387 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +565 -0
- package/dist/index.d.ts +565 -0
- package/dist/index.js +7525 -0
- package/dist/index.js.map +1 -0
- package/dist/indexing/index.cjs +736 -0
- package/dist/indexing/index.cjs.map +1 -0
- package/dist/indexing/index.d.cts +36 -0
- package/dist/indexing/index.d.ts +36 -0
- package/dist/indexing/index.js +77 -0
- package/dist/indexing/index.js.map +1 -0
- package/dist/lazy-builder-BwEoBQZ9.d.ts +304 -0
- package/dist/lazy-builder-CZVLKh0Z.d.cts +304 -0
- package/dist/ledger-HBBH2NPZ.js +33 -0
- package/dist/ledger-HBBH2NPZ.js.map +1 -0
- package/dist/mime-magic-CBBSOkjm.d.cts +50 -0
- package/dist/mime-magic-CBBSOkjm.d.ts +50 -0
- package/dist/periods/index.cjs +1035 -0
- package/dist/periods/index.cjs.map +1 -0
- package/dist/periods/index.d.cts +21 -0
- package/dist/periods/index.d.ts +21 -0
- package/dist/periods/index.js +25 -0
- package/dist/periods/index.js.map +1 -0
- package/dist/predicate-SBHmi6D0.d.cts +161 -0
- package/dist/predicate-SBHmi6D0.d.ts +161 -0
- package/dist/public-envelope-TLQA6REO.js +31 -0
- package/dist/public-envelope-TLQA6REO.js.map +1 -0
- package/dist/query/index.cjs +1999 -0
- package/dist/query/index.cjs.map +1 -0
- package/dist/query/index.d.cts +3 -0
- package/dist/query/index.d.ts +3 -0
- package/dist/query/index.js +73 -0
- package/dist/query/index.js.map +1 -0
- package/dist/session/index.cjs +495 -0
- package/dist/session/index.cjs.map +1 -0
- package/dist/session/index.d.cts +45 -0
- package/dist/session/index.d.ts +45 -0
- package/dist/session/index.js +51 -0
- package/dist/session/index.js.map +1 -0
- package/dist/shadow/index.cjs +133 -0
- package/dist/shadow/index.cjs.map +1 -0
- package/dist/shadow/index.d.cts +16 -0
- package/dist/shadow/index.d.ts +16 -0
- package/dist/shadow/index.js +20 -0
- package/dist/shadow/index.js.map +1 -0
- package/dist/store/index.cjs +1083 -0
- package/dist/store/index.cjs.map +1 -0
- package/dist/store/index.d.cts +491 -0
- package/dist/store/index.d.ts +491 -0
- package/dist/store/index.js +37 -0
- package/dist/store/index.js.map +1 -0
- package/dist/strategy-BSxFXGzb.d.cts +110 -0
- package/dist/strategy-BSxFXGzb.d.ts +110 -0
- package/dist/strategy-D-SrOLCl.d.cts +548 -0
- package/dist/strategy-D-SrOLCl.d.ts +548 -0
- package/dist/sync/index.cjs +1062 -0
- package/dist/sync/index.cjs.map +1 -0
- package/dist/sync/index.d.cts +42 -0
- package/dist/sync/index.d.ts +42 -0
- package/dist/sync/index.js +28 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/team/index.cjs +2606 -0
- package/dist/team/index.cjs.map +1 -0
- package/dist/team/index.d.cts +117 -0
- package/dist/team/index.d.ts +117 -0
- package/dist/team/index.js +106 -0
- package/dist/team/index.js.map +1 -0
- package/dist/tx/index.cjs +212 -0
- package/dist/tx/index.cjs.map +1 -0
- package/dist/tx/index.d.cts +20 -0
- package/dist/tx/index.d.ts +20 -0
- package/dist/tx/index.js +20 -0
- package/dist/tx/index.js.map +1 -0
- package/dist/types-DSFLtbKg.d.ts +9702 -0
- package/dist/types-zwwMOqkg.d.cts +9702 -0
- package/dist/ulid-COREQ2RQ.js +9 -0
- package/dist/ulid-COREQ2RQ.js.map +1 -0
- package/dist/util/index.cjs +230 -0
- package/dist/util/index.cjs.map +1 -0
- package/dist/util/index.d.cts +77 -0
- package/dist/util/index.d.ts +77 -0
- package/dist/util/index.js +190 -0
- package/dist/util/index.js.map +1 -0
- package/package.json +244 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { at as NoydbStore, ar as UnlockedKeyring } from '../types-zwwMOqkg.cjs';
|
|
2
|
+
export { b0 as BundleRecipient, bk as EnrollAuthenticatorOptions, bl as EnrollAuthenticatorWrappingDEKsOptions, bm as EnrollAuthenticatorWrappingKEKOptions, c1 as PaperRecoveryEntry, c8 as PresenceHandle, ct as RecoverPassphraseInput, cu as RecoverPassphraseResult, cv as RecoverUserOptions, cw as RecoveryProof, cz as RotatePassphraseInput, cC as SlotRewrapCeremony, cD as SlotRewrapContext, cK as SyncEngine, cS as SyncTransaction, c_ as UpdateAuthenticatorOptions, db as WrappedDeksBlob, dd as buildRecipientKeyringFile, de as burnPaperRecoveryEntry, dT as changeSecret, dU as createOwnerKeyring, dh as deriveMagicLinkContentKey, di as enrollAuthenticator, dV as ensureCollectionDEK, dk as evaluateExportCapability, dl as evaluateImportCapability, dm as findAuthenticator, dW as grant, dn as hasExportCapability, dp as hasImportCapability, dr as isMagicLinkGrantExpired, dw as listMagicLinkGrants, dx as listUsers, dy as listUsersWithEnvelopes, dX as loadKeyring, dA as loadPaperRecoveryEntries, dB as magicLinkGrantRecordId, dC as mintPaperRecoveryEntry, dD as mintWrappedDeksBlob, dY as persistKeyring, dE as readMagicLinkGrantRecord, du as recoverPassphrase, dF as recoverUser, dG as removeAuthenticator, dZ as revoke, dJ as revokeMagicLinkGrant, dv as rotatePassphrase, dK as savePaperRecoveryEntries, dL as unwrapDeksFromBlob, dM as unwrapDeksFromPaperEntry, dN as unwrapMagicLinkGrant, d_ as updateAuthenticator, d$ as updateKeyringIdentity, dS as writeMagicLinkGrant } from '../types-zwwMOqkg.cjs';
|
|
3
|
+
import '../lazy-builder-CZVLKh0Z.cjs';
|
|
4
|
+
import '../predicate-SBHmi6D0.cjs';
|
|
5
|
+
import '../strategy-D-SrOLCl.cjs';
|
|
6
|
+
import '../strategy-BSxFXGzb.cjs';
|
|
7
|
+
import '../index-CLRxPs-W.cjs';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* _sync_credentials reserved collection —
|
|
11
|
+
*
|
|
12
|
+
* Stores per-adapter OAuth tokens (and any other long-lived sync secrets) as
|
|
13
|
+
* encrypted records inside the vault itself. Tokens are wrapped with the
|
|
14
|
+
* compartment's own DEK, live on disk as ciphertext like any other record, and
|
|
15
|
+
* are accessed only through the dedicated API in this module — never via
|
|
16
|
+
* `vault.collection('_sync_credentials')`.
|
|
17
|
+
*
|
|
18
|
+
* Design decisions
|
|
19
|
+
* ────────────────
|
|
20
|
+
*
|
|
21
|
+
* **Why a reserved collection, not a separate store?**
|
|
22
|
+
* The compartment's existing encryption stack (AES-256-GCM + collection DEK)
|
|
23
|
+
* is exactly the right primitive for protecting OAuth tokens at rest. Using a
|
|
24
|
+
* separate store would require a new encryption surface, new adapter calls,
|
|
25
|
+
* and a new backup/restore path — all of which already exist for collections.
|
|
26
|
+
*
|
|
27
|
+
* **Why not exposed as a regular collection?**
|
|
28
|
+
* The same reason `_keyring` and `_ledger` aren't: they have invariants that
|
|
29
|
+
* must be enforced (naming scheme, no cross-user leakage, no schema
|
|
30
|
+
* validation, no history/ledger writes for privacy). Routing through a
|
|
31
|
+
* dedicated API enforces those invariants.
|
|
32
|
+
*
|
|
33
|
+
* **Token lifecycle:**
|
|
34
|
+
* - `putCredential(vault, adapterId, token)` — store or overwrite
|
|
35
|
+
* - `getCredential(vault, adapterId)` — load and decrypt
|
|
36
|
+
* - `deleteCredential(vault, adapterId)` — remove
|
|
37
|
+
* - `listCredentials(vault)` — enumerate adapter IDs (not tokens)
|
|
38
|
+
*
|
|
39
|
+
* The `adapterId` is the record ID within the `_sync_credentials` collection.
|
|
40
|
+
* It should be a stable, human-readable identifier for the adapter instance
|
|
41
|
+
* (e.g. `'google-drive'`, `'dropbox'`, `'s3-prod'`).
|
|
42
|
+
*
|
|
43
|
+
* **ACL:** only `owner` and `admin` roles can read/write sync credentials.
|
|
44
|
+
* Operators, viewers, and clients cannot call this API. The check is made
|
|
45
|
+
* against the caller's keyring role at call time.
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
/** The reserved collection name. Never collides with user collections. */
|
|
49
|
+
declare const SYNC_CREDENTIALS_COLLECTION = "_sync_credentials";
|
|
50
|
+
/**
|
|
51
|
+
* An OAuth/auth token stored in `_sync_credentials`.
|
|
52
|
+
*
|
|
53
|
+
* Fields mirror the OAuth2 token response shape. `customData` is an escape
|
|
54
|
+
* hatch for adapter-specific secrets (API keys, connection strings, etc.)
|
|
55
|
+
* that don't fit the OAuth2 shape.
|
|
56
|
+
*/
|
|
57
|
+
interface SyncCredential {
|
|
58
|
+
/** Stable identifier for the adapter instance (e.g. 'google-drive'). */
|
|
59
|
+
readonly adapterId: string;
|
|
60
|
+
/** OAuth token type, usually 'Bearer'. */
|
|
61
|
+
readonly tokenType: string;
|
|
62
|
+
/** The access token. Expires at `expiresAt` if set. */
|
|
63
|
+
readonly accessToken: string;
|
|
64
|
+
/** Long-lived refresh token for renewing the access token. */
|
|
65
|
+
readonly refreshToken?: string;
|
|
66
|
+
/** ISO timestamp when `accessToken` expires. Absent means "no expiry". */
|
|
67
|
+
readonly expiresAt?: string;
|
|
68
|
+
/** Space-separated OAuth scopes. */
|
|
69
|
+
readonly scopes?: string;
|
|
70
|
+
/** Adapter-specific opaque data (API keys, endpoints, etc.). */
|
|
71
|
+
readonly customData?: Record<string, string>;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Store or overwrite a sync credential for the given adapter.
|
|
75
|
+
*
|
|
76
|
+
* The credential is encrypted with the `_sync_credentials` collection DEK
|
|
77
|
+
* (auto-generated on first use). The record ID is the `adapterId`.
|
|
78
|
+
*
|
|
79
|
+
* Requires owner or admin role.
|
|
80
|
+
*/
|
|
81
|
+
declare function putCredential(adapter: NoydbStore, vault: string, keyring: UnlockedKeyring, credential: SyncCredential): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Load and decrypt a sync credential for the given adapter ID.
|
|
84
|
+
*
|
|
85
|
+
* Returns `null` if no credential exists for this adapter.
|
|
86
|
+
* Requires owner or admin role.
|
|
87
|
+
*/
|
|
88
|
+
declare function getCredential(adapter: NoydbStore, vault: string, keyring: UnlockedKeyring, adapterId: string): Promise<SyncCredential | null>;
|
|
89
|
+
/**
|
|
90
|
+
* Delete a sync credential by adapter ID.
|
|
91
|
+
*
|
|
92
|
+
* No-op if the credential doesn't exist. Requires owner or admin role.
|
|
93
|
+
*/
|
|
94
|
+
declare function deleteCredential(adapter: NoydbStore, vault: string, keyring: UnlockedKeyring, adapterId: string): Promise<void>;
|
|
95
|
+
/**
|
|
96
|
+
* List all adapter IDs that have stored credentials.
|
|
97
|
+
*
|
|
98
|
+
* Returns only the IDs, never the credential payloads. Useful for
|
|
99
|
+
* displaying "connected adapters" in UI without decrypting tokens.
|
|
100
|
+
* Requires owner or admin role.
|
|
101
|
+
*/
|
|
102
|
+
declare function listCredentials(adapter: NoydbStore, vault: string, keyring: UnlockedKeyring): Promise<string[]>;
|
|
103
|
+
/**
|
|
104
|
+
* Check whether a credential exists and whether its access token has expired.
|
|
105
|
+
*
|
|
106
|
+
* Returns `{ exists: false }` if no credential is stored, or
|
|
107
|
+
* `{ exists: true, expired: boolean }` based on the `expiresAt` field.
|
|
108
|
+
* Requires owner or admin role.
|
|
109
|
+
*/
|
|
110
|
+
declare function credentialStatus(adapter: NoydbStore, vault: string, keyring: UnlockedKeyring, adapterId: string): Promise<{
|
|
111
|
+
exists: false;
|
|
112
|
+
} | {
|
|
113
|
+
exists: true;
|
|
114
|
+
expired: boolean;
|
|
115
|
+
}>;
|
|
116
|
+
|
|
117
|
+
export { SYNC_CREDENTIALS_COLLECTION, type SyncCredential, UnlockedKeyring, credentialStatus, deleteCredential, getCredential, listCredentials, putCredential };
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { at as NoydbStore, ar as UnlockedKeyring } from '../types-DSFLtbKg.js';
|
|
2
|
+
export { b0 as BundleRecipient, bk as EnrollAuthenticatorOptions, bl as EnrollAuthenticatorWrappingDEKsOptions, bm as EnrollAuthenticatorWrappingKEKOptions, c1 as PaperRecoveryEntry, c8 as PresenceHandle, ct as RecoverPassphraseInput, cu as RecoverPassphraseResult, cv as RecoverUserOptions, cw as RecoveryProof, cz as RotatePassphraseInput, cC as SlotRewrapCeremony, cD as SlotRewrapContext, cK as SyncEngine, cS as SyncTransaction, c_ as UpdateAuthenticatorOptions, db as WrappedDeksBlob, dd as buildRecipientKeyringFile, de as burnPaperRecoveryEntry, dT as changeSecret, dU as createOwnerKeyring, dh as deriveMagicLinkContentKey, di as enrollAuthenticator, dV as ensureCollectionDEK, dk as evaluateExportCapability, dl as evaluateImportCapability, dm as findAuthenticator, dW as grant, dn as hasExportCapability, dp as hasImportCapability, dr as isMagicLinkGrantExpired, dw as listMagicLinkGrants, dx as listUsers, dy as listUsersWithEnvelopes, dX as loadKeyring, dA as loadPaperRecoveryEntries, dB as magicLinkGrantRecordId, dC as mintPaperRecoveryEntry, dD as mintWrappedDeksBlob, dY as persistKeyring, dE as readMagicLinkGrantRecord, du as recoverPassphrase, dF as recoverUser, dG as removeAuthenticator, dZ as revoke, dJ as revokeMagicLinkGrant, dv as rotatePassphrase, dK as savePaperRecoveryEntries, dL as unwrapDeksFromBlob, dM as unwrapDeksFromPaperEntry, dN as unwrapMagicLinkGrant, d_ as updateAuthenticator, d$ as updateKeyringIdentity, dS as writeMagicLinkGrant } from '../types-DSFLtbKg.js';
|
|
3
|
+
import '../lazy-builder-BwEoBQZ9.js';
|
|
4
|
+
import '../predicate-SBHmi6D0.js';
|
|
5
|
+
import '../strategy-D-SrOLCl.js';
|
|
6
|
+
import '../strategy-BSxFXGzb.js';
|
|
7
|
+
import '../index-DtV93TMP.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* _sync_credentials reserved collection —
|
|
11
|
+
*
|
|
12
|
+
* Stores per-adapter OAuth tokens (and any other long-lived sync secrets) as
|
|
13
|
+
* encrypted records inside the vault itself. Tokens are wrapped with the
|
|
14
|
+
* compartment's own DEK, live on disk as ciphertext like any other record, and
|
|
15
|
+
* are accessed only through the dedicated API in this module — never via
|
|
16
|
+
* `vault.collection('_sync_credentials')`.
|
|
17
|
+
*
|
|
18
|
+
* Design decisions
|
|
19
|
+
* ────────────────
|
|
20
|
+
*
|
|
21
|
+
* **Why a reserved collection, not a separate store?**
|
|
22
|
+
* The compartment's existing encryption stack (AES-256-GCM + collection DEK)
|
|
23
|
+
* is exactly the right primitive for protecting OAuth tokens at rest. Using a
|
|
24
|
+
* separate store would require a new encryption surface, new adapter calls,
|
|
25
|
+
* and a new backup/restore path — all of which already exist for collections.
|
|
26
|
+
*
|
|
27
|
+
* **Why not exposed as a regular collection?**
|
|
28
|
+
* The same reason `_keyring` and `_ledger` aren't: they have invariants that
|
|
29
|
+
* must be enforced (naming scheme, no cross-user leakage, no schema
|
|
30
|
+
* validation, no history/ledger writes for privacy). Routing through a
|
|
31
|
+
* dedicated API enforces those invariants.
|
|
32
|
+
*
|
|
33
|
+
* **Token lifecycle:**
|
|
34
|
+
* - `putCredential(vault, adapterId, token)` — store or overwrite
|
|
35
|
+
* - `getCredential(vault, adapterId)` — load and decrypt
|
|
36
|
+
* - `deleteCredential(vault, adapterId)` — remove
|
|
37
|
+
* - `listCredentials(vault)` — enumerate adapter IDs (not tokens)
|
|
38
|
+
*
|
|
39
|
+
* The `adapterId` is the record ID within the `_sync_credentials` collection.
|
|
40
|
+
* It should be a stable, human-readable identifier for the adapter instance
|
|
41
|
+
* (e.g. `'google-drive'`, `'dropbox'`, `'s3-prod'`).
|
|
42
|
+
*
|
|
43
|
+
* **ACL:** only `owner` and `admin` roles can read/write sync credentials.
|
|
44
|
+
* Operators, viewers, and clients cannot call this API. The check is made
|
|
45
|
+
* against the caller's keyring role at call time.
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
/** The reserved collection name. Never collides with user collections. */
|
|
49
|
+
declare const SYNC_CREDENTIALS_COLLECTION = "_sync_credentials";
|
|
50
|
+
/**
|
|
51
|
+
* An OAuth/auth token stored in `_sync_credentials`.
|
|
52
|
+
*
|
|
53
|
+
* Fields mirror the OAuth2 token response shape. `customData` is an escape
|
|
54
|
+
* hatch for adapter-specific secrets (API keys, connection strings, etc.)
|
|
55
|
+
* that don't fit the OAuth2 shape.
|
|
56
|
+
*/
|
|
57
|
+
interface SyncCredential {
|
|
58
|
+
/** Stable identifier for the adapter instance (e.g. 'google-drive'). */
|
|
59
|
+
readonly adapterId: string;
|
|
60
|
+
/** OAuth token type, usually 'Bearer'. */
|
|
61
|
+
readonly tokenType: string;
|
|
62
|
+
/** The access token. Expires at `expiresAt` if set. */
|
|
63
|
+
readonly accessToken: string;
|
|
64
|
+
/** Long-lived refresh token for renewing the access token. */
|
|
65
|
+
readonly refreshToken?: string;
|
|
66
|
+
/** ISO timestamp when `accessToken` expires. Absent means "no expiry". */
|
|
67
|
+
readonly expiresAt?: string;
|
|
68
|
+
/** Space-separated OAuth scopes. */
|
|
69
|
+
readonly scopes?: string;
|
|
70
|
+
/** Adapter-specific opaque data (API keys, endpoints, etc.). */
|
|
71
|
+
readonly customData?: Record<string, string>;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Store or overwrite a sync credential for the given adapter.
|
|
75
|
+
*
|
|
76
|
+
* The credential is encrypted with the `_sync_credentials` collection DEK
|
|
77
|
+
* (auto-generated on first use). The record ID is the `adapterId`.
|
|
78
|
+
*
|
|
79
|
+
* Requires owner or admin role.
|
|
80
|
+
*/
|
|
81
|
+
declare function putCredential(adapter: NoydbStore, vault: string, keyring: UnlockedKeyring, credential: SyncCredential): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Load and decrypt a sync credential for the given adapter ID.
|
|
84
|
+
*
|
|
85
|
+
* Returns `null` if no credential exists for this adapter.
|
|
86
|
+
* Requires owner or admin role.
|
|
87
|
+
*/
|
|
88
|
+
declare function getCredential(adapter: NoydbStore, vault: string, keyring: UnlockedKeyring, adapterId: string): Promise<SyncCredential | null>;
|
|
89
|
+
/**
|
|
90
|
+
* Delete a sync credential by adapter ID.
|
|
91
|
+
*
|
|
92
|
+
* No-op if the credential doesn't exist. Requires owner or admin role.
|
|
93
|
+
*/
|
|
94
|
+
declare function deleteCredential(adapter: NoydbStore, vault: string, keyring: UnlockedKeyring, adapterId: string): Promise<void>;
|
|
95
|
+
/**
|
|
96
|
+
* List all adapter IDs that have stored credentials.
|
|
97
|
+
*
|
|
98
|
+
* Returns only the IDs, never the credential payloads. Useful for
|
|
99
|
+
* displaying "connected adapters" in UI without decrypting tokens.
|
|
100
|
+
* Requires owner or admin role.
|
|
101
|
+
*/
|
|
102
|
+
declare function listCredentials(adapter: NoydbStore, vault: string, keyring: UnlockedKeyring): Promise<string[]>;
|
|
103
|
+
/**
|
|
104
|
+
* Check whether a credential exists and whether its access token has expired.
|
|
105
|
+
*
|
|
106
|
+
* Returns `{ exists: false }` if no credential is stored, or
|
|
107
|
+
* `{ exists: true, expired: boolean }` based on the `expiresAt` field.
|
|
108
|
+
* Requires owner or admin role.
|
|
109
|
+
*/
|
|
110
|
+
declare function credentialStatus(adapter: NoydbStore, vault: string, keyring: UnlockedKeyring, adapterId: string): Promise<{
|
|
111
|
+
exists: false;
|
|
112
|
+
} | {
|
|
113
|
+
exists: true;
|
|
114
|
+
expired: boolean;
|
|
115
|
+
}>;
|
|
116
|
+
|
|
117
|
+
export { SYNC_CREDENTIALS_COLLECTION, type SyncCredential, UnlockedKeyring, credentialStatus, deleteCredential, getCredential, listCredentials, putCredential };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SYNC_CREDENTIALS_COLLECTION,
|
|
3
|
+
burnPaperRecoveryEntry,
|
|
4
|
+
credentialStatus,
|
|
5
|
+
deleteCredential,
|
|
6
|
+
deriveMagicLinkContentKey,
|
|
7
|
+
enrollAuthenticator,
|
|
8
|
+
findAuthenticator,
|
|
9
|
+
getCredential,
|
|
10
|
+
isMagicLinkGrantExpired,
|
|
11
|
+
listCredentials,
|
|
12
|
+
listMagicLinkGrants,
|
|
13
|
+
loadPaperRecoveryEntries,
|
|
14
|
+
magicLinkGrantRecordId,
|
|
15
|
+
mintPaperRecoveryEntry,
|
|
16
|
+
mintWrappedDeksBlob,
|
|
17
|
+
putCredential,
|
|
18
|
+
readMagicLinkGrantRecord,
|
|
19
|
+
recoverPassphrase,
|
|
20
|
+
recoverUser,
|
|
21
|
+
removeAuthenticator,
|
|
22
|
+
revokeMagicLinkGrant,
|
|
23
|
+
rotatePassphrase,
|
|
24
|
+
savePaperRecoveryEntries,
|
|
25
|
+
unwrapDeksFromBlob,
|
|
26
|
+
unwrapDeksFromPaperEntry,
|
|
27
|
+
unwrapMagicLinkGrant,
|
|
28
|
+
updateAuthenticator,
|
|
29
|
+
writeMagicLinkGrant
|
|
30
|
+
} from "../chunk-YWKJZZGV.js";
|
|
31
|
+
import {
|
|
32
|
+
PresenceHandle,
|
|
33
|
+
SyncEngine,
|
|
34
|
+
SyncTransaction
|
|
35
|
+
} from "../chunk-A4NFZKRW.js";
|
|
36
|
+
import "../chunk-IGAROPKM.js";
|
|
37
|
+
import {
|
|
38
|
+
buildRecipientKeyringFile,
|
|
39
|
+
changeSecret,
|
|
40
|
+
createOwnerKeyring,
|
|
41
|
+
ensureCollectionDEK,
|
|
42
|
+
evaluateExportCapability,
|
|
43
|
+
evaluateImportCapability,
|
|
44
|
+
grant,
|
|
45
|
+
hasExportCapability,
|
|
46
|
+
hasImportCapability,
|
|
47
|
+
listUsers,
|
|
48
|
+
listUsersWithEnvelopes,
|
|
49
|
+
loadKeyring,
|
|
50
|
+
persistKeyring,
|
|
51
|
+
revoke,
|
|
52
|
+
updateKeyringIdentity
|
|
53
|
+
} from "../chunk-GHGXG53C.js";
|
|
54
|
+
import "../chunk-2QR2PQTT.js";
|
|
55
|
+
import "../chunk-UMMAVAYW.js";
|
|
56
|
+
import "../chunk-LVMMDXFT.js";
|
|
57
|
+
import "../chunk-NBYQNDXA.js";
|
|
58
|
+
export {
|
|
59
|
+
PresenceHandle,
|
|
60
|
+
SYNC_CREDENTIALS_COLLECTION,
|
|
61
|
+
SyncEngine,
|
|
62
|
+
SyncTransaction,
|
|
63
|
+
buildRecipientKeyringFile,
|
|
64
|
+
burnPaperRecoveryEntry,
|
|
65
|
+
changeSecret,
|
|
66
|
+
createOwnerKeyring,
|
|
67
|
+
credentialStatus,
|
|
68
|
+
deleteCredential,
|
|
69
|
+
deriveMagicLinkContentKey,
|
|
70
|
+
enrollAuthenticator,
|
|
71
|
+
ensureCollectionDEK,
|
|
72
|
+
evaluateExportCapability,
|
|
73
|
+
evaluateImportCapability,
|
|
74
|
+
findAuthenticator,
|
|
75
|
+
getCredential,
|
|
76
|
+
grant,
|
|
77
|
+
hasExportCapability,
|
|
78
|
+
hasImportCapability,
|
|
79
|
+
isMagicLinkGrantExpired,
|
|
80
|
+
listCredentials,
|
|
81
|
+
listMagicLinkGrants,
|
|
82
|
+
listUsers,
|
|
83
|
+
listUsersWithEnvelopes,
|
|
84
|
+
loadKeyring,
|
|
85
|
+
loadPaperRecoveryEntries,
|
|
86
|
+
magicLinkGrantRecordId,
|
|
87
|
+
mintPaperRecoveryEntry,
|
|
88
|
+
mintWrappedDeksBlob,
|
|
89
|
+
persistKeyring,
|
|
90
|
+
putCredential,
|
|
91
|
+
readMagicLinkGrantRecord,
|
|
92
|
+
recoverPassphrase,
|
|
93
|
+
recoverUser,
|
|
94
|
+
removeAuthenticator,
|
|
95
|
+
revoke,
|
|
96
|
+
revokeMagicLinkGrant,
|
|
97
|
+
rotatePassphrase,
|
|
98
|
+
savePaperRecoveryEntries,
|
|
99
|
+
unwrapDeksFromBlob,
|
|
100
|
+
unwrapDeksFromPaperEntry,
|
|
101
|
+
unwrapMagicLinkGrant,
|
|
102
|
+
updateAuthenticator,
|
|
103
|
+
updateKeyringIdentity,
|
|
104
|
+
writeMagicLinkGrant
|
|
105
|
+
};
|
|
106
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/tx/index.ts
|
|
21
|
+
var tx_exports = {};
|
|
22
|
+
__export(tx_exports, {
|
|
23
|
+
TxCollection: () => TxCollection,
|
|
24
|
+
TxContext: () => TxContext,
|
|
25
|
+
TxVault: () => TxVault,
|
|
26
|
+
runTransaction: () => runTransaction,
|
|
27
|
+
withTransactions: () => withTransactions
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(tx_exports);
|
|
30
|
+
|
|
31
|
+
// src/errors.ts
|
|
32
|
+
var NoydbError = class extends Error {
|
|
33
|
+
/** Machine-readable error code. Stable across library versions. */
|
|
34
|
+
code;
|
|
35
|
+
constructor(code, message) {
|
|
36
|
+
super(message);
|
|
37
|
+
this.name = "NoydbError";
|
|
38
|
+
this.code = code;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
var ConflictError = class extends NoydbError {
|
|
42
|
+
/** The actual stored version at the time of conflict. */
|
|
43
|
+
version;
|
|
44
|
+
constructor(version, message = "Version conflict") {
|
|
45
|
+
super("CONFLICT", message);
|
|
46
|
+
this.name = "ConflictError";
|
|
47
|
+
this.version = version;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// src/tx/transaction.ts
|
|
52
|
+
var TxContext = class {
|
|
53
|
+
/** @internal */
|
|
54
|
+
_ops = [];
|
|
55
|
+
/** @internal */
|
|
56
|
+
_db;
|
|
57
|
+
/** @internal */
|
|
58
|
+
constructor(db) {
|
|
59
|
+
this._db = db;
|
|
60
|
+
}
|
|
61
|
+
/** Scope subsequent `collection()` calls to the named vault. */
|
|
62
|
+
vault(name) {
|
|
63
|
+
const v = this._db.vault(name);
|
|
64
|
+
return new TxVault(this, v);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
var TxVault = class {
|
|
68
|
+
/** @internal */
|
|
69
|
+
_ctx;
|
|
70
|
+
/** @internal */
|
|
71
|
+
_vault;
|
|
72
|
+
/** @internal */
|
|
73
|
+
constructor(ctx, vault) {
|
|
74
|
+
this._ctx = ctx;
|
|
75
|
+
this._vault = vault;
|
|
76
|
+
}
|
|
77
|
+
/** Scope subsequent op calls to the named collection. */
|
|
78
|
+
collection(name) {
|
|
79
|
+
const c = this._vault.collection(name);
|
|
80
|
+
return new TxCollection(this._ctx, this._vault, c, name);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
var TxCollection = class {
|
|
84
|
+
/** @internal */
|
|
85
|
+
_ctx;
|
|
86
|
+
/** @internal */
|
|
87
|
+
_vault;
|
|
88
|
+
/** @internal */
|
|
89
|
+
_coll;
|
|
90
|
+
/** @internal */
|
|
91
|
+
_name;
|
|
92
|
+
/** @internal */
|
|
93
|
+
constructor(ctx, vault, coll, name) {
|
|
94
|
+
this._ctx = ctx;
|
|
95
|
+
this._vault = vault;
|
|
96
|
+
this._coll = coll;
|
|
97
|
+
this._name = name;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Read the current committed value, or the most-recently-staged
|
|
101
|
+
* value from the same transaction if one exists.
|
|
102
|
+
*/
|
|
103
|
+
async get(id) {
|
|
104
|
+
for (let i = this._ctx._ops.length - 1; i >= 0; i--) {
|
|
105
|
+
const op = this._ctx._ops[i];
|
|
106
|
+
if (op.vaultName === this._vault.name && op.collectionName === this._name && op.id === id) {
|
|
107
|
+
if (op.type === "delete") return null;
|
|
108
|
+
return op.record;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return this._coll.get(id);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Stage a put. Does not write until the transaction body returns.
|
|
115
|
+
* Supply `{ expectedVersion }` to enforce optimistic concurrency
|
|
116
|
+
* during the commit pre-flight.
|
|
117
|
+
*/
|
|
118
|
+
put(id, record, options) {
|
|
119
|
+
const op = {
|
|
120
|
+
type: "put",
|
|
121
|
+
vaultName: this._vault.name,
|
|
122
|
+
collectionName: this._name,
|
|
123
|
+
id,
|
|
124
|
+
record
|
|
125
|
+
};
|
|
126
|
+
if (options?.expectedVersion !== void 0) op.expectedVersion = options.expectedVersion;
|
|
127
|
+
this._ctx._ops.push(op);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Stage a delete. Does not write until the transaction body returns.
|
|
131
|
+
* Supply `{ expectedVersion }` to enforce optimistic concurrency
|
|
132
|
+
* during the commit pre-flight.
|
|
133
|
+
*/
|
|
134
|
+
delete(id, options) {
|
|
135
|
+
const op = {
|
|
136
|
+
type: "delete",
|
|
137
|
+
vaultName: this._vault.name,
|
|
138
|
+
collectionName: this._name,
|
|
139
|
+
id
|
|
140
|
+
};
|
|
141
|
+
if (options?.expectedVersion !== void 0) op.expectedVersion = options.expectedVersion;
|
|
142
|
+
this._ctx._ops.push(op);
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
async function runTransaction(db, fn) {
|
|
146
|
+
const ctx = new TxContext(db);
|
|
147
|
+
const bodyResult = await fn(ctx);
|
|
148
|
+
if (ctx._ops.length === 0) return bodyResult;
|
|
149
|
+
const priorEnvelopes = /* @__PURE__ */ new Map();
|
|
150
|
+
const store = db._store;
|
|
151
|
+
for (const op of ctx._ops) {
|
|
152
|
+
const key = keyOf(op);
|
|
153
|
+
if (!priorEnvelopes.has(key)) {
|
|
154
|
+
const env = await store.get(op.vaultName, op.collectionName, op.id);
|
|
155
|
+
priorEnvelopes.set(key, env);
|
|
156
|
+
}
|
|
157
|
+
if (op.expectedVersion !== void 0) {
|
|
158
|
+
const env = priorEnvelopes.get(key) ?? null;
|
|
159
|
+
const actual = env?._v ?? 0;
|
|
160
|
+
if (actual !== op.expectedVersion) {
|
|
161
|
+
throw new ConflictError(
|
|
162
|
+
actual,
|
|
163
|
+
`Transaction pre-flight: ${op.vaultName}/${op.collectionName}/${op.id} expected v${op.expectedVersion}, found v${actual}`
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const executed = [];
|
|
169
|
+
try {
|
|
170
|
+
for (const op of ctx._ops) {
|
|
171
|
+
const coll = db.vault(op.vaultName).collection(op.collectionName);
|
|
172
|
+
const key = keyOf(op);
|
|
173
|
+
const prior = priorEnvelopes.get(key) ?? null;
|
|
174
|
+
if (op.type === "put") {
|
|
175
|
+
await coll.put(op.id, op.record);
|
|
176
|
+
} else {
|
|
177
|
+
await coll.delete(op.id);
|
|
178
|
+
}
|
|
179
|
+
executed.push({ op, priorEnvelope: prior });
|
|
180
|
+
}
|
|
181
|
+
return bodyResult;
|
|
182
|
+
} catch (err) {
|
|
183
|
+
for (const { op, priorEnvelope } of executed.slice().reverse()) {
|
|
184
|
+
try {
|
|
185
|
+
if (priorEnvelope) {
|
|
186
|
+
await store.put(op.vaultName, op.collectionName, op.id, priorEnvelope);
|
|
187
|
+
} else {
|
|
188
|
+
await store.delete(op.vaultName, op.collectionName, op.id);
|
|
189
|
+
}
|
|
190
|
+
} catch {
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
throw err;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function keyOf(op) {
|
|
197
|
+
return `${op.vaultName}\0${op.collectionName}\0${op.id}`;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// src/tx/active.ts
|
|
201
|
+
function withTransactions() {
|
|
202
|
+
return { runTransaction };
|
|
203
|
+
}
|
|
204
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
205
|
+
0 && (module.exports = {
|
|
206
|
+
TxCollection,
|
|
207
|
+
TxContext,
|
|
208
|
+
TxVault,
|
|
209
|
+
runTransaction,
|
|
210
|
+
withTransactions
|
|
211
|
+
});
|
|
212
|
+
//# sourceMappingURL=index.cjs.map
|