@team-semicolon/semicolony-cli 4.18.93 → 4.18.94
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,117 @@
|
|
|
1
|
+
-- 193_workspace_asset_cas_capability.sql
|
|
2
|
+
--
|
|
3
|
+
-- Give the public Gateway one narrowly-scoped workspace asset CAS primitive.
|
|
4
|
+
-- sc_app keeps SELECT-only table access and receives EXECUTE on this function;
|
|
5
|
+
-- it never receives general INSERT/UPDATE/DELETE authority on knowledge_base.
|
|
6
|
+
-- The migration runner owns BEGIN/COMMIT.
|
|
7
|
+
|
|
8
|
+
CREATE OR REPLACE FUNCTION semicolony.compare_and_swap_workspace_asset(
|
|
9
|
+
p_sub_key text,
|
|
10
|
+
p_content text,
|
|
11
|
+
p_created_by text,
|
|
12
|
+
p_embedding text,
|
|
13
|
+
p_metadata jsonb,
|
|
14
|
+
p_expected_asset_version integer
|
|
15
|
+
)
|
|
16
|
+
RETURNS TABLE(
|
|
17
|
+
out_kb_id bigint,
|
|
18
|
+
out_domain varchar(100),
|
|
19
|
+
out_key varchar(255),
|
|
20
|
+
out_sub_key varchar(255),
|
|
21
|
+
out_content text,
|
|
22
|
+
out_metadata jsonb,
|
|
23
|
+
out_created_by varchar(50),
|
|
24
|
+
out_updated_at timestamptz
|
|
25
|
+
)
|
|
26
|
+
LANGUAGE plpgsql
|
|
27
|
+
SECURITY DEFINER
|
|
28
|
+
SET search_path = pg_catalog
|
|
29
|
+
AS $function$
|
|
30
|
+
BEGIN
|
|
31
|
+
IF p_sub_key IS NULL
|
|
32
|
+
OR left(p_sub_key, 11) <> 'team-asset-'
|
|
33
|
+
OR p_sub_key !~ '^team-asset-[a-z][a-z0-9-]{0,159}$' THEN
|
|
34
|
+
RAISE EXCEPTION 'invalid workspace asset key' USING ERRCODE = '22023';
|
|
35
|
+
END IF;
|
|
36
|
+
IF p_expected_asset_version IS NULL OR p_expected_asset_version < 0 THEN
|
|
37
|
+
RAISE EXCEPTION 'invalid expected workspace asset version' USING ERRCODE = '22023';
|
|
38
|
+
END IF;
|
|
39
|
+
IF p_content IS NULL
|
|
40
|
+
OR char_length(btrim(p_content)) < 1
|
|
41
|
+
OR char_length(p_content) > 30000 THEN
|
|
42
|
+
RAISE EXCEPTION 'invalid workspace asset content' USING ERRCODE = '22023';
|
|
43
|
+
END IF;
|
|
44
|
+
IF p_created_by IS NULL
|
|
45
|
+
OR char_length(p_created_by) < 3
|
|
46
|
+
OR char_length(p_created_by) > 50
|
|
47
|
+
OR p_created_by !~ '^(worker|agent):[a-z][a-z0-9-]{0,39}$' THEN
|
|
48
|
+
RAISE EXCEPTION 'invalid workspace asset publisher' USING ERRCODE = '22023';
|
|
49
|
+
END IF;
|
|
50
|
+
IF p_metadata IS NULL
|
|
51
|
+
OR jsonb_typeof(p_metadata) <> 'object'
|
|
52
|
+
OR p_metadata ->> 'asset_version' <> (p_expected_asset_version + 1)::text
|
|
53
|
+
OR jsonb_typeof(p_metadata -> 'asset') <> 'object'
|
|
54
|
+
OR p_metadata -> 'asset' ->> 'schema' <> 'semicolon.dev/team-asset/v1alpha1'
|
|
55
|
+
OR p_metadata -> 'asset' ->> 'asset_id' <> substring(p_sub_key FROM 12)
|
|
56
|
+
OR p_metadata -> 'asset' ->> 'status' <> 'active'
|
|
57
|
+
OR p_metadata -> 'asset' ->> 'classification' NOT IN ('project', 'team')
|
|
58
|
+
OR jsonb_typeof(p_metadata -> 'asset' -> 'allowed_projects') <> 'array'
|
|
59
|
+
OR jsonb_typeof(p_metadata -> 'asset' -> 'allowed_uses') <> 'array'
|
|
60
|
+
OR jsonb_typeof(p_metadata -> 'asset' -> 'source') <> 'object'
|
|
61
|
+
OR jsonb_typeof(p_metadata -> 'asset' -> 'tags') <> 'array'
|
|
62
|
+
OR jsonb_typeof(p_metadata -> 'asset' -> 'related_knowledge') <> 'array'
|
|
63
|
+
OR jsonb_typeof(p_metadata -> 'asset' -> 'renditions') <> 'object' THEN
|
|
64
|
+
RAISE EXCEPTION 'invalid workspace asset metadata' USING ERRCODE = '22023';
|
|
65
|
+
END IF;
|
|
66
|
+
|
|
67
|
+
-- Validate vector syntax and dimensionality before taking the CAS path.
|
|
68
|
+
PERFORM p_embedding::public.vector;
|
|
69
|
+
|
|
70
|
+
RETURN QUERY
|
|
71
|
+
INSERT INTO semicolony.knowledge_base AS kb (
|
|
72
|
+
domain, key, sub_key, content, created_by, embedding, metadata
|
|
73
|
+
)
|
|
74
|
+
SELECT
|
|
75
|
+
'semicolon'::varchar(100),
|
|
76
|
+
'memory'::varchar(255),
|
|
77
|
+
p_sub_key::varchar(255),
|
|
78
|
+
p_content,
|
|
79
|
+
p_created_by::varchar(50),
|
|
80
|
+
p_embedding::public.vector,
|
|
81
|
+
p_metadata
|
|
82
|
+
WHERE p_expected_asset_version = 0
|
|
83
|
+
OR EXISTS (
|
|
84
|
+
SELECT 1
|
|
85
|
+
FROM semicolony.knowledge_base AS current_asset
|
|
86
|
+
WHERE current_asset.domain = 'semicolon'
|
|
87
|
+
AND current_asset.key = 'memory'
|
|
88
|
+
AND current_asset.sub_key = p_sub_key
|
|
89
|
+
AND current_asset.metadata ->> 'asset_version' ~ '^[0-9]+$'
|
|
90
|
+
AND (current_asset.metadata ->> 'asset_version')::integer =
|
|
91
|
+
p_expected_asset_version
|
|
92
|
+
)
|
|
93
|
+
ON CONFLICT (domain, key, sub_key) DO UPDATE SET
|
|
94
|
+
content = EXCLUDED.content,
|
|
95
|
+
embedding = EXCLUDED.embedding,
|
|
96
|
+
metadata = EXCLUDED.metadata,
|
|
97
|
+
updated_at = clock_timestamp()
|
|
98
|
+
WHERE kb.metadata ->> 'asset_version' ~ '^[0-9]+$'
|
|
99
|
+
AND (kb.metadata ->> 'asset_version')::integer = p_expected_asset_version
|
|
100
|
+
RETURNING
|
|
101
|
+
kb.kb_id,
|
|
102
|
+
kb.domain,
|
|
103
|
+
kb.key,
|
|
104
|
+
kb.sub_key,
|
|
105
|
+
kb.content,
|
|
106
|
+
kb.metadata,
|
|
107
|
+
kb.created_by,
|
|
108
|
+
kb.updated_at;
|
|
109
|
+
END;
|
|
110
|
+
$function$;
|
|
111
|
+
|
|
112
|
+
REVOKE ALL ON FUNCTION semicolony.compare_and_swap_workspace_asset(
|
|
113
|
+
text, text, text, text, jsonb, integer
|
|
114
|
+
) FROM PUBLIC, sc_app, sc_provider;
|
|
115
|
+
GRANT EXECUTE ON FUNCTION semicolony.compare_and_swap_workspace_asset(
|
|
116
|
+
text, text, text, text, jsonb, integer
|
|
117
|
+
) TO sc_app;
|