@opengeni/db 0.19.0 → 0.22.1

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.
@@ -0,0 +1,208 @@
1
+ import type { EligibleKnowledgeClaim, KnowledgeChangeProposalRecord, KnowledgeClaimEvidencePolarity, KnowledgeClaimOrigin, KnowledgeClaimRecord, KnowledgeClaimRelationType, KnowledgeClaimReviewState, KnowledgeDocumentVersionRecord, KnowledgeFactObjectKind, KnowledgeFactRecord, KnowledgeLifecycleEventType, KnowledgeLifecycleState, KnowledgeProviderRecord, KnowledgeSourceAclVersionRecord, KnowledgeSourceObjectRecord, KnowledgeSourceRecord, KnowledgeSyncRunRecord, ScopedKnowledgeActor, ScopedKnowledgeScope } from "@opengeni/contracts";
2
+ import type { Database } from "./index";
3
+ type KnowledgeWriteContext = {
4
+ accountId: string;
5
+ workspaceId: string;
6
+ scope: ScopedKnowledgeScope;
7
+ operationId: string;
8
+ actor: ScopedKnowledgeActor;
9
+ };
10
+ type KnowledgeReadContext = {
11
+ accountId: string;
12
+ workspaceId: string;
13
+ initiatingSubjectId: string;
14
+ surface: "human" | "agent";
15
+ };
16
+ export declare class ScopedKnowledgeConflictError extends Error {
17
+ readonly name = "ScopedKnowledgeConflictError";
18
+ readonly code = "SCOPED_KNOWLEDGE_CONFLICT";
19
+ }
20
+ export declare class ScopedKnowledgeGenerationConflictError extends Error {
21
+ readonly name = "ScopedKnowledgeGenerationConflictError";
22
+ readonly code = "SCOPED_KNOWLEDGE_GENERATION_CONFLICT";
23
+ }
24
+ export declare class ScopedKnowledgeNotFoundError extends Error {
25
+ readonly name = "ScopedKnowledgeNotFoundError";
26
+ }
27
+ export declare class ScopedKnowledgeInvalidOperationError extends Error {
28
+ readonly name = "ScopedKnowledgeInvalidOperationError";
29
+ }
30
+ export declare class ScopedKnowledgeAuthorityError extends Error {
31
+ readonly name = "ScopedKnowledgeAuthorityError";
32
+ }
33
+ export declare function scopedKnowledgeInputHash(value: unknown): string;
34
+ export declare function normalizeScopedKnowledgeKey(value: string): string;
35
+ export declare function scopedKnowledgeScopeKey(scope: ScopedKnowledgeScope): string;
36
+ export declare function upsertKnowledgeProvider(db: Database, input: KnowledgeWriteContext & {
37
+ providerKey: string;
38
+ externalTenantId: string;
39
+ }): Promise<KnowledgeProviderRecord>;
40
+ export declare function upsertKnowledgeSource(db: Database, input: KnowledgeWriteContext & {
41
+ providerId: string;
42
+ externalSourceId: string;
43
+ sourceKind: string;
44
+ sourceUri?: string | null;
45
+ }): Promise<KnowledgeSourceRecord>;
46
+ export declare function appendKnowledgeSourceAclVersion(db: Database, input: Omit<KnowledgeWriteContext, "scope"> & {
47
+ sourceId: string;
48
+ audience: ScopedKnowledgeScope;
49
+ expectedSourceLifecycleGeneration: number;
50
+ expectedAclGeneration: number;
51
+ aclVersion?: string | null;
52
+ agentAccess: boolean;
53
+ reasonCode: string;
54
+ }): Promise<KnowledgeSourceAclVersionRecord>;
55
+ export declare function beginKnowledgeSyncRun(db: Database, input: Omit<KnowledgeWriteContext, "scope"> & {
56
+ sourceId: string;
57
+ expectedSourceLifecycleGeneration: number;
58
+ expectedSyncGeneration: number;
59
+ inputCursor: string | null;
60
+ }): Promise<KnowledgeSyncRunRecord>;
61
+ export declare function completeKnowledgeSyncRun(db: Database, input: {
62
+ accountId: string;
63
+ workspaceId: string;
64
+ initiatingSubjectId: string | null;
65
+ runId: string;
66
+ state: "succeeded" | "failed";
67
+ outputCursor?: string | null;
68
+ watermark?: string | null;
69
+ metadata?: Record<string, unknown> | undefined;
70
+ errorCode?: string | null;
71
+ reasonCode: string;
72
+ }): Promise<KnowledgeSyncRunRecord>;
73
+ export declare function upsertKnowledgeSourceObject(db: Database, input: Omit<KnowledgeWriteContext, "scope"> & {
74
+ sourceId: string;
75
+ externalObjectId: string;
76
+ documentId?: string | null;
77
+ }): Promise<KnowledgeSourceObjectRecord>;
78
+ export declare function appendKnowledgeDocumentVersion(db: Database, input: Omit<KnowledgeWriteContext, "scope"> & {
79
+ objectId: string;
80
+ expectedObjectLifecycleGeneration: number;
81
+ expectedVersionGeneration: number;
82
+ externalVersionId: string;
83
+ contentSha256: string;
84
+ ingestionKey: string;
85
+ sourceCursor?: string | null;
86
+ sourceMetadata?: Record<string, unknown> | undefined;
87
+ sourceCreatedAt?: string | null;
88
+ sourceUpdatedAt?: string | null;
89
+ aclVersionId: string;
90
+ aclGeneration: number;
91
+ documentId?: string | null;
92
+ fileId?: string | null;
93
+ locationMetadata?: Record<string, unknown> | undefined;
94
+ reasonCode: string;
95
+ }): Promise<KnowledgeDocumentVersionRecord>;
96
+ export declare function recordKnowledgeLifecycleEvent(db: Database, input: Omit<KnowledgeWriteContext, "scope"> & {
97
+ targetKind: "provider" | "source" | "object";
98
+ targetId: string;
99
+ eventType: Extract<KnowledgeLifecycleEventType, "deleted" | "revoked" | "restored">;
100
+ expectedGeneration: number;
101
+ reasonCode: string;
102
+ }): Promise<{
103
+ targetId: string;
104
+ lifecycleState: KnowledgeLifecycleState;
105
+ lifecycleGeneration: number;
106
+ replayed: boolean;
107
+ }>;
108
+ export declare function restoreKnowledgeSourceObject(db: Database, input: Omit<Parameters<typeof recordKnowledgeLifecycleEvent>[1], "targetKind" | "eventType">): Promise<{
109
+ targetId: string;
110
+ lifecycleState: KnowledgeLifecycleState;
111
+ lifecycleGeneration: number;
112
+ replayed: boolean;
113
+ }>;
114
+ export declare function upsertKnowledgeEntity(db: Database, input: KnowledgeWriteContext & {
115
+ entityType: string;
116
+ normalizedKey: string;
117
+ displayName: string;
118
+ }): Promise<{
119
+ id: string;
120
+ accountId: string;
121
+ scope: ScopedKnowledgeScope;
122
+ entityType: string;
123
+ normalizedKey: string;
124
+ displayName: string;
125
+ createdAt: string;
126
+ }>;
127
+ export declare function attachKnowledgeEntityAlias(db: Database, input: Omit<KnowledgeWriteContext, "scope"> & {
128
+ entityId: string;
129
+ alias: string;
130
+ }): Promise<{
131
+ id: string;
132
+ entityId: string;
133
+ alias: string;
134
+ normalizedAlias: string;
135
+ }>;
136
+ export declare function upsertKnowledgeFact(db: Database, input: Omit<KnowledgeWriteContext, "scope"> & {
137
+ subjectEntityId: string;
138
+ predicateKey: string;
139
+ object: {
140
+ kind: "entity";
141
+ entityId: string;
142
+ } | {
143
+ kind: Exclude<KnowledgeFactObjectKind, "entity">;
144
+ value: unknown;
145
+ };
146
+ }): Promise<KnowledgeFactRecord>;
147
+ export declare function appendKnowledgeClaim(db: Database, input: Omit<KnowledgeWriteContext, "scope"> & {
148
+ factId: string;
149
+ origin: KnowledgeClaimOrigin;
150
+ confidenceBps: number;
151
+ effectiveAt: string;
152
+ expiresAt?: string | null;
153
+ extractionMethod: string;
154
+ extractionMetadata?: Record<string, unknown> | undefined;
155
+ modelProvider?: string | null;
156
+ modelName?: string | null;
157
+ modelVersion?: string | null;
158
+ }): Promise<KnowledgeClaimRecord>;
159
+ export declare function linkKnowledgeClaims(db: Database, input: Omit<KnowledgeWriteContext, "scope"> & {
160
+ relationType: KnowledgeClaimRelationType;
161
+ fromClaimId: string;
162
+ toClaimId: string;
163
+ }): Promise<{
164
+ id: string;
165
+ relationType: KnowledgeClaimRelationType;
166
+ fromClaimId: string;
167
+ toClaimId: string;
168
+ }>;
169
+ export declare function appendKnowledgeClaimEvidence(db: Database, input: Omit<KnowledgeWriteContext, "scope"> & {
170
+ claimId: string;
171
+ documentVersionId: string;
172
+ polarity: KnowledgeClaimEvidencePolarity;
173
+ documentChunkId?: string | null;
174
+ chunkIndex?: number | null;
175
+ locator?: string | null;
176
+ quoteHash?: string | null;
177
+ contentHash: string;
178
+ }): Promise<{
179
+ id: string;
180
+ claimId: string;
181
+ documentVersionId: string;
182
+ polarity: KnowledgeClaimEvidencePolarity;
183
+ }>;
184
+ export declare function appendKnowledgeClaimReview(db: Database, input: Omit<KnowledgeWriteContext, "scope"> & {
185
+ claimId: string;
186
+ state: KnowledgeClaimReviewState;
187
+ reason: string;
188
+ }): Promise<{
189
+ id: string;
190
+ claimId: string;
191
+ state: KnowledgeClaimReviewState;
192
+ reviewRevision: number;
193
+ }>;
194
+ export declare function createKnowledgeChangeProposal(db: Database, input: Omit<KnowledgeWriteContext, "scope"> & {
195
+ claimId: string;
196
+ evidenceId: string;
197
+ targetKind: "instruction_policy" | "preference";
198
+ targetScope: string;
199
+ targetKey?: string | null;
200
+ content: string;
201
+ }): Promise<KnowledgeChangeProposalRecord>;
202
+ export declare function listEligibleKnowledgeClaims(db: Database, input: KnowledgeReadContext & {
203
+ limit?: number | undefined;
204
+ }): Promise<EligibleKnowledgeClaim[]>;
205
+ export declare function getEligibleKnowledgeClaim(db: Database, input: KnowledgeReadContext & {
206
+ claimId: string;
207
+ }): Promise<EligibleKnowledgeClaim | null>;
208
+ export {};
@@ -196,6 +196,7 @@ export declare function registerSessionTurnAttemptClaim(db: Database, input: {
196
196
  temporalActivityId: string;
197
197
  verifiedControlRevision: number;
198
198
  mcpApprovalPolicies: Record<string, SessionMcpApprovalPolicy>;
199
+ connectorActionPolicies: schema.ConnectorActionPolicySnapshotEntry[];
199
200
  }): Promise<typeof schema.sessionTurnAttempts.$inferSelect>;
