Skip to content

feat(engine): enforced config groups — opt-in governance guardrail#918

Merged
hugocorreia90 merged 1 commit into
mainfrom
feat/group-enforce
Jun 17, 2026
Merged

feat(engine): enforced config groups — opt-in governance guardrail#918
hugocorreia90 merged 1 commit into
mainfrom
feat/group-enforce

Conversation

@hugocorreia90

Copy link
Copy Markdown
Contributor

What

Adds enforce = true to a config group (built on #917). When set, the group's fields become binding rather than defaults: a member model that locally pins a field the group controls — its target schema or its strategy — fails the load with ModelError::GroupOverride, instead of silently routing or materializing itself differently from the rest of the group.

# models/groups/regulated.toml
enforce = true
schema_template = "mart_{region}"
[strategy]
type = "merge"
unique_key = ["id"]

A member that tries to escape:

Error: model 'orders' overrides 'target.schema', which its enforced group
'regulated' controls; remove the local override or set the group's enforce = false

Design

  • The check rides in the shared resolve_model_config using sidecar provenance (raw.<field>.is_some() ⇒ the model set it locally) — no provenance plumbing, no new compiler pass.
  • Because it's in the shared resolver, both the .sql loader and the .rocky salsa loader enforce with no extra wiring — verified end-to-end through rocky emit-sql (the compile path) rejecting an override.
  • Strictly opt-in: without enforce, groups stay overridable defaults (existing behavior unchanged). A model under an enforced group still supplies its own [args] and any field the group doesn't set (e.g. target.catalog).

Tests

enforced_group_rejects_local_override (both strategy and target.schema); enforcement_is_opt_in_and_allows_conforming_models (conforming model under an enforced group loads; the same override under a non-enforced group is allowed).

Context

This is the governance "teeth" of the config-groups keystone (C4): a set of models can be made to share routing + materialization by construction. Framed neutrally — it's "a model can't silently escape its group's config," with no domain-specific invariants. Shared tags (→ Dagster) and per-mode computed keys remain follow-ups.

cargo fmt + clippy --all-targets clean; no codegen/schema drift.

…uardrail

Adds `enforce = true` to a config group. When set, the group's fields are
binding rather than defaults: a member model that locally pins a field the group
controls (its target `schema` or its `strategy`) fails the load with
`ModelError::GroupOverride`, instead of silently routing or materializing itself
differently from the rest of the group.

The check rides in `resolve_model_config` using sidecar provenance
(`raw.<field>.is_some()` ⇒ the model set it locally), so both the `.sql` and
`.rocky` loaders enforce through the shared resolver with no extra wiring —
verified end-to-end through `rocky emit-sql` (compile path) rejecting an
override.

Enforcement is strictly opt-in: without `enforce`, groups stay overridable
defaults (existing behavior unchanged). A model under an enforced group still
supplies its own `[args]` and any field the group doesn't set (e.g.
`target.catalog`). This is the governance guarantee for the fan-out — a set of
models can be made to share routing and materialization by construction.

Documented in reference/model-format.md.
@hugocorreia90 hugocorreia90 merged commit 38aeeda into main Jun 17, 2026
13 checks passed
@hugocorreia90 hugocorreia90 deleted the feat/group-enforce branch June 17, 2026 22:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant