@opengeni/db 3.1.3-canary.38890816741001 → 3.2.2
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/dist/{chunk-JMX6XSIF.js → chunk-V2X2NK7T.js} +55 -4
- package/dist/{chunk-JMX6XSIF.js.map → chunk-V2X2NK7T.js.map} +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.js +3 -1
- package/dist/migrate.js +1 -1
- package/dist/vaults.d.ts +68 -3
- package/drizzle/0789_external_vault_sources.sql +318 -0
- package/package.json +9 -9
- package/src/index.ts +73 -9
- package/src/vaults.ts +84 -2
package/src/vaults.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
type VaultMode,
|
|
15
15
|
type VaultOwnerKind,
|
|
16
16
|
type VaultPolicy,
|
|
17
|
+
type VaultProviderOperations,
|
|
17
18
|
type VaultSource,
|
|
18
19
|
type VaultSyncStatus,
|
|
19
20
|
type VaultVersionCreatedByKind,
|
|
@@ -136,6 +137,16 @@ function json(value: unknown): string | null {
|
|
|
136
137
|
// Row shapes (as the routines return them; values encrypted)
|
|
137
138
|
// ---------------------------------------------------------------------------
|
|
138
139
|
|
|
140
|
+
/**
|
|
141
|
+
* What a provider (or its bridge) said about its own upstream freshness at
|
|
142
|
+
* the last successful check (0789). Opengeni's own check time is
|
|
143
|
+
* `lastSyncedAt`; it never stands in for `sourceSyncedAt`.
|
|
144
|
+
*/
|
|
145
|
+
export type StoredProviderFreshness = {
|
|
146
|
+
source: "live" | "cache" | "unknown";
|
|
147
|
+
sourceSyncedAt: string | null;
|
|
148
|
+
};
|
|
149
|
+
|
|
139
150
|
export type VaultRow = {
|
|
140
151
|
id: string;
|
|
141
152
|
workspaceId: string;
|
|
@@ -153,6 +164,15 @@ export type VaultRow = {
|
|
|
153
164
|
rateLimitedUntil: string | null;
|
|
154
165
|
providerConnectionId: string | null;
|
|
155
166
|
providerVaultRef: string | null;
|
|
167
|
+
/** Effective operations the provider last reported (0789); null before the first check. */
|
|
168
|
+
providerOperations?: VaultProviderOperations | null;
|
|
169
|
+
/** The provider's own freshness observation from the last successful check (0789). */
|
|
170
|
+
providerFreshness?: StoredProviderFreshness | null;
|
|
171
|
+
/**
|
|
172
|
+
* Durable value-cache epoch (0789, bigint as text). Every complete mirror
|
|
173
|
+
* replacement advances it; provider value caches compare it before reuse.
|
|
174
|
+
*/
|
|
175
|
+
providerCacheEpoch?: string;
|
|
156
176
|
availability: { allowedWorkspaceIds: string[] | null; allowPersonalWorkspaces: boolean } | null;
|
|
157
177
|
isDefault: boolean;
|
|
158
178
|
itemCount: number;
|
|
@@ -222,6 +242,8 @@ export type VaultFieldCiphertext = {
|
|
|
222
242
|
source: VaultSource;
|
|
223
243
|
providerConnectionId: string | null;
|
|
224
244
|
providerVaultRef: string | null;
|
|
245
|
+
/** The vault's value-cache epoch (0789). */
|
|
246
|
+
providerCacheEpoch?: string;
|
|
225
247
|
providerItemRef: string | null;
|
|
226
248
|
providerFieldRef: string | null;
|
|
227
249
|
};
|
|
@@ -263,6 +285,8 @@ export type SecretReferenceCandidate = {
|
|
|
263
285
|
source: VaultSource;
|
|
264
286
|
providerConnectionId: string | null;
|
|
265
287
|
providerVaultRef: string | null;
|
|
288
|
+
/** The vault's value-cache epoch (0789). */
|
|
289
|
+
providerCacheEpoch?: string;
|
|
266
290
|
itemId: string;
|
|
267
291
|
itemName: string;
|
|
268
292
|
itemType: VaultItemType;
|
|
@@ -752,6 +776,12 @@ export type ProviderVaultItemMirror = {
|
|
|
752
776
|
fields: Array<{ providerFieldRef: string; name: string; kind: VaultFieldKind }>;
|
|
753
777
|
};
|
|
754
778
|
|
|
779
|
+
/**
|
|
780
|
+
* Replace a connected vault's metadata mirror with one complete inventory
|
|
781
|
+
* (at most `VAULT_LIMITS.itemsPerVault` items; more is refused with
|
|
782
|
+
* `provider_inventory_incomplete` and the old mirror kept). Items missing
|
|
783
|
+
* from `items` are removed, and the vault's cache epoch advances (0789).
|
|
784
|
+
*/
|
|
755
785
|
export async function upsertProviderVaultItems(
|
|
756
786
|
db: Database,
|
|
757
787
|
context: VaultDbContext,
|
|
@@ -765,6 +795,13 @@ export async function upsertProviderVaultItems(
|
|
|
765
795
|
});
|
|
766
796
|
}
|
|
767
797
|
|
|
798
|
+
/**
|
|
799
|
+
* Record a connected vault's sync state. `operations` and `freshness` are
|
|
800
|
+
* optional (0789): absent keeps the stored value, null clears it. The optional
|
|
801
|
+
* mirror and status settle atomically, comparing `expectedCacheEpoch` under
|
|
802
|
+
* the vault lock; a mismatch raises provider_conflict with superseded=true.
|
|
803
|
+
* Every applied settlement advances the epoch, even unchanged or failed checks.
|
|
804
|
+
*/
|
|
768
805
|
export async function setVaultSyncStatus(
|
|
769
806
|
db: Database,
|
|
770
807
|
context: VaultDbContext,
|
|
@@ -774,6 +811,14 @@ export async function setVaultSyncStatus(
|
|
|
774
811
|
errorCode?: string | null;
|
|
775
812
|
errorMessage?: string | null;
|
|
776
813
|
rateLimitedUntil?: string | null;
|
|
814
|
+
/** The provider's effective operations for this vault. */
|
|
815
|
+
operations?: VaultProviderOperations | null;
|
|
816
|
+
/** The provider's own upstream freshness observation (never Opengeni's check time). */
|
|
817
|
+
freshness?: StoredProviderFreshness | null;
|
|
818
|
+
/** Reject a late refresh when another settlement advanced this epoch. */
|
|
819
|
+
expectedCacheEpoch?: string;
|
|
820
|
+
/** Complete inventory committed atomically with this successful status. */
|
|
821
|
+
mirror?: { contentVersion: string | null; items: ProviderVaultItemMirror[] };
|
|
777
822
|
},
|
|
778
823
|
): Promise<void> {
|
|
779
824
|
const { vaultId, ...status } = input;
|
|
@@ -784,7 +829,16 @@ export async function setVaultSyncStatus(
|
|
|
784
829
|
});
|
|
785
830
|
}
|
|
786
831
|
|
|
787
|
-
/**
|
|
832
|
+
/**
|
|
833
|
+
* Link a connected vault (W5, 0789). Every source but `host` needs an active
|
|
834
|
+
* `api_key` connection in the caller's workspace whose provider identity
|
|
835
|
+
* matches (`1password.com` with the 1Password service-account role, or
|
|
836
|
+
* `vault:<source>` with the `external_vault_provider` role and
|
|
837
|
+
* `metadata.vaultProvider.provider = source`, version 1, not pending
|
|
838
|
+
* verification) and whose ownership matches `ownerKind`: a personal
|
|
839
|
+
* connection backs only its owner's Only-me vaults. The mirror is filled by
|
|
840
|
+
* the first sync.
|
|
841
|
+
*/
|
|
788
842
|
export async function linkProviderVault(
|
|
789
843
|
db: Database,
|
|
790
844
|
context: VaultDbContext,
|
|
@@ -792,7 +846,7 @@ export async function linkProviderVault(
|
|
|
792
846
|
ownerKind: "user" | "workspace" | "organization";
|
|
793
847
|
name: string;
|
|
794
848
|
description?: string | null;
|
|
795
|
-
source:
|
|
849
|
+
source: Exclude<VaultSource, "opengeni">;
|
|
796
850
|
providerConnectionId?: string | null;
|
|
797
851
|
providerVaultRef: string;
|
|
798
852
|
mode: VaultMode;
|
|
@@ -809,6 +863,32 @@ export async function linkProviderVault(
|
|
|
809
863
|
);
|
|
810
864
|
}
|
|
811
865
|
|
|
866
|
+
/**
|
|
867
|
+
* Exercise the exact link policy before an irreversible provider create. The
|
|
868
|
+
* temporary link, personal authority and audit rows are all rolled back. This
|
|
869
|
+
* is a preflight, not a reservation: a race after it must return the confirmed
|
|
870
|
+
* upstream identity so the caller can link that vault instead of creating again.
|
|
871
|
+
* No database transaction is held open across provider I/O.
|
|
872
|
+
*/
|
|
873
|
+
export async function preflightProviderVaultLink(
|
|
874
|
+
db: Database,
|
|
875
|
+
context: VaultDbContext,
|
|
876
|
+
input: Omit<Parameters<typeof linkProviderVault>[2], "providerVaultRef">,
|
|
877
|
+
): Promise<void> {
|
|
878
|
+
const passed = new Error("vault link preflight passed");
|
|
879
|
+
try {
|
|
880
|
+
await db.transaction(async (tx) => {
|
|
881
|
+
await linkProviderVault(tx as unknown as Database, context, {
|
|
882
|
+
...input,
|
|
883
|
+
providerVaultRef: `preflight:${crypto.randomUUID()}`,
|
|
884
|
+
});
|
|
885
|
+
throw passed;
|
|
886
|
+
});
|
|
887
|
+
} catch (error) {
|
|
888
|
+
if (error !== passed) throw error;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
812
892
|
export type ProviderVaultSyncTargetRow = {
|
|
813
893
|
vaultId: string;
|
|
814
894
|
workspaceId: string;
|
|
@@ -818,6 +898,8 @@ export type ProviderVaultSyncTargetRow = {
|
|
|
818
898
|
providerVaultRef: string;
|
|
819
899
|
providerContentVersion: string | null;
|
|
820
900
|
rateLimitedUntil: string | null;
|
|
901
|
+
/** The vault's value-cache epoch (0789). */
|
|
902
|
+
providerCacheEpoch?: string;
|
|
821
903
|
};
|
|
822
904
|
|
|
823
905
|
/** The provider refs and mirror version of one reachable connected vault. */
|