200
201
  /**
201
202
  * Close the exact first-class owner while the caller still holds the owning
@@ -1,4 +1,4 @@
1
- import { ResourceRef, type LatencyMode, type ReasoningEffort, type TurnExecutionPolicyV1 } from "@opengeni/contracts";
1
+ import { ResourceRef, type McpPersonalConnectionDelegation, type LatencyMode, type ReasoningEffort, type TurnExecutionPolicyV1 } from "@opengeni/contracts";
2
2
  import type { Database } from "./index";
3
3
  import { type SessionCommandActor, type SessionCommandReceiptRow } from "./session-control";
4
4
  import * as schema from "./schema";
@@ -158,6 +158,7 @@ export declare function submitHumanPromptInTransaction(db: Database, input: {
158
158
  /** Trusted API/core admission snapshot. Omitted only by legacy low-level callers. */
159
159
  turnExecutionPolicy?: TurnExecutionPolicyV1;
160
160
  source: "user" | "api";
161
+ personalConnectionDelegations?: McpPersonalConnectionDelegation[];
161
162
  mcpCredentialUpdates?: Array<{
162
163
  id: string;
163
164
  headersEncrypted: Record<string, string>;
@@ -0,0 +1,181 @@
1
+ -- deployment-mode: rolling
2
+ -- Personal MCP authority is additive and frozen separately from causal initiators.
3
+
4
+ ALTER TABLE sessions
5
+ ADD COLUMN initial_personal_connection_delegations jsonb NOT NULL DEFAULT '[]'::jsonb,
6
+ ADD COLUMN parent_turn_id uuid,
7
+ ADD CONSTRAINT sessions_initial_personal_delegations_array_chk
8
+ CHECK (
9
+ jsonb_typeof(initial_personal_connection_delegations) = 'array'
10
+ AND jsonb_array_length(initial_personal_connection_delegations) <= 128
11
+ );
12
+
13
+ ALTER TABLE session_turns
14
+ ADD COLUMN personal_connection_delegations jsonb NOT NULL DEFAULT '[]'::jsonb,
15
+ ADD CONSTRAINT session_turns_personal_delegations_array_chk
16
+ CHECK (
17
+ jsonb_typeof(personal_connection_delegations) = 'array'
18
+ AND jsonb_array_length(personal_connection_delegations) <= 128
19
+ );
20
+
21
+ ALTER TABLE session_system_updates
22
+ ADD COLUMN personal_connection_delegations jsonb NOT NULL DEFAULT '[]'::jsonb,
23
+ ADD CONSTRAINT session_updates_personal_delegations_array_chk
24
+ CHECK (
25
+ jsonb_typeof(personal_connection_delegations) = 'array'
26
+ AND jsonb_array_length(personal_connection_delegations) <= 128
27
+ );
28
+
29
+ ALTER TABLE session_system_update_outbox
30
+ ADD COLUMN personal_connection_delegations jsonb NOT NULL DEFAULT '[]'::jsonb,
31
+ ADD CONSTRAINT session_update_outbox_personal_delegations_array_chk
32
+ CHECK (
33
+ jsonb_typeof(personal_connection_delegations) = 'array'
34
+ AND jsonb_array_length(personal_connection_delegations) <= 128
35
+ );
36
+
37
+ ALTER TABLE scheduled_tasks
38
+ ADD COLUMN created_by_kind text NOT NULL DEFAULT 'service',
39
+ ADD COLUMN created_by_subject_id text NOT NULL DEFAULT 'unattributed-legacy',
40
+ ADD COLUMN created_by_context jsonb NOT NULL DEFAULT '{"backfill":true}'::jsonb,
41
+ ADD COLUMN personal_connection_delegations jsonb NOT NULL DEFAULT '[]'::jsonb,
42
+ ADD CONSTRAINT scheduled_tasks_created_by_kind_check
43
+ CHECK (created_by_kind IN ('subject', 'service')),
44
+ ADD CONSTRAINT scheduled_tasks_created_by_subject_nonempty_check
45
+ CHECK (octet_length(btrim(created_by_subject_id)) BETWEEN 1 AND 512),
46
+ ADD CONSTRAINT scheduled_tasks_created_by_context_object_check
47
+ CHECK (jsonb_typeof(created_by_context) = 'object'),
48
+ ADD CONSTRAINT scheduled_tasks_personal_delegations_array_chk
49
+ CHECK (
50
+ jsonb_typeof(personal_connection_delegations) = 'array'
51
+ AND jsonb_array_length(personal_connection_delegations) <= 128
52
+ );
53
+
54
+ DROP FUNCTION opengeni_private.claim_session_system_update_outbox(integer);
55
+ CREATE FUNCTION opengeni_private.claim_session_system_update_outbox(p_limit integer)
56
+ RETURNS TABLE (
57
+ id uuid, account_id uuid, workspace_id uuid, source_session_id uuid,
58
+ target_session_id uuid, dedupe_key text, kind text, classification text,
59
+ source_id text, summary text, payload jsonb, lineage jsonb,
60
+ personal_connection_delegations jsonb
61
+ )
62
+ LANGUAGE plpgsql
63
+ SECURITY DEFINER
64
+ AS $$
65
+ BEGIN
66
+ RETURN QUERY
67
+ WITH claimed AS (
68
+ SELECT o.id FROM session_system_update_outbox o
69
+ WHERE o.status = 'pending'
70
+ ORDER BY o.created_at, o.id
71
+ FOR UPDATE SKIP LOCKED
72
+ LIMIT greatest(1, least(coalesce(p_limit, 100), 100))
73
+ )
74
+ UPDATE session_system_update_outbox o
75
+ SET attempts = o.attempts + 1, updated_at = now()
76
+ FROM claimed c WHERE o.id = c.id
77
+ RETURNING o.id, o.account_id, o.workspace_id, o.source_session_id,
78
+ o.target_session_id, o.dedupe_key, o.kind, o.classification,
79
+ o.source_id, o.summary, o.payload, o.lineage,
80
+ o.personal_connection_delegations;
81
+ END $$;
82
+ REVOKE ALL ON FUNCTION opengeni_private.claim_session_system_update_outbox(integer) FROM PUBLIC;
83
+
84
+ DO $$
85
+ BEGIN
86
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
87
+ GRANT EXECUTE ON FUNCTION opengeni_private.claim_session_system_update_outbox(integer)
88
+ TO opengeni_app;
89
+ END IF;
90
+ END $$;
91
+
92
+ CREATE OR REPLACE FUNCTION opengeni_private.prevent_personal_connection_authority_mutation()
93
+ RETURNS trigger
94
+ LANGUAGE plpgsql
95
+ AS $$
96
+ BEGIN
97
+ IF TG_TABLE_NAME = 'sessions' THEN
98
+ IF NEW.initial_personal_connection_delegations IS DISTINCT FROM OLD.initial_personal_connection_delegations
99
+ OR NEW.parent_turn_id IS DISTINCT FROM OLD.parent_turn_id
100
+ THEN
101
+ RAISE EXCEPTION 'session initial personal MCP authority is immutable' USING ERRCODE = '23514';
102
+ END IF;
103
+ ELSIF NEW.personal_connection_delegations IS DISTINCT FROM OLD.personal_connection_delegations THEN
104
+ RAISE EXCEPTION '% personal MCP authority is immutable', TG_TABLE_NAME USING ERRCODE = '23514';
105
+ END IF;
106
+ RETURN NEW;
107
+ END;
108
+ $$;
109
+
110
+ CREATE OR REPLACE FUNCTION opengeni_private.validate_session_parent_turn()
111
+ RETURNS trigger
112
+ LANGUAGE plpgsql
113
+ AS $$
114
+ BEGIN
115
+ IF NEW.parent_turn_id IS NULL THEN
116
+ RETURN NEW;
117
+ END IF;
118
+ IF NEW.parent_session_id IS NULL OR NOT EXISTS (
119
+ SELECT 1
120
+ FROM session_turns parent_turn
121
+ WHERE parent_turn.id = NEW.parent_turn_id
122
+ AND parent_turn.workspace_id = NEW.workspace_id
123
+ AND parent_turn.session_id = NEW.parent_session_id
124
+ ) THEN
125
+ RAISE EXCEPTION 'session parent turn must belong to its parent session and workspace'
126
+ USING ERRCODE = '23514';
127
+ END IF;
128
+ RETURN NEW;
129
+ END;
130
+ $$;
131
+
132
+ CREATE TRIGGER sessions_personal_authority_immutable
133
+ BEFORE UPDATE OF initial_personal_connection_delegations, parent_turn_id
134
+ ON sessions
135
+ FOR EACH ROW
136
+ EXECUTE FUNCTION opengeni_private.prevent_personal_connection_authority_mutation();
137
+
138
+ CREATE TRIGGER sessions_parent_turn_valid
139
+ BEFORE INSERT OR UPDATE OF parent_turn_id, parent_session_id, workspace_id
140
+ ON sessions
141
+ FOR EACH ROW
142
+ EXECUTE FUNCTION opengeni_private.validate_session_parent_turn();
143
+
144
+ CREATE TRIGGER session_turns_personal_authority_immutable
145
+ BEFORE UPDATE OF personal_connection_delegations
146
+ ON session_turns
147
+ FOR EACH ROW
148
+ EXECUTE FUNCTION opengeni_private.prevent_personal_connection_authority_mutation();
149
+
150
+ CREATE TRIGGER session_updates_personal_authority_immutable
151
+ BEFORE UPDATE OF personal_connection_delegations
152
+ ON session_system_updates
153
+ FOR EACH ROW
154
+ EXECUTE FUNCTION opengeni_private.prevent_personal_connection_authority_mutation();
155
+
156
+ CREATE TRIGGER session_update_outbox_personal_authority_immutable
157
+ BEFORE UPDATE OF personal_connection_delegations
158
+ ON session_system_update_outbox
159
+ FOR EACH ROW
160
+ EXECUTE FUNCTION opengeni_private.prevent_personal_connection_authority_mutation();
161
+
162
+ CREATE OR REPLACE FUNCTION opengeni_private.prevent_scheduled_task_creator_mutation()
163
+ RETURNS trigger
164
+ LANGUAGE plpgsql
165
+ AS $$
166
+ BEGIN
167
+ IF NEW.created_by_kind IS DISTINCT FROM OLD.created_by_kind
168
+ OR NEW.created_by_subject_id IS DISTINCT FROM OLD.created_by_subject_id
169
+ OR NEW.created_by_context IS DISTINCT FROM OLD.created_by_context
170
+ THEN
171
+ RAISE EXCEPTION 'scheduled task creator is immutable' USING ERRCODE = '23514';
172
+ END IF;
173
+ RETURN NEW;
174
+ END;
175
+ $$;
176
+
177
+ CREATE TRIGGER scheduled_tasks_creator_immutable
178
+ BEFORE UPDATE OF created_by_kind, created_by_subject_id, created_by_context
179
+ ON scheduled_tasks
180
+ FOR EACH ROW
181
+ EXECUTE FUNCTION opengeni_private.prevent_scheduled_task_creator_mutation();