feat(engine): model-level governance tags inherited from config groups#920
Merged
Conversation
Add a `[tags]` block to models and config groups so a governance attribute (domain, tier, owner, …) declared once on a group lands on its whole fan-out, with per-model overrides. - `GroupConfig.tags` + `RawModelConfig.tags` + `ModelConfig.tags` (all `#[serde(default)]`), merged in `resolve_model_config` — the shared `.sql`/`.rocky` resolution chokepoint — so both loaders inherit for free. Precedence mirrors schema/strategy: model `[tags]` override the group baseline per key (sidecar > group) without dropping the rest. - Surfaced on `rocky compile --output json` as `models_detail[].tags` (new `ModelDetail.tags`); regenerated schema + Pydantic + TS bindings via the codegen cascade. Lets `dagster-rocky` project them onto each derived asset's Dagster tags (follow-up PR). - Dual-path proof: unit tests on the `.sql` path (merge precedence, model-only tags) and a salsa-loader regression on the `.rocky` path, plus an end-to-end `rocky compile` check that a `.sql` and a `.rocky` member of the same group both resolve the group's tags. Docs: `[tags]` and "Group tags" sections in the model-format reference.
hugocorreia90
added a commit
that referenced
this pull request
Jun 18, 2026
…#921) * feat(dagster): project model governance tags onto derived asset specs Completes the C4 governed-materialization fan-out end-to-end: a model's resolved `[tags]` (its own, inherited from its config group) now reach the Dagster asset. - sdk: add `tags: dict[str, str] | None` to the hand-written `rocky_sdk.types.ModelDetail` (the curated model `parse_rocky_output` builds and dagster consumes). Populated automatically from the engine's `rocky compile` JSON `models_detail[].tags`. - dagster: `RockyDagsterTranslator.get_model_tags` projects governance tags as *first-class* Dagster tags (usable in `tag:domain=finance` selection), alongside the synthesized `rocky/*` metadata. Keys are sanitized to the Dagster-valid charset; synthesized keys keep their `/`, so a governance tag can never clobber Rocky's own metadata. Read via `getattr` so an older rocky-sdk degrades to "no governance tags" instead of crashing. Tests: sdk parse (tags present / absent→None); dagster build_model_specs projection, no-tags case, and key-sanitization / no-clobber edge cases. Release ordering: ship rocky-sdk (new field) before the dagster-rocky cut that floors on it. * docs(changelog): record model governance tags across engine, sdk, dagster Engine [Unreleased] gets the [tags] + group-inheritance entry (#920); sdk + dagster [Unreleased] get the ModelDetail.tags field and the asset-spec projection (#921).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a model-level
[tags]block, inheritable from config groups, so a governance attribute declared once on a group lands on its whole fan-out — completing the engine half of the governed-materialization story (the orchestrator half lands in a follow-updagster-rockyPR).→
rocky compile --output jsonnow emits per-modelmodels_detail[].tags:How
GroupConfig.tags+RawModelConfig.tags+ModelConfig.tags(all#[serde(default)]), merged inresolve_model_config— the shared.sql/.rockyresolution chokepoint, so both loaders inherit for free (the same placeenforcelives). Precedence mirrors schema/strategy: the model's own[tags]override the group baseline per key (sidecar > group) without dropping the rest of the group's tags.ModelDetail.tagson therocky compileJSON output; regenerated schema + Pydantic (rocky-sdk) + TS (vscode) bindings viajust codegen.ModelConfigliteral sites updated (noDefault; mechanical empty-map adds).Verification
cargo test --all-featuresgreen across rocky-core / rocky-compiler / rocky-cli / rocky-ai / rocky-server.cargo fmt --check+cargo clippy --all-targets --all-featuresclean..sqlonly" gap): unit tests on the.sqlpath (merge precedence + model-only tags), a salsa-loader regression on the.rockypath, and an end-to-endrocky compilecheck that a.sqland a.rockymember of the same group both resolve the group's tags.Follow-up
dagster-rockytranslator readsModelDetail.tagsand projects them onto the derivedAssetSpec.tags(separate PR — the JSON contract this PR establishes is the seam).🤖 Generated with Claude Code