22-- REQUIRE: src/config/functions_private.sql
33-- REQUIRE: src/encrypted/functions.sql
44
5-
6- -- Customer-facing configuration functions
7- -- Depends on private functions for implemenation
8- --
9- --
10-
11- --
12- -- Adds an index term to the configuration
13- --
14-
5+ -- ! @brief Add a search index configuration for an encrypted column
6+ -- !
7+ -- ! Configures a searchable encryption index (unique, match, ore, or ste_vec) on an
8+ -- ! encrypted column. Creates or updates the pending configuration, then migrates
9+ -- ! and activates it unless migrating flag is set.
10+ -- !
11+ -- ! @param table_name Text Name of the table containing the column
12+ -- ! @param column_name Text Name of the column to configure
13+ -- ! @param index_name Text Type of index ('unique', 'match', 'ore', 'ste_vec')
14+ -- ! @param cast_as Text PostgreSQL type for decrypted values (default: 'text')
15+ -- ! @param opts JSONB Index-specific options (default: '{}')
16+ -- ! @param migrating Boolean Skip auto-migration if true (default: false)
17+ -- ! @return JSONB Updated configuration object
18+ -- ! @throws Exception if index already exists for this column
19+ -- ! @throws Exception if cast_as is not a valid type
20+ -- !
21+ -- ! @example
22+ -- ! -- Add unique index for exact-match searches
23+ -- ! SELECT eql_v2.add_search_config('users', 'email', 'unique');
24+ -- !
25+ -- ! -- Add match index for LIKE searches with custom token length
26+ -- ! SELECT eql_v2.add_search_config('posts', 'content', 'match', 'text',
27+ -- ! '{"token_filters": [{"kind": "downcase"}], "tokenizer": {"kind": "ngram", "token_length": 3}}'
28+ -- ! );
29+ -- !
30+ -- ! @see eql_v2.add_column
31+ -- ! @see eql_v2.remove_search_config
1532CREATE FUNCTION eql_v2 .add_search_config(table_name text , column_name text , index_name text , cast_as text DEFAULT ' text' , opts jsonb DEFAULT ' {}' , migrating boolean DEFAULT false)
1633 RETURNS jsonb
1734
6885 END;
6986$$ LANGUAGE plpgsql;
7087
71-
72-
88+ -- ! @brief Remove a search index configuration from an encrypted column
89+ -- !
90+ -- ! Removes a previously configured search index from an encrypted column.
91+ -- ! Updates the pending configuration, then migrates and activates it
92+ -- ! unless migrating flag is set.
93+ -- !
94+ -- ! @param table_name Text Name of the table containing the column
95+ -- ! @param column_name Text Name of the column
96+ -- ! @param index_name Text Type of index to remove
97+ -- ! @param migrating Boolean Skip auto-migration if true (default: false)
98+ -- ! @return JSONB Updated configuration object
99+ -- ! @throws Exception if no active or pending configuration exists
100+ -- ! @throws Exception if table is not configured
101+ -- ! @throws Exception if column is not configured
102+ -- !
103+ -- ! @example
104+ -- ! -- Remove match index from column
105+ -- ! SELECT eql_v2.remove_search_config('posts', 'content', 'match');
106+ -- !
107+ -- ! @see eql_v2.add_search_config
108+ -- ! @see eql_v2.modify_search_config
73109CREATE FUNCTION eql_v2 .remove_search_config(table_name text , column_name text , index_name text , migrating boolean DEFAULT false)
74110 RETURNS jsonb
75111AS $$
@@ -118,8 +154,28 @@ AS $$
118154 END;
119155$$ LANGUAGE plpgsql;
120156
121-
122-
157+ -- ! @brief Modify a search index configuration for an encrypted column
158+ -- !
159+ -- ! Updates an existing search index configuration by removing and re-adding it
160+ -- ! with new options. Convenience function that combines remove and add operations.
161+ -- !
162+ -- ! @param table_name Text Name of the table containing the column
163+ -- ! @param column_name Text Name of the column
164+ -- ! @param index_name Text Type of index to modify
165+ -- ! @param cast_as Text PostgreSQL type for decrypted values (default: 'text')
166+ -- ! @param opts JSONB New index-specific options (default: '{}')
167+ -- ! @param migrating Boolean Skip auto-migration if true (default: false)
168+ -- ! @return JSONB Updated configuration object
169+ -- ! @throws Exception if index does not exist
170+ -- !
171+ -- ! @example
172+ -- ! -- Change match index tokenizer settings
173+ -- ! SELECT eql_v2.modify_search_config('posts', 'content', 'match', 'text',
174+ -- ! '{"tokenizer": {"kind": "ngram", "token_length": 4}}'
175+ -- ! );
176+ -- !
177+ -- ! @see eql_v2.add_search_config
178+ -- ! @see eql_v2.remove_search_config
123179CREATE FUNCTION eql_v2 .modify_search_config(table_name text , column_name text , index_name text , cast_as text DEFAULT ' text' , opts jsonb DEFAULT ' {}' , migrating boolean DEFAULT false)
124180 RETURNS jsonb
125181AS $$
@@ -129,20 +185,23 @@ AS $$
129185 END;
130186$$ LANGUAGE plpgsql;
131187
132-
133-
134- --
135- --
136- -- Marks the currently `pending` configuration as `encrypting`.
137- --
138- -- Validates the database schema and raises an exception if the configured columns are not `cs_encrypted_v2` type.
139- --
140- -- Accepts an optional `force` parameter.
141- -- If `force` is `true`, the schema validation is skipped.
142- --
143- -- Raises an exception if the configuration is already `encrypting` or if there is no `pending` configuration to encrypt.
144- --
145-
188+ -- ! @brief Migrate pending configuration to encrypting state
189+ -- !
190+ -- ! Transitions the pending configuration to encrypting state, validating that
191+ -- ! all configured columns have encrypted target columns ready. This is part of
192+ -- ! the configuration lifecycle: pending → encrypting → active.
193+ -- !
194+ -- ! @return Boolean True if migration succeeds
195+ -- ! @throws Exception if encryption already in progress
196+ -- ! @throws Exception if no pending configuration exists
197+ -- ! @throws Exception if configured columns lack encrypted targets
198+ -- !
199+ -- ! @example
200+ -- ! -- Manually migrate configuration (normally done automatically)
201+ -- ! SELECT eql_v2.migrate_config();
202+ -- !
203+ -- ! @see eql_v2.activate_config
204+ -- ! @see eql_v2.add_column
146205CREATE FUNCTION eql_v2 .migrate_config()
147206 RETURNS boolean
148207AS $$
@@ -165,8 +224,21 @@ AS $$
165224 END;
166225$$ LANGUAGE plpgsql;
167226
168-
169-
227+ -- ! @brief Activate encrypting configuration
228+ -- !
229+ -- ! Transitions the encrypting configuration to active state, making it the
230+ -- ! current operational configuration. Marks previous active configuration as
231+ -- ! inactive. Final step in configuration lifecycle: pending → encrypting → active.
232+ -- !
233+ -- ! @return Boolean True if activation succeeds
234+ -- ! @throws Exception if no encrypting configuration exists to activate
235+ -- !
236+ -- ! @example
237+ -- ! -- Manually activate configuration (normally done automatically)
238+ -- ! SELECT eql_v2.activate_config();
239+ -- !
240+ -- ! @see eql_v2.migrate_config
241+ -- ! @see eql_v2.add_column
170242CREATE FUNCTION eql_v2 .activate_config()
171243 RETURNS boolean
172244AS $$
@@ -182,8 +254,20 @@ AS $$
182254 END;
183255$$ LANGUAGE plpgsql;
184256
185-
186-
257+ -- ! @brief Discard pending configuration
258+ -- !
259+ -- ! Deletes the pending configuration without applying changes. Use this to
260+ -- ! abandon configuration changes before they are migrated and activated.
261+ -- !
262+ -- ! @return Boolean True if discard succeeds
263+ -- ! @throws Exception if no pending configuration exists to discard
264+ -- !
265+ -- ! @example
266+ -- ! -- Discard uncommitted configuration changes
267+ -- ! SELECT eql_v2.discard();
268+ -- !
269+ -- ! @see eql_v2.add_column
270+ -- ! @see eql_v2.add_search_config
187271CREATE FUNCTION eql_v2 .discard()
188272 RETURNS boolean
189273AS $$
@@ -197,8 +281,28 @@ AS $$
197281 END;
198282$$ LANGUAGE plpgsql;
199283
200-
201-
284+ -- ! @brief Configure a column for encryption
285+ -- !
286+ -- ! Adds a column to the encryption configuration, making it eligible for
287+ -- ! encrypted storage and search indexes. Creates or updates pending configuration,
288+ -- ! adds encrypted constraint, then migrates and activates unless migrating flag is set.
289+ -- !
290+ -- ! @param table_name Text Name of the table containing the column
291+ -- ! @param column_name Text Name of the column to encrypt
292+ -- ! @param cast_as Text PostgreSQL type to cast decrypted values (default: 'text')
293+ -- ! @param migrating Boolean Skip auto-migration if true (default: false)
294+ -- ! @return JSONB Updated configuration object
295+ -- ! @throws Exception if column already configured for encryption
296+ -- !
297+ -- ! @example
298+ -- ! -- Configure email column for encryption
299+ -- ! SELECT eql_v2.add_column('users', 'email', 'text');
300+ -- !
301+ -- ! -- Configure age column with integer casting
302+ -- ! SELECT eql_v2.add_column('users', 'age', 'int');
303+ -- !
304+ -- ! @see eql_v2.add_search_config
305+ -- ! @see eql_v2.remove_column
202306CREATE FUNCTION eql_v2 .add_column(table_name text , column_name text , cast_as text DEFAULT ' text' , migrating boolean DEFAULT false)
203307 RETURNS jsonb
204308AS $$
@@ -242,8 +346,26 @@ AS $$
242346 END;
243347$$ LANGUAGE plpgsql;
244348
245-
246-
349+ -- ! @brief Remove a column from encryption configuration
350+ -- !
351+ -- ! Removes a column from the encryption configuration, including all associated
352+ -- ! search indexes. Removes encrypted constraint, updates pending configuration,
353+ -- ! then migrates and activates unless migrating flag is set.
354+ -- !
355+ -- ! @param table_name Text Name of the table containing the column
356+ -- ! @param column_name Text Name of the column to remove
357+ -- ! @param migrating Boolean Skip auto-migration if true (default: false)
358+ -- ! @return JSONB Updated configuration object
359+ -- ! @throws Exception if no active or pending configuration exists
360+ -- ! @throws Exception if table is not configured
361+ -- ! @throws Exception if column is not configured
362+ -- !
363+ -- ! @example
364+ -- ! -- Remove email column from encryption
365+ -- ! SELECT eql_v2.remove_column('users', 'email');
366+ -- !
367+ -- ! @see eql_v2.add_column
368+ -- ! @see eql_v2.remove_search_config
247369CREATE FUNCTION eql_v2 .remove_column(table_name text , column_name text , migrating boolean DEFAULT false)
248370 RETURNS jsonb
249371AS $$
@@ -305,19 +427,38 @@ AS $$
305427 END;
306428$$ LANGUAGE plpgsql;
307429
308-
309-
430+ -- ! @brief Reload configuration from CipherStash Proxy
431+ -- !
432+ -- ! Placeholder function for reloading configuration from the CipherStash Proxy.
433+ -- ! Currently returns NULL without side effects.
434+ -- !
435+ -- ! @return Void
436+ -- !
437+ -- ! @note This function may be used for configuration synchronization in future versions
310438CREATE FUNCTION eql_v2 .reload_config()
311439 RETURNS void
312440LANGUAGE sql STRICT PARALLEL SAFE
313441BEGIN ATOMIC
314442 RETURN NULL ;
315443END;
316444
317-
318- -- A convenience function to return the configuration in a tabular format, allowing for easier filtering, and querying.
319- -- Query using `SELECT * FROM cs_config();`
320- --
445+ -- ! @brief Query encryption configuration in tabular format
446+ -- !
447+ -- ! Returns the active encryption configuration as a table for easier querying
448+ -- ! and filtering. Shows all configured tables, columns, cast types, and indexes.
449+ -- !
450+ -- ! @return TABLE Contains configuration state, relation name, column name, cast type, and indexes
451+ -- !
452+ -- ! @example
453+ -- ! -- View all encrypted columns
454+ -- ! SELECT * FROM eql_v2.config();
455+ -- !
456+ -- ! -- Find all columns with match indexes
457+ -- ! SELECT relation, col_name FROM eql_v2.config()
458+ -- ! WHERE indexes ? 'match';
459+ -- !
460+ -- ! @see eql_v2.add_column
461+ -- ! @see eql_v2.add_search_config
321462CREATE FUNCTION eql_v2 .config() RETURNS TABLE (
322463 state eql_v2_configuration_state,
323464 relation text ,
0 commit comments