@pgpm/metaschema-modules 0.17.0 → 0.18.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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # @pgpm/metaschema-modules
1
+ # @pgpm/db-meta-modules
2
2
 
3
3
  <p align="center" width="100%">
4
4
  <img height="250" src="https://raw.githubusercontent.com/constructive-io/constructive/refs/heads/main/assets/outline-logo.svg" />
@@ -9,14 +9,14 @@
9
9
  <img height="20" src="https://github.com/constructive-io/pgpm-modules/actions/workflows/ci.yml/badge.svg" />
10
10
  </a>
11
11
  <a href="https://github.com/constructive-io/pgpm-modules/blob/main/LICENSE"><img height="20" src="https://img.shields.io/badge/license-MIT-blue.svg"/></a>
12
- <a href="https://www.npmjs.com/package/@pgpm/metaschema-modules"><img height="20" src="https://img.shields.io/github/package-json/v/constructive-io/pgpm-modules?filename=packages%2Fmetaschema-modules%2Fpackage.json"/></a>
12
+ <a href="https://www.npmjs.com/package/@pgpm/db-meta-modules"><img height="20" src="https://img.shields.io/github/package-json/v/constructive-io/pgpm-modules?filename=packages%2Fdb-meta-modules%2Fpackage.json"/></a>
13
13
  </p>
14
14
 
15
15
  Module metadata handling and dependency tracking.
16
16
 
17
17
  ## Overview
18
18
 
19
- `@pgpm/metaschema-modules` extends the `@pgpm/metaschema-schema` package with module-specific metadata tables. This package provides tables for tracking various pgpm modules including authentication, permissions, memberships, encrypted secrets, and more. It enables configuration and metadata storage for modular application features.
19
+ `@pgpm/db-meta-modules` extends the `@pgpm/db-meta-schema` package with module-specific metadata tables. This package provides tables for tracking various pgpm modules including authentication, permissions, memberships, encrypted secrets, and more. It enables configuration and metadata storage for modular application features.
20
20
 
21
21
  ## Features
22
22
 
@@ -33,7 +33,7 @@ Module metadata handling and dependency tracking.
33
33
  If you have `pgpm` installed:
34
34
 
35
35
  ```bash
36
- pgpm install @pgpm/metaschema-modules
36
+ pgpm install @pgpm/db-meta-modules
37
37
  pgpm deploy
38
38
  ```
39
39
 
@@ -56,7 +56,7 @@ eval "$(pgpm env)"
56
56
 
