diff --git a/packages/metaschema-modules/__tests__/__snapshots__/modules.test.ts.snap b/packages/metaschema-modules/__tests__/__snapshots__/modules.test.ts.snap index 06a2f78e..086dea79 100644 --- a/packages/metaschema-modules/__tests__/__snapshots__/modules.test.ts.snap +++ b/packages/metaschema-modules/__tests__/__snapshots__/modules.test.ts.snap @@ -6,6 +6,7 @@ exports[`db_meta_modules should have all expected module tables 1`] = ` "agent_module", "billing_module", "billing_provider_module", + "certificate_module", "compute_log_module", "config_secrets_module", "config_secrets_org_module", @@ -43,6 +44,9 @@ exports[`db_meta_modules should have all expected module tables 1`] = ` "rate_limits_module", "realtime_module", "rls_module", + "route_module", + "server_definition_module", + "server_deployment_module", "session_secrets_module", "sessions_module", "storage_log_module", @@ -61,8 +65,8 @@ exports[`db_meta_modules should have all expected module tables 1`] = ` exports[`db_meta_modules should verify all module tables exist in metaschema_modules_public schema 1`] = ` { - "moduleTablesCount": 52, - "totalTables": 59, + "moduleTablesCount": 56, + "totalTables": 63, } `; @@ -129,13 +133,13 @@ exports[`db_meta_modules should verify emails_module table structure 1`] = ` exports[`db_meta_modules should verify module table structures have database_id foreign keys 1`] = ` { - "constraintCount": 325432, + "constraintCount": 325436, } `; exports[`db_meta_modules should verify module tables have proper foreign key relationships 1`] = ` { - "constraintCount": 482213, + "constraintCount": 482239, "foreignTables": [ "database", "field", @@ -144,6 +148,7 @@ exports[`db_meta_modules should verify module tables have proper foreign key rel "merkle_store_module", "namespace_module", "schema", + "server_definition_module", "table", ], } diff --git a/packages/metaschema-modules/deploy/schemas/metaschema_modules_public/tables/certificate_module/table.sql b/packages/metaschema-modules/deploy/schemas/metaschema_modules_public/tables/certificate_module/table.sql new file mode 100644 index 00000000..1f11b257 --- /dev/null +++ b/packages/metaschema-modules/deploy/schemas/metaschema_modules_public/tables/certificate_module/table.sql @@ -0,0 +1,66 @@ +-- Deploy schemas/metaschema_modules_public/tables/certificate_module/table to pg + +-- requires: schemas/metaschema_modules_public/schema + +BEGIN; + +CREATE TABLE metaschema_modules_public.certificate_module ( + id uuid PRIMARY KEY DEFAULT uuidv7(), + database_id uuid NOT NULL, + + -- Schema references (if uuid_nil, resolved from schema name or default) + schema_id uuid NOT NULL DEFAULT uuid_nil(), + private_schema_id uuid NOT NULL DEFAULT uuid_nil(), + + -- Optional schema name overrides (used when schema IDs are not provided) + public_schema_name text, + private_schema_name text, + + -- Generated table IDs (populated by the generator) + certificates_table_id uuid NOT NULL DEFAULT uuid_nil(), + certificate_domains_table_id uuid NOT NULL DEFAULT uuid_nil(), + certificate_events_table_id uuid NOT NULL DEFAULT uuid_nil(), + + -- Table names (input to the generator — bare names without scope prefix). + certificates_table_name text NOT NULL DEFAULT 'certificates', + certificate_domains_table_name text NOT NULL DEFAULT 'certificate_domains', + certificate_events_table_name text NOT NULL DEFAULT 'certificate_events', + + -- API routing (get-or-create: if set, schema is added to this API; if NULL, no API is added) + api_name text, + private_api_name text, + + -- Scope: determines the security level for this module instance. + scope text NOT NULL DEFAULT 'platform', + + -- Table name prefix. Auto-derived from scope by the trigger when empty. + prefix text NOT NULL DEFAULT '', + + -- Entity table for RLS + entity_table_id uuid NULL, + + -- Configurable security policies (NULL = use defaults based on scope). + policies jsonb NULL, + + -- Per-table provisions overrides from blueprint config. + provisions jsonb NULL, + + -- Default permissions: permission names auto-granted to new members. + default_permissions text[] DEFAULT NULL, + + -- Constraints + CONSTRAINT certificate_module_db_fkey FOREIGN KEY (database_id) REFERENCES metaschema_public.database (id) ON DELETE CASCADE, + CONSTRAINT certificate_module_schema_fkey FOREIGN KEY (schema_id) REFERENCES metaschema_public.schema (id) ON DELETE CASCADE, + CONSTRAINT certificate_module_private_schema_fkey FOREIGN KEY (private_schema_id) REFERENCES metaschema_public.schema (id) ON DELETE CASCADE, + CONSTRAINT certificate_module_certs_table_fkey FOREIGN KEY (certificates_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE, + CONSTRAINT certificate_module_cert_domains_table_fkey FOREIGN KEY (certificate_domains_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE, + CONSTRAINT certificate_module_events_table_fkey FOREIGN KEY (certificate_events_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE, + CONSTRAINT certificate_module_entity_table_fkey FOREIGN KEY (entity_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE +); + +CREATE INDEX certificate_module_database_id_idx ON metaschema_modules_public.certificate_module ( database_id ); + +-- Unique constraint: one certificate module per database per scope per prefix. +CREATE UNIQUE INDEX certificate_module_unique_scope ON metaschema_modules_public.certificate_module ( database_id, scope, prefix ); + +COMMIT; diff --git a/packages/metaschema-modules/deploy/schemas/metaschema_modules_public/tables/route_module/table.sql b/packages/metaschema-modules/deploy/schemas/metaschema_modules_public/tables/route_module/table.sql new file mode 100644 index 00000000..9bdfb2bd --- /dev/null +++ b/packages/metaschema-modules/deploy/schemas/metaschema_modules_public/tables/route_module/table.sql @@ -0,0 +1,63 @@ +-- Deploy schemas/metaschema_modules_public/tables/route_module/table to pg + +-- requires: schemas/metaschema_modules_public/schema + +BEGIN; + +CREATE TABLE metaschema_modules_public.route_module ( + id uuid PRIMARY KEY DEFAULT uuidv7(), + database_id uuid NOT NULL, + + -- Schema references (if uuid_nil, resolved from schema name or default) + schema_id uuid NOT NULL DEFAULT uuid_nil(), + private_schema_id uuid NOT NULL DEFAULT uuid_nil(), + + -- Optional schema name overrides (used when schema IDs are not provided) + public_schema_name text, + private_schema_name text, + + -- Generated table IDs (populated by the generator) + routes_table_id uuid NOT NULL DEFAULT uuid_nil(), + route_events_table_id uuid NOT NULL DEFAULT uuid_nil(), + + -- Table names (input to the generator — bare names without scope prefix). + routes_table_name text NOT NULL DEFAULT 'routes', + route_events_table_name text NOT NULL DEFAULT 'route_events', + + -- API routing (get-or-create: if set, schema is added to this API; if NULL, no API is added) + api_name text, + private_api_name text, + + -- Scope: determines the security level for this module instance. + scope text NOT NULL DEFAULT 'platform', + + -- Table name prefix. Auto-derived from scope by the trigger when empty. + prefix text NOT NULL DEFAULT '', + + -- Entity table for RLS + entity_table_id uuid NULL, + + -- Configurable security policies (NULL = use defaults based on scope). + policies jsonb NULL, + + -- Per-table provisions overrides from blueprint config. + provisions jsonb NULL, + + -- Default permissions: permission names auto-granted to new members. + default_permissions text[] DEFAULT NULL, + + -- Constraints + CONSTRAINT route_module_db_fkey FOREIGN KEY (database_id) REFERENCES metaschema_public.database (id) ON DELETE CASCADE, + CONSTRAINT route_module_schema_fkey FOREIGN KEY (schema_id) REFERENCES metaschema_public.schema (id) ON DELETE CASCADE, + CONSTRAINT route_module_private_schema_fkey FOREIGN KEY (private_schema_id) REFERENCES metaschema_public.schema (id) ON DELETE CASCADE, + CONSTRAINT route_module_routes_table_fkey FOREIGN KEY (routes_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE, + CONSTRAINT route_module_events_table_fkey FOREIGN KEY (route_events_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE, + CONSTRAINT route_module_entity_table_fkey FOREIGN KEY (entity_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE +); + +CREATE INDEX route_module_database_id_idx ON metaschema_modules_public.route_module ( database_id ); + +-- Unique constraint: one route module per database per scope per prefix. +CREATE UNIQUE INDEX route_module_unique_scope ON metaschema_modules_public.route_module ( database_id, scope, prefix ); + +COMMIT; diff --git a/packages/metaschema-modules/deploy/schemas/metaschema_modules_public/tables/server_definition_module/table.sql b/packages/metaschema-modules/deploy/schemas/metaschema_modules_public/tables/server_definition_module/table.sql new file mode 100644 index 00000000..33c4bdfb --- /dev/null +++ b/packages/metaschema-modules/deploy/schemas/metaschema_modules_public/tables/server_definition_module/table.sql @@ -0,0 +1,70 @@ +-- Deploy schemas/metaschema_modules_public/tables/server_definition_module/table to pg + +-- requires: schemas/metaschema_modules_public/schema + +BEGIN; + +CREATE TABLE metaschema_modules_public.server_definition_module ( + id uuid PRIMARY KEY DEFAULT uuidv7(), + database_id uuid NOT NULL, + + -- Schema references (if uuid_nil, resolved from schema name or default) + schema_id uuid NOT NULL DEFAULT uuid_nil(), + private_schema_id uuid NOT NULL DEFAULT uuid_nil(), + + -- Optional schema name overrides (used when schema IDs are not provided) + public_schema_name text, + private_schema_name text, + + -- Generated table IDs (populated by the generator) + definitions_table_id uuid NOT NULL DEFAULT uuid_nil(), + + -- Table names (input to the generator — bare names without scope prefix). + -- The trigger prepends the scope prefix automatically. + definitions_table_name text NOT NULL DEFAULT 'server_definitions', + + -- API routing (get-or-create: if set, schema is added to this API; if NULL, no API is added) + api_name text, + private_api_name text, + + -- Scope: determines the security level for this module instance. + -- Resolved to a membership_type integer at trigger time via membership_types table. + scope text NOT NULL DEFAULT 'platform', + + -- Table name prefix. Auto-derived from scope by the trigger when empty. + -- Override to create multiple module instances at the same scope. + prefix text NOT NULL DEFAULT '', + + -- Entity table for RLS (NULL for platform-level definitions, entity table for entity-scoped) + entity_table_id uuid NULL, + + -- Configurable security policies (NULL = use defaults based on scope). + -- When provided, replaces the default policy set in apply_server_definition_security. + -- Accepts a JSON array of policy objects: + -- {"$type": "AuthzEntityMembership", "privileges": ["select", "update"], "data": {...}} + policies jsonb NULL, + + -- Per-table provisions overrides from blueprint config. + -- Keys are table keys (definitions). + -- When a key is present, the module trigger skips default security for that table; + -- secure_table_provision applies the custom grants/policies instead. + provisions jsonb NULL, + + -- Default permissions: permission names auto-granted to new members. + -- NULL uses the module's built-in defaults; explicit array overrides them. + default_permissions text[] DEFAULT NULL, + + -- Constraints + CONSTRAINT server_definition_module_db_fkey FOREIGN KEY (database_id) REFERENCES metaschema_public.database (id) ON DELETE CASCADE, + CONSTRAINT server_definition_module_schema_fkey FOREIGN KEY (schema_id) REFERENCES metaschema_public.schema (id) ON DELETE CASCADE, + CONSTRAINT server_definition_module_private_schema_fkey FOREIGN KEY (private_schema_id) REFERENCES metaschema_public.schema (id) ON DELETE CASCADE, + CONSTRAINT server_definition_module_definitions_table_fkey FOREIGN KEY (definitions_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE, + CONSTRAINT server_definition_module_entity_table_fkey FOREIGN KEY (entity_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE +); + +CREATE INDEX server_definition_module_database_id_idx ON metaschema_modules_public.server_definition_module ( database_id ); + +-- Unique constraint: one server definition module per database per scope per prefix. +CREATE UNIQUE INDEX server_definition_module_unique_scope ON metaschema_modules_public.server_definition_module ( database_id, scope, prefix ); + +COMMIT; diff --git a/packages/metaschema-modules/deploy/schemas/metaschema_modules_public/tables/server_deployment_module/table.sql b/packages/metaschema-modules/deploy/schemas/metaschema_modules_public/tables/server_deployment_module/table.sql new file mode 100644 index 00000000..a3106ffd --- /dev/null +++ b/packages/metaschema-modules/deploy/schemas/metaschema_modules_public/tables/server_deployment_module/table.sql @@ -0,0 +1,83 @@ +-- Deploy schemas/metaschema_modules_public/tables/server_deployment_module/table to pg + +-- requires: schemas/metaschema_modules_public/schema +-- requires: schemas/metaschema_modules_public/tables/server_definition_module/table +-- requires: schemas/metaschema_modules_public/tables/namespace_module/table + +BEGIN; + +CREATE TABLE metaschema_modules_public.server_deployment_module ( + id uuid PRIMARY KEY DEFAULT uuidv7(), + database_id uuid NOT NULL, + + -- Schema references (if uuid_nil, resolved from schema name or default) + schema_id uuid NOT NULL DEFAULT uuid_nil(), + private_schema_id uuid NOT NULL DEFAULT uuid_nil(), + + -- Optional schema name overrides (used when schema IDs are not provided) + public_schema_name text, + private_schema_name text, + + -- Generated table IDs (populated by the generator) + deployments_table_id uuid NOT NULL DEFAULT uuid_nil(), + deployment_events_table_id uuid NOT NULL DEFAULT uuid_nil(), + + -- Table names (input to the generator — bare names without scope prefix). + -- The trigger prepends the scope prefix automatically. + deployments_table_name text NOT NULL DEFAULT 'server_deployments', + deployment_events_table_name text NOT NULL DEFAULT 'server_deployment_events', + + -- API routing (get-or-create: if set, schema is added to this API; if NULL, no API is added) + api_name text, + private_api_name text, + + -- Scope: determines the security level for this module instance. + -- Resolved to a membership_type integer at trigger time via membership_types table. + scope text NOT NULL DEFAULT 'app', + + -- Table name prefix. Auto-derived from scope by the trigger when empty. + -- Override to create multiple module instances at the same scope. + prefix text NOT NULL DEFAULT '', + + -- Entity table for RLS (NULL for app-level deployments, entity table for entity-scoped) + entity_table_id uuid NULL, + + -- FK to server_definition_module: which server definitions table deployments reference + server_definition_module_id uuid NULL, + + -- FK to namespace_module: which namespaces table deployments reference + namespace_module_id uuid NULL, + + -- Configurable security policies (NULL = use defaults based on scope). + -- When provided, replaces the default policy set in apply_server_deployment_security. + -- Accepts a JSON array of policy objects: + -- {"$type": "AuthzEntityMembership", "privileges": ["select", "update"], "data": {...}} + policies jsonb NULL, + + -- Per-table provisions overrides from blueprint config. + -- Keys are table keys (deployments, deployment_events). + -- When a key is present, the module trigger skips default security for that table; + -- secure_table_provision applies the custom grants/policies instead. + provisions jsonb NULL, + + -- Default permissions: permission names auto-granted to new members. + -- NULL uses the module's built-in defaults; explicit array overrides them. + default_permissions text[] DEFAULT NULL, + + -- Constraints + CONSTRAINT server_deployment_module_db_fkey FOREIGN KEY (database_id) REFERENCES metaschema_public.database (id) ON DELETE CASCADE, + CONSTRAINT server_deployment_module_schema_fkey FOREIGN KEY (schema_id) REFERENCES metaschema_public.schema (id) ON DELETE CASCADE, + CONSTRAINT server_deployment_module_private_schema_fkey FOREIGN KEY (private_schema_id) REFERENCES metaschema_public.schema (id) ON DELETE CASCADE, + CONSTRAINT server_deployment_module_deployments_table_fkey FOREIGN KEY (deployments_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE, + CONSTRAINT server_deployment_module_events_table_fkey FOREIGN KEY (deployment_events_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE, + CONSTRAINT server_deployment_module_entity_table_fkey FOREIGN KEY (entity_table_id) REFERENCES metaschema_public.table (id) ON DELETE CASCADE, + CONSTRAINT server_deployment_module_server_def_module_fkey FOREIGN KEY (server_definition_module_id) REFERENCES metaschema_modules_public.server_definition_module (id) ON DELETE SET NULL, + CONSTRAINT server_deployment_module_namespace_module_fkey FOREIGN KEY (namespace_module_id) REFERENCES metaschema_modules_public.namespace_module (id) ON DELETE SET NULL +); + +CREATE INDEX server_deployment_module_database_id_idx ON metaschema_modules_public.server_deployment_module ( database_id ); + +-- Unique constraint: one server deployment module per database per scope per prefix. +CREATE UNIQUE INDEX server_deployment_module_unique_scope ON metaschema_modules_public.server_deployment_module ( database_id, scope, prefix ); + +COMMIT; diff --git a/packages/metaschema-modules/pgpm.plan b/packages/metaschema-modules/pgpm.plan index 5257d81b..3e7395a5 100644 --- a/packages/metaschema-modules/pgpm.plan +++ b/packages/metaschema-modules/pgpm.plan @@ -70,3 +70,7 @@ schemas/metaschema_modules_public/tables/i18n_module/table [schemas/metaschema_m schemas/metaschema_modules_public/tables/function_deployment_module/table [schemas/metaschema_modules_public/schema schemas/metaschema_modules_public/tables/function_module/table schemas/metaschema_modules_public/tables/namespace_module/table] 2026-06-11T06:00:00Z devin # add function_deployment_module config table for function-to-namespace deployment binding schemas/metaschema_modules_public/tables/function_module/constraints/one_platform_database [schemas/metaschema_modules_public/tables/function_module/table] 2026-06-11T08:00:00Z devin # enforce at most one platform-scope function_module (unambiguous resolveDatabaseId) schemas/metaschema_modules_public/tables/principal_auth_module/table [schemas/metaschema_modules_public/schema] 2026-06-24T11:15:00Z devin # add principal_auth_module config table for scoped API keys and agent principals +schemas/metaschema_modules_public/tables/server_definition_module/table [schemas/metaschema_modules_public/schema] 2026-06-30T00:00:00Z devin # add server_definition_module config table for persistent server definitions (GraphQL, agentic, WebSocket, etc.) +schemas/metaschema_modules_public/tables/server_deployment_module/table [schemas/metaschema_modules_public/schema schemas/metaschema_modules_public/tables/server_definition_module/table schemas/metaschema_modules_public/tables/namespace_module/table] 2026-06-30T00:00:01Z devin # add server_deployment_module config table for server-to-namespace deployment binding +schemas/metaschema_modules_public/tables/route_module/table [schemas/metaschema_modules_public/schema] 2026-06-30T00:00:02Z devin # add route_module config table for gateway route rules (domain+path to backend target) +schemas/metaschema_modules_public/tables/certificate_module/table [schemas/metaschema_modules_public/schema] 2026-06-30T00:00:03Z devin # add certificate_module config table for TLS certificate lifecycle management diff --git a/packages/metaschema-modules/revert/schemas/metaschema_modules_public/tables/certificate_module/table.sql b/packages/metaschema-modules/revert/schemas/metaschema_modules_public/tables/certificate_module/table.sql new file mode 100644 index 00000000..c9fd3ccb --- /dev/null +++ b/packages/metaschema-modules/revert/schemas/metaschema_modules_public/tables/certificate_module/table.sql @@ -0,0 +1,7 @@ +-- Revert schemas/metaschema_modules_public/tables/certificate_module/table from pg + +BEGIN; + +DROP TABLE IF EXISTS metaschema_modules_public.certificate_module; + +COMMIT; diff --git a/packages/metaschema-modules/revert/schemas/metaschema_modules_public/tables/route_module/table.sql b/packages/metaschema-modules/revert/schemas/metaschema_modules_public/tables/route_module/table.sql new file mode 100644 index 00000000..41bcb8bb --- /dev/null +++ b/packages/metaschema-modules/revert/schemas/metaschema_modules_public/tables/route_module/table.sql @@ -0,0 +1,7 @@ +-- Revert schemas/metaschema_modules_public/tables/route_module/table from pg + +BEGIN; + +DROP TABLE IF EXISTS metaschema_modules_public.route_module; + +COMMIT; diff --git a/packages/metaschema-modules/revert/schemas/metaschema_modules_public/tables/server_definition_module/table.sql b/packages/metaschema-modules/revert/schemas/metaschema_modules_public/tables/server_definition_module/table.sql new file mode 100644 index 00000000..da2928d6 --- /dev/null +++ b/packages/metaschema-modules/revert/schemas/metaschema_modules_public/tables/server_definition_module/table.sql @@ -0,0 +1,7 @@ +-- Revert schemas/metaschema_modules_public/tables/server_definition_module/table from pg + +BEGIN; + +DROP TABLE IF EXISTS metaschema_modules_public.server_definition_module; + +COMMIT; diff --git a/packages/metaschema-modules/revert/schemas/metaschema_modules_public/tables/server_deployment_module/table.sql b/packages/metaschema-modules/revert/schemas/metaschema_modules_public/tables/server_deployment_module/table.sql new file mode 100644 index 00000000..d48a25fc --- /dev/null +++ b/packages/metaschema-modules/revert/schemas/metaschema_modules_public/tables/server_deployment_module/table.sql @@ -0,0 +1,7 @@ +-- Revert schemas/metaschema_modules_public/tables/server_deployment_module/table from pg + +BEGIN; + +DROP TABLE IF EXISTS metaschema_modules_public.server_deployment_module; + +COMMIT; diff --git a/packages/metaschema-modules/sql/metaschema-modules--0.15.5.sql b/packages/metaschema-modules/sql/metaschema-modules--0.15.5.sql index 6f691749..f96d836c 100644 --- a/packages/metaschema-modules/sql/metaschema-modules--0.15.5.sql +++ b/packages/metaschema-modules/sql/metaschema-modules--0.15.5.sql @@ -3466,4 +3466,210 @@ COMMENT ON CONSTRAINT session_credentials_table_fkey ON metaschema_modules_publi COMMENT ON CONSTRAINT principal_entities_table_fkey ON metaschema_modules_public.principal_auth_module IS '@omit'; -COMMENT ON TABLE metaschema_modules_public.principal_auth_module IS 'Provisions the principals subsystem: a principals table, a principal_entities junction table, create/delete mutations, and org API key management. Supports both human-owned principals (AuthzDirectOwner, AuthzHumanOnly) and org-owned principals (AuthzEntityMembership with is_admin). Org principal and org API key functions are only generated when an org-scoped memberships_module exists for the database.'; \ No newline at end of file +COMMENT ON TABLE metaschema_modules_public.principal_auth_module IS 'Provisions the principals subsystem: a principals table, a principal_entities junction table, create/delete mutations, and org API key management. Supports both human-owned principals (AuthzDirectOwner, AuthzHumanOnly) and org-owned principals (AuthzEntityMembership with is_admin). Org principal and org API key functions are only generated when an org-scoped memberships_module exists for the database.'; + +CREATE TABLE metaschema_modules_public.server_definition_module ( + id uuid PRIMARY KEY DEFAULT uuidv7(), + database_id uuid NOT NULL, + schema_id uuid NOT NULL DEFAULT uuid_nil(), + private_schema_id uuid NOT NULL DEFAULT uuid_nil(), + public_schema_name text, + private_schema_name text, + definitions_table_id uuid NOT NULL DEFAULT uuid_nil(), + definitions_table_name text NOT NULL DEFAULT 'server_definitions', + api_name text, + private_api_name text, + scope text NOT NULL DEFAULT 'platform', + prefix text NOT NULL DEFAULT '', + entity_table_id uuid NULL, + policies jsonb NULL, + provisions jsonb NULL, + default_permissions text[] DEFAULT NULL, + CONSTRAINT server_definition_module_db_fkey + FOREIGN KEY(database_id) + REFERENCES metaschema_public.database (id) + ON DELETE CASCADE, + CONSTRAINT server_definition_module_schema_fkey + FOREIGN KEY(schema_id) + REFERENCES metaschema_public.schema (id) + ON DELETE CASCADE, + CONSTRAINT server_definition_module_private_schema_fkey + FOREIGN KEY(private_schema_id) + REFERENCES metaschema_public.schema (id) + ON DELETE CASCADE, + CONSTRAINT server_definition_module_definitions_table_fkey + FOREIGN KEY(definitions_table_id) + REFERENCES metaschema_public."table" (id) + ON DELETE CASCADE, + CONSTRAINT server_definition_module_entity_table_fkey + FOREIGN KEY(entity_table_id) + REFERENCES metaschema_public."table" (id) + ON DELETE CASCADE +); + +CREATE INDEX server_definition_module_database_id_idx ON metaschema_modules_public.server_definition_module (database_id); + +CREATE UNIQUE INDEX server_definition_module_unique_scope ON metaschema_modules_public.server_definition_module (database_id, scope, prefix); + +CREATE TABLE metaschema_modules_public.server_deployment_module ( + id uuid PRIMARY KEY DEFAULT uuidv7(), + database_id uuid NOT NULL, + schema_id uuid NOT NULL DEFAULT uuid_nil(), + private_schema_id uuid NOT NULL DEFAULT uuid_nil(), + public_schema_name text, + private_schema_name text, + deployments_table_id uuid NOT NULL DEFAULT uuid_nil(), + deployment_events_table_id uuid NOT NULL DEFAULT uuid_nil(), + deployments_table_name text NOT NULL DEFAULT 'server_deployments', + deployment_events_table_name text NOT NULL DEFAULT 'server_deployment_events', + api_name text, + private_api_name text, + scope text NOT NULL DEFAULT 'app', + prefix text NOT NULL DEFAULT '', + entity_table_id uuid NULL, + server_definition_module_id uuid NULL, + namespace_module_id uuid NULL, + policies jsonb NULL, + provisions jsonb NULL, + default_permissions text[] DEFAULT NULL, + CONSTRAINT server_deployment_module_db_fkey + FOREIGN KEY(database_id) + REFERENCES metaschema_public.database (id) + ON DELETE CASCADE, + CONSTRAINT server_deployment_module_schema_fkey + FOREIGN KEY(schema_id) + REFERENCES metaschema_public.schema (id) + ON DELETE CASCADE, + CONSTRAINT server_deployment_module_private_schema_fkey + FOREIGN KEY(private_schema_id) + REFERENCES metaschema_public.schema (id) + ON DELETE CASCADE, + CONSTRAINT server_deployment_module_deployments_table_fkey + FOREIGN KEY(deployments_table_id) + REFERENCES metaschema_public."table" (id) + ON DELETE CASCADE, + CONSTRAINT server_deployment_module_events_table_fkey + FOREIGN KEY(deployment_events_table_id) + REFERENCES metaschema_public."table" (id) + ON DELETE CASCADE, + CONSTRAINT server_deployment_module_entity_table_fkey + FOREIGN KEY(entity_table_id) + REFERENCES metaschema_public."table" (id) + ON DELETE CASCADE, + CONSTRAINT server_deployment_module_server_def_module_fkey + FOREIGN KEY(server_definition_module_id) + REFERENCES metaschema_modules_public.server_definition_module (id) + ON DELETE SET NULL, + CONSTRAINT server_deployment_module_namespace_module_fkey + FOREIGN KEY(namespace_module_id) + REFERENCES metaschema_modules_public.namespace_module (id) + ON DELETE SET NULL +); + +CREATE INDEX server_deployment_module_database_id_idx ON metaschema_modules_public.server_deployment_module (database_id); + +CREATE UNIQUE INDEX server_deployment_module_unique_scope ON metaschema_modules_public.server_deployment_module (database_id, scope, prefix); + +CREATE TABLE metaschema_modules_public.route_module ( + id uuid PRIMARY KEY DEFAULT uuidv7(), + database_id uuid NOT NULL, + schema_id uuid NOT NULL DEFAULT uuid_nil(), + private_schema_id uuid NOT NULL DEFAULT uuid_nil(), + public_schema_name text, + private_schema_name text, + routes_table_id uuid NOT NULL DEFAULT uuid_nil(), + route_events_table_id uuid NOT NULL DEFAULT uuid_nil(), + routes_table_name text NOT NULL DEFAULT 'routes', + route_events_table_name text NOT NULL DEFAULT 'route_events', + api_name text, + private_api_name text, + scope text NOT NULL DEFAULT 'platform', + prefix text NOT NULL DEFAULT '', + entity_table_id uuid NULL, + policies jsonb NULL, + provisions jsonb NULL, + default_permissions text[] DEFAULT NULL, + CONSTRAINT route_module_db_fkey + FOREIGN KEY(database_id) + REFERENCES metaschema_public.database (id) + ON DELETE CASCADE, + CONSTRAINT route_module_schema_fkey + FOREIGN KEY(schema_id) + REFERENCES metaschema_public.schema (id) + ON DELETE CASCADE, + CONSTRAINT route_module_private_schema_fkey + FOREIGN KEY(private_schema_id) + REFERENCES metaschema_public.schema (id) + ON DELETE CASCADE, + CONSTRAINT route_module_routes_table_fkey + FOREIGN KEY(routes_table_id) + REFERENCES metaschema_public."table" (id) + ON DELETE CASCADE, + CONSTRAINT route_module_events_table_fkey + FOREIGN KEY(route_events_table_id) + REFERENCES metaschema_public."table" (id) + ON DELETE CASCADE, + CONSTRAINT route_module_entity_table_fkey + FOREIGN KEY(entity_table_id) + REFERENCES metaschema_public."table" (id) + ON DELETE CASCADE +); + +CREATE INDEX route_module_database_id_idx ON metaschema_modules_public.route_module (database_id); + +CREATE UNIQUE INDEX route_module_unique_scope ON metaschema_modules_public.route_module (database_id, scope, prefix); + +CREATE TABLE metaschema_modules_public.certificate_module ( + id uuid PRIMARY KEY DEFAULT uuidv7(), + database_id uuid NOT NULL, + schema_id uuid NOT NULL DEFAULT uuid_nil(), + private_schema_id uuid NOT NULL DEFAULT uuid_nil(), + public_schema_name text, + private_schema_name text, + certificates_table_id uuid NOT NULL DEFAULT uuid_nil(), + certificate_domains_table_id uuid NOT NULL DEFAULT uuid_nil(), + certificate_events_table_id uuid NOT NULL DEFAULT uuid_nil(), + certificates_table_name text NOT NULL DEFAULT 'certificates', + certificate_domains_table_name text NOT NULL DEFAULT 'certificate_domains', + certificate_events_table_name text NOT NULL DEFAULT 'certificate_events', + api_name text, + private_api_name text, + scope text NOT NULL DEFAULT 'platform', + prefix text NOT NULL DEFAULT '', + entity_table_id uuid NULL, + policies jsonb NULL, + provisions jsonb NULL, + default_permissions text[] DEFAULT NULL, + CONSTRAINT certificate_module_db_fkey + FOREIGN KEY(database_id) + REFERENCES metaschema_public.database (id) + ON DELETE CASCADE, + CONSTRAINT certificate_module_schema_fkey + FOREIGN KEY(schema_id) + REFERENCES metaschema_public.schema (id) + ON DELETE CASCADE, + CONSTRAINT certificate_module_private_schema_fkey + FOREIGN KEY(private_schema_id) + REFERENCES metaschema_public.schema (id) + ON DELETE CASCADE, + CONSTRAINT certificate_module_certs_table_fkey + FOREIGN KEY(certificates_table_id) + REFERENCES metaschema_public."table" (id) + ON DELETE CASCADE, + CONSTRAINT certificate_module_cert_domains_table_fkey + FOREIGN KEY(certificate_domains_table_id) + REFERENCES metaschema_public."table" (id) + ON DELETE CASCADE, + CONSTRAINT certificate_module_events_table_fkey + FOREIGN KEY(certificate_events_table_id) + REFERENCES metaschema_public."table" (id) + ON DELETE CASCADE, + CONSTRAINT certificate_module_entity_table_fkey + FOREIGN KEY(entity_table_id) + REFERENCES metaschema_public."table" (id) + ON DELETE CASCADE +); + +CREATE INDEX certificate_module_database_id_idx ON metaschema_modules_public.certificate_module (database_id); + +CREATE UNIQUE INDEX certificate_module_unique_scope ON metaschema_modules_public.certificate_module (database_id, scope, prefix); \ No newline at end of file diff --git a/packages/metaschema-modules/verify/schemas/metaschema_modules_public/tables/certificate_module/table.sql b/packages/metaschema-modules/verify/schemas/metaschema_modules_public/tables/certificate_module/table.sql new file mode 100644 index 00000000..73e31b98 --- /dev/null +++ b/packages/metaschema-modules/verify/schemas/metaschema_modules_public/tables/certificate_module/table.sql @@ -0,0 +1,7 @@ +-- Verify schemas/metaschema_modules_public/tables/certificate_module/table on pg + +BEGIN; + +SELECT verify_table ('metaschema_modules_public.certificate_module'); + +ROLLBACK; diff --git a/packages/metaschema-modules/verify/schemas/metaschema_modules_public/tables/route_module/table.sql b/packages/metaschema-modules/verify/schemas/metaschema_modules_public/tables/route_module/table.sql new file mode 100644 index 00000000..7916ae1c --- /dev/null +++ b/packages/metaschema-modules/verify/schemas/metaschema_modules_public/tables/route_module/table.sql @@ -0,0 +1,7 @@ +-- Verify schemas/metaschema_modules_public/tables/route_module/table on pg + +BEGIN; + +SELECT verify_table ('metaschema_modules_public.route_module'); + +ROLLBACK; diff --git a/packages/metaschema-modules/verify/schemas/metaschema_modules_public/tables/server_definition_module/table.sql b/packages/metaschema-modules/verify/schemas/metaschema_modules_public/tables/server_definition_module/table.sql new file mode 100644 index 00000000..19479eec --- /dev/null +++ b/packages/metaschema-modules/verify/schemas/metaschema_modules_public/tables/server_definition_module/table.sql @@ -0,0 +1,7 @@ +-- Verify schemas/metaschema_modules_public/tables/server_definition_module/table on pg + +BEGIN; + +SELECT verify_table ('metaschema_modules_public.server_definition_module'); + +ROLLBACK; diff --git a/packages/metaschema-modules/verify/schemas/metaschema_modules_public/tables/server_deployment_module/table.sql b/packages/metaschema-modules/verify/schemas/metaschema_modules_public/tables/server_deployment_module/table.sql new file mode 100644 index 00000000..7bb2e775 --- /dev/null +++ b/packages/metaschema-modules/verify/schemas/metaschema_modules_public/tables/server_deployment_module/table.sql @@ -0,0 +1,7 @@ +-- Verify schemas/metaschema_modules_public/tables/server_deployment_module/table on pg + +BEGIN; + +SELECT verify_table ('metaschema_modules_public.server_deployment_module'); + +ROLLBACK; diff --git a/packages/services/__tests__/__snapshots__/services.test.ts.snap b/packages/services/__tests__/__snapshots__/services.test.ts.snap index 892a7a90..068e12f2 100644 --- a/packages/services/__tests__/__snapshots__/services.test.ts.snap +++ b/packages/services/__tests__/__snapshots__/services.test.ts.snap @@ -15,11 +15,13 @@ exports[`services functionality should handle complete meta workflow with servic exports[`services functionality should handle complete meta workflow with services 2`] = ` { + "annotations": {}, "anon_role": "anonymous", "database_id": "[ID]", "dbname": "test-database", "id": "[ID]", "is_public": true, + "labels": {}, "name": "public", "role_name": "authenticated", } @@ -27,11 +29,13 @@ exports[`services functionality should handle complete meta workflow with servic exports[`services functionality should handle complete meta workflow with services 3`] = ` { + "annotations": {}, "anon_role": "administrator", "database_id": "[ID]", "dbname": "test-database", "id": "[ID]", "is_public": true, + "labels": {}, "name": "admin", "role_name": "administrator", } @@ -39,12 +43,14 @@ exports[`services functionality should handle complete meta workflow with servic exports[`services functionality should handle complete meta workflow with services 4`] = ` { + "annotations": {}, "apple_touch_icon": null, "database_id": "[ID]", "dbname": "test-database", "description": "Website Description", "favicon": null, "id": "[ID]", + "labels": {}, "logo": null, "og_image": null, "title": "Website Title", @@ -53,10 +59,13 @@ exports[`services functionality should handle complete meta workflow with servic exports[`services functionality should handle complete meta workflow with services 5`] = ` { + "annotations": {}, "api_id": "[ID]", "database_id": "[ID]", "domain": "pgpm.io", "id": "[ID]", + "labels": {}, + "service_id": null, "site_id": null, "subdomain": "api", } @@ -64,10 +73,13 @@ exports[`services functionality should handle complete meta workflow with servic exports[`services functionality should handle complete meta workflow with services 6`] = ` { + "annotations": {}, "api_id": null, "database_id": "[ID]", "domain": "pgpm.io", "id": "[ID]", + "labels": {}, + "service_id": null, "site_id": "[ID]", "subdomain": "app", } @@ -75,10 +87,13 @@ exports[`services functionality should handle complete meta workflow with servic exports[`services functionality should handle complete meta workflow with services 7`] = ` { + "annotations": {}, "api_id": "[ID]", "database_id": "[ID]", "domain": "pgpm.io", "id": "[ID]", + "labels": {}, + "service_id": null, "site_id": null, "subdomain": "admin", } diff --git a/packages/services/deploy/schemas/services_public/tables/apis/table.sql b/packages/services/deploy/schemas/services_public/tables/apis/table.sql index 1b068295..a68eea52 100644 --- a/packages/services/deploy/schemas/services_public/tables/apis/table.sql +++ b/packages/services/deploy/schemas/services_public/tables/apis/table.sql @@ -14,6 +14,9 @@ CREATE TABLE services_public.apis ( anon_role text NOT NULL DEFAULT 'anonymous', is_public boolean NOT NULL DEFAULT true, + labels jsonb NOT NULL DEFAULT '{}', + annotations jsonb NOT NULL DEFAULT '{}', + -- CONSTRAINT db_fkey FOREIGN KEY (database_id) REFERENCES metaschema_public.database (id) ON DELETE CASCADE, @@ -28,6 +31,8 @@ COMMENT ON COLUMN services_public.apis.dbname IS 'PostgreSQL database name to co COMMENT ON COLUMN services_public.apis.role_name IS 'PostgreSQL role used for authenticated requests'; COMMENT ON COLUMN services_public.apis.anon_role IS 'PostgreSQL role used for anonymous/unauthenticated requests'; COMMENT ON COLUMN services_public.apis.is_public IS 'Whether this API is publicly accessible without authentication'; +COMMENT ON COLUMN services_public.apis.labels IS 'Key/value pairs for selecting and filtering APIs'; +COMMENT ON COLUMN services_public.apis.annotations IS 'Freeform metadata for tooling and operational notes'; CREATE INDEX apis_database_id_idx ON services_public.apis ( database_id ); diff --git a/packages/services/deploy/schemas/services_public/tables/database_settings/table.sql b/packages/services/deploy/schemas/services_public/tables/database_settings/table.sql index ec660def..3712535a 100644 --- a/packages/services/deploy/schemas/services_public/tables/database_settings/table.sql +++ b/packages/services/deploy/schemas/services_public/tables/database_settings/table.sql @@ -26,6 +26,9 @@ CREATE TABLE services_public.database_settings ( -- Extensible JSON for future settings that don't warrant their own column options jsonb NOT NULL DEFAULT '{}'::jsonb, + labels jsonb NOT NULL DEFAULT '{}', + annotations jsonb NOT NULL DEFAULT '{}', + -- CONSTRAINT db_fkey FOREIGN KEY (database_id) REFERENCES metaschema_public.database (id) ON DELETE CASCADE @@ -47,6 +50,8 @@ COMMENT ON COLUMN services_public.database_settings.enable_realtime IS 'Enable r COMMENT ON COLUMN services_public.database_settings.enable_bulk IS 'Enable bulk mutation operations (insert, upsert, update, delete) in the GraphQL API'; COMMENT ON COLUMN services_public.database_settings.enable_i18n IS 'Enable internationalization plugin (localeStrings field, translation table discovery) in the GraphQL API'; COMMENT ON COLUMN services_public.database_settings.options IS 'Extensible JSON for additional settings that do not have dedicated columns'; +COMMENT ON COLUMN services_public.database_settings.labels IS 'Key/value pairs for selecting and filtering database settings'; +COMMENT ON COLUMN services_public.database_settings.annotations IS 'Freeform metadata for tooling and operational notes'; CREATE INDEX database_settings_database_id_idx ON services_public.database_settings (database_id); diff --git a/packages/services/deploy/schemas/services_public/tables/domains/table.sql b/packages/services/deploy/schemas/services_public/tables/domains/table.sql index bf1c12e8..77da24aa 100644 --- a/packages/services/deploy/schemas/services_public/tables/domains/table.sql +++ b/packages/services/deploy/schemas/services_public/tables/domains/table.sql @@ -13,18 +13,20 @@ CREATE TABLE services_public.domains ( api_id uuid, site_id uuid, + service_id uuid, subdomain hostname, domain hostname, + labels jsonb NOT NULL DEFAULT '{}', + annotations jsonb NOT NULL DEFAULT '{}', + -- CONSTRAINT db_fkey FOREIGN KEY (database_id) REFERENCES metaschema_public.database (id) ON DELETE CASCADE, CONSTRAINT api_fkey FOREIGN KEY (api_id) REFERENCES services_public.apis (id) ON DELETE CASCADE, CONSTRAINT site_fkey FOREIGN KEY (site_id) REFERENCES services_public.sites (id) ON DELETE CASCADE, CONSTRAINT one_route_chk CHECK ( - (api_id IS NULL AND site_id IS NULL) OR - (api_id IS NULL AND site_id IS NOT NULL) OR - (api_id IS NOT NULL AND site_id IS NULL) + num_nonnulls(api_id, site_id, service_id) <= 1 ), UNIQUE ( subdomain, domain ) ); @@ -33,7 +35,10 @@ COMMENT ON TABLE services_public.domains IS 'DNS domain and subdomain routing: m COMMENT ON COLUMN services_public.domains.id IS 'Unique identifier for this domain record'; COMMENT ON COLUMN services_public.domains.database_id IS 'Reference to the metaschema database this domain belongs to'; COMMENT ON COLUMN services_public.domains.api_id IS 'API endpoint this domain routes to (mutually exclusive with site_id)'; -COMMENT ON COLUMN services_public.domains.site_id IS 'Site this domain routes to (mutually exclusive with api_id)'; +COMMENT ON COLUMN services_public.domains.site_id IS 'Site this domain routes to (mutually exclusive with api_id and service_id)'; +COMMENT ON COLUMN services_public.domains.service_id IS 'Server deployment this domain routes to (mutually exclusive with api_id and site_id)'; +COMMENT ON COLUMN services_public.domains.labels IS 'Key/value pairs for selecting and filtering domains'; +COMMENT ON COLUMN services_public.domains.annotations IS 'Freeform metadata for tooling and operational notes'; COMMENT ON COLUMN services_public.domains.subdomain IS 'Subdomain portion of the hostname'; COMMENT ON COLUMN services_public.domains.domain IS 'Root domain of the hostname'; @@ -43,4 +48,6 @@ CREATE INDEX domains_api_id_idx ON services_public.domains ( api_id ); CREATE INDEX domains_site_id_idx ON services_public.domains ( site_id ); +CREATE INDEX domains_service_id_idx ON services_public.domains ( service_id ); + COMMIT; diff --git a/packages/services/deploy/schemas/services_public/tables/sites/table.sql b/packages/services/deploy/schemas/services_public/tables/sites/table.sql index 149a7178..9a016b52 100644 --- a/packages/services/deploy/schemas/services_public/tables/sites/table.sql +++ b/packages/services/deploy/schemas/services_public/tables/sites/table.sql @@ -18,6 +18,9 @@ CREATE TABLE services_public.sites ( -- do we need this? dbname text NOT NULL DEFAULT current_database(), + labels jsonb NOT NULL DEFAULT '{}', + annotations jsonb NOT NULL DEFAULT '{}', + -- CONSTRAINT db_fkey FOREIGN KEY (database_id) REFERENCES metaschema_public.database (id) ON DELETE CASCADE, CONSTRAINT max_title CHECK ( character_length(title) <= 120 ), @@ -34,6 +37,8 @@ COMMENT ON COLUMN services_public.sites.favicon IS 'Browser favicon attachment'; COMMENT ON COLUMN services_public.sites.apple_touch_icon IS 'Apple touch icon for iOS home screen bookmarks'; COMMENT ON COLUMN services_public.sites.logo IS 'Primary logo image for the site'; COMMENT ON COLUMN services_public.sites.dbname IS 'PostgreSQL database name this site connects to'; +COMMENT ON COLUMN services_public.sites.labels IS 'Key/value pairs for selecting and filtering sites'; +COMMENT ON COLUMN services_public.sites.annotations IS 'Freeform metadata for tooling and operational notes'; CREATE INDEX sites_database_id_idx ON services_public.sites ( database_id );