mcpscraper-memory-db 1.0.0

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 (104) hide show
  1. package/README.md +40 -0
  2. package/dist/db/chat-link.d.ts +7 -0
  3. package/dist/db/chat-link.js +50 -0
  4. package/dist/db/chat-link.js.map +1 -0
  5. package/dist/db/facts.d.ts +60 -0
  6. package/dist/db/facts.js +186 -0
  7. package/dist/db/facts.js.map +1 -0
  8. package/dist/db/interlink-state.d.ts +34 -0
  9. package/dist/db/interlink-state.js +42 -0
  10. package/dist/db/interlink-state.js.map +1 -0
  11. package/dist/db/keys.d.ts +44 -0
  12. package/dist/db/keys.js +118 -0
  13. package/dist/db/keys.js.map +1 -0
  14. package/dist/db/messages.d.ts +77 -0
  15. package/dist/db/messages.js +198 -0
  16. package/dist/db/messages.js.map +1 -0
  17. package/dist/db/notes.d.ts +109 -0
  18. package/dist/db/notes.js +249 -0
  19. package/dist/db/notes.js.map +1 -0
  20. package/dist/db/pool.d.ts +7 -0
  21. package/dist/db/pool.js +37 -0
  22. package/dist/db/pool.js.map +1 -0
  23. package/dist/db/presence.d.ts +4 -0
  24. package/dist/db/presence.js +25 -0
  25. package/dist/db/presence.js.map +1 -0
  26. package/dist/db/props-snapshots.d.ts +18 -0
  27. package/dist/db/props-snapshots.js +37 -0
  28. package/dist/db/props-snapshots.js.map +1 -0
  29. package/dist/db/provenance.d.ts +26 -0
  30. package/dist/db/provenance.js +43 -0
  31. package/dist/db/provenance.js.map +1 -0
  32. package/dist/db/schedule-entitlements.d.ts +24 -0
  33. package/dist/db/schedule-entitlements.js +70 -0
  34. package/dist/db/schedule-entitlements.js.map +1 -0
  35. package/dist/db/schedule-link.d.ts +7 -0
  36. package/dist/db/schedule-link.js +50 -0
  37. package/dist/db/schedule-link.js.map +1 -0
  38. package/dist/db/scheduled-actions.d.ts +58 -0
  39. package/dist/db/scheduled-actions.js +139 -0
  40. package/dist/db/scheduled-actions.js.map +1 -0
  41. package/dist/db/schema.d.ts +3 -0
  42. package/dist/db/schema.js +340 -0
  43. package/dist/db/schema.js.map +1 -0
  44. package/dist/db/secure-notes.d.ts +26 -0
  45. package/dist/db/secure-notes.js +59 -0
  46. package/dist/db/secure-notes.js.map +1 -0
  47. package/dist/db/shares.d.ts +45 -0
  48. package/dist/db/shares.js +141 -0
  49. package/dist/db/shares.js.map +1 -0
  50. package/dist/db/tables.d.ts +50 -0
  51. package/dist/db/tables.js +226 -0
  52. package/dist/db/tables.js.map +1 -0
  53. package/dist/db/trust.d.ts +10 -0
  54. package/dist/db/trust.js +88 -0
  55. package/dist/db/trust.js.map +1 -0
  56. package/dist/db/usage.d.ts +30 -0
  57. package/dist/db/usage.js +106 -0
  58. package/dist/db/usage.js.map +1 -0
  59. package/dist/db/vaults.d.ts +98 -0
  60. package/dist/db/vaults.js +316 -0
  61. package/dist/db/vaults.js.map +1 -0
  62. package/dist/db/video-runs.d.ts +70 -0
  63. package/dist/db/video-runs.js +176 -0
  64. package/dist/db/video-runs.js.map +1 -0
  65. package/dist/db/webhooks.d.ts +20 -0
  66. package/dist/db/webhooks.js +43 -0
  67. package/dist/db/webhooks.js.map +1 -0
  68. package/dist/lib/auth.d.ts +75 -0
  69. package/dist/lib/auth.js +248 -0
  70. package/dist/lib/auth.js.map +1 -0
  71. package/dist/lib/cost-rates.d.ts +19 -0
  72. package/dist/lib/cost-rates.js +36 -0
  73. package/dist/lib/cost-rates.js.map +1 -0
  74. package/dist/lib/credit-debit.d.ts +15 -0
  75. package/dist/lib/credit-debit.js +21 -0
  76. package/dist/lib/credit-debit.js.map +1 -0
  77. package/dist/lib/operator.d.ts +5 -0
  78. package/dist/lib/operator.js +14 -0
  79. package/dist/lib/operator.js.map +1 -0
  80. package/dist/lib/schedule-cadence.d.ts +6 -0
  81. package/dist/lib/schedule-cadence.js +66 -0
  82. package/dist/lib/schedule-cadence.js.map +1 -0
  83. package/dist/lib/secret-crypto.d.ts +4 -0
  84. package/dist/lib/secret-crypto.js +28 -0
  85. package/dist/lib/secret-crypto.js.map +1 -0
  86. package/dist/lib/vault-contracts.d.ts +18 -0
  87. package/dist/lib/vault-contracts.js +248 -0
  88. package/dist/lib/vault-contracts.js.map +1 -0
  89. package/dist/lib/video-reaper.d.ts +13 -0
  90. package/dist/lib/video-reaper.js +19 -0
  91. package/dist/lib/video-reaper.js.map +1 -0
  92. package/dist/rag/embedder.d.ts +6 -0
  93. package/dist/rag/embedder.js +93 -0
  94. package/dist/rag/embedder.js.map +1 -0
  95. package/dist/rag/index-pipeline.d.ts +22 -0
  96. package/dist/rag/index-pipeline.js +62 -0
  97. package/dist/rag/index-pipeline.js.map +1 -0
  98. package/dist/rag/query-tool.d.ts +47 -0
  99. package/dist/rag/query-tool.js +47 -0
  100. package/dist/rag/query-tool.js.map +1 -0
  101. package/dist/rag/vector-store.d.ts +7 -0
  102. package/dist/rag/vector-store.js +25 -0
  103. package/dist/rag/vector-store.js.map +1 -0
  104. package/package.json +47 -0
