From af752b0298a14e36f1d3d739fbfbe3b73d1f8372 Mon Sep 17 00:00:00 2001 From: "Gavin M. Roy" Date: Tue, 7 Jul 2026 17:07:15 -0400 Subject: [PATCH] Allow every object type as a dependency key (L8) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `ObjectType::from_plural_key` already recognized all 25 object types, but schemata/dependencies.yml listed only nine plural keys under `additionalProperties: false`, so a `dependencies:` block naming an aggregate, collation, event_trigger, materialized_view, publication, server, subscription, user, or user_mapping was rejected at validation before the loader ever saw it — you could depend on `views` but not `materialized_views`. This was carried over from Python's OBJ_KEYS; per the maintainer, 2.0 need not preserve that limitation. Add the nine missing keys (schema-qualified pattern for the schema-scoped types, bare for the schemaless ones). Resolution already works: the loader's `index_key` normalizes the namespace to None for schemaless types on both insert and lookup, and `from_plural_key` maps the keys. A new validate test confirms the widened keys pass and unknown keys are still rejected. Co-Authored-By: Claude Opus 4.8 (1M context) --- schemata/dependencies.yml | 36 ++++++++++++++++++++++++++++++++++++ src/project/validate.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/schemata/dependencies.yml b/schemata/dependencies.yml index 0c30da1..ae13973 100644 --- a/schemata/dependencies.yml +++ b/schemata/dependencies.yml @@ -4,10 +4,22 @@ $id: https://pglifecycle.readthedocs.io/en/stable/schemata/dependencies.html title: Dependencies type: object properties: + aggregates: + type: array + propertyNames: + pattern: ^([A-Za-z0-9_\-]+)\.([A-Za-z0-9_\-]+)$ + collations: + type: array + propertyNames: + pattern: ^([A-Za-z0-9_\-]+)\.([A-Za-z0-9_\-]+)$ domains: type: array propertyNames: pattern: ^([A-Za-z0-9_\-]+)\.([A-Za-z0-9_\-]+)$ + event_triggers: + type: array + propertyNames: + pattern: ^([A-Za-z0-9_\-]+)$ extensions: type: array propertyNames: @@ -24,10 +36,26 @@ properties: type: array propertyNames: pattern: ^([A-Za-z0-9_\-]+)$ + materialized_views: + type: array + propertyNames: + pattern: ^([A-Za-z0-9_\-]+)\.([A-Za-z0-9_\-]+)$ + publications: + type: array + propertyNames: + pattern: ^([A-Za-z0-9_\-]+)$ sequences: type: array propertyNames: pattern: ^([A-Za-z0-9_\-]+)\.([A-Za-z0-9_\-]+)$ + servers: + type: array + propertyNames: + pattern: ^([A-Za-z0-9_\-]+)$ + subscriptions: + type: array + propertyNames: + pattern: ^([A-Za-z0-9_\-]+)$ tables: type: array propertyNames: @@ -36,6 +64,14 @@ properties: type: array propertyNames: pattern: ^([A-Za-z0-9_\-]+)\.([A-Za-z0-9_\-]+)$ + user_mappings: + type: array + propertyNames: + pattern: ^([A-Za-z0-9_\-]+)$ + users: + type: array + propertyNames: + pattern: ^([A-Za-z0-9_\-]+)$ views: type: array propertyNames: diff --git a/src/project/validate.rs b/src/project/validate.rs index 4118203..11fe8ff 100644 --- a/src/project/validate.rs +++ b/src/project/validate.rs @@ -126,4 +126,35 @@ mod tests { assert!(items.get("properties").is_some()); assert!(items.get("$package_schema").is_none()); } + + #[test] + fn dependencies_schema_accepts_every_object_type() { + // the dependencies schema previously listed only nine plural + // keys with additionalProperties: false, so a dependency on an + // aggregate/collation/event_trigger/materialized_view/etc. failed + // validation even though the loader recognized the key + let schema = load_schema("dependencies").unwrap(); + let validator = jsonschema::validator_for(&schema).unwrap(); + let widened = json!({ + "aggregates": ["test.agg"], + "collations": ["test.c"], + "event_triggers": ["et"], + "materialized_views": ["test.mv"], + "publications": ["p"], + "servers": ["s"], + "subscriptions": ["sub"], + "user_mappings": ["um"], + "users": ["u"], + }); + assert!( + validator.iter_errors(&widened).next().is_none(), + "widened dependency keys should validate" + ); + // additionalProperties: false must still reject unknown keys + let unknown = json!({"bogus_type": ["x"]}); + assert!( + validator.iter_errors(&unknown).next().is_some(), + "unknown dependency keys must still be rejected" + ); + } }