@pgpm/metaschema-modules 0.21.1 → 0.22.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.
Files changed (48) hide show
  1. package/README.md +7 -8
  2. package/deploy/schemas/metaschema_modules_public/tables/billing_module/table.sql +47 -0
  3. package/deploy/schemas/metaschema_modules_public/tables/billing_provider_module/table.sql +61 -0
  4. package/deploy/schemas/metaschema_modules_public/tables/devices_module/table.sql +36 -0
  5. package/deploy/schemas/metaschema_modules_public/tables/entity_type_provision/table.sql +332 -0
  6. package/deploy/schemas/metaschema_modules_public/tables/identity_providers_module/table.sql +33 -0
  7. package/deploy/schemas/metaschema_modules_public/tables/invites_module/table.sql +8 -0
  8. package/deploy/schemas/metaschema_modules_public/tables/limits_module/table.sql +38 -2
  9. package/deploy/schemas/metaschema_modules_public/tables/memberships_module/table.sql +7 -0
  10. package/deploy/schemas/metaschema_modules_public/tables/notifications_module/table.sql +66 -0
  11. package/deploy/schemas/metaschema_modules_public/tables/permissions_module/table.sql +23 -1
  12. package/deploy/schemas/metaschema_modules_public/tables/plans_module/table.sql +46 -0
  13. package/deploy/schemas/metaschema_modules_public/tables/profiles_module/table.sql +5 -0
  14. package/deploy/schemas/metaschema_modules_public/tables/realtime_module/table.sql +48 -0
  15. package/deploy/schemas/metaschema_modules_public/tables/relation_provision/table.sql +10 -45
  16. package/deploy/schemas/metaschema_modules_public/tables/secure_table_provision/table.sql +8 -39
  17. package/deploy/schemas/metaschema_modules_public/tables/session_secrets_module/table.sql +31 -0
  18. package/deploy/schemas/metaschema_modules_public/tables/storage_module/table.sql +42 -4
  19. package/deploy/schemas/metaschema_modules_public/tables/user_auth_module/table.sql +2 -2
  20. package/deploy/schemas/metaschema_modules_public/tables/webauthn_auth_module/table.sql +63 -0
  21. package/deploy/schemas/metaschema_modules_public/tables/webauthn_credentials_module/table.sql +32 -0
  22. package/package.json +5 -5
  23. package/pgpm.plan +12 -1
  24. package/revert/schemas/metaschema_modules_public/tables/billing_module/table.sql +3 -0
  25. package/revert/schemas/metaschema_modules_public/tables/billing_provider_module/table.sql +3 -0
  26. package/revert/schemas/metaschema_modules_public/tables/devices_module/table.sql +7 -0
  27. package/revert/schemas/metaschema_modules_public/tables/entity_type_provision/table.sql +7 -0
  28. package/revert/schemas/metaschema_modules_public/tables/identity_providers_module/table.sql +7 -0
  29. package/revert/schemas/metaschema_modules_public/tables/notifications_module/table.sql +7 -0
  30. package/revert/schemas/metaschema_modules_public/tables/plans_module/table.sql +7 -0
  31. package/revert/schemas/metaschema_modules_public/tables/realtime_module/table.sql +7 -0
  32. package/revert/schemas/metaschema_modules_public/tables/session_secrets_module/table.sql +7 -0
  33. package/revert/schemas/metaschema_modules_public/tables/webauthn_auth_module/table.sql +7 -0
  34. package/revert/schemas/metaschema_modules_public/tables/webauthn_credentials_module/table.sql +7 -0
  35. package/sql/metaschema-modules--0.15.5.sql +1269 -469
  36. package/verify/schemas/metaschema_modules_public/tables/billing_module/table.sql +23 -0
  37. package/verify/schemas/metaschema_modules_public/tables/billing_provider_module/table.sql +29 -0
  38. package/verify/schemas/metaschema_modules_public/tables/devices_module/table.sql +7 -0
  39. package/verify/schemas/metaschema_modules_public/tables/entity_type_provision/table.sql +7 -0
  40. package/verify/schemas/metaschema_modules_public/tables/identity_providers_module/table.sql +7 -0
  41. package/verify/schemas/metaschema_modules_public/tables/notifications_module/table.sql +7 -0
  42. package/verify/schemas/metaschema_modules_public/tables/plans_module/table.sql +13 -0
  43. package/verify/schemas/metaschema_modules_public/tables/realtime_module/table.sql +7 -0
  44. package/verify/schemas/metaschema_modules_public/tables/relation_provision/table.sql +2 -8
  45. package/verify/schemas/metaschema_modules_public/tables/secure_table_provision/table.sql +2 -8
  46. package/verify/schemas/metaschema_modules_public/tables/session_secrets_module/table.sql +7 -0
  47. package/verify/schemas/metaschema_modules_public/tables/webauthn_auth_module/table.sql +7 -0
  48. package/verify/schemas/metaschema_modules_public/tables/webauthn_credentials_module/table.sql +7 -0
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
@@ -108,7 +108,6 @@ The package provides metadata tables for the following modules:
108
108
  - **invites_module**: Invitation system configuration
