@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.
- package/dist/{chunk-XOXEQ7HG.js → chunk-BNGEN5QZ.js} +85 -1
- package/dist/chunk-BNGEN5QZ.js.map +1 -0
- package/dist/{chunk-SZP6KRLC.js → chunk-CYGFLLMN.js} +2698 -1918
- package/dist/chunk-CYGFLLMN.js.map +1 -0
- package/dist/index.d.ts +108 -1
- package/dist/index.js +5940 -2907
- package/dist/index.js.map +1 -1
- package/dist/provision-roles.js +1 -1
- package/dist/runtime-posture.d.ts +4 -4
- package/dist/schema.d.ts +1147 -101
- package/dist/schema.js +37 -1
- package/dist/scoped-knowledge-schema.d.ts +5341 -0
- package/dist/scoped-knowledge.d.ts +208 -0
- package/dist/session-control.d.ts +1 -0
- package/dist/session-queue-commands.d.ts +2 -1
- package/drizzle/0153_mcp_personal_connection_delegations.sql +181 -0
- package/drizzle/0154_scoped_knowledge_foundation.sql +2292 -0
- package/drizzle/0155_connector_action_policies.sql +218 -0
- package/package.json +3 -3
- package/src/connection-token-resolver.ts +3 -0
- package/src/index.ts +1211 -7
- package/src/provision-roles.ts +48 -0
- package/src/runtime-posture.ts +36 -0
- package/src/schema.ts +228 -2
- package/src/scoped-knowledge-schema.ts +603 -0
- package/src/scoped-knowledge.ts +2891 -0
- package/src/session-control.ts +3 -0
- package/src/session-queue-commands.ts +48 -0
- package/dist/chunk-SZP6KRLC.js.map +0 -1
- package/dist/chunk-XOXEQ7HG.js.map +0 -1
|
@@ -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();
|