@@ -0,0 +1,106 @@
1
+ import { ensureSchema, query } from "./pool";
2
+ import { storageCostUsdForDay } from "../lib/cost-rates";
3
+ import { debitAiCredits } from "../lib/credit-debit";
4
+ const AI_SOURCES = /* @__PURE__ */ new Set(["embed", "compute", "llm"]);
5
+ async function totalBytesForVaults(vaults) {
6
+ if (vaults.length === 0) return 0;
7
+ const res = await query(
8
+ `SELECT COALESCE(SUM(octet_length(content)), 0)::bigint AS bytes FROM mem_notes WHERE vault = ANY($1)`,
9
+ [vaults]
10
+ );
11
+ return Number(res.rows[0]?.bytes ?? 0);
12
+ }
13
+ function periodOf(ts) {
14
+ return `${ts.getUTCFullYear()}-${String(ts.getUTCMonth() + 1).padStart(2, "0")}`;
15
+ }
16
+ async function recordCost(args) {
17
+ await ensureSchema();
18
+ const now = /* @__PURE__ */ new Date();
19
+ await query(
20
+ `INSERT INTO mem_usage_ledger (identity, ts, source, op, tokens, cost_usd, vault, period)
21
+ VALUES ($1, now(), $2, $3, $4, $5, $6, $7)`,
22
+ [args.identity, args.source, args.op, Math.round(args.tokens ?? 0), args.costUsd, args.vault ?? null, periodOf(now)]
23
+ );
24
+ const debitBasisUsd = args.rawCostUsd ?? args.costUsd;
25
+ if (AI_SOURCES.has(args.source) && debitBasisUsd > 0) {
26
+ const res = await debitAiCredits({ identity: args.identity, costUsd: debitBasisUsd, op: args.op, source: args.source });
27
+ if (!res.ok) {
28
+ console.warn(JSON.stringify({ event: "ai_debit_failed", identity: args.identity, source: args.source, op: args.op, costUsd: debitBasisUsd, reason: res.reason }));
29
+ }
30
+ }
31
+ }
32
+ async function userCostThisPeriod(identity, period) {
33
+ await ensureSchema();
34
+ const p = period ?? periodOf(/* @__PURE__ */ new Date());
35
+ const res = await query(
36
+ `SELECT source, COALESCE(SUM(cost_usd), 0)::float8 AS total
37
+ FROM mem_usage_ledger WHERE identity = $1 AND period = $2 GROUP BY source`,
38
+ [identity, p]
39
+ );
40
+ const bySource = {};
41
+ let total = 0;
42
+ for (const r of res.rows) {
43
+ const v = Number(r.total);
44
+ bySource[r.source] = v;
45
+ total += v;
46
+ }
47
+ return { total, bySource };
48
+ }
49
+ async function costByTier(period) {
50
+ await ensureSchema();
51
+ const p = period ?? periodOf(/* @__PURE__ */ new Date());
52
+ const res = await query(
53
+ `SELECT k.plan AS plan, COUNT(DISTINCT l.identity)::int AS users, COALESCE(SUM(l.cost_usd), 0)::float8 AS total
54
+ FROM mem_usage_ledger l
55
+ LEFT JOIN LATERAL (
56
+ SELECT plan FROM mem_keys WHERE identity = l.identity ORDER BY created_at DESC LIMIT 1
57
+ ) k ON true
58
+ WHERE l.period = $1
59
+ GROUP BY k.plan
60
+ ORDER BY k.plan`,
61
+ [p]
62
+ );
63
+ return res.rows.map((r) => {
64
+ const users = Number(r.users) || 0;
65
+ const totalUsd = Number(r.total) || 0;
66
+ return {
67
+ plan: r.plan ?? "unknown",
68
+ users,
69
+ totalUsd,
70
+ avgUsdPerUser: users > 0 ? totalUsd / users : 0
71
+ };
72
+ });
73
+ }
74
+ async function snapshotStorageCostForIdentity(identity, vaults) {
75
+ const totalBytes = await totalBytesForVaults(vaults);
76
+ const costUsd = storageCostUsdForDay(totalBytes);
77
+ if (totalBytes > 0) {
78
+ await recordCost({ identity, source: "storage", op: "daily-snapshot", costUsd, tokens: 0 });
79
+ }
80
+ return costUsd;
81
+ }
82
+ async function snapshotAllStorageCost() {
83
+ await ensureSchema();
84
+ const res = await query(
85
+ `SELECT DISTINCT owner_identity, vault FROM mem_vault_registry`
86
+ );
87
+ const byIdentity = /* @__PURE__ */ new Map();
88
+ for (const r of res.rows) {
89
+ const arr = byIdentity.get(r.owner_identity) ?? [];
90
+ arr.push(r.vault);
91
+ byIdentity.set(r.owner_identity, arr);
92
+ }
93
+ let totalUsd = 0;
94
+ for (const [identity, vaults] of byIdentity) {
95
+ totalUsd += await snapshotStorageCostForIdentity(identity, vaults);
96
+ }
97
+ return { identities: byIdentity.size, totalUsd };
98
+ }
99
+ export {
100
+ costByTier,
101
+ recordCost,
102
+ snapshotAllStorageCost,
103
+ snapshotStorageCostForIdentity,
104
+ userCostThisPeriod
105
+ };
106
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/db/usage.ts"],"sourcesContent":["import { ensureSchema, query } from './pool'\nimport { storageCostUsdForDay } from '../lib/cost-rates'\nimport { debitAiCredits } from '../lib/credit-debit'\n\nconst AI_SOURCES = new Set(['embed', 'compute', 'llm']) // NOT 'storage'\n\nasync function totalBytesForVaults(vaults: string[]): Promise<number> {\n if (vaults.length === 0) return 0\n const res = await query<{ bytes: string }>(\n `SELECT COALESCE(SUM(octet_length(content)), 0)::bigint AS bytes FROM mem_notes WHERE vault = ANY($1)`,\n [vaults],\n )\n return Number(res.rows[0]?.bytes ?? 0)\n}\n\nexport type CostSource = 'llm' | 'embed' | 'storage' | 'compute'\n\nfunction periodOf(ts: Date): string {\n return `${ts.getUTCFullYear()}-${String(ts.getUTCMonth() + 1).padStart(2, '0')}`\n}\n\nexport interface RecordCostArgs {\n identity: string\n source: CostSource\n op: string\n tokens?: number\n costUsd: number\n vault?: string\n rawCostUsd?: number\n}\n\nexport async function recordCost(args: RecordCostArgs): Promise<void> {\n await ensureSchema()\n const now = new Date()\n await query(\n `INSERT INTO mem_usage_ledger (identity, ts, source, op, tokens, cost_usd, vault, period)\n VALUES ($1, now(), $2, $3, $4, $5, $6, $7)`,\n [args.identity, args.source, args.op, Math.round(args.tokens ?? 0), args.costUsd, args.vault ?? null, periodOf(now)],\n )\n const debitBasisUsd = args.rawCostUsd ?? args.costUsd\n if (AI_SOURCES.has(args.source) && debitBasisUsd > 0) {\n const res = await debitAiCredits({ identity: args.identity, costUsd: debitBasisUsd, op: args.op, source: args.source })\n if (!res.ok) {\n console.warn(JSON.stringify({ event: 'ai_debit_failed', identity: args.identity, source: args.source, op: args.op, costUsd: debitBasisUsd, reason: res.reason }))\n }\n }\n}\n\nexport interface CostSummary {\n total: number\n bySource: Record<string, number>\n}\n\nexport async function userCostThisPeriod(identity: string, period?: string): Promise<CostSummary> {\n await ensureSchema()\n const p = period ?? periodOf(new Date())\n const res = await query<{ source: string; total: string }>(\n `SELECT source, COALESCE(SUM(cost_usd), 0)::float8 AS total\n FROM mem_usage_ledger WHERE identity = $1 AND period = $2 GROUP BY source`,\n [identity, p],\n )\n const bySource: Record<string, number> = {}\n let total = 0\n for (const r of res.rows) {\n const v = Number(r.total)\n bySource[r.source] = v\n total += v\n }\n return { total, bySource }\n}\n\nexport interface TierCost {\n plan: string\n users: number\n totalUsd: number\n avgUsdPerUser: number\n}\n\nexport async function costByTier(period?: string): Promise<TierCost[]> {\n await ensureSchema()\n const p = period ?? periodOf(new Date())\n const res = await query<{ plan: string | null; users: string; total: string }>(\n `SELECT k.plan AS plan, COUNT(DISTINCT l.identity)::int AS users, COALESCE(SUM(l.cost_usd), 0)::float8 AS total\n FROM mem_usage_ledger l\n LEFT JOIN LATERAL (\n SELECT plan FROM mem_keys WHERE identity = l.identity ORDER BY created_at DESC LIMIT 1\n ) k ON true\n WHERE l.period = $1\n GROUP BY k.plan\n ORDER BY k.plan`,\n [p],\n )\n return res.rows.map(r => {\n const users = Number(r.users) || 0\n const totalUsd = Number(r.total) || 0\n return {\n plan: r.plan ?? 'unknown',\n users,\n totalUsd,\n avgUsdPerUser: users > 0 ? totalUsd / users : 0,\n }\n })\n}\n\nexport async function snapshotStorageCostForIdentity(identity: string, vaults: string[]): Promise<number> {\n const totalBytes = await totalBytesForVaults(vaults)\n const costUsd = storageCostUsdForDay(totalBytes)\n if (totalBytes > 0) {\n await recordCost({ identity, source: 'storage', op: 'daily-snapshot', costUsd, tokens: 0 })\n }\n return costUsd\n}\n\nexport async function snapshotAllStorageCost(): Promise<{ identities: number; totalUsd: number }> {\n await ensureSchema()\n const res = await query<{ owner_identity: string; vault: string }>(\n `SELECT DISTINCT owner_identity, vault FROM mem_vault_registry`,\n )\n const byIdentity = new Map<string, string[]>()\n for (const r of res.rows) {\n const arr = byIdentity.get(r.owner_identity) ?? []\n arr.push(r.vault)\n byIdentity.set(r.owner_identity, arr)\n }\n let totalUsd = 0\n for (const [identity, vaults] of byIdentity) {\n totalUsd += await snapshotStorageCostForIdentity(identity, vaults)\n }\n return { identities: byIdentity.size, totalUsd }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,98 @@
1
+ import { Scope } from '../lib/auth.js';
2
+ import { VaultContract } from '../lib/vault-contracts.js';
3
+
4
+ interface VaultEntitlement {
5
+ handle: string;
6
+ vault: string;
7
+ ownerIdentity: string;
8
+ entitlement: Scope;
9
+ shared: boolean;
10
+ kind: 'notes' | 'channel' | 'secure';
11
+ }
12
+ declare function sharedHandle(ownerIdentity: string, vault: string): string;
13
+ declare function entitledVaults(identity: string): Promise<VaultEntitlement[]>;
14
+ declare function addEntitlement(args: {
15
+ grantee: string;
16
+ handle: string;
17
+ vault: string;
18
+ ownerIdentity: string;
19
+ entitlement: Scope;
20
+ shared: boolean;
21
+ }): Promise<void>;
22
+ declare function shareVaultRow(args: {
23
+ grantee: string;
24
+ vault: string;
25
+ ownerIdentity: string;
26
+ entitlement: Scope;
27
+ }): Promise<void>;
28
+ interface VaultMember {
29
+ grantee: string;
30
+ entitlement: Scope;
31
+ createdAt: string;
32
+ }
33
+ declare function isChannelVault(ownerIdentity: string, vault: string): Promise<boolean>;
34
+ declare function isSecureVault(ownerIdentity: string, vault: string): Promise<boolean>;
35
+ declare function listVaultMembers(ownerIdentity: string, vault: string): Promise<VaultMember[]>;
36
+ declare function revokeVaultMember(ownerIdentity: string, vault: string, grantee: string): Promise<boolean>;
37
+ interface IdentityVault {
38
+ handle: string;
39
+ vault: string;
40
+ role: 'owner' | 'shared';
41
+ sharedBy?: string;
42
+ entitlement: Scope;
43
+ kind: 'notes' | 'channel' | 'secure';
44
+ }
45
+ declare function listVaultsForIdentity(identity: string): Promise<IdentityVault[]>;
46
+ declare function physicalVaultsForIdentity(identity: string, opts?: {
47
+ ownedOnly?: boolean;
48
+ }): Promise<string[]>;
49
+ declare function isVaultOwner(identity: string, handle: string): Promise<boolean>;
50
+ declare function vaultOwnerIdentity(vault: string): Promise<string | null>;
51
+ declare function deleteVaultRegistry(grantee: string, handle: string): Promise<number>;
52
+ declare function scopedVault(owner: string, vault: string): string;
53
+ declare function vaultOwnerAndName(grantee: string, handle: string): Promise<{
54
+ ownerIdentity: string;
55
+ vault: string;
56
+ } | null>;
57
+ declare function physicalVaultFor(grantee: string, handle: string): Promise<string>;
58
+ declare const VAULT_NAME_RE: RegExp;
59
+ declare function createVault(args: {
60
+ identity: string;
61
+ vault: string;
62
+ owner?: string;
63
+ }): Promise<{
64
+ vault: string;
65
+ created: boolean;
66
+ owner: string;
67
+ }>;
68
+ declare function setVaultContract(grantee: string, vault: string, contract: VaultContract): Promise<void>;
69
+ declare function provisionDefaultVaults(identity: string): Promise<{
70
+ created: string[];
71
+ vaults: string[];
72
+ }>;
73
+ declare function setKeyVaults(keyId: string, vaults: string[]): Promise<boolean>;
74
+ declare function getActiveVault(_sessionId: string, identity: string): Promise<string | null>;
75
+ declare function setActiveVault(_sessionId: string, identity: string, vault: string): Promise<void>;
76
+ interface ActiveContext {
77
+ activeOwner: string | null;
78
+ activeVault: string | null;
79
+ }
80
+ declare function getActiveContext(identity: string): Promise<ActiveContext>;
81
+ declare function setActiveOwner(identity: string, owner: string | null, vault: string | null): Promise<void>;
82
+ interface AccountGrant {
83
+ ownerIdentity: string;
84
+ grantee: string;
85
+ entitlement: Scope;
86
+ }
87
+ declare function addAccountGrant(args: {
88
+ ownerIdentity: string;
89
+ grantee: string;
90
+ entitlement: Scope;
91
+ }): Promise<void>;
92
+ declare function getAccountGrant(ownerIdentity: string, grantee: string): Promise<Scope | null>;
93
+ declare function accountGrantsForGrantee(grantee: string): Promise<AccountGrant[]>;
94
+ declare function revokeAccountGrant(ownerIdentity: string, grantee: string): Promise<number>;
95
+ declare function ownedVaultNames(owner: string): Promise<string[]>;
96
+ declare function listAllNoteVaults(): Promise<string[]>;
97
+
98
+ export { type AccountGrant, type ActiveContext, type IdentityVault, VAULT_NAME_RE, type VaultEntitlement, type VaultMember, accountGrantsForGrantee, addAccountGrant, addEntitlement, createVault, deleteVaultRegistry, entitledVaults, getAccountGrant, getActiveContext, getActiveVault, isChannelVault, isSecureVault, isVaultOwner, listAllNoteVaults, listVaultMembers, listVaultsForIdentity, ownedVaultNames, physicalVaultFor, physicalVaultsForIdentity, provisionDefaultVaults, revokeAccountGrant, revokeVaultMember, scopedVault, setActiveOwner, setActiveVault, setKeyVaults, setVaultContract, shareVaultRow, sharedHandle, vaultOwnerAndName, vaultOwnerIdentity };
@@ -0,0 +1,316 @@
1
+ import { ensureSchema, query } from "./pool";
2
+ import { normalizeScope } from "../lib/auth";
3
+ import { DEFAULT_VAULTS, VAULT_CONTRACTS } from "../lib/vault-contracts";
4
+ function sharedHandle(ownerIdentity, vault) {
5
+ return `${ownerIdentity}/${vault}`;
6
+ }
7
+ function contractKind(contract) {
8
+ const c = contract;
9
+ if (c?.kind === "channel") return "channel";
10
+ if (c?.kind === "secure") return "secure";
11
+ return "notes";
12
+ }
13
+ async function entitledVaults(identity) {
14
+ await ensureSchema();
15
+ const res = await query(
16
+ `SELECT COALESCE(r.handle, r.vault) AS handle, r.vault, r.owner_identity, r.entitlement, r.shared,
17
+ (SELECT owner.contract FROM mem_vault_registry owner
18
+ WHERE owner.owner_identity = r.owner_identity AND owner.vault = r.vault AND owner.grantee = owner.owner_identity
19
+ LIMIT 1) AS contract
20
+ FROM mem_vault_registry r WHERE r.grantee = $1 ORDER BY r.created_at ASC`,
21
+ [identity]
22
+ );
23
+ return res.rows.map((r) => ({
24
+ handle: r.handle,
25
+ vault: r.vault,
26
+ ownerIdentity: r.owner_identity,
27
+ entitlement: normalizeScope(r.entitlement),
28
+ shared: r.shared,
29
+ kind: contractKind(r.contract)
30
+ }));
31
+ }
32
+ async function addEntitlement(args) {
33
+ await ensureSchema();
34
+ await query(
35
+ `INSERT INTO mem_vault_registry (grantee, handle, vault, owner_identity, entitlement, shared)
36
+ VALUES ($1, $2, $3, $4, $5::jsonb, $6)
37
+ ON CONFLICT (grantee, handle) DO UPDATE SET entitlement = EXCLUDED.entitlement, shared = EXCLUDED.shared`,
38
+ [args.grantee, args.handle, args.vault, args.ownerIdentity, JSON.stringify(args.entitlement), args.shared]
39
+ );
40
+ }
41
+ async function shareVaultRow(args) {
42
+ await addEntitlement({ ...args, handle: sharedHandle(args.ownerIdentity, args.vault), shared: true });
43
+ }
44
+ async function isChannelVault(ownerIdentity, vault) {
45
+ await ensureSchema();
46
+ const res = await query(
47
+ `SELECT contract FROM mem_vault_registry WHERE owner_identity = $1 AND vault = $2 LIMIT 1`,
48
+ [ownerIdentity, vault]
49
+ );
50
+ const contract = res.rows[0]?.contract;
51
+ return contract?.kind === "channel";
52
+ }
53
+ async function isSecureVault(ownerIdentity, vault) {
54
+ await ensureSchema();
55
+ const res = await query(
56
+ `SELECT contract FROM mem_vault_registry WHERE owner_identity = $1 AND vault = $2 LIMIT 1`,
57
+ [ownerIdentity, vault]
58
+ );
59
+ const contract = res.rows[0]?.contract;
60
+ return contract?.kind === "secure";
61
+ }
62
+ async function listVaultMembers(ownerIdentity, vault) {
63
+ await ensureSchema();
64
+ const res = await query(
65
+ `SELECT grantee, entitlement, created_at FROM mem_vault_registry
66
+ WHERE owner_identity = $1 AND vault = $2 AND grantee != $1 ORDER BY created_at ASC`,
67
+ [ownerIdentity, vault]
68
+ );
69
+ return res.rows.map((r) => ({ grantee: r.grantee, entitlement: normalizeScope(r.entitlement), createdAt: r.created_at }));
70
+ }
71
+ async function revokeVaultMember(ownerIdentity, vault, grantee) {
72
+ await ensureSchema();
73
+ const res = await query(
74
+ `DELETE FROM mem_vault_registry WHERE owner_identity = $1 AND vault = $2 AND grantee = $3`,
75
+ [ownerIdentity, vault, grantee]
76
+ );
77
+ return (res.rowCount ?? 0) > 0;
78
+ }
79
+ async function listVaultsForIdentity(identity) {
80
+ const ents = await entitledVaults(identity);
81
+ const seen = /* @__PURE__ */ new Map();
82
+ for (const e of ents) {
83
+ if (seen.has(e.handle)) continue;
84
+ const isOwner = e.ownerIdentity === identity;
85
+ seen.set(e.handle, {
86
+ handle: e.handle,
87
+ vault: e.vault,
88
+ role: isOwner ? "owner" : "shared",
89
+ sharedBy: isOwner ? void 0 : e.ownerIdentity,
90
+ entitlement: e.entitlement,
91
+ kind: e.kind
92
+ });
93
+ }
94
+ return [...seen.values()];
95
+ }
96
+ async function physicalVaultsForIdentity(identity, opts) {
97
+ const vaults = await listVaultsForIdentity(identity);
98
+ return vaults.filter((v) => opts?.ownedOnly ? v.role === "owner" : true).map((v) => scopedVault(v.role === "owner" ? identity : v.sharedBy ?? identity, v.vault));
99
+ }
100
+ async function isVaultOwner(identity, handle) {
101
+ await ensureSchema();
102
+ const res = await query(
103
+ `SELECT owner_identity FROM mem_vault_registry WHERE grantee = $1 AND COALESCE(handle, vault) = $2 LIMIT 1`,
104
+ [identity, handle]
105
+ );
106
+ return res.rows[0]?.owner_identity === identity;
107
+ }
108
+ async function vaultOwnerIdentity(vault) {
109
+ await ensureSchema();
110
+ const res = await query(
111
+ `SELECT owner_identity FROM mem_vault_registry
112
+ WHERE grantee = owner_identity AND (owner_identity || ' ' || vault) = $1
113
+ LIMIT 1`,
114
+ [vault]
115
+ );
116
+ return res.rows[0]?.owner_identity ?? null;
117
+ }
118
+ async function deleteVaultRegistry(grantee, handle) {
119
+ await ensureSchema();
120
+ const res = await query(`DELETE FROM mem_vault_registry WHERE grantee = $1 AND COALESCE(handle, vault) = $2`, [grantee, handle]);
121
+ return res.rowCount ?? 0;
122
+ }
123
+ function scopedVault(owner, vault) {
124
+ return `${owner} ${vault}`;
125
+ }
126
+ async function vaultOwnerAndName(grantee, handle) {
127
+ await ensureSchema();
128
+ const res = await query(
129
+ `SELECT owner_identity, vault FROM mem_vault_registry WHERE grantee = $1 AND COALESCE(handle, vault) = $2 LIMIT 1`,
130
+ [grantee, handle]
131
+ );
132
+ return res.rows[0] ? { ownerIdentity: res.rows[0].owner_identity, vault: res.rows[0].vault } : null;
133
+ }
134
+ async function physicalVaultFor(grantee, handle) {
135
+ await ensureSchema();
136
+ const res = await query(
137
+ `SELECT owner_identity, vault FROM mem_vault_registry WHERE grantee = $1 AND COALESCE(handle, vault) = $2 LIMIT 1`,
138
+ [grantee, handle]
139
+ );
140
+ const row = res.rows[0];
141
+ if (row) return scopedVault(row.owner_identity, row.vault);
142
+ const ctx = await getActiveContext(grantee);
143
+ if (ctx.activeOwner && ctx.activeOwner !== grantee) return scopedVault(ctx.activeOwner, handle);
144
+ return scopedVault(grantee, handle);
145
+ }
146
+ const VAULT_NAME_RE = /^[A-Za-z0-9 _-]{1,48}$/;
147
+ async function createVault(args) {
148
+ await ensureSchema();
149
+ if (!VAULT_NAME_RE.test(args.vault)) {
150
+ throw new Error(`invalid vault name "${args.vault}" (allowed: letters, digits, space, _ or -, 1-48 chars)`);
151
+ }
152
+ const owner = args.owner ?? args.identity;
153
+ const existing = await query(
154
+ `SELECT 1 FROM mem_vault_registry WHERE grantee = $1 AND vault = $2 LIMIT 1`,
155
+ [owner, args.vault]
156
+ );
157
+ if ((existing.rowCount ?? 0) > 0) {
158
+ return { vault: args.vault, created: false, owner };
159
+ }
160
+ await addEntitlement({
161
+ grantee: owner,
162
+ handle: args.vault,
163
+ vault: args.vault,
164
+ ownerIdentity: owner,
165
+ entitlement: normalizeScope({ read: true, write: true, export: true, index: true, admin: true, swap: true }),
166
+ shared: false
167
+ });
168
+ return { vault: args.vault, created: true, owner };
169
+ }
170
+ async function setVaultContract(grantee, vault, contract) {
171
+ await ensureSchema();
172
+ await query(
173
+ `UPDATE mem_vault_registry SET contract = $3::jsonb WHERE grantee = $1 AND vault = $2`,
174
+ [grantee, vault, JSON.stringify(contract)]
175
+ );
176
+ }
177
+ async function provisionDefaultVaults(identity) {
178
+ await ensureSchema();
179
+ const created = [];
180
+ for (const vault of DEFAULT_VAULTS) {
181
+ const result = await createVault({ identity, vault, owner: identity });
182
+ if (result.created) created.push(vault);
183
+ const contract = VAULT_CONTRACTS[vault];
184
+ if (contract) await setVaultContract(identity, vault, contract);
185
+ }
186
+ return { created, vaults: [...DEFAULT_VAULTS] };
187
+ }
188
+ async function setKeyVaults(keyId, vaults) {
189
+ await ensureSchema();
190
+ const res = await query(
191
+ `UPDATE mem_keys SET vaults = $2::jsonb WHERE key_id = $1`,
192
+ [keyId, JSON.stringify(vaults)]
193
+ );
194
+ return (res.rowCount ?? 0) > 0;
195
+ }
196
+ async function getActiveVault(_sessionId, identity) {
197
+ await ensureSchema();
198
+ const res = await query(
199
+ `SELECT active_vault FROM mem_active_context WHERE identity = $1 LIMIT 1`,
200
+ [identity]
201
+ );
202
+ return res.rows[0]?.active_vault ?? null;
203
+ }
204
+ async function setActiveVault(_sessionId, identity, vault) {
205
+ await ensureSchema();
206
+ await query(
207
+ `INSERT INTO mem_active_context (identity, active_vault, updated_at)
208
+ VALUES ($1, $2, now())
209
+ ON CONFLICT (identity) DO UPDATE SET active_vault = EXCLUDED.active_vault, updated_at = now()`,
210
+ [identity, vault]
211
+ );
212
+ }
213
+ async function getActiveContext(identity) {
214
+ await ensureSchema();
215
+ const res = await query(
216
+ `SELECT active_owner, active_vault FROM mem_active_context WHERE identity = $1 LIMIT 1`,
217
+ [identity]
218
+ );
219
+ const r = res.rows[0];
220
+ return { activeOwner: r?.active_owner ?? null, activeVault: r?.active_vault ?? null };
221
+ }
222
+ async function setActiveOwner(identity, owner, vault) {
223
+ await ensureSchema();
224
+ await query(
225
+ `INSERT INTO mem_active_context (identity, active_owner, active_vault, updated_at)
226
+ VALUES ($1, $2, $3, now())
227
+ ON CONFLICT (identity) DO UPDATE SET active_owner = EXCLUDED.active_owner, active_vault = EXCLUDED.active_vault, updated_at = now()`,
228
+ [identity, owner, vault]
229
+ );
230
+ }
231
+ async function addAccountGrant(args) {
232
+ await ensureSchema();
233
+ await query(
234
+ `INSERT INTO mem_account_grants (owner_identity, grantee, entitlement)
235
+ VALUES ($1, $2, $3::jsonb)
236
+ ON CONFLICT (owner_identity, grantee) DO UPDATE SET entitlement = EXCLUDED.entitlement`,
237
+ [args.ownerIdentity, args.grantee, JSON.stringify(args.entitlement)]
238
+ );
239
+ }
240
+ async function getAccountGrant(ownerIdentity, grantee) {
241
+ await ensureSchema();
242
+ const res = await query(
243
+ `SELECT entitlement FROM mem_account_grants WHERE owner_identity = $1 AND grantee = $2 LIMIT 1`,
244
+ [ownerIdentity, grantee]
245
+ );
246
+ const r = res.rows[0];
247
+ return r ? normalizeScope(r.entitlement) : null;
248
+ }
249
+ async function accountGrantsForGrantee(grantee) {
250
+ await ensureSchema();
251
+ const res = await query(
252
+ `SELECT owner_identity, entitlement FROM mem_account_grants WHERE grantee = $1 ORDER BY created_at ASC`,
253
+ [grantee]
254
+ );
255
+ return res.rows.map((r) => ({
256
+ ownerIdentity: r.owner_identity,
257
+ grantee,
258
+ entitlement: normalizeScope(r.entitlement)
259
+ }));
260
+ }
261
+ async function revokeAccountGrant(ownerIdentity, grantee) {
262
+ await ensureSchema();
263
+ const res = await query(`DELETE FROM mem_account_grants WHERE owner_identity = $1 AND grantee = $2`, [ownerIdentity, grantee]);
264
+ return res.rowCount ?? 0;
265
+ }
266
+ async function ownedVaultNames(owner) {
267
+ await ensureSchema();
268
+ const res = await query(
269
+ `SELECT vault FROM mem_vault_registry WHERE grantee = $1 AND owner_identity = $1 ORDER BY created_at ASC`,
270
+ [owner]
271
+ );
272
+ return res.rows.map((r) => r.vault);
273
+ }
274
+ async function listAllNoteVaults() {
275
+ await ensureSchema();
276
+ const res = await query(
277
+ `SELECT (owner_identity || ' ' || vault) AS physical FROM mem_vault_registry
278
+ WHERE grantee = owner_identity AND COALESCE(contract->>'kind', '') != 'channel'
279
+ ORDER BY owner_identity, vault`
280
+ );
281
+ return res.rows.map((r) => r.physical);
282
+ }
283
+ export {
284
+ VAULT_NAME_RE,
285
+ accountGrantsForGrantee,
286
+ addAccountGrant,
287
+ addEntitlement,
288
+ createVault,
289
+ deleteVaultRegistry,
290
+ entitledVaults,
291
+ getAccountGrant,
292
+ getActiveContext,
293
+ getActiveVault,
294
+ isChannelVault,
295
+ isSecureVault,
296
+ isVaultOwner,
297
+ listAllNoteVaults,
298
+ listVaultMembers,
299
+ listVaultsForIdentity,
300
+ ownedVaultNames,
301
+ physicalVaultFor,
302
+ physicalVaultsForIdentity,
303
+ provisionDefaultVaults,
304
+ revokeAccountGrant,
305
+ revokeVaultMember,
306
+ scopedVault,
307
+ setActiveOwner,
308
+ setActiveVault,
309
+ setKeyVaults,
310
+ setVaultContract,
311
+ shareVaultRow,
312
+ sharedHandle,
313
+ vaultOwnerAndName,
314
+ vaultOwnerIdentity
315
+ };
316
+ //# sourceMappingURL=vaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/db/vaults.ts"],"sourcesContent":["import { ensureSchema, query } from './pool'\nimport { normalizeScope } from '../lib/auth'\nimport type { Scope } from '../lib/auth'\nimport { DEFAULT_VAULTS, VAULT_CONTRACTS } from '../lib/vault-contracts'\nimport type { VaultContract } from '../lib/vault-contracts'\n\nexport interface VaultEntitlement {\n handle: string\n vault: string\n ownerIdentity: string\n entitlement: Scope\n shared: boolean\n kind: 'notes' | 'channel' | 'secure'\n}\n\ninterface VaultRow {\n handle: string\n vault: string\n owner_identity: string\n entitlement: unknown\n shared: boolean\n contract: unknown\n}\n\nexport function sharedHandle(ownerIdentity: string, vault: string): string {\n return `${ownerIdentity}/${vault}`\n}\n\nfunction contractKind(contract: unknown): 'notes' | 'channel' | 'secure' {\n const c = contract as { kind?: string } | null\n if (c?.kind === 'channel') return 'channel'\n if (c?.kind === 'secure') return 'secure'\n return 'notes'\n}\n\nexport async function entitledVaults(identity: string): Promise<VaultEntitlement[]> {\n await ensureSchema()\n const res = await query<VaultRow>(\n `SELECT COALESCE(r.handle, r.vault) AS handle, r.vault, r.owner_identity, r.entitlement, r.shared,\n (SELECT owner.contract FROM mem_vault_registry owner\n WHERE owner.owner_identity = r.owner_identity AND owner.vault = r.vault AND owner.grantee = owner.owner_identity\n LIMIT 1) AS contract\n FROM mem_vault_registry r WHERE r.grantee = $1 ORDER BY r.created_at ASC`,\n [identity],\n )\n return res.rows.map(r => ({\n handle: r.handle,\n vault: r.vault,\n ownerIdentity: r.owner_identity,\n entitlement: normalizeScope(r.entitlement as Record<string, boolean>),\n shared: r.shared,\n kind: contractKind(r.contract),\n }))\n}\n\nexport async function addEntitlement(args: {\n grantee: string\n handle: string\n vault: string\n ownerIdentity: string\n entitlement: Scope\n shared: boolean\n}): Promise<void> {\n await ensureSchema()\n await query(\n `INSERT INTO mem_vault_registry (grantee, handle, vault, owner_identity, entitlement, shared)\n VALUES ($1, $2, $3, $4, $5::jsonb, $6)\n ON CONFLICT (grantee, handle) DO UPDATE SET entitlement = EXCLUDED.entitlement, shared = EXCLUDED.shared`,\n [args.grantee, args.handle, args.vault, args.ownerIdentity, JSON.stringify(args.entitlement), args.shared],\n )\n}\n\nexport async function shareVaultRow(args: {\n grantee: string\n vault: string\n ownerIdentity: string\n entitlement: Scope\n}): Promise<void> {\n await addEntitlement({ ...args, handle: sharedHandle(args.ownerIdentity, args.vault), shared: true })\n}\n\nexport interface VaultMember {\n grantee: string\n entitlement: Scope\n createdAt: string\n}\n\nexport async function isChannelVault(ownerIdentity: string, vault: string): Promise<boolean> {\n await ensureSchema()\n const res = await query<{ contract: unknown }>(\n `SELECT contract FROM mem_vault_registry WHERE owner_identity = $1 AND vault = $2 LIMIT 1`,\n [ownerIdentity, vault],\n )\n const contract = res.rows[0]?.contract as { kind?: string } | null\n return contract?.kind === 'channel'\n}\n\nexport async function isSecureVault(ownerIdentity: string, vault: string): Promise<boolean> {\n await ensureSchema()\n const res = await query<{ contract: unknown }>(\n `SELECT contract FROM mem_vault_registry WHERE owner_identity = $1 AND vault = $2 LIMIT 1`,\n [ownerIdentity, vault],\n )\n const contract = res.rows[0]?.contract as { kind?: string } | null\n return contract?.kind === 'secure'\n}\n\nexport async function listVaultMembers(ownerIdentity: string, vault: string): Promise<VaultMember[]> {\n await ensureSchema()\n const res = await query<{ grantee: string; entitlement: unknown; created_at: string }>(\n `SELECT grantee, entitlement, created_at FROM mem_vault_registry\n WHERE owner_identity = $1 AND vault = $2 AND grantee != $1 ORDER BY created_at ASC`,\n [ownerIdentity, vault],\n )\n return res.rows.map(r => ({ grantee: r.grantee, entitlement: normalizeScope(r.entitlement as Record<string, boolean>), createdAt: r.created_at }))\n}\n\nexport async function revokeVaultMember(ownerIdentity: string, vault: string, grantee: string): Promise<boolean> {\n await ensureSchema()\n const res = await query(\n `DELETE FROM mem_vault_registry WHERE owner_identity = $1 AND vault = $2 AND grantee = $3`,\n [ownerIdentity, vault, grantee],\n )\n return (res.rowCount ?? 0) > 0\n}\n\nexport interface IdentityVault {\n handle: string\n vault: string\n role: 'owner' | 'shared'\n sharedBy?: string\n entitlement: Scope\n kind: 'notes' | 'channel' | 'secure'\n}\n\nexport async function listVaultsForIdentity(identity: string): Promise<IdentityVault[]> {\n const ents = await entitledVaults(identity)\n const seen = new Map<string, IdentityVault>()\n for (const e of ents) {\n if (seen.has(e.handle)) continue\n const isOwner = e.ownerIdentity === identity\n seen.set(e.handle, {\n handle: e.handle,\n vault: e.vault,\n role: isOwner ? 'owner' : 'shared',\n sharedBy: isOwner ? undefined : e.ownerIdentity,\n entitlement: e.entitlement,\n kind: e.kind,\n })\n }\n return [...seen.values()]\n}\n\nexport async function physicalVaultsForIdentity(identity: string, opts?: { ownedOnly?: boolean }): Promise<string[]> {\n const vaults = await listVaultsForIdentity(identity)\n return vaults\n .filter(v => (opts?.ownedOnly ? v.role === 'owner' : true))\n .map(v => scopedVault(v.role === 'owner' ? identity : (v.sharedBy ?? identity), v.vault))\n}\n\nexport async function isVaultOwner(identity: string, handle: string): Promise<boolean> {\n await ensureSchema()\n const res = await query<{ owner_identity: string }>(\n `SELECT owner_identity FROM mem_vault_registry WHERE grantee = $1 AND COALESCE(handle, vault) = $2 LIMIT 1`,\n [identity, handle],\n )\n return res.rows[0]?.owner_identity === identity\n}\n\nexport async function vaultOwnerIdentity(vault: string): Promise<string | null> {\n await ensureSchema()\n const res = await query<{ owner_identity: string }>(\n `SELECT owner_identity FROM mem_vault_registry\n WHERE grantee = owner_identity AND (owner_identity || ' ' || vault) = $1\n LIMIT 1`,\n [vault],\n )\n return res.rows[0]?.owner_identity ?? null\n}\n\nexport async function deleteVaultRegistry(grantee: string, handle: string): Promise<number> {\n await ensureSchema()\n const res = await query(`DELETE FROM mem_vault_registry WHERE grantee = $1 AND COALESCE(handle, vault) = $2`, [grantee, handle])\n return res.rowCount ?? 0\n}\n\nexport function scopedVault(owner: string, vault: string): string {\n return `${owner} ${vault}`\n}\n\nexport async function vaultOwnerAndName(grantee: string, handle: string): Promise<{ ownerIdentity: string; vault: string } | null> {\n await ensureSchema()\n const res = await query<{ owner_identity: string; vault: string }>(\n `SELECT owner_identity, vault FROM mem_vault_registry WHERE grantee = $1 AND COALESCE(handle, vault) = $2 LIMIT 1`,\n [grantee, handle],\n )\n return res.rows[0] ? { ownerIdentity: res.rows[0].owner_identity, vault: res.rows[0].vault } : null\n}\n\nexport async function physicalVaultFor(grantee: string, handle: string): Promise<string> {\n await ensureSchema()\n const res = await query<{ owner_identity: string; vault: string }>(\n `SELECT owner_identity, vault FROM mem_vault_registry WHERE grantee = $1 AND COALESCE(handle, vault) = $2 LIMIT 1`,\n [grantee, handle],\n )\n const row = res.rows[0]\n if (row) return scopedVault(row.owner_identity, row.vault)\n const ctx = await getActiveContext(grantee)\n if (ctx.activeOwner && ctx.activeOwner !== grantee) return scopedVault(ctx.activeOwner, handle)\n return scopedVault(grantee, handle)\n}\n\nexport const VAULT_NAME_RE = /^[A-Za-z0-9 _-]{1,48}$/\n\nexport async function createVault(args: { identity: string; vault: string; owner?: string }): Promise<{ vault: string; created: boolean; owner: string }> {\n await ensureSchema()\n if (!VAULT_NAME_RE.test(args.vault)) {\n throw new Error(`invalid vault name \"${args.vault}\" (allowed: letters, digits, space, _ or -, 1-48 chars)`)\n }\n const owner = args.owner ?? args.identity\n const existing = await query(\n `SELECT 1 FROM mem_vault_registry WHERE grantee = $1 AND vault = $2 LIMIT 1`,\n [owner, args.vault],\n )\n if ((existing.rowCount ?? 0) > 0) {\n return { vault: args.vault, created: false, owner }\n }\n await addEntitlement({\n grantee: owner,\n handle: args.vault,\n vault: args.vault,\n ownerIdentity: owner,\n entitlement: normalizeScope({ read: true, write: true, export: true, index: true, admin: true, swap: true }),\n shared: false,\n })\n return { vault: args.vault, created: true, owner }\n}\n\nexport async function setVaultContract(grantee: string, vault: string, contract: VaultContract): Promise<void> {\n await ensureSchema()\n await query(\n `UPDATE mem_vault_registry SET contract = $3::jsonb WHERE grantee = $1 AND vault = $2`,\n [grantee, vault, JSON.stringify(contract)],\n )\n}\n\nexport async function provisionDefaultVaults(identity: string): Promise<{ created: string[]; vaults: string[] }> {\n await ensureSchema()\n const created: string[] = []\n for (const vault of DEFAULT_VAULTS) {\n const result = await createVault({ identity, vault, owner: identity })\n if (result.created) created.push(vault)\n const contract = VAULT_CONTRACTS[vault]\n if (contract) await setVaultContract(identity, vault, contract)\n }\n return { created, vaults: [...DEFAULT_VAULTS] }\n}\n\nexport async function setKeyVaults(keyId: string, vaults: string[]): Promise<boolean> {\n await ensureSchema()\n const res = await query(\n `UPDATE mem_keys SET vaults = $2::jsonb WHERE key_id = $1`,\n [keyId, JSON.stringify(vaults)],\n )\n return (res.rowCount ?? 0) > 0\n}\n\nexport async function getActiveVault(_sessionId: string, identity: string): Promise<string | null> {\n await ensureSchema()\n const res = await query<{ active_vault: string | null }>(\n `SELECT active_vault FROM mem_active_context WHERE identity = $1 LIMIT 1`,\n [identity],\n )\n return res.rows[0]?.active_vault ?? null\n}\n\nexport async function setActiveVault(_sessionId: string, identity: string, vault: string): Promise<void> {\n await ensureSchema()\n await query(\n `INSERT INTO mem_active_context (identity, active_vault, updated_at)\n VALUES ($1, $2, now())\n ON CONFLICT (identity) DO UPDATE SET active_vault = EXCLUDED.active_vault, updated_at = now()`,\n [identity, vault],\n )\n}\n\nexport interface ActiveContext {\n activeOwner: string | null\n activeVault: string | null\n}\n\nexport async function getActiveContext(identity: string): Promise<ActiveContext> {\n await ensureSchema()\n const res = await query<{ active_owner: string | null; active_vault: string | null }>(\n `SELECT active_owner, active_vault FROM mem_active_context WHERE identity = $1 LIMIT 1`,\n [identity],\n )\n const r = res.rows[0]\n return { activeOwner: r?.active_owner ?? null, activeVault: r?.active_vault ?? null }\n}\n\nexport async function setActiveOwner(identity: string, owner: string | null, vault: string | null): Promise<void> {\n await ensureSchema()\n await query(\n `INSERT INTO mem_active_context (identity, active_owner, active_vault, updated_at)\n VALUES ($1, $2, $3, now())\n ON CONFLICT (identity) DO UPDATE SET active_owner = EXCLUDED.active_owner, active_vault = EXCLUDED.active_vault, updated_at = now()`,\n [identity, owner, vault],\n )\n}\n\nexport interface AccountGrant {\n ownerIdentity: string\n grantee: string\n entitlement: Scope\n}\n\nexport async function addAccountGrant(args: { ownerIdentity: string; grantee: string; entitlement: Scope }): Promise<void> {\n await ensureSchema()\n await query(\n `INSERT INTO mem_account_grants (owner_identity, grantee, entitlement)\n VALUES ($1, $2, $3::jsonb)\n ON CONFLICT (owner_identity, grantee) DO UPDATE SET entitlement = EXCLUDED.entitlement`,\n [args.ownerIdentity, args.grantee, JSON.stringify(args.entitlement)],\n )\n}\n\nexport async function getAccountGrant(ownerIdentity: string, grantee: string): Promise<Scope | null> {\n await ensureSchema()\n const res = await query<{ entitlement: unknown }>(\n `SELECT entitlement FROM mem_account_grants WHERE owner_identity = $1 AND grantee = $2 LIMIT 1`,\n [ownerIdentity, grantee],\n )\n const r = res.rows[0]\n return r ? normalizeScope(r.entitlement as Record<string, boolean>) : null\n}\n\nexport async function accountGrantsForGrantee(grantee: string): Promise<AccountGrant[]> {\n await ensureSchema()\n const res = await query<{ owner_identity: string; entitlement: unknown }>(\n `SELECT owner_identity, entitlement FROM mem_account_grants WHERE grantee = $1 ORDER BY created_at ASC`,\n [grantee],\n )\n return res.rows.map(r => ({\n ownerIdentity: r.owner_identity,\n grantee,\n entitlement: normalizeScope(r.entitlement as Record<string, boolean>),\n }))\n}\n\nexport async function revokeAccountGrant(ownerIdentity: string, grantee: string): Promise<number> {\n await ensureSchema()\n const res = await query(`DELETE FROM mem_account_grants WHERE owner_identity = $1 AND grantee = $2`, [ownerIdentity, grantee])\n return res.rowCount ?? 0\n}\n\nexport async function ownedVaultNames(owner: string): Promise<string[]> {\n await ensureSchema()\n const res = await query<{ vault: string }>(\n `SELECT vault FROM mem_vault_registry WHERE grantee = $1 AND owner_identity = $1 ORDER BY created_at ASC`,\n [owner],\n )\n return res.rows.map(r => r.vault)\n}\n\nexport async function listAllNoteVaults(): Promise<string[]> {\n await ensureSchema()\n const res = await query<{ physical: string }>(\n `SELECT (owner_identity || ' ' || vault) AS physical FROM mem_vault_registry\n WHERE grantee = owner_identity AND COALESCE(contract->>'kind', '') != 'channel'\n ORDER BY owner_identity, vault`,\n )\n return res.rows.map(r => r.physical)\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,70 @@
1
+ type VideoRunStatus = 'queued' | 'resolving' | 'analyzing' | 'synthesizing' | 'detail' | 'done' | 'failed';
2
+ interface VideoRunRow {
3
+ id: string;
4
+ identity: string;
5
+ vault: string;
6
+ sourceUrl: string;
7
+ mediaUrl: string | null;
8
+ scraperApiKey: string | null;
9
+ intervalS: number;
10
+ maxFrames: number;
11
+ detail: string;
12
+ durationS: number | null;
13
+ frameCount: number;
14
+ status: VideoRunStatus;
15
+ error: string | null;
16
+ transcript: unknown;
17
+ metrics: unknown;
18
+ lenses: unknown;
19
+ qc: unknown;
20
+ reportMd: string | null;
21
+ artifactPath: string | null;
22
+ costUsd: number;
23
+ createdAt: Date;
24
+ updatedAt: Date;
25
+ }
26
+ declare function createVideoRun(args: {
27
+ identity: string;
28
+ vault: string;
29
+ sourceUrl: string;
30
+ intervalS: number;
31
+ maxFrames: number;
32
+ detail: string;
33
+ scraperApiKey: string | null;
34
+ }): Promise<string>;
35
+ declare function getVideoRun(id: string, identity: string): Promise<VideoRunRow | null>;
36
+ declare const PATCH_COLS: Record<string, string>;
37
+ declare function updateVideoRun(id: string, patch: Partial<Record<keyof typeof PATCH_COLS, unknown>>): Promise<void>;
38
+ declare function insertFrames(runId: string, frames: Array<{
39
+ idx: number;
40
+ tSec: number;
41
+ imgB64?: string;
42
+ }>): Promise<void>;
43
+ declare function setFrameObservation(runId: string, idx: number, observation: unknown, status: 'ok' | 'error'): Promise<void>;
44
+ interface PendingFrame {
45
+ idx: number;
46
+ tSec: number;
47
+ imgB64: string;
48
+ }
49
+ declare function listPendingImageFrames(runId: string, limit: number): Promise<PendingFrame[]>;
50
+ declare function countPendingFrames(runId: string): Promise<number>;
51
+ declare function setFrameDetail(runId: string, idx: number, detail: unknown): Promise<void>;
52
+ interface FrameRow {
53
+ idx: number;
54
+ tSec: number;
55
+ observation: unknown;
56
+ detail: unknown;
57
+ status: string;
58
+ }
59
+ declare function listFrames(runId: string): Promise<FrameRow[]>;
60
+ declare function listQueuedVideoRuns(limit: number): Promise<Array<{
61
+ id: string;
62
+ identity: string;
63
+ }>>;
64
+ declare function reapStaleVideoRun(id: string, reapMinutes: number): Promise<VideoRunRow | null>;
65
+ declare function runProgress(runId: string): Promise<{
66
+ total: number;
67
+ analyzed: number;
68
+ }>;
69
+
70
+ export { type FrameRow, type PendingFrame, type VideoRunRow, type VideoRunStatus, countPendingFrames, createVideoRun, getVideoRun, insertFrames, listFrames, listPendingImageFrames, listQueuedVideoRuns, reapStaleVideoRun, runProgress, setFrameDetail, setFrameObservation, updateVideoRun };