57
57
  ```bash
58
58
  # 1. Install the package
59
- pgpm install @pgpm/metaschema-modules
59
+ pgpm install @pgpm/db-meta-modules
60
60
 
61
61
  # 2. Deploy locally
62
62
  pgpm deploy
@@ -74,7 +74,7 @@ pgpm init
74
74
 
75
75
  # 3. Install a package
76
76
  cd packages/my-module
77
- pgpm install @pgpm/metaschema-modules
77
+ pgpm install @pgpm/db-meta-modules
78
78
 
79
79
  # 4. Deploy everything
80
80
  pgpm deploy --createdb --database mydb1
@@ -213,8 +213,7 @@ Use module tables as feature flags:
213
213
 
214
214
  ## Dependencies
215
215
 
216
- - `@pgpm/metaschema-schema`: Core metadata management
217
- - `@pgpm/services`: Services schemas for APIs, sites, and domains
216
+ - `@pgpm/db-meta-schema`: Core metadata management
218
217
  - `@pgpm/verify`: Verification utilities
219
218
 
220
219
  ## Testing
@@ -13,8 +13,14 @@ CREATE TABLE metaschema_modules_public.field_module (
13
13
  table_id uuid NOT NULL DEFAULT uuid_nil(),
14
14
  field_id uuid NOT NULL DEFAULT uuid_nil(),
15
15
 
16
+ -- Node type from node_type_registry (e.g., 'FieldSlug', 'FieldImmutable', 'FieldInflection', 'FieldOwned')
16
17
  node_type text NOT NULL,
17
18
 
19
+ -- Type-specific parameters as jsonb
20
+ -- FieldSlug: {"source_field_id": "uuid"}
21
+ -- FieldImmutable: {} (no extra params)
22
+ -- FieldInflection: {"ops": ["snake_case", "uppercase"]}
23
+ -- FieldOwned: {"role_key_field_id": "uuid", "protected_field_ids": ["uuid", ...]}
18
24
  data jsonb NOT NULL DEFAULT '{}',
19
25
 
20
26
  triggers text[],
@@ -35,4 +41,3 @@ CREATE INDEX field_module_database_id_idx ON metaschema_modules_public.field_mod
35
41
  CREATE INDEX field_module_node_type_idx ON metaschema_modules_public.field_module ( node_type );
36
42
 
37
43
  COMMIT;
38
-
@@ -27,8 +27,6 @@ CREATE TABLE metaschema_modules_public.profiles_module (
27
27
  profile_definition_grants_table_id uuid NOT NULL DEFAULT uuid_nil(),
28
28
  profile_definition_grants_table_name text NOT NULL DEFAULT '',
29
29
 
30
- -- Configuration
31
- bitlen int NOT NULL DEFAULT 24,
32
30
  membership_type int NOT NULL,
33
31
 
34
32
  -- Entity table for org/group scoped profiles (NULL for app-level)
@@ -0,0 +1,287 @@
1
+ -- Deploy schemas/metaschema_modules_public/tables/relation_provision/table to pg
2
+
3
+ -- requires: schemas/metaschema_modules_public/schema
4
+
5
+ BEGIN;
6
+
7
+ CREATE TABLE metaschema_modules_public.relation_provision (
8
+ id uuid PRIMARY KEY DEFAULT uuid_generate_v4 (),
9
+
10
+ database_id uuid NOT NULL,
11
+
12
+ -- =========================================================================
13
+ -- Relation type and tables
14
+ -- =========================================================================
15
+
16
+ relation_type text NOT NULL CHECK (relation_type IN (
17
+ 'RelationBelongsTo', 'RelationHasOne', 'RelationHasMany', 'RelationManyToMany'
18
+ )),
19
+
20
+ source_table_id uuid NOT NULL,
21
+
22
+ target_table_id uuid NOT NULL,
23
+
24
+ -- =========================================================================
25
+ -- BelongsTo / HasOne / HasMany: FK field config
26
+ -- =========================================================================
27
+
28
+ field_name text DEFAULT NULL,
29
+
30
+ delete_action text DEFAULT NULL,
31
+
32
+ is_required boolean NOT NULL DEFAULT true,
33
+
34
+ -- =========================================================================
35
+ -- ManyToMany: junction table identity
36
+ -- =========================================================================
37
+
38
+ junction_table_id uuid NOT NULL DEFAULT uuid_nil(),
39
+
40
+ junction_table_name text DEFAULT NULL,
41
+
42
+ junction_schema_id uuid DEFAULT NULL,
43
+
44
+ source_field_name text DEFAULT NULL,
45
+
46
+ target_field_name text DEFAULT NULL,
47
+
48
+ -- =========================================================================
49
+ -- ManyToMany: junction table primary key strategy
50
+ -- =========================================================================
51
+
52
+ use_composite_key boolean NOT NULL DEFAULT false,
53
+
54
+ -- =========================================================================
55
+ -- ManyToMany: field creation (forwarded to secure_table_provision)
56
+ -- =========================================================================
57
+
58
+ node_type text DEFAULT NULL,
59
+
60
+ node_data jsonb NOT NULL DEFAULT '{}',
61
+
62
+ -- =========================================================================
63
+ -- ManyToMany: grants (forwarded to secure_table_provision)
64
+ -- =========================================================================
65
+
66
+ grant_roles text[] NOT NULL DEFAULT ARRAY['authenticated'],
67
+
68
+ grant_privileges jsonb NOT NULL DEFAULT '[["select","*"],["insert","*"],["delete","*"]]',
69
+
70
+ -- =========================================================================
71
+ -- ManyToMany: RLS policies (forwarded to secure_table_provision)
72
+ -- =========================================================================
73
+
74
+ policy_type text DEFAULT NULL,
75
+
76
+ policy_privileges text[] DEFAULT NULL,
77
+
78
+ policy_role text DEFAULT NULL,
79
+
80
+ policy_permissive boolean NOT NULL DEFAULT true,
81
+
82
+ policy_name text DEFAULT NULL,
83
+
84
+ policy_data jsonb NOT NULL DEFAULT '{}',
85
+
86
+ -- =========================================================================
87
+ -- Output columns (populated by the trigger, not set by callers)
88
+ -- =========================================================================
89
+
90
+ out_field_id uuid DEFAULT NULL,
91
+
92
+ out_junction_table_id uuid DEFAULT NULL,
93
+
94
+ out_source_field_id uuid DEFAULT NULL,
95
+
96
+ out_target_field_id uuid DEFAULT NULL,
97
+
98
+ CONSTRAINT db_fkey FOREIGN KEY (database_id) REFERENCES metaschema_public.database (id) ON DELETE CASCADE,
99
+ CONSTRAINT source_table_fkey FOREIGN KEY (source_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
100
+ CONSTRAINT target_table_fkey FOREIGN KEY (target_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE
101
+ );
102
+
103
+ -- =============================================================================
104
+ -- Table-level comment
105
+ -- =============================================================================
106
+
107
+ COMMENT ON TABLE metaschema_modules_public.relation_provision IS
108
+ 'Provisions relational structure between tables. Supports four relation types:
109
+ - RelationBelongsTo: adds a FK field on the source table referencing the target table (child perspective: "tasks belongs to projects" -> tasks.project_id).
110
+ - RelationHasMany: adds a FK field on the target table referencing the source table (parent perspective: "projects has many tasks" -> tasks.project_id). Inverse of BelongsTo.
111
+ - RelationHasOne: adds a FK field with a unique constraint on the source table referencing the target table. Also supports shared-primary-key patterns where the FK field IS the primary key (set field_name to the existing PK field name).
112
+ - RelationManyToMany: creates a junction table with FK fields to both source and target tables, delegating table creation and security to secure_table_provision.
113
+ This is a one-and-done structural provisioner. To layer additional security onto junction tables after creation, use secure_table_provision directly.
114
+ All operations are graceful: existing fields, FK constraints, and unique constraints are reused if found.
115
+ The trigger never injects values the caller did not provide. All security config is forwarded to secure_table_provision as-is.';
116
+
117
+ -- =============================================================================
118
+ -- Relation type and tables
119
+ -- =============================================================================
120
+
121
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.id IS
122
+ 'Unique identifier for this relation provision row.';
123
+
124
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.database_id IS
125
+ 'The database this relation belongs to. Required. Must match the database of both source_table_id and target_table_id.';
126
+
127
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.relation_type IS
128
+ 'The type of relation to create. Uses SuperCase naming matching the node_type_registry:
129
+ - RelationBelongsTo: creates a FK field on source_table referencing target_table (e.g., tasks belongs to projects -> tasks.project_id). Field name auto-derived from target table.
130
+ - RelationHasMany: creates a FK field on target_table referencing source_table (e.g., projects has many tasks -> tasks.project_id). Field name auto-derived from source table. Inverse of BelongsTo — same FK, different perspective.
131
+ - RelationHasOne: creates a FK field + unique constraint on source_table referencing target_table (e.g., user_settings has one user -> user_settings.user_id with UNIQUE). Also supports shared-primary-key patterns (e.g., user_profiles.id = users.id) by setting field_name to the existing PK field.
132
+ - RelationManyToMany: creates a junction table with FK fields to both tables (e.g., projects and tags -> project_tags table).
133
+ Each relation type uses a different subset of columns on this table. Required.';
134
+
135
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.source_table_id IS
136
+ 'The source table in the relation. Required.
137
+ - RelationBelongsTo: the table that receives the FK field (e.g., tasks in "tasks belongs to projects").
138
+ - RelationHasMany: the parent table being referenced (e.g., projects in "projects has many tasks"). The FK field is created on the target table.
139
+ - RelationHasOne: the table that receives the FK field + unique constraint (e.g., user_settings in "user_settings has one user").
140
+ - RelationManyToMany: one of the two tables being joined (e.g., projects in "projects and tags"). The junction table will have a FK field referencing this table.';
141
+
142
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.target_table_id IS
143
+ 'The target table in the relation. Required.
144
+ - RelationBelongsTo: the table being referenced by the FK (e.g., projects in "tasks belongs to projects").
145
+ - RelationHasMany: the table that receives the FK field (e.g., tasks in "projects has many tasks").
146
+ - RelationHasOne: the table being referenced by the FK (e.g., users in "user_settings has one user").
147
+ - RelationManyToMany: the other table being joined (e.g., tags in "projects and tags"). The junction table will have a FK field referencing this table.';
148
+
149
+ -- =============================================================================
150
+ -- BelongsTo / HasOne / HasMany: FK field config
151
+ -- =============================================================================
152
+
153
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.field_name IS
154
+ 'FK field name for RelationBelongsTo, RelationHasOne, and RelationHasMany.
155
+ - RelationBelongsTo/RelationHasOne: if NULL, auto-derived from the target table name (e.g., target "projects" derives "project_id").
156
+ - RelationHasMany: if NULL, auto-derived from the source table name (e.g., source "projects" derives "project_id").
157
+ For RelationHasOne shared-primary-key patterns, set field_name to the existing PK field (e.g., "id") so the FK reuses it.
158
+ Ignored for RelationManyToMany — use source_field_name/target_field_name instead.';
159
+
160
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.delete_action IS
161
+ 'FK delete action for RelationBelongsTo, RelationHasOne, and RelationHasMany. One of: c (CASCADE), r (RESTRICT), n (SET NULL), d (SET DEFAULT), a (NO ACTION). Required — the trigger raises an error if not provided. The caller must explicitly choose the cascade behavior; there is no default. Ignored for RelationManyToMany (junction FK fields always use CASCADE).';
162
+
163
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.is_required IS
164
+ 'Whether the FK field is NOT NULL. Defaults to true.
165
+ - RelationBelongsTo: set to false for optional associations (e.g., tasks.assignee_id that can be NULL).
166
+ - RelationHasMany: set to false if the child can exist without a parent.
167
+ - RelationHasOne: typically true.
168
+ Ignored for RelationManyToMany (junction FK fields are always required).';
169
+
170
+ -- =============================================================================
171
+ -- ManyToMany: junction table identity
172
+ -- =============================================================================
173
+
174
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.junction_table_id IS
175
+ 'For RelationManyToMany: an existing junction table to use. Defaults to uuid_nil().
176
+ - When uuid_nil(): the trigger creates a new junction table via secure_table_provision using junction_table_name.
177
+ - When set to a valid table UUID: the trigger skips table creation and only adds FK fields, composite key (if use_composite_key is true), and security to the existing table.
178
+ Ignored for RelationBelongsTo/RelationHasOne.';
179
+
180
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.junction_table_name IS
181
+ 'For RelationManyToMany: name of the junction table to create or look up. If NULL, auto-derived from source and target table names using inflection_db (e.g., "projects" + "tags" derives "project_tags"). Only used when junction_table_id is uuid_nil(). Ignored for RelationBelongsTo/RelationHasOne.';
182
+
183
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.junction_schema_id IS
184
+ 'For RelationManyToMany: schema for the junction table. If NULL, defaults to the source table''s schema. Ignored for RelationBelongsTo/RelationHasOne.';
185
+
186
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.source_field_name IS
187
+ 'For RelationManyToMany: FK field name on the junction table referencing the source table. If NULL, auto-derived from the source table name using inflection_db.get_foreign_key_field_name() (e.g., source table "projects" derives "project_id"). Ignored for RelationBelongsTo/RelationHasOne.';
188
+
189
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.target_field_name IS
190
+ 'For RelationManyToMany: FK field name on the junction table referencing the target table. If NULL, auto-derived from the target table name using inflection_db.get_foreign_key_field_name() (e.g., target table "tags" derives "tag_id"). Ignored for RelationBelongsTo/RelationHasOne.';
191
+
192
+ -- =============================================================================
193
+ -- ManyToMany: junction table primary key strategy
194
+ -- =============================================================================
195
+
196
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.use_composite_key IS
197
+ 'For RelationManyToMany: whether to create a composite primary key from the two FK fields (source + target) on the junction table. Defaults to false.
198
+ - When true: the trigger calls metaschema.pk() with ARRAY[source_field_id, target_field_id] to create a composite PK. No separate id column is created. This enforces uniqueness of the pair and is suitable for simple junction tables.
199
+ - When false: no primary key is created by the trigger. The caller should provide node_type=''DataId'' to create a UUID primary key, or handle the PK strategy via a separate secure_table_provision row.
200
+ use_composite_key and node_type=''DataId'' are mutually exclusive — using both would create two conflicting PKs.
201
+ Ignored for RelationBelongsTo/RelationHasOne.';
202
+
203
+ -- =============================================================================
204
+ -- ManyToMany: field creation (forwarded to secure_table_provision)
205
+ -- =============================================================================
206
+
207
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.node_type IS
208
+ 'For RelationManyToMany: which generator to invoke for field creation on the junction table. Forwarded to secure_table_provision as-is. The trigger does not interpret or validate this value.
209
+ Examples: DataId (creates UUID primary key), DataDirectOwner (creates owner_id field), DataEntityMembership (creates entity_id field), DataOwnershipInEntity (creates both owner_id and entity_id), DataTimestamps, DataPeoplestamps, DataPublishable, DataSoftDelete.
210
+ NULL means no field creation beyond the FK fields (and composite key if use_composite_key is true).
211
+ Ignored for RelationBelongsTo/RelationHasOne.';
212
+
213
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.node_data IS
214
+ 'For RelationManyToMany: configuration passed to the generator function for field creation on the junction table. Forwarded to secure_table_provision as-is. The trigger does not interpret or validate this value.
215
+ Only used when node_type is set. Structure varies by node_type. Examples:
216
+ - DataId: {"field_name": "id"} (default field name is ''id'')
217
+ - DataEntityMembership: {"entity_field_name": "entity_id", "include_id": false, "include_user_fk": true}
218
+ - DataDirectOwner: {"owner_field_name": "owner_id"}
219
+ Defaults to ''{}'' (empty object).
220
+ Ignored for RelationBelongsTo/RelationHasOne.';
221
+
222
+ -- =============================================================================
223
+ -- ManyToMany: grants (forwarded to secure_table_provision)
224
+ -- =============================================================================
225
+
226
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.grant_roles IS
227
+ 'For RelationManyToMany: database roles to grant privileges to on the junction table. Forwarded to secure_table_provision as-is. Supports multiple roles, e.g. ARRAY[''authenticated'', ''admin'']. Each role receives all privileges defined in grant_privileges. Defaults to ARRAY[''authenticated'']. Ignored for RelationBelongsTo/RelationHasOne.';
228
+
229
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.grant_privileges IS
230
+ 'For RelationManyToMany: privilege grants for the junction table. Forwarded to secure_table_provision as-is. Format: array of [privilege, columns] tuples. Examples: [["select","*"],["insert","*"]] for full access, or [["update",["name","bio"]]] for column-level grants. "*" means all columns. Defaults to select/insert/delete for all columns. Ignored for RelationBelongsTo/RelationHasOne.';
231
+
232
+ -- =============================================================================
233
+ -- ManyToMany: RLS policies (forwarded to secure_table_provision)
234
+ -- =============================================================================
235
+
236
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.policy_type IS
237
+ 'For RelationManyToMany: RLS policy type for the junction table. Forwarded to secure_table_provision as-is. The trigger does not interpret or validate this value.
238
+ Examples: AuthzEntityMembership, AuthzMembership, AuthzAllowAll, AuthzDirectOwner, AuthzOrgHierarchy.
239
+ NULL means no policy is created — the junction table will have RLS enabled but no policies (unless added separately via secure_table_provision).
240
+ Ignored for RelationBelongsTo/RelationHasOne.';
241
+
242
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.policy_privileges IS
243
+ 'For RelationManyToMany: privileges the policy applies to, e.g. ARRAY[''select'',''insert'',''delete'']. Forwarded to secure_table_provision as-is. NULL means privileges are derived from the grant_privileges verbs by secure_table_provision. Ignored for RelationBelongsTo/RelationHasOne.';
244
+
245
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.policy_role IS
246
+ 'For RelationManyToMany: database role the policy targets, e.g. ''authenticated''. Forwarded to secure_table_provision as-is. NULL means secure_table_provision falls back to the first role in grant_roles. Ignored for RelationBelongsTo/RelationHasOne.';
247
+
248
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.policy_permissive IS
249
+ 'For RelationManyToMany: whether the policy is PERMISSIVE (true) or RESTRICTIVE (false). Forwarded to secure_table_provision as-is. Defaults to true. Ignored for RelationBelongsTo/RelationHasOne.';
250
+
251
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.policy_name IS
252
+ 'For RelationManyToMany: custom suffix for the generated policy name. Forwarded to secure_table_provision as-is. When NULL and policy_type is set, secure_table_provision auto-derives a suffix from policy_type (e.g. AuthzDirectOwner becomes direct_owner, producing policy names like auth_sel_direct_owner). When explicitly set, used as-is. This ensures multiple policies on the same junction table do not collide. Ignored for RelationBelongsTo/RelationHasOne.';
253
+
254
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.policy_data IS
255
+ 'For RelationManyToMany: opaque policy configuration forwarded to secure_table_provision as-is. The trigger does not interpret or validate this value. Structure varies by policy_type. Examples:
256
+ - AuthzEntityMembership: {"entity_field": "entity_id", "membership_type": 2}
257
+ - AuthzDirectOwner: {"owner_field": "owner_id"}
258
+ - AuthzMembership: {"membership_type": 2}
259
+ Defaults to ''{}'' (empty object).
260
+ Ignored for RelationBelongsTo/RelationHasOne.';
261
+
262
+ -- =============================================================================
263
+ -- Output columns
264
+ -- =============================================================================
265
+
266
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.out_field_id IS
267
+ 'Output column for RelationBelongsTo/RelationHasOne/RelationHasMany: the UUID of the FK field created (or found). For BelongsTo/HasOne this is on the source table; for HasMany this is on the target table. Populated by the trigger. NULL for RelationManyToMany. Callers should not set this directly.';
268
+
269
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.out_junction_table_id IS
270
+ 'Output column for RelationManyToMany: the UUID of the junction table created (or found). Populated by the trigger. NULL for RelationBelongsTo/RelationHasOne. Callers should not set this directly.';
271
+
272
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.out_source_field_id IS
273
+ 'Output column for RelationManyToMany: the UUID of the FK field on the junction table referencing the source table. Populated by the trigger. NULL for RelationBelongsTo/RelationHasOne. Callers should not set this directly.';
274
+
275
+ COMMENT ON COLUMN metaschema_modules_public.relation_provision.out_target_field_id IS
276
+ 'Output column for RelationManyToMany: the UUID of the FK field on the junction table referencing the target table. Populated by the trigger. NULL for RelationBelongsTo/RelationHasOne. Callers should not set this directly.';
277
+
278
+ COMMENT ON CONSTRAINT db_fkey ON metaschema_modules_public.relation_provision IS E'@omit manyToMany';
279
+ COMMENT ON CONSTRAINT source_table_fkey ON metaschema_modules_public.relation_provision IS E'@omit manyToMany';
280
+ COMMENT ON CONSTRAINT target_table_fkey ON metaschema_modules_public.relation_provision IS E'@omit manyToMany';
281
+
282
+ CREATE INDEX relation_provision_database_id_idx ON metaschema_modules_public.relation_provision ( database_id );
283
+ CREATE INDEX relation_provision_relation_type_idx ON metaschema_modules_public.relation_provision ( relation_type );
284
+ CREATE INDEX relation_provision_source_table_id_idx ON metaschema_modules_public.relation_provision ( source_table_id );
285
+ CREATE INDEX relation_provision_target_table_id_idx ON metaschema_modules_public.relation_provision ( target_table_id );
286
+
287
+ COMMIT;
@@ -12,7 +12,8 @@ CREATE TABLE metaschema_modules_public.rls_module (
12
12
  api_id uuid NOT NULL DEFAULT uuid_nil(),
13
13
  schema_id uuid NOT NULL DEFAULT uuid_nil(),
14
14
  private_schema_id uuid NOT NULL DEFAULT uuid_nil(),
15
- tokens_table_id uuid NOT NULL DEFAULT uuid_nil(),
15
+ session_credentials_table_id uuid NOT NULL DEFAULT uuid_nil(),
16
+ sessions_table_id uuid NOT NULL DEFAULT uuid_nil(),
16
17
  users_table_id uuid NOT NULL DEFAULT uuid_nil(),
17
18
 
18
19
  --
@@ -25,7 +26,8 @@ CREATE TABLE metaschema_modules_public.rls_module (
25
26
  --
26
27
  CONSTRAINT db_fkey FOREIGN KEY (database_id) REFERENCES metaschema_public.database (id) ON DELETE CASCADE,
27
28
  CONSTRAINT api_fkey FOREIGN KEY (api_id) REFERENCES services_public.apis (id) ON DELETE CASCADE,
28
- CONSTRAINT tokens_table_fkey FOREIGN KEY (tokens_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
29
+ CONSTRAINT session_credentials_table_fkey FOREIGN KEY (session_credentials_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
30
+ CONSTRAINT sessions_table_fkey FOREIGN KEY (sessions_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
29
31
  CONSTRAINT users_table_fkey FOREIGN KEY (users_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
30
32
  CONSTRAINT schema_fkey FOREIGN KEY (schema_id) REFERENCES metaschema_public.schema (id) ON DELETE CASCADE,
31
33
  CONSTRAINT pschema_fkey FOREIGN KEY (private_schema_id) REFERENCES metaschema_public.schema (id) ON DELETE CASCADE,
@@ -39,7 +41,8 @@ COMMENT ON CONSTRAINT schema_fkey ON metaschema_modules_public.rls_module IS E'@
39
41
  COMMENT ON CONSTRAINT pschema_fkey ON metaschema_modules_public.rls_module IS E'@omit manyToMany';
40
42
 
41
43
  COMMENT ON CONSTRAINT db_fkey ON metaschema_modules_public.rls_module IS E'@omit';
42
- COMMENT ON CONSTRAINT tokens_table_fkey ON metaschema_modules_public.rls_module IS E'@omit';
44
+ COMMENT ON CONSTRAINT session_credentials_table_fkey ON metaschema_modules_public.rls_module IS E'@omit';
45
+ COMMENT ON CONSTRAINT sessions_table_fkey ON metaschema_modules_public.rls_module IS E'@omit';
43
46
  COMMENT ON CONSTRAINT users_table_fkey ON metaschema_modules_public.rls_module IS E'@omit';
44
47
  CREATE INDEX rls_module_database_id_idx ON metaschema_modules_public.rls_module ( database_id );
45
48
 
@@ -33,6 +33,8 @@ CREATE TABLE metaschema_modules_public.secure_table_provision (
33
33
 
34
34
  policy_permissive boolean NOT NULL DEFAULT true,
35
35
 
36
+ policy_name text DEFAULT NULL,
37
+
36
38
  policy_data jsonb NOT NULL DEFAULT '{}',
37
39
 
38
40
  out_fields uuid[] DEFAULT NULL,
@@ -87,6 +89,9 @@ COMMENT ON COLUMN metaschema_modules_public.secure_table_provision.policy_role I
87
89
  COMMENT ON COLUMN metaschema_modules_public.secure_table_provision.policy_permissive IS
88
90
  'Whether the policy is PERMISSIVE (true) or RESTRICTIVE (false). Defaults to true.';
89
91
 
92
+ COMMENT ON COLUMN metaschema_modules_public.secure_table_provision.policy_name IS
93
+ 'Custom suffix for the generated policy name. When NULL and policy_type is set, the trigger auto-derives a suffix from policy_type by stripping the Authz prefix and underscoring the remainder (e.g. AuthzDirectOwner becomes direct_owner, producing policy names like auth_sel_direct_owner). When explicitly set, the value is passed through as-is to metaschema.create_policy name parameter. This ensures multiple policies on the same table do not collide (e.g. AuthzDirectOwner + AuthzPublishable each get unique names).';
94
+
90
95
  COMMENT ON COLUMN metaschema_modules_public.secure_table_provision.policy_data IS
91
96
  'Opaque configuration passed through to metaschema.create_policy(). Structure varies by policy_type and is not interpreted by this trigger. Defaults to ''{}''.';
92
97
 
@@ -7,24 +7,27 @@ BEGIN;
7
7
  CREATE TABLE metaschema_modules_public.table_module (
8
8
  id uuid PRIMARY KEY DEFAULT uuid_generate_v4 (),
9
9
  database_id uuid NOT NULL,
10
-
11
- private_schema_id uuid NOT NULL DEFAULT uuid_nil(),
12
-
13
- table_id uuid NOT NULL,
10
+
11
+ schema_id uuid NOT NULL DEFAULT uuid_nil(),
12
+
13
+ table_id uuid NOT NULL DEFAULT uuid_nil(),
14
+
15
+ table_name text DEFAULT NULL,
14
16
 
15
17
  node_type text NOT NULL,
16
18
 
19
+ use_rls boolean NOT NULL DEFAULT true,
20
+
17
21
  data jsonb NOT NULL DEFAULT '{}',
18
22
 
19
23
  fields uuid[],
20
24
 
21
- --
22
25
  CONSTRAINT db_fkey FOREIGN KEY (database_id) REFERENCES metaschema_public.database (id) ON DELETE CASCADE,
23
26
  CONSTRAINT table_fkey FOREIGN KEY (table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
24
- CONSTRAINT private_schema_fkey FOREIGN KEY (private_schema_id) REFERENCES metaschema_public.schema (id) ON DELETE CASCADE
27
+ CONSTRAINT schema_fkey FOREIGN KEY (schema_id) REFERENCES metaschema_public.schema (id) ON DELETE CASCADE
25
28
  );
26
29
 
27
- COMMENT ON CONSTRAINT private_schema_fkey ON metaschema_modules_public.table_module IS E'@omit manyToMany';
30
+ COMMENT ON CONSTRAINT schema_fkey ON metaschema_modules_public.table_module IS E'@omit manyToMany';
28
31
  COMMENT ON CONSTRAINT table_fkey ON metaschema_modules_public.table_module IS E'@omit manyToMany';
29
32
  COMMENT ON CONSTRAINT db_fkey ON metaschema_modules_public.table_module IS E'@omit manyToMany';
30
33
  CREATE INDEX table_module_database_id_idx ON metaschema_modules_public.table_module ( database_id );
@@ -16,8 +16,13 @@ CREATE TABLE metaschema_modules_public.table_template_module (
16
16
 
17
17
  table_name text NOT NULL,
18
18
 
19
+ -- Node type from node_type_registry (e.g., 'TableUserProfiles', 'TableOrganizationSettings', 'TableUserSettings')
19
20
  node_type text NOT NULL,
20
21
 
22
+ -- Type-specific parameters as jsonb
23
+ -- TableUserProfiles: {} (uses default fields)
24
+ -- TableOrganizationSettings: {} (uses default fields)
25
+ -- TableUserSettings: {} (uses default fields)
21
26
  data jsonb NOT NULL DEFAULT '{}',
22
27
 
23
28
  --
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pgpm/metaschema-modules",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "description": "Module metadata handling and dependency tracking",
5
5
  "author": "Dan Lynch <pyramation@gmail.com>",
6
6
  "contributors": [
@@ -21,12 +21,11 @@
21
21
  "test:watch": "jest --watch"
22
22
  },
23
23
  "dependencies": {
24
- "@pgpm/metaschema-schema": "0.17.0",
25
- "@pgpm/services": "0.17.0",
26
- "@pgpm/verify": "0.17.0"
24
+ "@pgpm/metaschema-schema": "0.18.0",
25
+ "@pgpm/verify": "0.18.0"
27
26
  },
28
27
  "devDependencies": {
29
- "pgpm": "^1.3.0"
28
+ "pgpm": "^4.2.3"
30
29
  },
31
30
  "repository": {
32
31
  "type": "git",
@@ -36,5 +35,5 @@
36
35
  "bugs": {
37
36
  "url": "https://github.com/constructive-io/pgpm-modules/issues"
38
37
  },
39
- "gitHead": "8eb8b9e3a6784fb45a3a9e86838f8417f061925c"
38
+ "gitHead": "8144027c7fab4956bcdebd736d04c0d4f57344bc"
40
39
  }
package/pgpm.plan CHANGED
@@ -32,4 +32,5 @@ schemas/metaschema_modules_public/tables/users_module/table [schemas/metaschema_
32
32
  schemas/metaschema_modules_public/tables/uuid_module/table [schemas/metaschema_modules_public/schema] 2017-08-11T08:11:51Z skitch <skitch@5b0c196eeb62> # add schemas/metaschema_modules_public/tables/uuid_module/table
33
33
  schemas/metaschema_modules_public/tables/hierarchy_module/table [schemas/metaschema_modules_public/schema] 2024-12-28T00:00:00Z skitch <skitch@5b0c196eeb62> # add schemas/metaschema_modules_public/tables/hierarchy_module/table
34
34
  schemas/metaschema_modules_public/tables/table_template_module/table [schemas/metaschema_modules_public/schema] 2026-01-14T00:00:00Z devin <devin@cognition.ai> # add schemas/metaschema_modules_public/tables/table_template_module/table
35
- schemas/metaschema_modules_public/tables/secure_table_provision/table [schemas/metaschema_modules_public/schema] 2026-02-26T00:00:00Z devin <devin@cognition.ai> # add schemas/metaschema_modules_public/tables/secure_table_provision/table
35
+ schemas/metaschema_modules_public/tables/secure_table_provision/table [schemas/metaschema_modules_public/schema] 2026-02-25T00:00:00Z Constructive <developers@constructive.io> # add schemas/metaschema_modules_public/tables/secure_table_provision/table
36
+ schemas/metaschema_modules_public/tables/relation_provision/table [schemas/metaschema_modules_public/schema] 2026-02-26T00:00:00Z Constructive <developers@constructive.io> # add schemas/metaschema_modules_public/tables/relation_provision/table
@@ -2,6 +2,6 @@
2
2
 
3
3
  BEGIN;
4
4
 
5
- DROP TABLE metaschema_modules_public.field_module;
5
+ DROP TABLE IF EXISTS metaschema_modules_public.field_module;
6
6
 
7
7
  COMMIT;
@@ -0,0 +1,7 @@
1
+ -- Revert schemas/metaschema_modules_public/tables/relation_provision/table from pg
2
+
3
+ BEGIN;
4
+
5
+ DROP TABLE IF EXISTS metaschema_modules_public.relation_provision;
6
+
7
+ COMMIT;