fix(ingestion): drop always-NULL class_people.org_unit_id column - #2044
fix(ingestion): drop always-NULL class_people.org_unit_id column#2044mitasovr wants to merge 6 commits into
Conversation
`silver.class_people.org_unit_id Nullable(UUID)` was hardcoded to NULL by all
four HR staging models and had no producer anywhere: no `org_units` table
exists in ClickHouse or MariaDB, so no org-unit UUID is ever minted. The
org-chart domain design (`docs/domain/org-chart/specs/`) that would own such
UUIDs is unimplemented.
The column was reported by a data-quality audit as "high in bronze inputs but
0% in silver — lost in transform". It is neither: bronze carries `department`
(a name), not a UUID, and MariaDB `identity.org_chart` is a
`child_person_id -> parent_person_id` supervisor edge table with no
`org_unit_id` column at all.
Everything downstream that is called `org_unit_id` is already a department
NAME string, sourced from `department`:
bronze department
-> insight.people.org_unit_id (argMax(department))
-> insight.team_member (FROM insight.people)
-> frontend RawTeamMemberRow.org_unit_id (typed `string | null`)
-> frontend sends back `org_unit_id in ('Engineering', ...)`
The sole reader of the silver column was
`gold/metric_entity_cohorts_current.sql`, which coalesced past it to
`department_name`. That coalesce was also a latent trap: because it preferred
`org_unit_id`, populating the column would have flipped cohort ids from
department names to UUIDs while `insight.people` and the frontend kept using
names, silently emptying every peer metric. Dropping the column removes the
trap and stops the audit false positive from recurring.
Verified on the virtuozzo cluster: the rewritten cohort query returns 1402
rows / 63 cohorts / 1402 entities, and the symmetric set difference of
(tenant_id, entity_id, cohort_id) against the current view is 0 in both
directions. All four staging models still project an identical 25-column set,
satisfying cpt-dataflow-constraint-staging-class-column-types-match.
Refs: docs/domain/ingestion-data-flow/specs/DESIGN.md,
docs/domain/org-chart/specs/DESIGN.md
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Roman Mitasov <Roman.Mitasov@constructor.tech>
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
💤 Files with no reviewable changes (1)
📝 WalkthroughWalkthroughHR directory staging views and the Silver ChangesOrg unit cohort derivation
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
The committed DDL snapshot landed upstream (via the active-directory bootstrap-db fix) while `class_people.org_unit_id` still existed, so it declares a column this branch removes: - `connectors-ddl/silver.sql`: drop `org_unit_id Nullable(UUID)` from `silver.class_people`. - `connectors-ddl/insight.sql`: `metric_entity_cohorts_current` now reads `nullIf(department_name, '')` instead of coalescing the dropped column ahead of the department name. Every other `org_unit_id` in the snapshot is left untouched and is a different thing: `insight.sql` occurrences are the department NAME string (`String` columns, `argMax(department)`, `coalesce(department_name, 'Unknown')`), and `person.sql` occurrences belong to `person.persons`, the identity-owned golden record created by the init-identity migration. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Roman Mitasov <Roman.Mitasov@constructor.tech>
…' into fix/drop-dead-org-unit-id-column
|
Superseded by #2124 — recreated with the branch in this repository instead of a fork, so the full CI suite runs on it. Same commits, plus a sync of the committed Closing this one; please review #2124. |
Problem
A data-quality audit flagged
silver.class_people.org_unit_idas "high in bronze inputs but 0% populated in silver — lost in transform", citing MariaDBidentity.org_chart(252 rows) as proof that org data exists.That framing is wrong on all three counts:
CAST(NULL AS Nullable(UUID)) AS org_unit_id, following the type-uniformity convention indocs/domain/ingestion-data-flow/specs/DESIGN.md.SELECT … FROM system.tables WHERE name ILIKE '%org_unit%'returns nothing in ClickHouse, and there is no such table in MariaDB either. The org-chart design (docs/domain/org-chart/specs/) that would mint these UUIDs is unimplemented — its PRD even claims all its tables live in ClickHouse, which is not the case.identity.org_chartis not an org-unit table. Its columns arechild_person_id→parent_person_id— a person-to-supervisor edge graph rebuilt by the identity-resolution service from BambooHRsupervisorEmail. It has noorg_unit_idcolumn, so it could never have been the source.What
org_unit_idactually means downstreamEverything in the serving path called
org_unit_idis already a department name string:Live values on virtuozzo are
VZ - R&D - Engineering,VZ - Support, etc. The frontend round-trips the value and never sees the silver column; the four CRM gold views likewise usecoalesce(department_name, 'Unknown') AS org_unit_id.The latent trap this removes
The only reader of the silver column was
gold/metric_entity_cohorts_current.sql:Because that coalesce preferred
org_unit_id, anyone "fixing" the reported 0% by populating the column would have flippedcohort_idfrom department names to UUIDs, whileinsight.peopleand the frontend kept sending names — silently emptying every peer metric tenant-wide. Dropping the column removes that possibility and stops the audit false positive from recurring. The replacement expression carries a comment warning against reintroducing a UUID branch without migratinginsight.peopleand the frontend in the same change.Changes
active_directory__to_class_people.sqlorg_unit_idprojectionbamboohr__to_class_people.sqlorg_unit_idprojectionms_entra__to_class_people.sqlorg_unit_idprojectionworkday__to_class_people.sqlorg_unit_idprojectiongold/metric_entity_cohorts_current.sqlcoalesce(...)→nullIf(department_name, '')No DDL migration is needed:
silver.class_peopleismaterialized='table', so dbt rebuilds it without the column.Verification
(tenant_id, entity_id, cohort_id)is 0 in both directions.cpt-dataflow-constraint-staging-class-column-types-match(removing the column from only some models would raiseCode: 386).org_unit_idno longer appears insrc/ingestion/connectors/,silver/, orgold/outside explanatory comments. All ~40p.org_unit_idoccurrences inscripts/migrations/resolve toinsight.people, not silver.insight-front, 51 occurrences): typedstring | null, documented as "Department the member belongs to", zero UUID validation or parsing.dbt parsewas not run locally with the project's engine — the available binary isdbt-fusion 2.0.0-preview.200while the project pinsdbt-core>=1.9+dbt-clickhouse, and fusion reports ~1000 pre-existing errors in unrelated files. None of the five changed files appear among them; CI will validate on the correct engine.Out of scope (found while investigating)
insight.peopleis bamboohr-only. It readsbronze_bamboohr.employeesdirectly (bronze → gold, skipping silver), so a tenant on ms-entra, workday, or active-directory gets an emptyinsight.peopleand loses all org attribution. Virtuozzo only survives because BambooHR is its sole HR source. Repointing it at silver would need a fix forsupervisor_emailfirst:class_people.manager_person_idholdssupervisorEId(an ID, not an email).active_directory__to_class_people.sqlprojectsmanager_person_idasNullable(UUID)while the other three sources and the live column areNullable(String)— this will raiseCode: 386once active-directory runs alongside another HR source.org_unit_id/person_id$filtervalues inanalytics/src/api/handlers.rs(a TODO at the injection site), whichdocs/components/backend/specs/analytics-views-api.mdrequires. Tenant isolation is enforced; within-tenant cross-team reads are not.Refs:
docs/domain/ingestion-data-flow/specs/DESIGN.md,docs/domain/org-chart/specs/DESIGN.md🤖 Generated with Claude Code
Summary by CodeRabbit
cohort_idfromdepartment_name.org_unit_idfield fromclass_peopleoutputs across HR directory integrations, aligning schemas and downstream cohort behavior.