@opengeni/db 3.2.0-canary.0 → 3.4.0-canary.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.
- package/dist/canonical-human-identities.js +3 -3
- package/dist/{chunk-SIBYBA2D.js → chunk-6DPJA36C.js} +30 -11
- package/dist/chunk-6DPJA36C.js.map +1 -0
- package/dist/{chunk-KRLPEMLH.js → chunk-C2AFP7SB.js} +184 -6
- package/dist/chunk-C2AFP7SB.js.map +1 -0
- package/dist/{chunk-AZHW7R5V.js → chunk-H7MXYG7R.js} +12 -8
- package/dist/chunk-H7MXYG7R.js.map +1 -0
- package/dist/{chunk-2PRS4J5Q.js → chunk-HY3F5Q4E.js} +3 -3
- package/dist/{chunk-NAB6FKFN.js → chunk-O6FTELKH.js} +3 -3
- package/dist/{chunk-UZNXG44K.js → chunk-PYMY3AJW.js} +324 -8
- package/dist/chunk-PYMY3AJW.js.map +1 -0
- package/dist/{chunk-6HMM2R5T.js → chunk-TRBOWUG3.js} +98 -4
- package/dist/chunk-TRBOWUG3.js.map +1 -0
- package/dist/{chunk-E6CLMKEE.js → chunk-V3TRUXFJ.js} +2 -2
- package/dist/{chunk-2EH4WRHL.js → chunk-ZWRIPCTR.js} +2 -2
- package/dist/editable-artifact-durable-export.js +2 -2
- package/dist/editable-artifacts.js +3 -3
- package/dist/governed-learning-activation.d.ts +16 -0
- package/dist/index.d.ts +108 -7
- package/dist/index.js +3605 -1417
- package/dist/index.js.map +1 -1
- package/dist/insights-model-bundle.d.ts +30 -0
- package/dist/insights-usage-bundle.d.ts +32 -0
- package/dist/insights.d.ts +10 -2
- package/dist/lossless-json.d.ts +1 -1
- package/dist/managed-user-setup.d.ts +82 -0
- package/dist/memory-domain.d.ts +2 -2
- package/dist/migrate.d.ts +3 -1
- package/dist/migrate.js +1 -1
- package/dist/new-session-drafts.d.ts +4 -4
- package/dist/organization-membership-lifecycle.d.ts +60 -1
- package/dist/pr-review.d.ts +44 -3
- package/dist/provision-roles.js +1 -1
- package/dist/runtime-posture.d.ts +12 -7
- package/dist/schema.d.ts +839 -101
- package/dist/schema.js +9 -1
- package/dist/session-background-commands.js +3 -3
- package/dist/session-tenancy.d.ts +12 -1
- package/dist/session-tenancy.js +3 -3
- package/dist/video-generation.js +3 -3
- package/drizzle/0348_named_signup_and_user_setup.sql +838 -0
- package/drizzle/0349_greenfield_session_tenancy_activation.sql +792 -0
- package/drizzle/0350_organization_shared_workspace_administration.sql +889 -0
- package/drizzle/0351_organization_user_setup_delivery.sql +978 -0
- package/drizzle/0352_session_variable_set_attachments.sql +1661 -0
- package/drizzle/0353_automatic_session_title_policy_fence.sql +476 -0
- package/drizzle/0354_automatic_session_title_quarantine_index.sql +9 -0
- package/drizzle/0355_automatic_session_title_quarantine.sql +92 -0
- package/drizzle/0356_set_based_insights_session_visibility.sql +237 -0
- package/drizzle/0357_rig_platform_base_only.sql +44 -0
- package/drizzle/0358_pr_review_managed_github_app.sql +108 -0
- package/drizzle/0359_insights_force_rls_read_capability.sql +936 -0
- package/drizzle/0360_organization_identity_confirmation_prompt.sql +103 -0
- package/drizzle/0361_remember_knowledge_memory_materialization.sql +249 -0
- package/package.json +6 -6
- package/src/database.ts +12 -8
- package/src/governed-learning-activation.ts +74 -2
- package/src/index.ts +879 -92
- package/src/insights-model-bundle.ts +681 -0
- package/src/insights-usage-bundle.ts +240 -0
- package/src/insights.ts +265 -152
- package/src/lossless-json.ts +2 -1
- package/src/managed-user-setup.ts +316 -0
- package/src/memory-domain.ts +3 -3
- package/src/migrate.ts +38 -14
- package/src/new-session-drafts.ts +22 -15
- package/src/organization-membership-lifecycle.ts +253 -1
- package/src/pr-review.ts +449 -6
- package/src/provision-roles.ts +92 -0
- package/src/runtime-posture.ts +247 -4
- package/src/schema.ts +210 -4
- package/src/session-tenancy.ts +120 -2
- package/dist/chunk-6HMM2R5T.js.map +0 -1
- package/dist/chunk-AZHW7R5V.js.map +0 -1
- package/dist/chunk-KRLPEMLH.js.map +0 -1
- package/dist/chunk-SIBYBA2D.js.map +0 -1
- package/dist/chunk-UZNXG44K.js.map +0 -1
- /package/dist/{chunk-2PRS4J5Q.js.map → chunk-HY3F5Q4E.js.map} +0 -0
- /package/dist/{chunk-NAB6FKFN.js.map → chunk-O6FTELKH.js.map} +0 -0
- /package/dist/{chunk-E6CLMKEE.js.map → chunk-V3TRUXFJ.js.map} +0 -0
- /package/dist/{chunk-2EH4WRHL.js.map → chunk-ZWRIPCTR.js.map} +0 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
-- deployment-mode: rolling
|
|
2
|
+
-- The durable company-profile storage contract retains its historical list
|
|
3
|
+
-- fields for revision compatibility, but new product surfaces use only the
|
|
4
|
+
-- small always-on organization identity and mission. Existing proposal rows
|
|
5
|
+
-- keep their immutable human-input payload; only proposals prepared after this
|
|
6
|
+
-- migration receive the narrowed confirmation copy.
|
|
7
|
+
|
|
8
|
+
CREATE OR REPLACE FUNCTION company_profile_agent_confirmation_summary(p_content_json text)
|
|
9
|
+
RETURNS text
|
|
10
|
+
LANGUAGE plpgsql IMMUTABLE
|
|
11
|
+
AS $body$
|
|
12
|
+
DECLARE
|
|
13
|
+
profile jsonb := p_content_json::jsonb;
|
|
14
|
+
summary text;
|
|
15
|
+
list_name text;
|
|
16
|
+
list_text text;
|
|
17
|
+
BEGIN
|
|
18
|
+
summary := 'Identity: ' || coalesce(nullif(btrim(profile->>'identity'), ''), '(none)')
|
|
19
|
+
|| E'\nMission: ' || coalesce(nullif(btrim(profile->>'mission'), ''), '(none)');
|
|
20
|
+
-- Rolling compatibility: old API instances may still submit these fields.
|
|
21
|
+
-- Never hide nonempty content from the human confirmation. New instances
|
|
22
|
+
-- submit empty arrays, so the narrowed identity UI remains concise.
|
|
23
|
+
FOREACH list_name IN ARRAY ARRAY['products', 'customers', 'goals', 'constraints'] LOOP
|
|
24
|
+
IF jsonb_array_length(coalesce(profile->list_name, '[]'::jsonb)) > 0 THEN
|
|
25
|
+
SELECT string_agg('- ' || (item->>'key') || ': ' || (item->>'content'), E'\n'
|
|
26
|
+
ORDER BY entries.ordinality)
|
|
27
|
+
INTO list_text
|
|
28
|
+
FROM jsonb_array_elements(profile->list_name)
|
|
29
|
+
WITH ORDINALITY AS entries(item, ordinality);
|
|
30
|
+
summary := summary || E'\nLegacy ' || initcap(list_name)
|
|
31
|
+
|| ' (retained compatibility context):' || E'\n' || list_text;
|
|
32
|
+
END IF;
|
|
33
|
+
END LOOP;
|
|
34
|
+
-- HumanInputQuestion.helpText is capped at 2048 UTF-16 code units; the
|
|
35
|
+
-- revision/hash prefix uses under 100. Bound the rendered bytes (a UTF-16
|
|
36
|
+
-- unit never needs more bytes than it needs units) without splitting a
|
|
37
|
+
-- character.
|
|
38
|
+
IF octet_length(summary) > 1800 THEN
|
|
39
|
+
WHILE octet_length(summary) > 1797 LOOP
|
|
40
|
+
summary := left(
|
|
41
|
+
summary,
|
|
42
|
+
length(summary) - greatest(1, (octet_length(summary) - 1797) / 4)
|
|
43
|
+
);
|
|
44
|
+
END LOOP;
|
|
45
|
+
summary := summary || '...';
|
|
46
|
+
END IF;
|
|
47
|
+
RETURN summary;
|
|
48
|
+
END
|
|
49
|
+
$body$;
|
|
50
|
+
|
|
51
|
+
CREATE OR REPLACE FUNCTION company_profile_agent_confirmation_prompt(
|
|
52
|
+
p_revision_id uuid,
|
|
53
|
+
p_revision bigint,
|
|
54
|
+
p_content_hash text,
|
|
55
|
+
p_content_json text
|
|
56
|
+
) RETURNS jsonb
|
|
57
|
+
LANGUAGE sql IMMUTABLE
|
|
58
|
+
AS $body$
|
|
59
|
+
SELECT jsonb_build_object(
|
|
60
|
+
'questions', jsonb_build_array(jsonb_build_object(
|
|
61
|
+
'id', 'company-profile:' || p_revision_id::text,
|
|
62
|
+
'kind', 'single_select',
|
|
63
|
+
'prompt', CASE
|
|
64
|
+
WHEN jsonb_array_length(coalesce((p_content_json::jsonb)->'products', '[]'::jsonb))
|
|
65
|
+
+ jsonb_array_length(coalesce((p_content_json::jsonb)->'customers', '[]'::jsonb))
|
|
66
|
+
+ jsonb_array_length(coalesce((p_content_json::jsonb)->'goals', '[]'::jsonb))
|
|
67
|
+
+ jsonb_array_length(coalesce((p_content_json::jsonb)->'constraints', '[]'::jsonb)) > 0
|
|
68
|
+
THEN 'Activate this organization identity and retained legacy details?'
|
|
69
|
+
ELSE 'Activate this organization identity and mission?'
|
|
70
|
+
END,
|
|
71
|
+
'label', 'Organization identity',
|
|
72
|
+
'helpText', 'Revision ' || p_revision::text || '; SHA-256 ' || p_content_hash
|
|
73
|
+
|| E'.\n\n' || company_profile_agent_confirmation_summary(p_content_json),
|
|
74
|
+
'options', jsonb_build_array(
|
|
75
|
+
jsonb_build_object('id', 'activate', 'label', 'Activate'),
|
|
76
|
+
jsonb_build_object('id', 'skip', 'label', 'Do not activate')
|
|
77
|
+
),
|
|
78
|
+
'required', true,
|
|
79
|
+
'allowOther', true
|
|
80
|
+
)),
|
|
81
|
+
'allowSkip', false
|
|
82
|
+
)
|
|
83
|
+
$body$;
|
|
84
|
+
|
|
85
|
+
-- CREATE OR REPLACE resets per-function configuration. Restore the pinned
|
|
86
|
+
-- search path installed by migration 0324 so these helpers retain the same
|
|
87
|
+
-- schema-agnostic hardening after the rolling replacement.
|
|
88
|
+
DO $organization_identity_confirmation_hardening$
|
|
89
|
+
DECLARE
|
|
90
|
+
target_schema text := current_schema();
|
|
91
|
+
BEGIN
|
|
92
|
+
EXECUTE format(
|
|
93
|
+
'ALTER FUNCTION %I.company_profile_agent_confirmation_summary(text) '
|
|
94
|
+
|| 'SET search_path = pg_catalog, %I, pg_temp',
|
|
95
|
+
target_schema, target_schema
|
|
96
|
+
);
|
|
97
|
+
EXECUTE format(
|
|
98
|
+
'ALTER FUNCTION %I.company_profile_agent_confirmation_prompt(uuid,bigint,text,text) '
|
|
99
|
+
|| 'SET search_path = pg_catalog, %I, pg_temp',
|
|
100
|
+
target_schema, target_schema
|
|
101
|
+
);
|
|
102
|
+
END
|
|
103
|
+
$organization_identity_confirmation_hardening$;
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
-- deployment-mode: rolling
|
|
2
|
+
-- A human-confirmed `remember` Knowledge claim materializes into one exact
|
|
3
|
+
-- Memory record. The confirmation receipt is the idempotency identity: general
|
|
4
|
+
-- Memory deduplication must never substitute a normalized lookalike, and replay
|
|
5
|
+
-- must keep returning the same Memory id after later archival.
|
|
6
|
+
|
|
7
|
+
SET lock_timeout = '5s';
|
|
8
|
+
SET statement_timeout = '60s';
|
|
9
|
+
|
|
10
|
+
CREATE TABLE remember_knowledge_memory_materializations (
|
|
11
|
+
confirmation_receipt_id uuid PRIMARY KEY
|
|
12
|
+
REFERENCES remember_knowledge_confirmation_receipts(id) ON DELETE CASCADE,
|
|
13
|
+
account_id uuid NOT NULL REFERENCES managed_accounts(id) ON DELETE CASCADE,
|
|
14
|
+
workspace_id uuid NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
15
|
+
session_id uuid NOT NULL,
|
|
16
|
+
memory_id uuid NOT NULL,
|
|
17
|
+
task_note_text_hash text NOT NULL,
|
|
18
|
+
created_at timestamptz NOT NULL DEFAULT transaction_timestamp(),
|
|
19
|
+
CONSTRAINT remember_knowledge_memory_materializations_workspace_account_fk
|
|
20
|
+
FOREIGN KEY (workspace_id, account_id)
|
|
21
|
+
REFERENCES workspaces(id, account_id) ON DELETE CASCADE,
|
|
22
|
+
CONSTRAINT remember_knowledge_memory_materializations_session_fk
|
|
23
|
+
FOREIGN KEY (workspace_id, session_id)
|
|
24
|
+
REFERENCES sessions(workspace_id, id) ON DELETE CASCADE,
|
|
25
|
+
CONSTRAINT remember_knowledge_memory_materializations_memory_uq
|
|
26
|
+
UNIQUE (workspace_id, memory_id),
|
|
27
|
+
CONSTRAINT remember_knowledge_memory_materializations_hash_chk
|
|
28
|
+
CHECK (task_note_text_hash ~ '^[0-9a-f]{64}$')
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
CREATE INDEX remember_knowledge_memory_materializations_workspace_time_idx
|
|
32
|
+
ON remember_knowledge_memory_materializations (workspace_id, created_at DESC, memory_id);
|
|
33
|
+
|
|
34
|
+
ALTER TABLE remember_knowledge_memory_materializations ENABLE ROW LEVEL SECURITY;
|
|
35
|
+
ALTER TABLE remember_knowledge_memory_materializations FORCE ROW LEVEL SECURITY;
|
|
36
|
+
CREATE POLICY remember_knowledge_memory_materializations_tenant
|
|
37
|
+
ON remember_knowledge_memory_materializations
|
|
38
|
+
USING (opengeni_private.workspace_rls_visible(account_id, workspace_id))
|
|
39
|
+
WITH CHECK (opengeni_private.workspace_rls_visible(account_id, workspace_id));
|
|
40
|
+
CREATE POLICY session_visibility_isolation
|
|
41
|
+
ON remember_knowledge_memory_materializations AS RESTRICTIVE
|
|
42
|
+
USING (session_reference_visible(account_id, workspace_id, session_id))
|
|
43
|
+
WITH CHECK (session_reference_visible(account_id, workspace_id, session_id));
|
|
44
|
+
|
|
45
|
+
CREATE OR REPLACE FUNCTION reject_remember_knowledge_memory_materialization_mutation()
|
|
46
|
+
RETURNS trigger LANGUAGE plpgsql AS $body$
|
|
47
|
+
BEGIN
|
|
48
|
+
IF TG_OP = 'DELETE' AND pg_catalog.pg_trigger_depth() > 1 AND (
|
|
49
|
+
NOT EXISTS (SELECT 1 FROM workspaces WHERE id = OLD.workspace_id)
|
|
50
|
+
OR NOT EXISTS (
|
|
51
|
+
SELECT 1 FROM sessions WHERE workspace_id = OLD.workspace_id AND id = OLD.session_id
|
|
52
|
+
)
|
|
53
|
+
OR NOT EXISTS (
|
|
54
|
+
SELECT 1 FROM remember_knowledge_confirmation_receipts
|
|
55
|
+
WHERE id = OLD.confirmation_receipt_id
|
|
56
|
+
)
|
|
57
|
+
) THEN
|
|
58
|
+
RETURN OLD;
|
|
59
|
+
END IF;
|
|
60
|
+
RAISE EXCEPTION 'remember Knowledge Memory materializations are immutable'
|
|
61
|
+
USING ERRCODE = '55000';
|
|
62
|
+
END
|
|
63
|
+
$body$;
|
|
64
|
+
|
|
65
|
+
CREATE TRIGGER remember_knowledge_memory_materializations_immutable
|
|
66
|
+
BEFORE UPDATE OR DELETE ON remember_knowledge_memory_materializations
|
|
67
|
+
FOR EACH ROW EXECUTE FUNCTION reject_remember_knowledge_memory_materialization_mutation();
|
|
68
|
+
|
|
69
|
+
CREATE OR REPLACE FUNCTION materialize_remember_knowledge_memory(
|
|
70
|
+
p_account_id uuid,
|
|
71
|
+
p_workspace_id uuid,
|
|
72
|
+
p_confirmation_receipt_id uuid
|
|
73
|
+
) RETURNS SETOF remember_knowledge_memory_materializations
|
|
74
|
+
LANGUAGE plpgsql SECURITY DEFINER AS $body$
|
|
75
|
+
DECLARE
|
|
76
|
+
caller_subject_id text := nullif(current_setting('opengeni.subject_id', true), '');
|
|
77
|
+
receipt_row remember_knowledge_confirmation_receipts%ROWTYPE;
|
|
78
|
+
result_row remember_knowledge_memory_materializations%ROWTYPE;
|
|
79
|
+
source_text text;
|
|
80
|
+
memory_id_value uuid;
|
|
81
|
+
normalized_text text;
|
|
82
|
+
normalized_text_hash text;
|
|
83
|
+
visible_count integer;
|
|
84
|
+
BEGIN
|
|
85
|
+
IF p_account_id IS NULL OR p_workspace_id IS NULL OR p_confirmation_receipt_id IS NULL
|
|
86
|
+
OR caller_subject_id IS NULL OR length(btrim(caller_subject_id)) NOT BETWEEN 1 AND 1024
|
|
87
|
+
OR p_account_id IS DISTINCT FROM opengeni_private.current_account_id()
|
|
88
|
+
OR p_workspace_id IS DISTINCT FROM opengeni_private.current_workspace_id()
|
|
89
|
+
THEN
|
|
90
|
+
RAISE EXCEPTION 'remember Knowledge Memory materialization requires exact tenant authority'
|
|
91
|
+
USING ERRCODE = '42501';
|
|
92
|
+
END IF;
|
|
93
|
+
|
|
94
|
+
-- Serialize every first materialization/replay on the immutable confirmation
|
|
95
|
+
-- identity. The Memory row may later become archived; the mapping remains the
|
|
96
|
+
-- stable answer and is deliberately not foreign-keyed to mutable Memory state.
|
|
97
|
+
SELECT * INTO receipt_row
|
|
98
|
+
FROM remember_knowledge_confirmation_receipts receipt
|
|
99
|
+
WHERE receipt.id = p_confirmation_receipt_id
|
|
100
|
+
AND receipt.account_id = p_account_id
|
|
101
|
+
AND receipt.workspace_id = p_workspace_id
|
|
102
|
+
AND receipt.initiating_human_subject_id = caller_subject_id
|
|
103
|
+
FOR UPDATE;
|
|
104
|
+
IF NOT FOUND THEN
|
|
105
|
+
RAISE EXCEPTION 'remember Knowledge confirmation is unavailable'
|
|
106
|
+
USING ERRCODE = '42501';
|
|
107
|
+
END IF;
|
|
108
|
+
|
|
109
|
+
SELECT * INTO result_row
|
|
110
|
+
FROM remember_knowledge_memory_materializations materialization
|
|
111
|
+
WHERE materialization.confirmation_receipt_id = p_confirmation_receipt_id;
|
|
112
|
+
IF FOUND THEN
|
|
113
|
+
IF result_row.account_id <> p_account_id
|
|
114
|
+
OR result_row.workspace_id <> p_workspace_id
|
|
115
|
+
OR result_row.session_id <> receipt_row.session_id
|
|
116
|
+
OR result_row.task_note_text_hash <> receipt_row.task_note_text_hash
|
|
117
|
+
THEN
|
|
118
|
+
RAISE EXCEPTION 'remember Knowledge Memory materialization conflicts with immutable receipt'
|
|
119
|
+
USING ERRCODE = '23505';
|
|
120
|
+
END IF;
|
|
121
|
+
RETURN NEXT result_row;
|
|
122
|
+
RETURN;
|
|
123
|
+
END IF;
|
|
124
|
+
|
|
125
|
+
SELECT fact.object_value #>> '{}'
|
|
126
|
+
INTO source_text
|
|
127
|
+
FROM knowledge_claims claim
|
|
128
|
+
JOIN knowledge_facts fact
|
|
129
|
+
ON fact.account_id = claim.account_id
|
|
130
|
+
AND fact.scope_key = claim.scope_key
|
|
131
|
+
AND fact.id = claim.fact_id
|
|
132
|
+
JOIN knowledge_claim_evidence evidence
|
|
133
|
+
ON evidence.account_id = claim.account_id
|
|
134
|
+
AND evidence.scope_key = claim.scope_key
|
|
135
|
+
AND evidence.claim_id = claim.id
|
|
136
|
+
JOIN knowledge_claim_reviews review
|
|
137
|
+
ON review.account_id = claim.account_id
|
|
138
|
+
AND review.scope_key = claim.scope_key
|
|
139
|
+
AND review.claim_id = claim.id
|
|
140
|
+
WHERE claim.account_id = p_account_id
|
|
141
|
+
AND claim.scope_kind = 'workspace'
|
|
142
|
+
AND claim.scope_workspace_id = p_workspace_id
|
|
143
|
+
AND claim.scope_subject_id IS NULL
|
|
144
|
+
AND claim.id = receipt_row.claim_id
|
|
145
|
+
AND claim.extraction_method = 'task-note-promotion-v1'
|
|
146
|
+
AND claim.initiating_human_subject_id = caller_subject_id
|
|
147
|
+
AND fact.object_kind = 'text'
|
|
148
|
+
AND evidence.id = receipt_row.evidence_id
|
|
149
|
+
AND evidence.task_note_id = receipt_row.task_note_id
|
|
150
|
+
AND evidence.task_note_version = 1
|
|
151
|
+
AND evidence.content_hash = receipt_row.task_note_text_hash
|
|
152
|
+
AND review.id = receipt_row.approval_review_id
|
|
153
|
+
AND review.review_revision = receipt_row.approval_review_revision
|
|
154
|
+
AND review.state = 'approved'
|
|
155
|
+
LIMIT 1;
|
|
156
|
+
|
|
157
|
+
normalized_text := lower(btrim(regexp_replace(source_text, '\s+', ' ', 'g')));
|
|
158
|
+
IF source_text IS NULL OR normalized_text = '' OR length(source_text) > 4000
|
|
159
|
+
OR encode(sha256(convert_to(source_text, 'UTF8')), 'hex')
|
|
160
|
+
<> receipt_row.task_note_text_hash
|
|
161
|
+
THEN
|
|
162
|
+
RAISE EXCEPTION 'remember Knowledge confirmation no longer resolves to its exact approved text'
|
|
163
|
+
USING ERRCODE = '23514';
|
|
164
|
+
END IF;
|
|
165
|
+
normalized_text_hash := encode(sha256(convert_to(normalized_text, 'UTF8')), 'hex');
|
|
166
|
+
|
|
167
|
+
SELECT count(*)::integer INTO visible_count
|
|
168
|
+
FROM knowledge_memories memory
|
|
169
|
+
WHERE memory.account_id = p_account_id
|
|
170
|
+
AND memory.workspace_id = p_workspace_id
|
|
171
|
+
AND memory.status IN ('active', 'approved');
|
|
172
|
+
IF visible_count >= 2000 THEN
|
|
173
|
+
RAISE EXCEPTION 'Workspace visible Memory is full (2000 visible records)'
|
|
174
|
+
USING ERRCODE = '54000';
|
|
175
|
+
END IF;
|
|
176
|
+
|
|
177
|
+
memory_id_value := gen_random_uuid();
|
|
178
|
+
PERFORM set_config('opengeni.memory_actor_kind', 'subject', true);
|
|
179
|
+
PERFORM set_config('opengeni.memory_actor_id', caller_subject_id, true);
|
|
180
|
+
PERFORM set_config('opengeni.memory_session_id', receipt_row.session_id::text, true);
|
|
181
|
+
|
|
182
|
+
INSERT INTO knowledge_memories (
|
|
183
|
+
id, account_id, workspace_id, status, kind, scope, text, text_codec_version,
|
|
184
|
+
source_refs, confidence, metadata, created_by_session_id, pinned,
|
|
185
|
+
scope_type, scope_subject_id, scope_role_key, scope_session_id,
|
|
186
|
+
namespace_key, labels, text_hash
|
|
187
|
+
) VALUES (
|
|
188
|
+
memory_id_value, p_account_id, p_workspace_id, 'active', 'semantic', 'workspace',
|
|
189
|
+
source_text, NULL,
|
|
190
|
+
jsonb_build_array(jsonb_build_object(
|
|
191
|
+
'kind', 'session_event', 'id', receipt_row.session_id, 'metadata', '{}'::jsonb
|
|
192
|
+
)),
|
|
193
|
+
100,
|
|
194
|
+
jsonb_build_object(
|
|
195
|
+
'origin', 'human',
|
|
196
|
+
'source', 'remember_confirmation',
|
|
197
|
+
'confirmationReceiptId', receipt_row.id,
|
|
198
|
+
'claimId', receipt_row.claim_id,
|
|
199
|
+
'evidenceId', receipt_row.evidence_id,
|
|
200
|
+
'taskNoteId', receipt_row.task_note_id
|
|
201
|
+
),
|
|
202
|
+
receipt_row.session_id, false,
|
|
203
|
+
'workspace', NULL, NULL, NULL,
|
|
204
|
+
'remember/' || receipt_row.id::text, '{}'::text[], normalized_text_hash
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
INSERT INTO remember_knowledge_memory_materializations (
|
|
208
|
+
confirmation_receipt_id, account_id, workspace_id, session_id,
|
|
209
|
+
memory_id, task_note_text_hash
|
|
210
|
+
) VALUES (
|
|
211
|
+
receipt_row.id, p_account_id, p_workspace_id, receipt_row.session_id,
|
|
212
|
+
memory_id_value, receipt_row.task_note_text_hash
|
|
213
|
+
) RETURNING * INTO result_row;
|
|
214
|
+
|
|
215
|
+
RETURN NEXT result_row;
|
|
216
|
+
END
|
|
217
|
+
$body$;
|
|
218
|
+
|
|
219
|
+
REVOKE ALL ON TABLE remember_knowledge_memory_materializations FROM PUBLIC;
|
|
220
|
+
REVOKE ALL ON FUNCTION materialize_remember_knowledge_memory(uuid, uuid, uuid) FROM PUBLIC;
|
|
221
|
+
|
|
222
|
+
DO $remember_knowledge_memory_materialization_hardening$
|
|
223
|
+
DECLARE
|
|
224
|
+
target_schema text := current_schema();
|
|
225
|
+
runtime_role text := nullif(current_setting('opengeni.runtime_role', true), '');
|
|
226
|
+
BEGIN
|
|
227
|
+
EXECUTE format(
|
|
228
|
+
'ALTER FUNCTION %I.materialize_remember_knowledge_memory(uuid,uuid,uuid) '
|
|
229
|
+
|| 'SET search_path = pg_catalog, %I, pg_temp',
|
|
230
|
+
target_schema, target_schema
|
|
231
|
+
);
|
|
232
|
+
IF runtime_role IS NULL AND EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
|
|
233
|
+
runtime_role := 'opengeni_app';
|
|
234
|
+
END IF;
|
|
235
|
+
IF runtime_role IS NOT NULL THEN
|
|
236
|
+
EXECUTE format(
|
|
237
|
+
'REVOKE ALL ON TABLE %I.remember_knowledge_memory_materializations FROM %I',
|
|
238
|
+
target_schema, runtime_role
|
|
239
|
+
);
|
|
240
|
+
EXECUTE format(
|
|
241
|
+
'GRANT EXECUTE ON FUNCTION %I.materialize_remember_knowledge_memory(uuid,uuid,uuid) TO %I',
|
|
242
|
+
target_schema, runtime_role
|
|
243
|
+
);
|
|
244
|
+
END IF;
|
|
245
|
+
END
|
|
246
|
+
$remember_knowledge_memory_materialization_hardening$;
|
|
247
|
+
|
|
248
|
+
RESET statement_timeout;
|
|
249
|
+
RESET lock_timeout;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/db",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0-canary.0",
|
|
4
4
|
"description": "OpenGeni persistence: Drizzle schema, RLS-scoped query layer, the SQL migration runner, and role provisioning.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -74,11 +74,11 @@
|
|
|
74
74
|
"prepublishOnly": "bash ../../scripts/prepublish-guard"
|
|
75
75
|
},
|
|
76
76
|
"dependencies": {
|
|
77
|
-
"@opengeni/codemode": "^0.4.
|
|
78
|
-
"@opengeni/codex": "^0.2.19-canary.
|
|
79
|
-
"@opengeni/config": "^0.
|
|
80
|
-
"@opengeni/contracts": "^2.
|
|
81
|
-
"@opengeni/network": "^0.2.3-canary.
|
|
77
|
+
"@opengeni/codemode": "^0.4.15-canary.0",
|
|
78
|
+
"@opengeni/codex": "^0.2.19-canary.1",
|
|
79
|
+
"@opengeni/config": "^0.20.1-canary.0",
|
|
80
|
+
"@opengeni/contracts": "^2.5.0-canary.0",
|
|
81
|
+
"@opengeni/network": "^0.2.3-canary.1",
|
|
82
82
|
"drizzle-orm": "^0.45.2",
|
|
83
83
|
"postgres": "^3.4.7"
|
|
84
84
|
},
|
package/src/database.ts
CHANGED
|
@@ -317,11 +317,14 @@ export function createDb(databaseUrl: string, options: CreateDbOptions = {}): Db
|
|
|
317
317
|
prepare: false,
|
|
318
318
|
idle_timeout: 30,
|
|
319
319
|
max_lifetime: 1800,
|
|
320
|
-
// `connection` carries per-session Postgres STARTUP parameters.
|
|
321
|
-
//
|
|
322
|
-
//
|
|
323
|
-
//
|
|
324
|
-
//
|
|
320
|
+
// `connection` carries per-session Postgres STARTUP parameters. The exact
|
|
321
|
+
// `application_name` is also the PgBouncer-compatible current-image receipt
|
|
322
|
+
// for migration 0352's restrictive sessions policy; arbitrary custom startup
|
|
323
|
+
// parameters are not portable through transaction poolers. `search_path`
|
|
324
|
+
// (embedded only) is the supported, query-param-free way to scope a connection
|
|
325
|
+
// to a dedicated schema — postgres-js IGNORES a URL `?search_path=`. Unset
|
|
326
|
+
// searchPath → omit it so the server default (`public`) is unchanged for
|
|
327
|
+
// standalone.
|
|
325
328
|
connection: {
|
|
326
329
|
application_name: LOSSLESS_CONTENT_WRITER_APPLICATION_NAME,
|
|
327
330
|
...(options.searchPath ? { search_path: options.searchPath } : {}),
|
|
@@ -377,12 +380,13 @@ export async function setRlsContext(db: Database, context: RlsContext): Promise<
|
|
|
377
380
|
);
|
|
378
381
|
// Transaction-local writer identity covers supported injected/embedded
|
|
379
382
|
// database handles whose connection-level application_name is host-owned.
|
|
380
|
-
//
|
|
381
|
-
//
|
|
383
|
+
// Standalone createDb connections also carry version receipts in their exact
|
|
384
|
+
// application_name, while old OpenGeni binaries set neither current receipt.
|
|
382
385
|
await db.execute(sql`select set_config('opengeni.lossless_content_writer', '1', true)`);
|
|
383
386
|
await db.execute(sql`select
|
|
384
387
|
set_config('opengeni.sandbox_recovery_protocol_v2', '1', true),
|
|
385
|
-
set_config('opengeni.pending_tool_event_output_v1', '1', true)
|
|
388
|
+
set_config('opengeni.pending_tool_event_output_v1', '1', true),
|
|
389
|
+
set_config('opengeni.session_variable_set_attachments_v1', '1', true)`);
|
|
386
390
|
const sessionActor = sessionRlsActorContext.getStore();
|
|
387
391
|
if (sessionActor) {
|
|
388
392
|
await setSubjectRlsContext(db, sessionActor.subjectId);
|
|
@@ -174,8 +174,17 @@ function undoFromRow(row: UndoRow): UndoReceipt {
|
|
|
174
174
|
/** Subject-filtered activation and compensation history for Workspace State. */
|
|
175
175
|
export async function listGovernedLearningActivationHistory(
|
|
176
176
|
db: Database,
|
|
177
|
-
input: {
|
|
178
|
-
|
|
177
|
+
input: {
|
|
178
|
+
workspaceId: string;
|
|
179
|
+
subjectId: string;
|
|
180
|
+
principalKind: string;
|
|
181
|
+
limit: number;
|
|
182
|
+
},
|
|
183
|
+
): Promise<{
|
|
184
|
+
activations: ActivationReceipt[];
|
|
185
|
+
undos: UndoReceipt[];
|
|
186
|
+
truncated: boolean;
|
|
187
|
+
}> {
|
|
179
188
|
if (input.principalKind !== "human_session") {
|
|
180
189
|
throw new GovernedLearningActivationAuthorityError(
|
|
181
190
|
"Governed-learning history requires an exact authenticated human actor",
|
|
@@ -562,6 +571,69 @@ export async function confirmRememberKnowledgeClaim(
|
|
|
562
571
|
}
|
|
563
572
|
}
|
|
564
573
|
|
|
574
|
+
export type RememberKnowledgeMemoryMaterialization = {
|
|
575
|
+
confirmationReceiptId: string;
|
|
576
|
+
accountId: string;
|
|
577
|
+
workspaceId: string;
|
|
578
|
+
sessionId: string;
|
|
579
|
+
memoryId: string;
|
|
580
|
+
taskNoteTextHash: string;
|
|
581
|
+
createdAt: string;
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Materialize the exact approved Task-note text behind one completed remember
|
|
586
|
+
* confirmation. The database capability owns the insert and its immutable
|
|
587
|
+
* confirmation-to-Memory mapping, so generic deduplication cannot substitute a
|
|
588
|
+
* normalized lookalike and replay keeps the same Memory id after archival.
|
|
589
|
+
*/
|
|
590
|
+
export async function materializeConfirmedRememberKnowledgeMemory(
|
|
591
|
+
db: Database,
|
|
592
|
+
receipt: RememberKnowledgeConfirmationReceiptType,
|
|
593
|
+
): Promise<RememberKnowledgeMemoryMaterialization> {
|
|
594
|
+
const confirmed = RememberKnowledgeConfirmationReceipt.parse(receipt);
|
|
595
|
+
try {
|
|
596
|
+
return await withWorkspaceSubjectRls(
|
|
597
|
+
db,
|
|
598
|
+
confirmed.workspaceId,
|
|
599
|
+
confirmed.initiatingHumanSubjectId,
|
|
600
|
+
async (scoped) => {
|
|
601
|
+
const rows = await rawRows<{
|
|
602
|
+
confirmation_receipt_id: string;
|
|
603
|
+
account_id: string;
|
|
604
|
+
workspace_id: string;
|
|
605
|
+
session_id: string;
|
|
606
|
+
memory_id: string;
|
|
607
|
+
task_note_text_hash: string;
|
|
608
|
+
created_at: Date | string;
|
|
609
|
+
}>(
|
|
610
|
+
scoped,
|
|
611
|
+
sql`SELECT * FROM materialize_remember_knowledge_memory(
|
|
612
|
+
${confirmed.accountId}::uuid,
|
|
613
|
+
${confirmed.workspaceId}::uuid,
|
|
614
|
+
${confirmed.id}::uuid
|
|
615
|
+
)`,
|
|
616
|
+
);
|
|
617
|
+
const row = rows[0];
|
|
618
|
+
if (rows.length !== 1 || !row) {
|
|
619
|
+
throw new Error("remember Knowledge Memory materialization returned no unique receipt");
|
|
620
|
+
}
|
|
621
|
+
return {
|
|
622
|
+
confirmationReceiptId: row.confirmation_receipt_id,
|
|
623
|
+
accountId: row.account_id,
|
|
624
|
+
workspaceId: row.workspace_id,
|
|
625
|
+
sessionId: row.session_id,
|
|
626
|
+
memoryId: row.memory_id,
|
|
627
|
+
taskNoteTextHash: row.task_note_text_hash,
|
|
628
|
+
createdAt: iso(row.created_at),
|
|
629
|
+
};
|
|
630
|
+
},
|
|
631
|
+
);
|
|
632
|
+
} catch (error) {
|
|
633
|
+
translate(error);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
565
637
|
/**
|
|
566
638
|
* Read the initiating human bound to one workspace-scoped Knowledge claim under
|
|
567
639
|
* workspace RLS. Used by `remember_confirm` for the Knowledge lane; exposes no
|