109
109
 
110
110
  ### Other Modules
111
- - **field_module**: Custom field configurations
112
111
  - **default_ids_module**: Default ID generation settings
113
112
  - **limits_module**: Rate limiting and quota configurations
114
113
  - **rls_module**: Row-level security configurations
@@ -213,7 +212,7 @@ Use module tables as feature flags:
213
212
 
214
213
  ## Dependencies
215
214
 
216
- - `@pgpm/metaschema-schema`: Core metadata management
215
+ - `@pgpm/db-meta-schema`: Core metadata management
217
216
  - `@pgpm/verify`: Verification utilities
218
217
 
219
218
  ## Testing
@@ -0,0 +1,47 @@
1
+ -- Deploy schemas/metaschema_modules_public/tables/billing_module/table to pg
2
+
3
+ -- requires: schemas/metaschema_modules_public/schema
4
+
5
+ BEGIN;
6
+
7
+ CREATE TABLE metaschema_modules_public.billing_module (
8
+ id uuid PRIMARY KEY DEFAULT uuidv7(),
9
+ database_id uuid NOT NULL,
10
+
11
+ schema_id uuid NOT NULL DEFAULT uuid_nil(),
12
+ private_schema_id uuid NOT NULL DEFAULT uuid_nil(),
13
+
14
+ -- Meters table: defines what you track (quota, boolean, credit_pool)
15
+ meters_table_id uuid NOT NULL DEFAULT uuid_nil(),
16
+ meters_table_name text NOT NULL DEFAULT '',
17
+
18
+ -- Plan subscriptions table: assigns plans to entities with lifecycle
19
+ plan_subscriptions_table_id uuid NOT NULL DEFAULT uuid_nil(),
20
+ plan_subscriptions_table_name text NOT NULL DEFAULT '',
21
+
22
+ -- Ledger table: append-only event log
23
+ ledger_table_id uuid NOT NULL DEFAULT uuid_nil(),
24
+ ledger_table_name text NOT NULL DEFAULT '',
25
+
26
+ -- Balances SPRT: denormalized current state (RLS-exempt fast lookups)
27
+ balances_table_id uuid NOT NULL DEFAULT uuid_nil(),
28
+ balances_table_name text NOT NULL DEFAULT '',
29
+
30
+ -- Generated functions
31
+ record_usage_function text NOT NULL DEFAULT '',
32
+
33
+ prefix text NULL,
34
+
35
+ CONSTRAINT db_fkey FOREIGN KEY (database_id) REFERENCES metaschema_public.database (id) ON DELETE CASCADE,
36
+ CONSTRAINT schema_fkey FOREIGN KEY (schema_id) REFERENCES metaschema_public.schema (id) ON DELETE CASCADE,
37
+ CONSTRAINT private_schema_fkey FOREIGN KEY (private_schema_id) REFERENCES metaschema_public.schema (id) ON DELETE CASCADE,
38
+ CONSTRAINT meters_table_fkey FOREIGN KEY (meters_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
39
+ CONSTRAINT plan_subscriptions_table_fkey FOREIGN KEY (plan_subscriptions_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
40
+ CONSTRAINT ledger_table_fkey FOREIGN KEY (ledger_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
41
+ CONSTRAINT balances_table_fkey FOREIGN KEY (balances_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
42
+ CONSTRAINT billing_module_database_id_unique UNIQUE (database_id)
43
+ );
44
+
45
+ CREATE INDEX billing_module_database_id_idx ON metaschema_modules_public.billing_module ( database_id );
46
+
47
+ COMMIT;
@@ -0,0 +1,61 @@
1
+ -- Deploy schemas/metaschema_modules_public/tables/billing_provider_module/table to pg
2
+
3
+ -- requires: schemas/metaschema_modules_public/schema
4
+
5
+ BEGIN;
6
+
7
+ CREATE TABLE metaschema_modules_public.billing_provider_module (
8
+ id uuid PRIMARY KEY DEFAULT uuidv7(),
9
+ database_id uuid NOT NULL,
10
+
11
+ schema_id uuid NOT NULL DEFAULT uuid_nil(),
12
+ private_schema_id uuid NOT NULL DEFAULT uuid_nil(),
13
+
14
+ -- Provider: which billing provider (stripe, paddle, lemon_squeezy, etc.)
15
+ provider text NOT NULL DEFAULT 'stripe',
16
+
17
+ -- Parameterized FK targets: pass in your own tables
18
+ -- For SaaS: plans, plan_pricing, plan_subscriptions
19
+ -- For e-commerce: products, product_variants, orders
20
+ products_table_id uuid NULL,
21
+ prices_table_id uuid NULL,
22
+ subscriptions_table_id uuid NULL,
23
+
24
+ -- Created mapping tables
25
+ billing_customers_table_id uuid NOT NULL DEFAULT uuid_nil(),
26
+ billing_customers_table_name text NOT NULL DEFAULT '',
27
+
28
+ billing_products_table_id uuid NOT NULL DEFAULT uuid_nil(),
29
+ billing_products_table_name text NOT NULL DEFAULT '',
30
+
31
+ billing_prices_table_id uuid NOT NULL DEFAULT uuid_nil(),
32
+ billing_prices_table_name text NOT NULL DEFAULT '',
33
+
34
+ billing_subscriptions_table_id uuid NOT NULL DEFAULT uuid_nil(),
35
+ billing_subscriptions_table_name text NOT NULL DEFAULT '',
36
+
37
+ billing_webhook_events_table_id uuid NOT NULL DEFAULT uuid_nil(),
38
+ billing_webhook_events_table_name text NOT NULL DEFAULT '',
39
+
40
+ -- Generated functions
41
+ process_billing_event_function text NOT NULL DEFAULT '',
42
+
43
+ prefix text NULL,
44
+
45
+ CONSTRAINT db_fkey FOREIGN KEY (database_id) REFERENCES metaschema_public.database (id) ON DELETE CASCADE,
46
+ CONSTRAINT schema_fkey FOREIGN KEY (schema_id) REFERENCES metaschema_public.schema (id) ON DELETE CASCADE,
47
+ CONSTRAINT private_schema_fkey FOREIGN KEY (private_schema_id) REFERENCES metaschema_public.schema (id) ON DELETE CASCADE,
48
+ CONSTRAINT billing_customers_table_fkey FOREIGN KEY (billing_customers_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
49
+ CONSTRAINT billing_products_table_fkey FOREIGN KEY (billing_products_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
50
+ CONSTRAINT billing_prices_table_fkey FOREIGN KEY (billing_prices_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
51
+ CONSTRAINT billing_subscriptions_table_fkey FOREIGN KEY (billing_subscriptions_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
52
+ CONSTRAINT billing_webhook_events_table_fkey FOREIGN KEY (billing_webhook_events_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
53
+ CONSTRAINT products_table_fkey FOREIGN KEY (products_table_id) REFERENCES metaschema_public.table (id) ON DELETE SET NULL,
54
+ CONSTRAINT prices_table_fkey FOREIGN KEY (prices_table_id) REFERENCES metaschema_public.table (id) ON DELETE SET NULL,
55
+ CONSTRAINT subscriptions_table_fkey FOREIGN KEY (subscriptions_table_id) REFERENCES metaschema_public.table (id) ON DELETE SET NULL,
56
+ CONSTRAINT billing_provider_module_database_id_unique UNIQUE (database_id)
57
+ );
58
+
59
+ CREATE INDEX billing_provider_module_database_id_idx ON metaschema_modules_public.billing_provider_module ( database_id );
60
+
61
+ COMMIT;
@@ -0,0 +1,36 @@
1
+ -- Deploy schemas/metaschema_modules_public/tables/devices_module/table to pg
2
+
3
+ -- requires: schemas/metaschema_modules_public/schema
4
+
5
+ BEGIN;
6
+
7
+ CREATE TABLE metaschema_modules_public.devices_module (
8
+ id uuid PRIMARY KEY DEFAULT uuidv7(),
9
+ database_id uuid NOT NULL,
10
+
11
+ --
12
+ schema_id uuid NOT NULL DEFAULT uuid_nil(),
13
+ user_devices_table_id uuid NOT NULL DEFAULT uuid_nil(),
14
+ device_settings_table_id uuid NOT NULL DEFAULT uuid_nil(),
15
+
16
+ user_devices_table text NOT NULL DEFAULT 'auth_user_devices',
17
+ device_settings_table text NOT NULL DEFAULT 'app_settings_device',
18
+ --
19
+
20
+ CONSTRAINT db_fkey FOREIGN KEY (database_id) REFERENCES metaschema_public.database (id) ON DELETE CASCADE,
21
+ CONSTRAINT schema_fkey FOREIGN KEY (schema_id) REFERENCES metaschema_public.schema (id) ON DELETE CASCADE,
22
+ CONSTRAINT user_devices_table_fkey FOREIGN KEY (user_devices_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
23
+ CONSTRAINT device_settings_table_fkey FOREIGN KEY (device_settings_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
24
+
25
+ --
26
+ CONSTRAINT devices_module_database_id_uniq UNIQUE(database_id)
27
+ );
28
+
29
+ CREATE INDEX devices_module_database_id_idx ON metaschema_modules_public.devices_module ( database_id );
30
+
31
+ COMMENT ON CONSTRAINT user_devices_table_fkey
32
+ ON metaschema_modules_public.devices_module IS E'@fieldName userDevicesTableByUserDevicesTableId';
33
+ COMMENT ON CONSTRAINT device_settings_table_fkey
34
+ ON metaschema_modules_public.devices_module IS E'@fieldName deviceSettingsTableByDeviceSettingsTableId';
35
+
36
+ COMMIT;
@@ -0,0 +1,332 @@
1
+ -- Deploy schemas/metaschema_modules_public/tables/entity_type_provision/table to pg
2
+
3
+ -- requires: schemas/metaschema_modules_public/schema
4
+
5
+ BEGIN;
6
+
7
+ CREATE TABLE metaschema_modules_public.entity_type_provision (
8
+ id uuid PRIMARY KEY DEFAULT uuidv7(),
9
+
10
+ database_id uuid NOT NULL,
11
+
12
+ -- =========================================================================
13
+ -- Identity: what this membership type is called
14
+ -- =========================================================================
15
+
16
+ name text NOT NULL,
17
+
18
+ prefix text NOT NULL,
19
+
20
+ description text NOT NULL DEFAULT '',
21
+
22
+ -- =========================================================================
23
+ -- Parentage: which entity type is the parent (resolved by trigger)
24
+ -- =========================================================================
25
+
26
+ parent_entity text NOT NULL DEFAULT 'org',
27
+
28
+ -- =========================================================================
29
+ -- Entity table name override
30
+ -- =========================================================================
31
+
32
+ table_name text DEFAULT NULL,
33
+
34
+ -- =========================================================================
35
+ -- Visibility: can parent members see child entities?
36
+ -- =========================================================================
37
+
38
+ is_visible boolean NOT NULL DEFAULT true,
39
+
40
+ -- =========================================================================
41
+ -- Optional modules
42
+ -- =========================================================================
43
+
44
+ has_limits boolean NOT NULL DEFAULT false,
45
+
46
+ has_profiles boolean NOT NULL DEFAULT false,
47
+
48
+ has_levels boolean NOT NULL DEFAULT false,
49
+
50
+ has_storage boolean NOT NULL DEFAULT false,
51
+
52
+ has_invites boolean NOT NULL DEFAULT false,
53
+
54
+ -- =========================================================================
55
+ -- Storage configuration: module-level overrides + initial bucket defs.
56
+ -- Only used when has_storage = true. NULL = use defaults.
57
+ -- =========================================================================
58
+
59
+ storage_config jsonb DEFAULT NULL,
60
+
61
+ -- =========================================================================
62
+ -- Escape hatch: skip default entity table RLS policies
63
+ -- =========================================================================
64
+
65
+ skip_entity_policies boolean NOT NULL DEFAULT false,
66
+
67
+ -- =========================================================================
68
+ -- Table provisioning override: single jsonb object describing the full
69
+ -- security setup to apply to the entity table, using the same vocabulary
70
+ -- as metaschema_modules_public.provision_table() and blueprint tables[]
71
+ -- entries (policies[], nodes[], fields[], grants[], use_rls).
72
+ --
73
+ -- Semantics:
74
+ -- - NULL (default) -> apply the 5 default entity-table policies
75
+ -- (gated by is_visible / skip_entity_policies)
76
+ -- - non-NULL object -> fan table_provision.policies[] into N
77
+ -- secure_table_provision rows; the 5 defaults
78
+ -- are implicitly skipped, and is_visible is
79
+ -- a no-op on this path.
80
+ -- =========================================================================
81
+
82
+ table_provision jsonb DEFAULT NULL,
83
+
84
+ -- =========================================================================
85
+ -- Output columns (populated by the trigger, not set by callers)
86
+ -- =========================================================================
87
+
88
+ out_membership_type int DEFAULT NULL,
89
+
90
+ out_entity_table_id uuid DEFAULT NULL,
91
+
92
+ out_entity_table_name text DEFAULT NULL,
93
+
94
+ out_installed_modules text[] DEFAULT NULL,
95
+
96
+ out_storage_module_id uuid DEFAULT NULL,
97
+
98
+ out_buckets_table_id uuid DEFAULT NULL,
99
+
100
+ out_files_table_id uuid DEFAULT NULL,
101
+
102
+ out_path_shares_table_id uuid DEFAULT NULL,
103
+
104
+ out_invites_module_id uuid DEFAULT NULL,
105
+
106
+ -- =========================================================================
107
+ -- Constraints
108
+ -- =========================================================================
109
+
110
+ CONSTRAINT entity_type_provision_unique_prefix UNIQUE (database_id, prefix),
111
+ CONSTRAINT entity_type_provision_db_fkey FOREIGN KEY (database_id)
112
+ REFERENCES metaschema_public.database (id) ON DELETE CASCADE
113
+ );
114
+
115
+ -- =============================================================================
116
+ -- Table-level comment
117
+ -- =============================================================================
118
+
119
+ COMMENT ON TABLE metaschema_modules_public.entity_type_provision IS
120
+ 'Provisions a new membership entity type. Each INSERT creates an entity table, registers a membership type,
121
+ and installs the required modules (permissions, memberships, limits) plus optional modules (profiles, levels, invites).
122
+ Uses provision_membership_table() internally. Graceful: duplicate (database_id, prefix) pairs are silently skipped
123
+ via the unique constraint (use INSERT ... ON CONFLICT DO NOTHING).
124
+ Policy behavior: by default the five entity-table RLS policies are applied (gated by is_visible).
125
+ Set table_provision to a single jsonb object (using the same shape as provision_table() /
126
+ blueprint tables[] entries) to replace the defaults with your own; set skip_entity_policies=true
127
+ as an escape hatch to apply zero policies.';
128
+
129
+ -- =============================================================================
130
+ -- Identity columns
131
+ -- =============================================================================
132
+
133
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.id IS
134
+ 'Unique identifier for this provision row.';
135
+
136
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.database_id IS
137
+ 'The database to provision this entity type in. Required.';
138
+
139
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.name IS
140
+ 'Human-readable name for this entity type, e.g. ''Data Room'', ''Team Channel''. Required.
141
+ Stored in the entity_types registry table.';
142
+
143
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.prefix IS
144
+ 'SQL prefix used for table and module naming, e.g. ''data_room'', ''team_channel''. Required.
145
+ Drives entity table name (prefix || ''s'' by default), module labels (permissions_module:prefix),
146
+ and membership table names (prefix_memberships, prefix_members, etc.).
147
+ Must be unique per database — the (database_id, prefix) constraint ensures graceful ON CONFLICT DO NOTHING.';
148
+
149
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.description IS
150
+ 'Description of this entity type. Stored in the entity_types registry table. Defaults to empty string.';
151
+
152
+ -- =============================================================================
153
+ -- Parentage
154
+ -- =============================================================================
155
+
156
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.parent_entity IS
157
+ 'Prefix of the parent entity type. The trigger resolves this to a membership_type integer
158
+ by looking up memberships_module WHERE prefix = parent_entity.
159
+ Defaults to ''org'' (the organization-level type). For nested types, set to the parent''s prefix
160
+ (e.g. ''data_room'' for a team_channel nested under data_room).
161
+ The parent type must already be provisioned before this INSERT.';
162
+
163
+ -- =============================================================================
164
+ -- Entity table name override
165
+ -- =============================================================================
166
+
167
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.table_name IS
168
+ 'Override the entity table name. When NULL (default), the table name is derived as prefix || ''s''
169
+ (e.g. prefix ''data_room'' produces table ''data_rooms'').
170
+ Set this when the pluralization rule doesn''t apply (e.g. prefix ''staff'' should produce ''staff'' not ''staffs'').';
171
+
172
+ -- =============================================================================
173
+ -- Visibility
174
+ -- =============================================================================
175
+
176
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.is_visible IS
177
+ 'Whether members of the parent entity can see child entities. Defaults to true.
178
+ When true: a SELECT policy allows parent members to list child entities (e.g. org members can see all data rooms).
179
+ When false: only direct members of the entity itself can see it (private entity mode).
180
+ Controls whether the parent_member SELECT policy is created on the entity table.
181
+ Only meaningful on the defaults path — ignored (no-op) when table_provision is non-NULL or
182
+ skip_entity_policies=true, since no default policies are being applied in those cases.';
183
+
184
+ -- =============================================================================
185
+ -- Optional modules
186
+ -- =============================================================================
187
+
188
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.has_limits IS
189
+ 'Whether to apply limits_module security for this type. Defaults to false.
190
+ The limits_module table structure is always created (memberships_module requires it),
191
+ but when false, no RLS policies are applied to the limits tables.
192
+ Set to true if this entity type needs configurable resource limits per membership.';
193
+
194
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.has_profiles IS
195
+ 'Whether to provision profiles_module for this type. Defaults to false.
196
+ Profiles provide named permission roles (e.g. ''Editor'', ''Viewer'') with pre-configured permission bitmasks.
197
+ When true, creates profile tables and applies profiles security.';
198
+
199
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.has_levels IS
200
+ 'Whether to provision levels_module for this type. Defaults to false.
201
+ Levels provide gamification/achievement tracking for members.
202
+ When true, creates level steps, achievements, and level tables with security.';
203
+
204
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.has_storage IS
205
+ 'Whether to provision storage_module for this type. Defaults to false.
206
+ When true, creates {prefix}_buckets and {prefix}_files tables
207
+ with entity-scoped RLS (AuthzEntityMembership) using the entity''s membership_type.
208
+ Storage tables get owner_id FK to the entity table, so files are owned by the entity.';
209
+
210
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.has_invites IS
211
+ 'Whether to provision invites_module for this type. Defaults to false.
212
+ When true, the trigger inserts a row into invites_module which in turn
213
+ (via insert_invites_module BEFORE INSERT) creates {prefix}_invites and
214
+ {prefix}_claimed_invites tables plus the submit_{prefix}_invite_code() function.
215
+ Symmetric counterpart of has_storage. Re-provisioning is idempotent: the
216
+ UNIQUE (database_id, membership_type) constraint on invites_module combined with
217
+ ON CONFLICT DO NOTHING in the fan-out makes repeated INSERTs safe.';
218
+
219
+ -- =============================================================================
220
+ -- Escape hatch
221
+ -- =============================================================================
222
+
223
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.skip_entity_policies IS
224
+ 'Escape hatch: when true, apply zero RLS policies to the entity table. Defaults to false.
225
+ Use this only when you want the entity table provisioned with zero policies (e.g. because you
226
+ plan to insert secure_table_provision rows yourself later). In most cases, prefer leaving this
227
+ false and either accepting the five defaults (table_provision=NULL) or overriding them via
228
+ table_provision.
229
+ Defaults (applied when table_provision IS NULL and skip_entity_policies=false):
230
+ - SELECT (parent_member): parent entity members can see child entities (only when is_visible=true)
231
+ - SELECT (self_member): direct members of the entity can see it
232
+ - INSERT: create_entity permission on the parent entity
233
+ - UPDATE: admin_entity permission on the entity itself
234
+ - DELETE: owner of the entity can delete it';
235
+
236
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.table_provision IS
237
+ 'Single jsonb object describing the full security setup to apply to the entity table.
238
+ Uses the same vocabulary as metaschema_modules_public.provision_table() and blueprint tables[]
239
+ entries, so an entity table is configured the same way an ordinary blueprint table is.
240
+ Defaults to NULL; when non-NULL, the five default policies are implicitly replaced by
241
+ table_provision.policies[] (is_visible becomes a no-op on this path).
242
+ Recognized keys (all optional):
243
+ - use_rls (boolean, default true)
244
+ - nodes (jsonb array of {"$type","data"} Data* module entries)
245
+ - fields (jsonb array of field objects: name,type,is_required,default,min,max,regexp,index)
246
+ - grants (jsonb array of grant objects; each with roles[] and privileges[])
247
+ - policies (jsonb array of policy objects; each with $type, privileges, data, name, role, permissive)
248
+ The trigger forwards all setup (nodes/fields/grants/policies) as a single secure_table_provision row
249
+ against the newly created entity table.
250
+ Example — override with two SELECT policies:
251
+ table_provision := jsonb_build_object(
252
+ ''policies'', jsonb_build_array(
253
+ jsonb_build_object(
254
+ ''$type'', ''AuthzEntityMembership'',
255
+ ''privileges'', jsonb_build_array(''select''),
256
+ ''data'', jsonb_build_object(''entity_field'', ''id'', ''membership_type'', 3),
257
+ ''name'', ''self_member''
258
+ ),
259
+ jsonb_build_object(
260
+ ''$type'', ''AuthzDirectOwner'',
261
+ ''privileges'', jsonb_build_array(''select'', ''update''),
262
+ ''data'', jsonb_build_object(''owner_field'', ''owner_id'')
263
+ )
264
+ )
265
+ )';
266
+
267
+ -- =============================================================================
268
+ -- Output columns
269
+ -- =============================================================================
270
+
271
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.out_membership_type IS
272
+ 'Output: the auto-assigned integer membership type ID. Populated by the trigger after successful provisioning.
273
+ This is the ID used in entity_types, memberships_module, and all module tables.';
274
+
275
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.out_entity_table_id IS
276
+ 'Output: the UUID of the created entity table. Populated by the trigger.
277
+ Use this to reference the entity table in subsequent relation_provision or secure_table_provision rows.';
278
+
279
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.out_entity_table_name IS
280
+ 'Output: the name of the created entity table (e.g. ''data_rooms''). Populated by the trigger.';
281
+
282
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.out_installed_modules IS
283
+ 'Output: array of installed module labels (e.g. ARRAY[''permissions_module:data_room'', ''memberships_module:data_room'', ''invites_module:data_room'']).
284
+ Populated by the trigger. Useful for verifying which modules were provisioned.';
285
+
286
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.storage_config IS
287
+ 'Optional jsonb object for storage module configuration and initial bucket seeding.
288
+ Only used when has_storage = true; ignored otherwise. NULL = use defaults.
289
+ Recognized keys (all optional):
290
+ - upload_url_expiry_seconds (integer) presigned PUT URL expiry override
291
+ - download_url_expiry_seconds (integer) presigned GET URL expiry override
292
+ - default_max_file_size (bigint) global max file size in bytes for this scope
293
+ - allowed_origins (text[]) default CORS origins for all buckets in this scope
294
+ - buckets (jsonb[]) array of initial bucket definitions to seed
295
+ Each bucket in the buckets array recognizes:
296
+ - name (text, required) bucket name e.g. ''documents''
297
+ - description (text) human-readable description
298
+ - is_public (boolean) whether files are publicly readable (default false)
299
+ - allowed_mime_types (text[]) whitelist of MIME types (null = any)
300
+ - max_file_size (bigint) max file size in bytes (null = use scope default)
301
+ - allowed_origins (text[]) per-bucket CORS override
302
+ - provisions (jsonb object) optional: customize storage tables
303
+ with additional nodes, fields, grants, and policies.
304
+ Keyed by table role: "files", "buckets".
305
+ Each value uses the same shape as table_provision:
306
+ { nodes, fields, grants, use_rls, policies }. Fanned out
307
+ to secure_table_provision targeting the corresponding table.
308
+ When a key includes policies[], those REPLACE the default
309
+ storage policies for that table; tables without a key still
310
+ get defaults. Missing "data" on policy entries is auto-populated
311
+ with storage-specific defaults (same as table_provision).
312
+ Example: add SearchBm25 for full-text search on files:
313
+ {"provisions": {"files": {"nodes": [{"$type":
314
+ "SearchBm25", "data": {"source_fields": ["description"]}}]}}}
315
+ Example:
316
+ storage_config := ''{"buckets": [{"name": "documents", "is_public": false, "allowed_mime_types": ["application/pdf"]}], "provisions": {"files": {"nodes": [{"$type": "SearchBm25", "data": {"source_fields": ["description"]}}]}}}''::jsonb';
317
+
318
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.out_storage_module_id IS
319
+ 'Output: the UUID of the storage_module row created for this entity type. Populated by the trigger when has_storage=true.';
320
+
321
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.out_buckets_table_id IS
322
+ 'Output: the UUID of the generated buckets table (e.g. data_room_buckets). Populated by the trigger when has_storage=true.';
323
+
324
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.out_files_table_id IS
325
+ 'Output: the UUID of the generated files table (e.g. data_room_files). Populated by the trigger when has_storage=true.';
326
+
327
+ COMMENT ON COLUMN metaschema_modules_public.entity_type_provision.out_invites_module_id IS
328
+ 'Output: the UUID of the invites_module row created for this entity type. Populated by the trigger when has_invites=true.
329
+ NULL when has_invites=false, or when re-provisioning hits ON CONFLICT DO NOTHING
330
+ (i.e. the invites_module row was created in a previous run).';
331
+
332
+ COMMIT;
@@ -0,0 +1,33 @@
1
+ -- Deploy schemas/metaschema_modules_public/tables/identity_providers_module/table to pg
2
+
3
+ -- requires: schemas/metaschema_modules_public/schema
4
+
5
+ BEGIN;
6
+
7
+ CREATE TABLE metaschema_modules_public.identity_providers_module (
8
+ id uuid PRIMARY KEY DEFAULT uuidv7(),
9
+ database_id uuid NOT NULL,
10
+
11
+ schema_id uuid NOT NULL DEFAULT uuid_nil(),
12
+ private_schema_id uuid NOT NULL DEFAULT uuid_nil(),
13
+
14
+ table_id uuid NOT NULL DEFAULT uuid_nil(),
15
+
16
+ table_name text NOT NULL DEFAULT 'identity_providers',
17
+
18
+ --
19
+ CONSTRAINT db_fkey FOREIGN KEY (database_id) REFERENCES metaschema_public.database (id) ON DELETE CASCADE,
20
+ CONSTRAINT table_fkey FOREIGN KEY (table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
21
+ CONSTRAINT schema_fkey FOREIGN KEY (schema_id) REFERENCES metaschema_public.schema (id) ON DELETE CASCADE,
22
+ CONSTRAINT private_schema_fkey FOREIGN KEY (private_schema_id) REFERENCES metaschema_public.schema (id) ON DELETE CASCADE
23
+ );
24
+
25
+ CREATE INDEX identity_providers_module_database_id_idx ON metaschema_modules_public.identity_providers_module ( database_id );
26
+ CREATE INDEX identity_providers_module_schema_id_idx ON metaschema_modules_public.identity_providers_module ( schema_id );
27
+ CREATE INDEX identity_providers_module_private_schema_id_idx ON metaschema_modules_public.identity_providers_module ( private_schema_id );
28
+ CREATE INDEX identity_providers_module_table_id_idx ON metaschema_modules_public.identity_providers_module ( table_id );
29
+
30
+ COMMENT ON TABLE metaschema_modules_public.identity_providers_module IS 'Config row for the identity_providers_module, which provisions a per-database identity_providers config table holding OAuth2 / OIDC (and future SAML) provider definitions: protocol kind, endpoint URLs, encrypted client secret, scopes, audience validation, PKCE, and email-handling flags. Built-in providers (google, github, apple, ...) are seeded as is_built_in=true rows; custom providers use slugs of the form custom:<slug>.';
31
+ COMMENT ON COLUMN metaschema_modules_public.identity_providers_module.private_schema_id IS 'Private schema that hosts SECURITY DEFINER admin helpers which write to identity_providers (create / update / enable / disable / rotate-secret / delete) and the per-app quota check.';
32
+
33
+ COMMIT;
@@ -41,4 +41,12 @@ CREATE TABLE metaschema_modules_public.invites_module (
41
41
 
42
42
  CREATE INDEX invites_module_database_id_idx ON metaschema_modules_public.invites_module ( database_id );
43
43
 
44
+ -- Unique constraint on (database_id, membership_type) so the
45
+ -- entity_type_provision fan-out can use ON CONFLICT DO NOTHING for idempotent
46
+ -- re-provisioning. invites_module is always entity-scoped (membership_type
47
+ -- is NOT NULL on this table), so no COALESCE-NULL trick is needed here,
48
+ -- unlike storage_module which supports an app-level singleton row.
49
+ CREATE UNIQUE INDEX invites_module_unique_scope
50
+ ON metaschema_modules_public.invites_module (database_id, membership_type);
51
+
44
52
  COMMIT;
@@ -24,7 +24,35 @@ CREATE TABLE metaschema_modules_public.limits_module (
24
24
  limit_decrement_trigger text NOT NULL DEFAULT '',
25
25
  limit_update_trigger text NOT NULL DEFAULT '',
26
26
  limit_check_function text NOT NULL DEFAULT '',
27
-
27
+
28
+ -- Credit grants ledger table
29
+ limit_credits_table_id uuid NULL,
30
+
31
+ -- Events audit trail table
32
+ events_table_id uuid NULL,
33
+
34
+ -- Credit codes table (app-level only, database-wide)
35
+ credit_codes_table_id uuid NULL,
36
+
37
+ -- Credit code items table (app-level only, database-wide)
38
+ credit_code_items_table_id uuid NULL,
39
+
40
+ -- Credit redemptions table (app-level only, database-wide)
41
+ credit_redemptions_table_id uuid NULL,
42
+
43
+ -- Aggregate entity limits (org-level caps, no actor_id)
44
+ aggregate_table_id uuid NULL,
45
+
46
+ -- Cap tables (static config limits, no metering)
47
+ limit_caps_table_id uuid NULL,
48
+ limit_caps_defaults_table_id uuid NULL,
49
+
50
+ -- Cap check trigger function (gates inserts behind cap/feature flag values)
51
+ cap_check_trigger text NOT NULL DEFAULT '',
52
+
53
+ -- Resolve cap function (COALESCE lookup: per-entity → default → 0)
54
+ resolve_cap_function text NOT NULL DEFAULT '',
55
+
28
56
  prefix text NULL,
29
57
 
30
58
  membership_type int NOT NULL,
@@ -41,7 +69,15 @@ CREATE TABLE metaschema_modules_public.limits_module (
41
69
  CONSTRAINT table_fkey FOREIGN KEY (table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
42
70
  CONSTRAINT default_table_fkey FOREIGN KEY (default_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
43
71
  CONSTRAINT entity_table_fkey FOREIGN KEY (entity_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
44
- CONSTRAINT actor_table_fkey FOREIGN KEY (actor_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE
72
+ CONSTRAINT actor_table_fkey FOREIGN KEY (actor_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
73
+ CONSTRAINT aggregate_table_fkey FOREIGN KEY (aggregate_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
74
+ CONSTRAINT limit_credits_table_fkey FOREIGN KEY (limit_credits_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
75
+ CONSTRAINT events_table_fkey FOREIGN KEY (events_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
76
+ CONSTRAINT credit_codes_table_fkey FOREIGN KEY (credit_codes_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
77
+ CONSTRAINT credit_code_items_table_fkey FOREIGN KEY (credit_code_items_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
78
+ CONSTRAINT credit_redemptions_table_fkey FOREIGN KEY (credit_redemptions_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
79
+ CONSTRAINT limit_caps_table_fkey FOREIGN KEY (limit_caps_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE,
80
+ CONSTRAINT limit_caps_defaults_table_fkey FOREIGN KEY (limit_caps_defaults_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE
45
81
 
46
82
  );
47
83