Tuva 1.0.0 Release Notes
Tuva 1.0 brings a modular architecture, a richer common data model, and a new Data Quality framework to the open-source project. Teams can build on a consistent foundation for claims and clinical data, install the analytical packages they need, and understand the quality of their inputs before putting results to work.
This release includes breaking changes. The upgrade guide below covers installation, Input Layer mappings, configuration, changed identifiers and grains, and validation against Tuva 0.18.0.
Release Highlights
1. Modular Architecture
Tuva Core now owns the shared transformation path: the Input Layer, normalization, Claims Preprocessing, the Core Data Model, and optional Data Quality. Six analytical Data Marts plus FHIR Preprocessing and Semantic Layer are independently installable dbt packages, with separate repositories and release lifecycles. Each asset-bearing package owns its reference data.
This makes it easier to start with the foundation you need and add capabilities such as risk adjustment, quality measures, or clinical grouping as your use cases grow. For now, install Core and selected packages from their v1.0.0 GitHub tags. The dbt Hub release will follow in the near future. See the package architecture and complete installation example.
2. Core Data Model Enhancements
The common model expands from 16 to 18 tables and adds reusable analytical capabilities that previously required more downstream work:
- Cost & Utilization: New
core.costandcore.utilizationtables organize paid and allowed amounts and claims-derived encounter counts at the member-month coverage grain. Join them tocore.member_monthusingmember_month_idto analyze spending and use together while retaining payer, plan, member, and source context. - Condition & Procedure Groupers: Core exposes
condition_familyandcondition_name, plusprocedure_familyandprocedure_name, so analysts can work with understandable clinical groupings alongside individual codes. Condition grouping covers supported normalized ICD-10-CM and SNOMED CT mappings; procedure grouping covers supported ICD-10-PCS mappings. Unmapped codes retain null groupings. The separate CCSR package remains available for AHRQ classifications. - Provider Attribution: Attribution moves into Claims Preprocessing and makes claims-based primary-care assignments available to member-month analytics. Teams can review a transparent CMS-style methodology and combine calculated assignments with mapped payer attribution for provider panels, cost, quality, and outreach. It is opt-in and requires the provider-attribution Input Layer contract.
- Medication Table:
core.medicationcombines clinical medication records and adjudicated pharmacy-claim lines in one source-aware table. CodeRx Open supplies shared NDC, RxNorm, and ATC enrichment, making medication analysis more consistent across payer and clinical data. The key(medication_id, source_type, data_source)preserves the distinction between those records.
The release also strengthens source-scoped identifiers, open-ended eligibility, and direct Input-to-Core extension columns. See the Core Data Model changes before updating downstream joins or extracts.
3. New Data Quality Framework
Input Data Quality becomes a queryable framework with two clear responsibilities. Structural Data Quality checks table population, columns, types, and primary keys. Logical Data Quality provides 314 checks for missing, invalid, temporal, referential, and inconsistent values and relationships.
Stable result tables support review by source, table, check, and severity. Optional failure keys help trace aggregate findings to affected records, and pass, failure, and not-applicable outcomes preserve what each check actually evaluated. Enable the framework with data_quality_enabled: true; it is disabled by default. See the Data Quality changes and tutorial.
4. dbt Core 2.0 and Fusion Support
The package ecosystem supports the transition to dbt Core 2.0 and Fusion while retaining a minimum dbt version of 1.10.5. Compatibility work covers package resolution, shared macros, parsing, seed loading, and execution across the combined Core and standalone-package graph.
The release includes separate DuckDB validation on dbt Core 2.0.0-beta.2 and Fusion 2.0.0-preview.218, alongside Core 1.x validation. The five cloud-warehouse release builds use dbt Core 1.11.14. See tested versions and scope when choosing an adapter and runtime.
5. SQL Server & AWS Athena Compatibility
Tuva 1.0 adds adapter-specific SQL and data-loading paths for SQL Server 2022 and AWS Athena engine v3, extending the portability of the project to more deployment environments. SQL Server loads published assets from Tuva’s Azure mirror using native decompression and CSV parsing. Athena reads the published S3 assets through external CSV tables and materializes typed seed tables.
These paths are new compatibility work, with package-specific limitations. The release does not establish full end-to-end support for every mart on either adapter. Review the warehouse setup and validation scope before planning a deployment.
Upgrade to Tuva 1.0
These instructions describe how to upgrade a project from Tuva 0.18.0 to Tuva 1.0.0. Continue using the connector or root dbt project that currently runs Tuva, but make the upgrade changes in a separate copy and build every 1.0 output in the separate output location defined below. Keep the 0.18.0 project and its output location available until post-upgrade validation is complete.
Compatibility and Prerequisites
Tuva Core requires dbt >=1.10.5,<3.0.0. The supported warehouse set is Snowflake, BigQuery, Databricks, Microsoft Fabric, Redshift, and DuckDB. Core 2.0 and Fusion have separate DuckDB validation; this is not a claim that those runtimes were tested on every supported warehouse. See dbt compatibility for the tested scope.
Upgrade Steps
The following terms are used throughout these steps:
- 0.18 project: The connector or root dbt project that currently runs Tuva 0.18.0.
- 1.0 project: A complete copy of the 0.18 project where you will make the Tuva 1.0.0 changes.
- 0.18 output location: The database, catalog, or Google Cloud project where the 0.18 project currently writes its Tuva models.
- 1.0 output location: A new, empty database, catalog, or Google Cloud project used only for the 1.0 project. Use a separate DuckDB file for a local DuckDB upgrade. The profile settings depend on the adapter, as specified in Step 2.
- source tables: The tables that the connector currently reads and maps into the Tuva Input Layer.
- 1.0 target: A copy of the 0.18 project's dbt target, named
tuva_1_0, that writes to the 1.0 output location.
1. Create the 1.0 project. Copy the entire directory that contains the 0.18 project's dbt_project.yml. The copy must include the project's packages.yml, models, macros, and project variables. Do not edit or delete the 0.18 project. Make every change in the 1.0 project, and run every remaining upgrade command from the 1.0 project. Do not delete or replace the 0.18 output location until Post-Upgrade Validation is complete.
2. Create the 1.0 output location and target. Create a new, empty output location in the same data warehouse account: a database for Snowflake or Redshift; a Warehouse for Fabric; a catalog for Databricks; a Google Cloud project for BigQuery; or a new database file for DuckDB. Give the dbt user permission to create schemas and relations in it. Record its exact name as <1.0-output-location>. Then complete these steps in order:
- Open the
profiles.ymlfile used by the 0.18 project. If you do not know its location, rundbt debug --config-dirfrom the 0.18 project. - Under
outputs:, copy the target used by the 0.18 project and name the copytuva_1_0. Configure the copied target for the new destination:databasefor Snowflake,catalogfor Databricks,projectfor BigQuery,dbnamefor Redshift, orpathfor DuckDB. For Fabric, use the new Warehouse database and SQL endpoint. Update any destination-specific connection identifiers, permissions, and authentication settings required by your adapter; retain the existing source credentials where appropriate. - In the 1.0 project, inspect every connector
sources:block. If a source omitsdatabasebecause it inherits the 0.18 target's database, catalog, or project, adddatabaseand set it to that source's original location. Do not point any source to<1.0-output-location>; both projects must read the same source tables. Verify that the adapter can read the original source location from the new target. On Redshift this requires an RA3 or Serverless environment,ra3_node: true, and cross-database privileges. For DuckDB, attach the unchanged source database or read the same source files in both projects. - Inspect
dbt_project.yml, model, seed, and snapshot configurations, and macros for output-location overrides. Update every+databaseor model, seed, or snapshotdatabaseconfiguration,tuva_databasevariable,cms_chronic_conditions_databasevariable, and customgenerate_database_namemacro that would otherwise write a 1.0 relation to the 0.18 output location. Standalone packages read Tuva Core models throughref()and do not require input-database variables. - From the 1.0 project, run
dbt debug --target tuva_1_0. Continue only after dbt reportsAll checks passed!.
3. Replace and install the package dependencies. Remove retired Tuva package dependencies. The following packages.yml installs Tuva Core and all eight standalone packages at v1.0.0. Remove optional packages you do not use, while retaining the dependencies of packages you keep. The root connector owns this complete dependency set; install each Tuva package once.
dbt supports Git packages with a tagged revision. GitHub tags are the current installation path while we prepare the dbt Hub release, which will follow in the near future. Use the published v1.0.0 tag from each repository. If a requested tag does not resolve, check that repository's Releases page and stop; substituting main changes the code being installed. Do not declare the same package through both package: and git: entries.
packages:
- git: "https://github.com/tuva-health/tuva-core.git"
revision: "v1.0.0"
- git: "https://github.com/tuva-health/ahrq_quality_indicators.git"
revision: "v1.0.0"
- git: "https://github.com/tuva-health/ccsr.git"
revision: "v1.0.0"
- git: "https://github.com/tuva-health/cms_chronic_conditions.git"
revision: "v1.0.0"
- git: "https://github.com/tuva-health/cms_hcc.git"
revision: "v1.0.0"
- git: "https://github.com/tuva-health/fhir_preprocessing.git"
revision: "v1.0.0"
- git: "https://github.com/tuva-health/nyu_ed_classification.git"
revision: "v1.0.0"
- git: "https://github.com/tuva-health/quality_measures.git"
revision: "v1.0.0"
- git: "https://github.com/tuva-health/semantic-layer.git"
revision: "v1.0.0"
Installing Semantic Layer requires Tuva Core, AHRQ Quality Indicators, CCSR, CMS HCC, NYU ED Classification, and Quality Measures as side-by-side dependencies. After editing packages.yml, run:
dbt deps
Keep the resulting package-lock.yml with the 1.0 project so later installations resolve the same dependencies. Verify each installed dbt_project.yml identifies the expected package and version before continuing.
4. Update the existing Input Layer mappings. The 1.0 Input Layer has 86 table-and-column contract changes:
- Claims: 21 changes.
- Clinical: 61 changes.
- Provider attribution: 4 changes.
Apply every applicable change in the complete Input Layer migration. Keep the connector's existing source logic, but make every enabled Input Layer Model satisfy the 1.0 column names, declared data types, and primary-key grain.
5. Update project configuration. Add this dbt flag:
flags:
require_ref_searches_node_package_before_root: true
Update the Tuva variables as follows:
- Keep:
claims_enabled,clinical_enabled, andprovider_attribution_enabledretain their 0.18 meanings. Set them for the Input Layer domains the connector maps.provider_attribution_as_of_datealso remains supported. - Replace: Replace
enable_data_qualityandenable_legacy_data_qualitywithdata_quality_enabled. The new variable defaults tofalse; set it totrueduring upgrade validation. - Add only when needed:
enable_data_quality_failure_keysenables record-level keys for failed Logical Data Quality results.parity_enabledenables the parity model used during post-upgrade validation. Both default tofalse. - Remove without replacement: Remove
enable_input_layer_testing,enable_normalize_engine,claims_preprocessing_enabled, andtuva_marts_enabled. - Remove package enablement variables: Remove
ed_classification_enabled,fhir_preprocessing_enabled, andsemantic_layer_enabled. Installing a standalone package enables that package. Removebrand_generic_enabledbecause the former Pharmacy Data Mart has no standalone 1.0 successor. Removesnapshots_enabled; the former CMS HCC and Quality Measures snapshots are not part of the standalone 1.0 packages. - Replace legacy Data Asset version variables: Remove
tuva_seed_versionandtuva_seed_versions. Tuva Core uses onetuva_core_data_asset_versionfor its complete snapshot; each asset-bearing standalone package has its own namespaced version variable. Package code and asset versions are independent and use package-tested defaults. - Move package behavior variables: Configure
record_type,dxccsr_version, andprccsr_versionin CCSR;cms_hcc_payment_yearin CMS HCC; andquality_measures_period_endin Quality Measures, following each package's documentation.
Use native YAML booleans (true and false without quotes) for the domain,
Data Quality, failure-key, parity, and CodeRx switches. An env_var() expression
returns a string; generate typed YAML or JSON when using environment-driven
configuration. Set use_coderx_enterprise: true only when the user-managed
coderx.packages, coderx.drugs, and coderx.classes relations are ready.
Update selectors and package-qualified ref() calls for relations that moved out of Core. See dbt Variables, Data Assets, and Migrating Data Mart dependencies.
After updating the mappings and configuration, parse the 1.0 project with its
new target. With dbt Core v1, run dbt parse --target tuva_1_0 --no-partial-parse;
with Core v2 or Fusion, run dbt parse --target tuva_1_0. Resolve compilation
errors before starting a build.
6. Validate the Input Layer with Structural and Logical Data Quality. Keep data_quality_enabled: true.
Before loading assets or building models, run the following command and inspect its database values. Ignore models where config.materialized is ephemeral; continue only after every other model, seed, and snapshot resolves to <1.0-output-location>.
dbt ls --target tuva_1_0 --resource-type model seed snapshot \
--output json \
--output-keys unique_id resource_type config database schema alias
Load the installed packages' seed assets, including the terminology required by Logical Data Quality:
dbt seed --target tuva_1_0
Then build the connector's Input Layer Models and Tuva Core's Input Layer Wrappers:
dbt build --full-refresh --target tuva_1_0 \
--select "package:<your_connector_project_name>,tag:input_layer"
dbt run --target tuva_1_0 --select "package:the_tuva_project,tag:input_layer"
Replace <your_connector_project_name> with the root dbt project name. Tag the connector's staging and final models with input_layer, or select their explicit paths so all required staging relations are built. The second command materializes the package-owned wrappers without running their attached data tests first, allowing Structural Data Quality to report readiness problems. The complete project build in Step 7 still runs those tests.
Run Structural Data Quality:
dbt build --target tuva_1_0 --select tag:dq_structural
Review columns_exist, data_types_correct, table_populated, and primary_key_correct in data_quality.structural. Fix every fail. If a result is not evaluated, fix its failed prerequisite and rerun Structural Data Quality. An empty input necessarily fails population and leaves its primary-key check not evaluated. A typed empty model resolves the dbt dependency but cannot satisfy this readiness workflow by rerunning it. Resolve source population or revisit the enabled domains/features and affected analytics; do not report the missing population as a pass. Continue this validation path only when all four results pass.
Then build Logical Data Quality and its result models:
dbt build --target tuva_1_0 --select tag:dq_logical
Review failures in data_quality.logical_test_results. Fix every S1 failure, investigate every S2 and S3 failure, and rerun the affected Input Layer and Data Quality models after each connector correction. See the tutorial instructions for Structural Data Quality and Logical Data Quality for the complete workflow.
7. Build the complete 1.0 project. Run dbt build --full-refresh --target tuva_1_0 without a selector. This builds the connector, loads package-owned Data Assets, builds Tuva Core and every installed standalone package, and runs their tests. Keep every output in the 1.0 output location.
See Getting Started for the current connector and package installation pattern.
Post-Upgrade Validation
Compare the preserved 0.18 and new 1.0 outputs using the same source snapshot. Freeze or snapshot changing source tables so both builds read identical records. Use the same effective values for variables that exist in both versions.
-
Compare retained populations and amounts. Reconcile row counts and paid/allowed amounts by
data_source, then compare records at their documented natural grain. For medical claims, compare(claim_id, claim_line_number, data_source)rather than generated encounter or condition IDs. Investigate missing keys, duplicate keys, changed values, and expected increases from retained undetermined claims. Use the migration catalog to distinguish intentional changes from defects. -
Optionally collect the 1.0 claims metric catalog. Add
parity_enabled: trueto the 1.0 project's complete variable set, keepclaims_enabled: true, and run:dbt build --target tuva_1_0 --select parity__metricsThis creates
parity.metrics, or<tuva_schema_prefix>_parity.metricswhen configured. It contains 101 claims-focused metrics (0001through0101) for Core and Claims Preprocessing. Tuva 0.18 does not include this producer. To compare these metrics across versions, calculate the same definitions over the preserved 0.18 outputs, adapting changed relation and field names; the metric SQL defines each calculation. A 1.0 metric table alone is not a cross-version comparison. -
Validate the remaining outputs and consumers. Review Structural and Logical Data Quality; test clinical and standalone-package outputs; update downstream keys and joins for the identity and grain changes; and rebuild custom models, dashboards, extracts, applications, and scheduled jobs against the 1.0 output location. The 101 metrics do not cover clinical outputs, Data Quality, standalone packages, or row-level equality.
-
Approve cutover only after reconciliation. Document intentional differences and confirm that downstream consumers accept them. Retain the 0.18 project and output location until the 1.0 consumers and scheduled builds are verified.
For example, the following Snowflake query compares medical-claim volume and
amounts by source. Replace baseline_db and upgrade_db with the two output
locations and adapt identifier quoting for another warehouse. Aggregate checks
are a starting point; follow them with natural-key comparisons.
with baseline as (
select data_source, count(*) as claim_lines,
sum(coalesce(paid_amount, 0)) as paid,
sum(coalesce(allowed_amount, 0)) as allowed
from baseline_db.core.medical_claim
group by data_source
), upgraded as (
select data_source, count(*) as claim_lines,
sum(coalesce(paid_amount, 0)) as paid,
sum(coalesce(allowed_amount, 0)) as allowed
from upgrade_db.core.medical_claim
group by data_source
)
select coalesce(b.data_source, u.data_source) as data_source,
b.claim_lines as baseline_claim_lines,
u.claim_lines as upgraded_claim_lines,
u.paid - b.paid as paid_change,
u.allowed - b.allowed as allowed_change
from baseline as b
full outer join upgraded as u
on b.data_source = u.data_source
or (b.data_source is null and u.data_source is null);
Architecture and Package Ecosystem
Tuva 1.0 reorganizes the project into four groups. The common transformation path remains in Tuva Core, while optional analytics and interoperability capabilities can be installed independently. Supporting projects also move out of Tuva Core. This reduces the amount of code every user must install and gives each optional package a separate release lifecycle.
Tuva Core
- Tuva Core is the shared dbt package for the Input Layer, Normalized Layer, Data Quality, Claims Preprocessing, Core Data Model, and Core-owned Data Assets.
Data Marts
Data Marts are optional analytical dbt packages that run on top of Tuva Core:
The Data Marts section explains where the Data Marts included in Tuva 0.18 are located in Tuva 1.0.
Tools & Extensions
Tools and Extensions provide optional interoperability and analytics capabilities:
- FHIR Preprocessing creates FHIR-resource-aligned tables from Tuva Core.
- Semantic Layer provides reusable dimensions and facts for BI tools and downstream analytics.
Supporting projects
These repositories support the open-source project without adding code to the Tuva Core dbt package:
- The Docs project owns the public documentation site.
- DAG Viewer provides the Tuva lineage application in a separate repository.
- Maintainer utilities own release and Data Asset publication tooling outside the Tuva Core package.
Tuva Core
Tuva Core remains the common path from standardized Input Layer data through Claims Preprocessing and the Core Data Model.
Input Layer
Input Layer contract change totals
The comparison below uses Tuva Core v0.18.0 as the pre-1.0 baseline and the reviewed 1.0 contract as the new contract. All 15 Input Layer tables are retained; no table was added or deleted.
| New tables | Columns added | Columns modified | Columns deleted |
|---|---|---|---|
| 0 | 13 | 28 | 45 |
The modified total includes nine renames plus changes to declared data types, primary-key roles, or mapping-format requirements. "Deleted" means removed from the standard Input Layer contract.
Date and time migration
All 53 Input Layer calendar-date columns remain native SQL DATE fields in
1.0. When source data is text, connectors must parse it before exposing the
Input Layer model; the canonical serialized representation is ISO 8601
YYYY-MM-DD. Structural Data Quality validates the native warehouse type, not
the original source string. Logical Data Quality separately applies exactly one
S2 invalid range check to each of the 72 Input Layer DATE and timestamp
fields and checks each ordinary populated value against one field-specific
reasonable range.
The Logical ranges are inclusive and use the warehouse current date when the test runs:
| Input Layer fields | Minimum | Maximum |
|---|---|---|
| Eligibility and patient birth and death dates; condition recorded, onset, and resolved dates; immunization occurrence date | 1900-01-01 | Current date |
| Eligibility enrollment start date and finite enrollment end date | 1900-01-01 | Current date plus 12 months |
| Appointment start and end timestamps | 2000-01-01 | Current date plus 12 months |
| Claims, pharmacy, encounter, medication, observation, procedure, lab, file, and ingestion dates and timestamps | 2000-01-01 | Current date |
These profiles distinguish historical facts from operational events. Birth, death, condition, and immunization history can legitimately reach back to 1900, but cannot occur in the future. Appointments can be booked up to 12 months ahead, and eligibility can be supplied for the same future horizon. Other transactional, file, and ingestion dates use 2000 as a reasonable lower bound and cannot be in the future. Timestamp fields are evaluated using their calendar date, so their time-of-day value is preserved.
The fixed 190001 through 210012 member-month spine is a separate analytics
boundary and does not define whether an Input Layer date is reasonable. Keeping
one range check per temporal field also prevents a single value from failing
both a general date-range test and a narrower field-specific test.
Tuva 0.18 explicitly recommended MM/DD/YYYY source text for
eligibility.enrollment_start_date, enrollment_end_date, birth_date, and
death_date. Tuva 1.0 changes those four mapping instructions to
YYYY-MM-DD; each appears in the migration table below. Other Input Layer date
fields either already used YYYY-MM-DD or had no conflicting serialized
format requirement. Those are the serialized-format changes called out as
individual rows in the migration table. Field-specific reasonable-range
validation is new in 1.0 for all 53 dates and all 19 timestamps, including
fields whose type and serialized guidance did not otherwise change.
ingest_datetime is now available on all 15 Input Layer tables. Compared with
0.18, it is added to appointment, location, practitioner, and
provider_attribution; the other 11 tables already exposed it. Issue
#1399 completed this
uniform contract by adding the three missing clinical fields and their S2
Logical checks. Map the source-record extraction or warehouse-load timestamp
when available, otherwise leave it null. Every populated ingest_datetime has
one S2 range check from 2000-01-01 through the current date.
Timestamps remain timestamps because they retain time-of-day information.
provider_attribution.year_month remains the one serialized period key: it is
an exact six-character YYYYMM value in 1.0 and now has an S1 Logical Data
Quality format check.
For eligibility, null is the canonical open enrollment_end_date.
9999-12-31 remains a backward-compatible ingestion alias and is normalized
to null downstream. Null and that alias are not applicable to the finite-end
Logical range check.
Binary flags and categorical codes
Tuva 1.0 reserves the _flag suffix for public binary model fields. Their
declared type is integer and their complete value domain is 1, 0, or null:
1 means true or present, 0 means false or absent, and null means unknown or
not applicable. A field description specifies the exact null meaning and may
require a derived flag to be non-null when Tuva can determine it completely.
Connector mappings must convert Boolean true and false values to 1 and 0.
This contract applies to public model fields in the Input Layer, Normalized Layer, public Claims Preprocessing outputs, Core Data Model, and standalone package outputs. It does not govern internal working flags or Data Asset and terminology seed attributes.
The Input Layer changes are field-specific: eligibility.death_flag,
medical_claim.in_network_flag, patient.death_flag, and
pharmacy_claim.in_network_flag now declare the integer contract. The
categorical lab interpretations have been renamed from
lab_result.source_abnormal_flag and normalized_abnormal_flag to
source_abnormal_code and normalized_abnormal_code. Their values are
categorical interpretations rather than binary facts, so the fields remain
varchar codes instead of _flag fields. Each change appears as its own row in
the migration catalog below.
Appointment descriptions remain source-native. Map the source EHR values to
appointment.type, status, reason, and cancellation_reason, all of which
are varchar description fields with no Tuva-controlled accepted values. The
migration catalog records the two field consolidations: type_description is
renamed to type and type_code is removed; status_description is renamed
to status and status_code is removed. reason and cancellation_reason
retain their 0.18 names and varchar contracts.
Complete Input Layer migration by table and column
Each row below represents one affected column in one Input Layer table. Filter by table or change type, or search the contracts and What Changed & Why descriptions. All 15 retained tables have at least one documented 1.0 column-contract change.
| Input Table | v0.18.0 Column Contract | 1.0 Column Contract | Change | What Changed & Why |
|---|---|---|---|---|
appointment | type_descriptionvarchar; source-EHR appointment type description; not marked as a primary key | typevarchar; source-EHR appointment type description; not marked as a primary key | ModifiedRenamed | Renamed type_description to type. Map the descriptive appointment type supplied by the source EHR; Tuva does not normalize this field or restrict it to a controlled vocabulary. |
appointment | type_codevarchar; source appointment type code; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed the separate appointment type code. Map the source EHR appointment type description to type instead. |
appointment | status_descriptionvarchar; source-EHR appointment status description; not marked as a primary key | statusvarchar; source-EHR appointment status description; not marked as a primary key | ModifiedRenamed | Renamed status_description to status. Map the descriptive appointment status supplied by the source EHR; Tuva does not normalize this field or restrict it to a controlled vocabulary. |
appointment | status_codevarchar; source appointment status code; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed the separate appointment status code. Map the source EHR appointment status description to status instead. |
appointment | data_sourcevarchar; not marked as a primary key | data_sourcevarchar; primary key | Modified | Added data_source to the declared primary key. Structural checks now evaluate the documented (appointment_id, data_source) grain, allowing the same appointment_id in different data sources. |
appointment | Not presentNot present in the v0.18.0 contract | ingest_datetimetimestamp; nullable and not marked as a primary key | Added | Added ingest_datetime to record when the source appointment was extracted or loaded. Map the source record timestamp when available; it supports version reconciliation without changing appointment grain. One S2 Logical invalid check flags populated values before 2000-01-01 or after the current date. |
condition | condition_idtype not declared; not marked as a primary key | source_condition_idvarchar; primary key | ModifiedRenamed | Renamed condition_id to source_condition_id, declared it as varchar, and made it part of the primary key with data_source. This distinguishes the source identifier from the condition_id Tuva creates downstream. |
condition | payertype not declared; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed payer from clinical condition input because that path does not use it. Conditions derived from claims receive payer from medical_claim. |
condition | person_idvarchar; primary key | person_idvarchar; not marked as a primary key | Modified | Removed person_id from the declared primary key. Condition grain is (source_condition_id, data_source); person_id still identifies the associated person. |
condition | claim_idvarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed claim_id from clinical condition input because clinical conditions are not linked to claims through this table. Claims-derived diagnoses are built from medical_claim. |
condition | source_code_typevarchar; not marked as a primary key | code_systemvarchar; not marked as a primary key; exact lowercase values icd-9-cm, icd-10-cm, snomed-ct, or unknown | ModifiedRenamed | Renamed source_code_type to code_system and standardized the accepted values. Map exactly one of the documented lowercase codes; mixed-case and other spellings fail the S2 Logical invalid check. |
condition | condition_ranknumber; not marked as a primary key | condition_rankinteger; not marked as a primary key; null or a value greater than or equal to 1 | Modified | Narrowed condition_rank from the generic number type to integer. Map a positive whole-number diagnosis position when the source ranks conditions, or null when rank is not applicable. An S2 Logical invalid check flags populated values less than 1. |
condition | normalized_code_typevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed normalized_code_type from the Input Layer. Normalized processing standardizes code_system and no longer accepts a separate pre-normalized code-system value from connectors. |
condition | normalized_codevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed normalized_code from the Input Layer. Tuva derives it from code_system and source_code using supported condition terminology, so connectors provide source coding only. |
condition | normalized_descriptionvarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed normalized_description from the Input Layer. Tuva derives it from code_system and source_code using supported condition terminology, so connectors no longer map the normalized description. |
condition | present_on_admit_descriptionvarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed present_on_admit_description from the Input Layer. Tuva derives it from present_on_admit_code using the present-on-admission terminology asset. |
condition | file_namevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed file_name because clinical sources are not typically delivered as files. File-level provenance remains part of claims inputs; data_source and ingest_datetime remain for clinical source and load provenance. |
eligibility | enrollment_start_datedate; primary key; source-text mapping guidance used MM/DD/YYYY | enrollment_start_datedate; primary key; native SQL DATE; valid values 1900-01-01 through the current date plus 12 months; YYYY-MM-DD when serialized | Modified | Changed the connector mapping guidance from MM/DD/YYYY to ISO 8601 YYYY-MM-DD. Parse source text to a native SQL DATE before exposing the model. Structural Data Quality validates the DATE type, and one S2 Logical invalid check flags populated values before 1900-01-01 or after the current date plus 12 months. |
eligibility | enrollment_end_datedate; primary key; source-text mapping guidance used MM/DD/YYYY; no open-span representation declared | enrollment_end_datedate; nullable and not marked as a primary key; native SQL DATE; valid finite values 1900-01-01 through the current date plus 12 months; YYYY-MM-DD when serialized; null means the span has not ended | Modified | Changed source-text guidance from MM/DD/YYYY to YYYY-MM-DD and made enrollment_end_date a nullable span attribute instead of part of identity. Map an unknown end to null. The interim 9999-12-31 ingestion alias is not applicable to the finite-date range check and is canonicalized to null without a range failure. The stable span key is person_id, member_id, enrollment_start_date, payer, plan, and data_source. Consolidate rows that share this key and differ only by enrollment_end_date because they are duplicate stable spans and fail Structural primary-key uniqueness. |
eligibility | birth_datedate; source-text mapping guidance used MM/DD/YYYY | birth_datedate; native SQL DATE; valid values 1900-01-01 through the current date; YYYY-MM-DD when serialized | Modified | Changed the connector mapping guidance from MM/DD/YYYY to ISO 8601 YYYY-MM-DD. Parse source text to a native SQL DATE before exposing the model. Structural Data Quality validates the DATE type, and one S2 Logical invalid check flags populated values before 1900-01-01 or after the current date. |
eligibility | death_datedate; source-text mapping guidance used MM/DD/YYYY | death_datedate; native SQL DATE; valid values 1900-01-01 through the current date; YYYY-MM-DD when serialized | Modified | Changed the connector mapping guidance from MM/DD/YYYY to ISO 8601 YYYY-MM-DD. Parse source text to a native SQL DATE before exposing the model. Structural Data Quality validates the DATE type, and one S2 Logical invalid check flags populated values before 1900-01-01 or after the current date. |
eligibility | death_flagboolean; not marked as a primary key; documented values 1, 0, or null | death_flaginteger; not marked as a primary key; 1 means deceased, 0 means not known deceased, and null means death status is unknown | Modified | Changed death_flag from boolean to nullable integer so every public binary _flag field uses the same 1/0/null contract. Convert true to 1 and false to 0 in connector mappings; retain null when death status is unknown. |
eligibility | gendervarchar; not marked as a primary key | sexvarchar; not marked as a primary key | ModifiedRenamed | Renamed gender to sex. This aligns eligibility with the canonical sex field used in core.patient. |
eligibility | medicare_status_codetype not declared; not marked as a primary key | medicare_status_codevarchar; not marked as a primary key | Modified | Declared medicare_status_code as varchar; v0.18.0 did not declare a type. This matches eligibility normalization and lets Structural Data Quality validate the mapping. |
eligibility | enrollment_statustype not declared; not marked as a primary key | enrollment_statusvarchar; not marked as a primary key | Modified | Declared enrollment_status as varchar; v0.18.0 did not declare a type. This matches eligibility normalization and lets Structural Data Quality validate the mapping. |
eligibility | hospice_flagtype not declared; not marked as a primary key | hospice_flaginteger; not marked as a primary key | Modified | Declared hospice_flag as integer; v0.18.0 did not declare a type. This matches eligibility normalization and lets Structural Data Quality validate the mapping. |
eligibility | institutional_snp_flagtype not declared; not marked as a primary key | institutional_snp_flaginteger; not marked as a primary key | Modified | Declared institutional_snp_flag as integer; v0.18.0 did not declare a type. This matches eligibility normalization and lets Structural Data Quality validate the mapping. |
eligibility | long_term_institutional_flagtype not declared; not marked as a primary key | long_term_institutional_flaginteger; not marked as a primary key | Modified | Declared long_term_institutional_flag as integer; v0.18.0 did not declare a type. This matches eligibility normalization and lets Structural Data Quality validate the mapping. |
eligibility | Not presentNot present in the v0.18.0 contract | medicaid_indicatorinteger; not marked as a primary key | Added | Added medicaid_indicator as a documented, typed eligibility field. It carries Medicaid coverage through normalized and Core eligibility instead of leaving it outside the standard contract. |
eligibility | Not presentNot present in the v0.18.0 contract | part_d_raf_typevarchar; not marked as a primary key | Added | Added part_d_raf_type as a documented, typed eligibility field. It makes the Medicare Part D risk-adjustment factor type available through Core. |
eligibility | Not presentNot present in the v0.18.0 contract | low_income_subsidy_indicatorinteger; not marked as a primary key | Added | Added low_income_subsidy_indicator as a documented, typed eligibility field. It makes Part D Low Income Subsidy status available through Core. |
eligibility | Not presentNot present in the v0.18.0 contract | metal_levelvarchar; not marked as a primary key | Added | Added metal_level as a documented, typed eligibility field. It makes the ACA exchange plan tier available through Core. |
eligibility | Not presentNot present in the v0.18.0 contract | csr_indicatorinteger; not marked as a primary key | Added | Added csr_indicator as a documented, typed eligibility field. It makes the ACA Cost Sharing Reduction variant available through Core. |
eligibility | Not presentNot present in the v0.18.0 contract | enrollment_duration_monthsinteger; not marked as a primary key | Added | Added enrollment_duration_months as a documented, typed eligibility field. It makes benefit-year coverage duration available through Core for coverage and risk-adjustment use cases. |
eligibility | Not presentNot present in the v0.18.0 contract | esrd_statusinteger; not marked as a primary key | Added | Added esrd_status as a documented, typed eligibility field. It makes end-stage renal disease status available through Core for downstream risk adjustment. |
eligibility | Not presentNot present in the v0.18.0 contract | transplant_duration_monthsinteger; not marked as a primary key | Added | Added transplant_duration_months as a documented, typed eligibility field. It makes time since kidney transplant available through Core for downstream risk adjustment. |
encounter | length_of_staynumber; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed length_of_stay from the Input Layer. Tuva calculates it from normalized encounter start and end dates, avoiding a mapped value that can conflict with those dates. |
encounter | admit_source_descriptionvarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed admit_source_description from the Input Layer. Tuva looks it up from admit_source_code, keeping the description consistent with the code. |
encounter | admit_type_descriptionvarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed admit_type_description from the Input Layer. Tuva looks it up from admit_type_code, keeping the description consistent with the code. |
encounter | discharge_disposition_descriptionvarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed discharge_disposition_description from the Input Layer. Tuva looks it up from discharge_disposition_code, keeping the description consistent with the code. |
encounter | primary_diagnosis_descriptionvarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed primary_diagnosis_description from the Input Layer. Tuva derives it from primary_diagnosis_code_type and primary_diagnosis_code using ICD terminology. |
encounter | drg_descriptionvarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed drg_description from the Input Layer. Tuva derives it from drg_code_type and drg_code using MS-DRG or APR-DRG terminology. |
encounter | file_namevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed file_name because clinical sources are not typically delivered as files. File-level provenance remains part of claims inputs; data_source and ingest_datetime remain for clinical source and load provenance. |
immunization | normalized_code_typevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed normalized_code_type from the Input Layer. Tuva identifies CVX as the normalized code system when source_code_type and source_code match CVX terminology. |
immunization | normalized_codevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed normalized_code from the Input Layer. Tuva derives it from source_code when the retained source fields match CVX terminology. |
immunization | normalized_descriptionvarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed normalized_description from the Input Layer. Tuva derives it from the CVX match, so connectors no longer map the normalized description. |
immunization | normalized_dosevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed normalized_dose from the Input Layer because Tuva does not implement a dose-normalization rule. The downstream Core field remains null for schema compatibility. |
immunization | file_namevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed file_name because clinical sources are not typically delivered as files. File-level provenance remains part of claims inputs; data_source and ingest_datetime remain for clinical source and load provenance. |
lab_result | normalized_order_typevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed normalized_order_type from the Input Layer. Tuva determines the normalized order code system from source_order_type and source_order_code using LOINC or SNOMED CT terminology. |
lab_result | normalized_order_codevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed normalized_order_code from the Input Layer. Tuva derives it from source_order_type and source_order_code using LOINC or SNOMED CT terminology. |
lab_result | normalized_order_descriptionvarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed normalized_order_description from the Input Layer. Tuva derives it from source_order_type and source_order_code using LOINC or SNOMED CT terminology. |
lab_result | normalized_component_typevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed normalized_component_type from the Input Layer. Tuva determines the normalized component code system from source_component_type and source_component_code using LOINC or SNOMED CT terminology. |
lab_result | normalized_component_codevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed normalized_component_code from the Input Layer. Tuva derives it from source_component_type and source_component_code using LOINC or SNOMED CT terminology. |
lab_result | normalized_component_descriptionvarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed normalized_component_description from the Input Layer. Tuva derives it from source_component_type and source_component_code using LOINC or SNOMED CT terminology. |
lab_result | source_abnormal_flagnumber; not marked as a primary key | source_abnormal_codevarchar; not marked as a primary key | ModifiedRenamed | Renamed source_abnormal_flag to source_abnormal_code and changed its type from number to varchar. The field contains a categorical source interpretation such as high, low, normal, abnormal, or critical, so it is a code rather than a binary flag. |
lab_result | normalized_abnormal_flagnumber; not marked as a primary key | normalized_abnormal_codevarchar; not marked as a primary key | ModifiedRenamed | Renamed normalized_abnormal_flag to normalized_abnormal_code and changed its type from number to varchar. Normalized abnormal interpretations are categorical codes rather than binary flags. |
lab_result | file_namevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed file_name because clinical sources are not typically delivered as files. File-level provenance remains part of claims inputs; data_source and ingest_datetime remain for clinical source and load provenance. |
location | Not presentNot present in the v0.18.0 contract | ingest_datetimetimestamp; nullable and not marked as a primary key | Added | Added ingest_datetime to record when the source location was extracted or loaded. Map the source record timestamp when available; it supports source-version and load auditing without changing location grain. One S2 Logical invalid check flags populated values before 2000-01-01 or after the current date. |
medical_claim | in_network_flagboolean; not marked as a primary key; description documented values 1, 0, or null | in_network_flaginteger; not marked as a primary key; 1 means in network, 0 means out of network, and null means network status is unknown | Modified | Changed in_network_flag from boolean to nullable integer so every public binary _flag field uses the same 1/0/null contract. Convert true to 1 and false to 0 in connector mappings; retain null when the source does not provide network status. |
medication | person_idtype not declared; not marked as a primary key | person_idvarchar; not marked as a primary key | Modified | Declared person_id as varchar; v0.18.0 did not declare a type. This matches medication normalization and lets Structural Data Quality validate the mapping. |
medication | payervarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed payer from clinical medication input because that path does not use it. Claims-derived medication records receive payer from pharmacy_claim. |
medication | ndc_descriptionvarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed ndc_description from the Input Layer. core.medication derives it from the selected CodeRx packages relation when the NDC matches, so connectors supply the source code rather than a standardized description. |
medication | rxnorm_descriptionvarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed rxnorm_description from the Input Layer. core.medication derives it from the selected CodeRx packages and drugs relations when an NDC or RxNorm mapping is available. |
medication | atc_descriptionvarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed atc_description from the Input Layer. core.medication derives it from the matching CodeRx class hierarchy when a supported RxNorm mapping is available. |
medication | file_namevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed file_name because clinical sources are not typically delivered as files. File-level provenance remains part of claims inputs; data_source and ingest_datetime remain for clinical source and load provenance. |
observation | person_idtype not declared; not marked as a primary key | person_idvarchar; not marked as a primary key | Modified | Declared person_id as varchar; v0.18.0 did not declare a type. This matches observation normalization and lets Structural Data Quality validate the mapping. |
observation | payervarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed payer from observation input because neither observation normalization nor core.observation uses it. |
observation | normalized_code_typevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed normalized_code_type from the Input Layer. Tuva identifies the normalized code system from source_code_type and source_code using supported terminology. |
observation | normalized_codevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed normalized_code from the Input Layer. Tuva derives it from source_code_type and source_code using supported terminology, so connectors provide source coding only. |
observation | normalized_descriptionvarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed normalized_description from the Input Layer. Tuva derives it from the matched terminology code, so connectors no longer map the normalized description. |
observation | file_namevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed file_name because clinical sources are not typically delivered as files. File-level provenance remains part of claims inputs; data_source and ingest_datetime remain for clinical source and load provenance. |
patient | file_namevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed file_name because clinical sources are not typically delivered as files. File-level provenance remains part of claims inputs; data_source and ingest_datetime remain for clinical source and load provenance. |
patient | death_flagnumber; not marked as a primary key | death_flaginteger; not marked as a primary key; 1 means deceased, 0 means not known deceased, and null means death status is unknown | Modified | Narrowed death_flag from the generic number type to nullable integer so every public binary _flag field uses the same 1/0/null contract. Map only 1, 0, or null. |
pharmacy_claim | in_network_flagboolean; not marked as a primary key; description documented values 1, 0, or null | in_network_flaginteger; not marked as a primary key; 1 means in network, 0 means out of network, and null means network status is unknown | Modified | Changed in_network_flag from boolean to nullable integer so every public binary _flag field uses the same 1/0/null contract. Convert true to 1 and false to 0 in connector mappings; retain null when the source does not provide network status. |
practitioner | Not presentNot present in the v0.18.0 contract | ingest_datetimetimestamp; nullable and not marked as a primary key | Added | Added ingest_datetime to record when the source practitioner was extracted or loaded. Map the source record timestamp when available; it supports source-version and load auditing without changing practitioner grain. One S2 Logical invalid check flags populated values before 2000-01-01 or after the current date. |
procedure | procedure_idvarchar; primary key | source_procedure_idvarchar; primary key | ModifiedRenamed | Renamed procedure_id to source_procedure_id while retaining it as a primary key with data_source. This distinguishes the source identifier from the procedure_id Tuva creates downstream. |
procedure | claim_idvarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed claim_id from clinical procedure input because clinical procedures are not linked to claims through this table. Claims-derived procedures are built from medical_claim. |
procedure | source_code_typevarchar; not marked as a primary key | code_systemvarchar; not marked as a primary key | ModifiedRenamed | Renamed source_code_type to code_system. The new name identifies the coding system used to normalize source_code. |
procedure | normalized_code_typevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed normalized_code_type from the Input Layer. Normalized processing standardizes code_system and no longer accepts a separate pre-normalized code-system value from connectors. |
procedure | normalized_codevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed normalized_code from the Input Layer. Tuva derives it from code_system and source_code using supported procedure terminology, so connectors provide source coding only. |
procedure | normalized_descriptionvarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed normalized_description from the Input Layer. Tuva derives it from code_system and source_code using supported procedure terminology, so connectors no longer map the normalized description. |
procedure | file_namevarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed file_name because clinical sources are not typically delivered as files. File-level provenance remains part of claims inputs; data_source and ingest_datetime remain for clinical source and load provenance. |
provider_attribution | year_monthvarchar; primary key; exact format not declared | year_monthvarchar; primary key; exact six-character YYYYMM period key | Modified | Standardized provider attribution month keys as YYYYMM and added an S1 Logical Data Quality check for six digits with a valid month from 01 through 12. |
provider_attribution | patient_idvarchar; not marked as a primary key | Not presentRemoved from the standard 1.0 contract | Removed | Removed patient_id because provider attribution does not use a clinical patient identifier. Attribution joins use person_id, member_id, year_month, payer, plan, and data_source. |
provider_attribution | Not presentNot present in the v0.18.0 contract | file_namevarchar; not marked as a primary key | Added | Added file_name to retain source-file lineage for externally supplied attribution records. This supports reconciliation and troubleshooting without changing attribution grain. |
provider_attribution | Not presentNot present in the v0.18.0 contract | ingest_datetimetimestamp; not marked as a primary key | Added | Added ingest_datetime to record when externally supplied attribution data was loaded. This supports refresh auditing and troubleshooting without changing attribution grain. |
For eligibility, leave enrollment_end_date null while a span remains open.
The field is no longer part of the Input Layer primary key, and the stable
eligibility_id no longer includes it. Tuva treats null and the
backward-compatible 9999-12-31 ingestion alias as not applicable to the
finite-end date-range check and canonicalizes the alias to null. Fully refresh
Core and any downstream package outputs because existing eligibility IDs will
change. Before
rebuilding, consolidate rows that share the stable key and differ only by
enrollment_end_date; these are now duplicate spans and fail the Structural
primary-key check. FHIR Preprocessing derives Coverage resource IDs and EOB
coverage references from eligibility_id, so those identifiers change once
during this upgrade and then remain stable when an open span later closes.
Review the Input Layer dictionary and update connectors when a mapped table or column no longer satisfies the 1.0 contract.
Data Quality
Tuva 1.0 replaces the legacy collection of Data Quality tests with a structured, queryable framework organized around Structural and Logical Data Quality. Results can be reviewed at a high level by source, table, and severity, then traced to the specific check and affected records that require investigation.
The framework is optional and disabled by default. Set data_quality_enabled: true to use it; projects that do not use Data Quality no longer need selectors or exclusion tags to keep it out of ordinary builds.
- Structural Data Quality verifies that each enabled Input Layer table and source is populated, contains the required columns and compatible data types, and satisfies its primary-key grain.
- Logical Data Quality evaluates values and relationships at their native grain. The current 1.0 catalog includes 314 tests across the missing, invalid, temporal, referential, and consistency test types.
The 1.0 framework covers Input Data Quality. Downstream Output Data Quality mappings and rollups are outside this release.
Date validation follows the Structural/Logical boundary described in the Input Layer date and time migration: Structural Data Quality validates the native warehouse type, and one Logical range test covers each temporal field. The Data Quality Test Catalog lists the current field-level tests.
Projects upgrading from the legacy framework must stop using the removed dq, dq1, dq2, dq_analytics, and dq_analytical selector tags and use the Structural and Logical selectors shown above. The legacy data_quality.logical relation is also removed. Replace it with data_quality.logical_test_results, mapping the old table field to input_table_name and test_result to failed_count. dbt does not automatically drop a relation when its model is removed, so verify that no consumer still uses data_quality.logical, then explicitly drop any stale table or perform the upgrade in a separate 1.0 schema.
Read the Data Quality overview, review Structural Data Quality and Logical Data Quality, browse the Data Quality Test Catalog, or follow the Data Quality tutorial.
Claims Preprocessing
Tuva 1.0 adds provider attribution and improves encounter grouping:
- Member months: Claims Preprocessing expands eligibility across a complete
month spine from
190001through210012. Both finite and open spans stop at the calendar month containing the date portion oftuva_last_run, so future member months are never emitted. See Member Months. - Provider attribution: When enabled, Claims Preprocessing runs Tuva's transparent, CMS-style provider attribution methodology. It assigns members to the providers most likely to manage their primary care, making provider panels available for quality, cost, contracting, and outreach workflows from claims evidence. Enable both
claims_enabledandprovider_attribution_enabled, and supply theprovider_attributionInput Layer model. Existing payer and custom assignments can be included through that model; an empty contract-shaped model resolves the dbt dependency but does not satisfy Structural Data Quality population checks. See Provider Attribution. - Encounter grouping: The Encounter Grouper now scopes claim lines by
data_sourceso claims from different source systems cannot collide when they reuse an identifier. It also generates deterministic 32-characterencounter_idvalues so unrelated data changes do not renumber existing encounters. Downstream schemas and joins that storeencounter_idmust support the new string value. See the Encounter Grouper.
See Claims Preprocessing for the complete workflow.
Core Data Model
The Core contract comparison uses the executed public model SQL in Tuva Core
v0.18.0
and the reviewed 1.0 contract.
It also identifies dictionary-only corrections where the v0.18 documentation
did not match the relation users actually received.
The physical public schema changes are:
- 16 public Core tables and 417 fixed columns in v0.18.0 become 18 tables and 587 fixed columns in 1.0.
costandutilizationare new tables with 99 and 56 columns, respectively. Both expose the authoritativemember_month_idfromcore.member_monthas their primary key.member_monthsis renamed tomember_month; no public Core table is removed without a successor.- Across the 16 paired old and new tables, 10 columns are physically renamed, 33 are physically added, and 18 are physically removed. Two additional practitioner names are dictionary-only corrections. The catalog also includes grain, identity, type, population, value-semantic, and other dictionary-only changes, so its row count is larger than this structural schema delta.
Eleven of the added Core columns are nullable ingest_datetime timestamps on
source-oriented tables: appointment, condition, encounter,
immunization, lab_result, location, medication, observation,
patient, practitioner, and procedure. Tuva preserves the timestamp when
the Core row can be attributed to one source record. It publishes null when a
claims-derived row combines multiple records or otherwise lacks reliable
record-level provenance, including claims-derived conditions and encounters,
claims-derived locations and practitioners, eligibility-derived patients, and
claim-header procedures.
Extension columns
Tuva 1.0 supports connector-defined extension columns only for the 14 same-named Input Layer and Core table pairs. PR #1402 established this direct-only contract: an extension travels through the Input Layer Wrapper and internal normalization path to that same-named Core table. It is not copied to another table merely because that table is derived from the input.
The configured passthrough.prefix identifies extension columns, and
passthrough.strip can remove that prefix exactly once in the final supported
Core table. Extension columns do not generically propagate into Claims
Preprocessing, standalone packages, or derived Core outputs. In particular,
eligibility extensions remain available on core.eligibility; they do not
flow into core.member_month, core.cost, core.utilization, or
core.patient. Build an explicit downstream model when a derived output needs
one of those values, including a documented join or aggregation rule for its
different grain.
See the Column Extensions guide for the complete
table inventory, configuration, collision rules, examples, and migration
checklist. Projects upgrading from 0.18.0 with passthrough.strip: true must
also update downstream references for Core appointment and Core patient:
those tables preserved the prefix in 0.18.0 but strip it in 1.0. For example,
core.appointment.x_scheduling_channel becomes
core.appointment.scheduling_channel, and a retained clinical
core.patient.x_care_navigator becomes core.patient.care_navigator.
Projects that previously relied on eligibility extensions in
core.member_month or core.patient must move that logic to an explicit
downstream model before upgrading; those values are removed rather than
renamed. Full-refresh the Input Layer and affected Core tables after making
these changes.
Complete Core migration by table and column
Each row below represents one affected public Core model or column. Filter by
table or change type, or search the old contract, new contract, rationale, and
upgrade impact. person_id_crosswalk is included in the table filter and
returns a no-change confirmation when selected.
| Catalog level | Added | Modified | Removed | Total |
|---|---|---|---|---|
| Public models | 2 | 12, including 1 rename | 0 | 14 |
| Public columns | 33 | 111, including 12 catalog renames | 21 | 165 |
| All audited changes | 35 | 123 | 21 | 179 |
The column catalog totals include semantic and dictionary-only contract changes. Of the 12 catalog renames, 10 change physical SQL column names and two correct practitioner names that were wrong only in the v0.18 dictionary. Of the 21 catalog removals, 18 remove physical columns and three remove dictionary-only fields that v0.18 SQL never emitted.
| Core Table | v0.18.0 Contract | 1.0 Contract | Change | What Changed & Why | Upgrade Impact |
|---|---|---|---|---|---|
appointmentModel-level | appointmentOne row per appointment per patient; appointment_id was tested as globally unique. | appointmentOne row per appointment per patient per data source; primary key is (appointment_id, data_source). | Modified | Source EHR appointment identifiers are only required to be unique inside a data source. Source descriptions are retained without Tuva terminology normalization. | Fully refresh core.appointment. Update uniqueness tests and downstream keys to include data_source, and update selects for the smaller descriptive contract. |
appointmentColumn-level | durationDocumented as number; SQL already cast the value to an integer number of minutes. | durationinteger; scheduled duration in minutes. | Modified | The dictionary now states the whole-number type already emitted by the Core SQL. | Documentation correction only: the fixed SQL column name or type did not change. |
appointmentColumn-level | type_descriptionvarchar source-EHR appointment type description. | typevarchar source-EHR appointment type description; no Tuva-controlled vocabulary. | ModifiedRenamed | Renamed type_description to type and made the source-description contract explicit. | Replace references to type_description with type. Values remain source-specific across EHRs. |
appointmentColumn-level | status_descriptionvarchar source-EHR appointment status description. | statusvarchar source-EHR appointment status description; no Tuva-controlled vocabulary. | ModifiedRenamed | Renamed status_description to status and made the source-description contract explicit. | Replace references to status_description with status. Values remain source-specific across EHRs. |
appointmentColumn-level | type_codevarchar source appointment type code. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | The source-code field was removed; Core retains the source type description in type. | Remove this field from downstream selects. There is no code-valued successor. |
appointmentColumn-level | type_code_normvarchar normalized appointment type code. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | Tuva no longer applies appointment-type terminology normalization. | Remove this field and any filters on its former canonical values. |
appointmentColumn-level | type_description_normvarchar normalized appointment type description. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | Tuva no longer applies appointment-type terminology normalization. | Use type for the source EHR description or implement project-specific normalization downstream. |
appointmentColumn-level | status_codevarchar source appointment status code. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | The source-code field was removed; Core retains the source status description in status. | Remove this field from downstream selects. There is no code-valued successor. |
appointmentColumn-level | status_code_normvarchar normalized appointment status code. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | Tuva no longer applies appointment-status terminology normalization. | Remove this field and any filters on its former canonical values. |
appointmentColumn-level | status_description_normvarchar normalized appointment status description. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | Tuva no longer applies appointment-status terminology normalization. | Use status for the source EHR description or implement project-specific normalization downstream. |
appointmentColumn-level | cancellation_reason_code_normvarchar normalized cancellation-reason code. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | Tuva no longer applies cancellation-reason terminology normalization. | Remove this field; cancellation_reason retains the source EHR description. |
appointmentColumn-level | cancellation_reason_description_normvarchar normalized cancellation-reason description. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | Tuva no longer applies cancellation-reason terminology normalization. | Use cancellation_reason for the source EHR description or normalize it downstream. |
appointmentColumn-level | Not presentNot present in the v0.18.0 fixed Core output | ingest_datetimenullable timestamp for the source appointment extraction or warehouse load time. | Added | Adds source-record ingestion provenance to the public appointment output. | Add the nullable timestamp to downstream schemas and selects when upgrading. Existing appointment grain and identifiers do not change. |
costModel-level | Not presentNo fixed Core model | costOne row per (person_id, member_id, year_month, payer, plan, data_source), with 99 fixed columns and member_month_id as the primary key; paid and allowed amounts include inpatient long-term acute care, inpatient substance use, and outpatient substance use, plus provider attribution. | Added | Moves foundational member-month cost concepts formerly embedded in Financial PMPM into Core without reproducing every legacy PMPM summary. | Build the new model if needed and point analyses at its documented measures. Do not assume it is a drop-in replacement for every Financial PMPM relation. |
conditionModel-level | conditionOne row per distinct condition; claims-derived rows excluded diagnoses from medical-claim lines whose claim_type was 'undetermined'. | conditionOne row per distinct condition; every populated medical-claim diagnosis can produce a billing_diagnosis row, including diagnoses from claim_type = 'undetermined'. When no classified claim-line encounter exists, encounter_id remains null. | Modified | Claim classification controls which claim-level categorization and encounter algorithm applies, not whether a populated diagnosis is retained. Tuva preserves the diagnosis without guessing a replacement claim type. | Fully refresh core.condition and every dependent relation, package, export, metric, or application. Row counts can increase when previously discarded diagnoses produce distinct conditions; review downstream condition counts and logic that assumes every claims-derived condition has an encounter. |
conditionColumn-level | condition_idSource clinical ID passed through; claims ID used delimiter-based concatenation. | condition_idDeterministic 32-character lowercase identifier built from null-marked, escaped components and a clinical- or claims-condition domain marker. | Modified | The collision-safe encoding prevents different component boundaries or source domains from producing the same identifier. | Fully refresh core.condition and every persisted downstream relation, FHIR resource identifier, foreign key, extract, or join that stores condition_id. |
conditionColumn-level | Not presentNot present in the v0.18.0 fixed Core output | source_condition_idvarchar source clinical condition identifier; null on claims-derived rows. | Added | Core now preserves the source identifier separately because condition_id is a Tuva-generated identifier. | Use source_condition_id for clinical source reconciliation; do not expect it on billing diagnoses. |
conditionColumn-level | encounter_idClinical rows passed through encounter_id; claims-derived rows were always null. | encounter_idClinical rows retain the mapped encounter; claims-derived rows receive the selected, data-source-scoped claim-line encounter assignment when one exists and otherwise remain null. | Modified | Claims conditions can now be analyzed at the grouped encounter level without a separate join. | Rebuild condition-dependent outputs and review logic that assumed claims-derived encounter_id was null. |
conditionColumn-level | claim_idClaims rows used the source claim ID; clinical rows could pass through an Input Layer claim_id. | claim_idClaims rows retain claim_id; clinical rows are null because clinical condition input no longer carries a claim link. | Modified | This keeps source clinical records separate from diagnoses derived from medical claims. | Remove clinical workflows that relied on input_layer.condition.claim_id; join claims-derived rows through claim_id instead. |
conditionColumn-level | payerPhysically emitted for claims-derived rows but omitted from the v0.18 Core dictionary. | payerDeclared varchar; populated from the medical claim for claims-derived rows and null for clinical rows. | Modified | The dictionary now documents the existing claims payer output and its source-specific null behavior. | Documentation correction only: the fixed SQL column name or type did not change. |
conditionColumn-level | statusClinical value passed through; every claims-derived diagnosis was hard-coded to active. | statusClinical value passes through; claims-derived rows are null. | Modified | A billed diagnosis establishes that a code appeared on a claim, not that a condition remains clinically active. | Remove assumptions that every claims diagnosis is active and handle null explicitly in downstream clinical-status logic. |
conditionColumn-level | condition_typeClaims-derived diagnoses were labeled discharge_diagnosis. | condition_typeClaims-derived diagnoses are labeled billing_diagnosis; clinical rows retain their source type. | Modified | Professional-claim diagnoses are billing diagnoses and must not be presented as evidence of a hospital discharge. | Replace claims-derived discharge_diagnosis filters or mappings with billing_diagnosis and rebuild condition-dependent products. |
conditionColumn-level | source_code_typevarchar source code-system field named source_code_type. | code_systemvarchar code system; claims use the diagnosis code type and clinical input accepts icd-9-cm, icd-10-cm, snomed-ct, or unknown. | ModifiedRenamed | Renamed the field to the package-wide code_system convention and moved normalization to the Normalized Layer. | Replace source_code_type with code_system and normalize clinical connector values to the documented lowercase vocabulary. |
conditionColumn-level | normalized_codeCould be supplied upstream or populated in Core by ICD/SNOMED terminology joins. | normalized_codeDerived in the Normalized Layer from code_system and source_code using supported ICD-9-CM, ICD-10-CM, and SNOMED CT assets. | Modified | Tuva now owns one normalization path instead of accepting connector-supplied normalized condition values. | Revalidate custom mappings and expect null when a source code does not match a supported terminology asset. |
conditionColumn-level | normalized_descriptionClinical normalization could honor supplied values and used ICD short descriptions; claims used long descriptions. | normalized_descriptionTerminology-derived for both paths; ICD-9-CM and ICD-10-CM rows use the long description. | Modified | The same normalized code now receives the same, more descriptive label across source paths. | Refresh search indexes, cached labels, extracts, snapshots, and equality-based tests that persisted short or custom descriptions. |
conditionColumn-level | Not presentNot present in the v0.18.0 fixed Core output | condition_familyvarchar analytic family from the Tuva Condition Grouper for mapped ICD-10-CM and SNOMED CT codes. | Added | Provides a stable higher-level grouping without requiring each downstream product to duplicate the mapping. | Adopt when useful; unsupported or unmapped code systems, including ICD-9-CM, remain null. |
conditionColumn-level | Not presentNot present in the v0.18.0 fixed Core output | condition_namevarchar mutually exclusive condition from the Tuva Condition Grouper for mapped ICD-10-CM and SNOMED CT codes. | Added | Exposes a reusable analytic condition label alongside the broader condition_family. | Adopt when useful and handle null for unsupported or unmapped codes. |
conditionColumn-level | condition_rankDocumented as generic number; SQL already emitted integer claim diagnosis positions. | condition_rankinteger; claims retain diagnosis positions 1 through 25 and clinical rows use a positive integer or null. | Modified | The contract now matches the whole-number semantics and the Logical Data Quality range check. | Ensure mapped clinical values are positive whole numbers; otherwise there is no physical Core type change. |
conditionColumn-level | present_on_admit_descriptionClaims rows used Tuva terminology; clinical rows could pass through a connector-supplied description. | present_on_admit_descriptionDerived from present_on_admit_code with Tuva present-on-admission terminology for both source paths. | Modified | The code now determines one consistent description across clinical and claims records. | Expect connector-specific descriptions to be replaced; unmatched or null codes yield null descriptions. |
conditionColumn-level | normalized_code_typevarchar normalized condition code system. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | The normalized code system duplicated code_system after terminology matching. | Use code_system with normalized_code. |
conditionColumn-level | mapping_methodvarchar value describing manual, automatic, or custom normalization. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | The legacy normalization-engine provenance field was removed with the former Core mapping path. | Remove downstream references; use code presence and package terminology lineage instead. |
conditionColumn-level | Not presentNot present in the v0.18.0 fixed Core output | ingest_datetimenullable timestamp from the originating clinical condition; null for claims-derived conditions that can consolidate diagnoses from multiple claim lines. | Added | Adds source-record provenance without inventing one claim-line timestamp for a condition assembled from more than one source record. | Add the nullable timestamp to downstream schemas and selects. Fully refresh conditions; claims-derived rows must not be interpreted as having line-level ingestion provenance when this field is null. |
eligibilityColumn-level | eligibility_idIdentifier included enrollment_end_date and uniqueness was tested with data_source. | eligibility_idStable varchar primary key built from person_id, member_id, enrollment_start_date, payer, plan, and data_source; enrollment_end_date is excluded. | Modified | An enrollment span now keeps the same identity when an open end is later populated, and data_source is already encoded in the key. | Fully refresh eligibility and downstream member-month outputs; rebuild stored keys and deduplicate rows that differ only by enrollment_end_date. |
eligibilityColumn-level | enrollment_start_dateNative DATE, but normalization required the value to exist in the bounded published daily calendar. | enrollment_start_dateNative DATE passed through without a terminology-calendar membership join. | Modified | Range validation belongs to Logical Data Quality; normalization no longer erases an already-typed value solely because it is outside the published calendar. | Out-of-range values remain visible for remediation instead of becoming null. Review any logic that depended on the old nulling behavior. |
eligibilityColumn-level | enrollment_end_dateRequired DATE used in identity; normalization required calendar membership and did not define an open span. | enrollment_end_dateNullable DATE span attribute; null means open, 9999-12-31 is accepted as an ingestion alias and published as null, and finite dates pass through without calendar membership. | Modified | Separating identity from the mutable end date supports open eligibility while preventing bounded-calendar data loss. | Map open spans to null, stop keying on enrollment_end_date, and fully refresh eligibility plus member-month and enrollment-match outputs. |
eligibilityColumn-level | birth_dateNative DATE, but normalization required the value to exist in the bounded published daily calendar. | birth_dateNative DATE passed through without a terminology-calendar membership join. | Modified | Logical Data Quality now reports unreasonable dates without normalization destroying the source value. | Out-of-range values remain visible rather than becoming null; update tests that expected the former null. |
eligibilityColumn-level | death_dateNative DATE, but normalization required the value to exist in the bounded published daily calendar. | death_dateNative DATE passed through without a terminology-calendar membership join. | Modified | Logical Data Quality now reports unreasonable dates without normalization destroying the source value. | Out-of-range values remain visible rather than becoming null; update tests that expected the former null. |
eligibilityColumn-level | institutional_snp_flagPhysically emitted by v0.18 SQL but omitted from its Core dictionary. | institutional_snp_flagDeclared integer binary flag; 1 yes, 0 no, null unknown or not applicable. | Modified | The dictionary now documents the existing physical column and the public binary-flag domain. | Documentation correction only: the fixed SQL column name or type did not change. |
eligibilityColumn-level | Not presentDeclared in the v0.18 dictionary but not emitted by its fixed Core SQL. | medicaid_indicatorinteger Medicaid coverage indicator; 1 yes, 0 no, null not applicable. | Added | The field was documented in v0.18 but is now actually projected from normalized eligibility into Core. | A new physical column appears after full refresh; remove extension workarounds and update fixed downstream schemas. |
eligibilityColumn-level | Not presentDeclared in the v0.18 dictionary but not emitted by its fixed Core SQL. | part_d_raf_typevarchar Medicare Part D risk-adjustment factor type. | Added | The field was documented in v0.18 but is now actually projected from normalized eligibility into Core. | A new physical column appears after full refresh; update fixed downstream schemas. |
eligibilityColumn-level | Not presentDeclared as varchar in the v0.18 dictionary but not emitted by its fixed Core SQL. | low_income_subsidy_indicatorinteger low-income subsidy indicator; null when not applicable. | Added | The formerly documentation-only field is now emitted, with its contract corrected from varchar to integer. | A new physical integer column appears after full refresh; update fixed schemas and casts. |
eligibilityColumn-level | Not presentDeclared in the v0.18 dictionary but not emitted by its fixed Core SQL. | metal_levelvarchar ACA exchange metal tier; null when not applicable. | Added | The field was documented in v0.18 but is now actually projected from normalized eligibility into Core. | A new physical column appears after full refresh; update fixed downstream schemas. |
eligibilityColumn-level | Not presentDeclared in the v0.18 dictionary but not emitted by its fixed Core SQL. | csr_indicatorinteger ACA cost-sharing-reduction variant indicator; null when not applicable. | Added | The field was documented in v0.18 but is now actually projected from normalized eligibility into Core. | A new physical column appears after full refresh; update fixed downstream schemas. |
eligibilityColumn-level | Not presentDeclared in the v0.18 dictionary but not emitted by its fixed Core SQL. | enrollment_duration_monthsinteger months covered during the benefit year for ACA exchange enrollment. | Added | The field was documented in v0.18 but is now actually projected from normalized eligibility into Core. | A new physical column appears after full refresh; update fixed downstream schemas. |
eligibilityColumn-level | Not presentDeclared as varchar in the v0.18 dictionary but not emitted by its fixed Core SQL. | esrd_statusinteger end-stage renal disease indicator; null when not applicable. | Added | The formerly documentation-only field is now emitted, with its contract corrected from varchar to integer. | A new physical integer column appears after full refresh; update fixed schemas and casts. |
eligibilityColumn-level | Not presentDeclared in the v0.18 dictionary but not emitted by its fixed Core SQL. | transplant_duration_monthsinteger months since kidney transplant; null when not applicable. | Added | The field was documented in v0.18 but is now actually projected from normalized eligibility into Core. | A new physical column appears after full refresh; update fixed downstream schemas. |
eligibilityColumn-level | normalized_state_namevarchar normalized state name named normalized_state_name. | fips_state_namevarchar ANSI/FIPS state name matched from the source state value. | ModifiedRenamed | Renamed the column so all three state normalization fields use the fips_state prefix. | Replace normalized_state_name with fips_state_name in downstream selects and schemas. |
eligibilityColumn-level | snp_typeDeclared in the v0.18 dictionary but never emitted by the fixed Core SQL. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | The stale dictionary entry was removed; institutional_snp_flag documents the supported institutional SNP concept. | No physical SQL column is dropped. Remove any schema expectation based only on the former dictionary entry. |
eligibilityColumn-level | file_datetimestamp. | file_dateNative SQL DATE; YYYY-MM-DD when serialized. | Modified | A file date is a calendar date and does not carry a time of day. | Fully refresh core.eligibility and update downstream timestamp casts or schemas to DATE. |
eligibilityColumn-level | file_namePhysically emitted by v0.18 SQL but omitted from its Core dictionary. | file_nameDeclared varchar source file name. | Modified | The dictionary now documents the existing lineage column. | Documentation correction only: the fixed SQL column name or type did not change. |
eligibilityColumn-level | tuva_last_runSQL emitted a timestamp, but the v0.18 dictionary incorrectly declared varchar. | tuva_last_runDeclared timestamp matching the existing physical SQL output. | Modified | Corrected stale contract metadata without changing the expression. | Documentation correction only: the fixed SQL column name or type did not change. |
encounterModel-level | encounterOne row per globally unique encounter_id; claims grouper identifiers could be renumbered and cross-source joins did not always include data_source. | encounterOne row per (encounter_id, data_source); claims IDs are deterministic 32-character source-scoped values, while clinical IDs remain source-native and source-scoped. Contract-valid undetermined claim lines receive a source-scoped orphaned claim encounter rather than a classified encounter. | Modified | Source-scoped grouping prevents unrelated claims with reused identifiers from colliding, deterministic IDs do not renumber when unrelated data changes, and the orphan fallback preserves undetermined claims without guessing their billing form. | Fully refresh encounter and rebuild stored claims encounter IDs. Update clinical uniqueness tests and downstream joins to include data_source; encounter and utilization counts can increase when undetermined claims were previously omitted. |
encounterColumn-level | encounter_idClinical source ID or unstable claims-grouper ID; treated as globally unique. | encounter_idClinical source ID scoped by data_source, or deterministic 32-character claims encounter ID. | Modified | Claims identity is now source-isolated and stable across unrelated data changes. | Rebuild all persisted claims encounter keys and ensure destination schemas support 32 characters; join clinical IDs with data_source. |
encounterColumn-level | encounter_groupClaims-derived rows used the canonical inpatient, outpatient, office based, or other group, while every clinical row was hard-coded to 'clinical' regardless of encounter_type. | encounter_groupClaims-derived rows use the canonical inpatient, outpatient, office based, or other group, including other for orphaned undetermined claims. Clinical rows derive those same groups from canonical encounter_type terminology; a null or unmatched encounter_type produces a null group. | Modified | Removes the noncanonical 'clinical' bucket, makes encounter-group analysis consistent across claims and clinical sources, and preserves undetermined claims without inferring a classified group. | No schema change. Fully refresh Core encounter and revalidate cross-source group analysis, FHIR resources, and quality-measure consumers because clinical rows can be reclassified. Claims utilization remains claims-only, but other_count and orphaned_claim_count can increase when undetermined claims are restored. |
encounterColumn-level | length_of_stayDocumented as number; claims supplied the grouper result and clinical rows passed through the mapped value. | length_of_stayinteger day count; clinical rows derive it from normalized start/end dates, with same-day encounters set to 1. | Modified | The type is narrowed to integer and clinical length of stay is calculated consistently from encounter dates. | No claims type expression changes; clinical values can change when the mapped duration differed from the date-derived result. |
encounterColumn-level | admit_source_descriptionClinical source description passed through; claims descriptions were terminology-derived. | admit_source_descriptionDescription derived from admit_source_code with Tuva admit-source terminology. | Modified | Clinical and claims encounters now use the same canonical description logic. | Expect source-specific clinical labels to change or become null when the code is not in Tuva terminology. |
encounterColumn-level | admit_type_descriptionClinical source description passed through; claims descriptions were terminology-derived. | admit_type_descriptionDescription derived from admit_type_code with Tuva admit-type terminology. | Modified | Clinical and claims encounters now use the same canonical description logic. | Expect source-specific clinical labels to change or become null when the code is not in Tuva terminology. |
encounterColumn-level | discharge_disposition_descriptionClinical source description passed through; claims descriptions were terminology-derived. | discharge_disposition_descriptionDescription derived from discharge_disposition_code with Tuva terminology. | Modified | Clinical and claims encounters now use the same canonical description logic. | Expect source-specific clinical labels to change or become null when the code is not in Tuva terminology. |
encounterColumn-level | primary_diagnosis_descriptionClinical source description passed through. | primary_diagnosis_descriptionTerminology long description derived from primary_diagnosis_code_type and primary_diagnosis_code for supported ICD systems. | Modified | The normalized description is consistent across sources and does not depend on connector-supplied display text. | Refresh cached labels and handle null for unsupported or unmatched codes. |
encounterColumn-level | drg_descriptionClinical source description passed through. | drg_descriptionTerminology description derived from drg_code_type and drg_code for supported MS-DRG and APR-DRG codes. | Modified | The normalized description is consistent across sources and does not depend on connector-supplied display text. | Refresh cached labels and handle null for unsupported or unmatched codes. |
encounterColumn-level | observation_flagDocumented as generic number; SQL already emitted an integer observation-stay flag. | observation_flaginteger observation-stay flag; 1 true, 0 false, null unknown or not applicable. | Modified | The dictionary now applies the public integer binary-flag contract to the existing SQL output. | No Core SQL type expression changed. Validate downstream domains that previously accepted values outside 1, 0, and null. |
encounterColumn-level | lab_flagDocumented as generic number; SQL already emitted an integer laboratory-service flag. | lab_flaginteger laboratory-service flag; 1 true, 0 false, null unknown or not applicable. | Modified | The dictionary now applies the public integer binary-flag contract to the existing SQL output. | No Core SQL type expression changed. Validate downstream domains that previously accepted values outside 1, 0, and null. |
encounterColumn-level | dme_flagDocumented as generic number; SQL already emitted an integer durable-medical-equipment flag. | dme_flaginteger durable-medical-equipment flag; 1 true, 0 false, null unknown or not applicable. | Modified | The dictionary now applies the public integer binary-flag contract to the existing SQL output. | No Core SQL type expression changed. Validate downstream domains that previously accepted values outside 1, 0, and null. |
encounterColumn-level | ambulance_flagDocumented as generic number; SQL already emitted an integer ambulance-service flag. | ambulance_flaginteger ambulance-service flag; 1 true, 0 false, null unknown or not applicable. | Modified | The dictionary now applies the public integer binary-flag contract to the existing SQL output. | No Core SQL type expression changed. Validate downstream domains that previously accepted values outside 1, 0, and null. |
encounterColumn-level | pharmacy_flagDocumented as generic number; SQL already emitted an integer pharmacy-service flag. | pharmacy_flaginteger pharmacy-service flag; 1 true, 0 false, null unknown or not applicable. | Modified | The dictionary now applies the public integer binary-flag contract to the existing SQL output. | No Core SQL type expression changed. Validate downstream domains that previously accepted values outside 1, 0, and null. |
encounterColumn-level | ed_flagDocumented as generic number; SQL already emitted an integer emergency-department flag. | ed_flaginteger emergency-department flag; 1 true, 0 false, null unknown or not applicable. | Modified | The dictionary now applies the public integer binary-flag contract to the existing SQL output. | No Core SQL type expression changed. Validate downstream domains that previously accepted values outside 1, 0, and null. |
encounterColumn-level | delivery_flagDocumented as generic number; SQL already emitted an integer delivery flag. | delivery_flaginteger delivery flag; 1 true, 0 false, null unknown or not applicable. | Modified | The dictionary now applies the public integer binary-flag contract to the existing SQL output. | No Core SQL type expression changed. Validate downstream domains that previously accepted values outside 1, 0, and null. |
encounterColumn-level | newborn_flagDocumented as generic number; SQL already emitted an integer newborn flag. | newborn_flaginteger newborn flag; 1 true, 0 false, null unknown or not applicable. | Modified | The dictionary now applies the public integer binary-flag contract to the existing SQL output. | No Core SQL type expression changed. Validate downstream domains that previously accepted values outside 1, 0, and null. |
encounterColumn-level | nicu_flagDocumented as generic number; SQL already emitted an integer NICU flag. | nicu_flaginteger NICU flag; 1 true, 0 false, null unknown or not applicable. | Modified | The dictionary now applies the public integer binary-flag contract to the existing SQL output. | No Core SQL type expression changed. Validate downstream domains that previously accepted values outside 1, 0, and null. |
encounterColumn-level | snf_part_b_flagDocumented as generic number; SQL already emitted an integer SNF Part B flag. | snf_part_b_flaginteger SNF Part B flag; 1 true, 0 false, null unknown or not applicable. | Modified | The dictionary now applies the public integer binary-flag contract to the existing SQL output. | No Core SQL type expression changed. Validate downstream domains that previously accepted values outside 1, 0, and null. |
encounterColumn-level | claim_countDocumented as generic number; SQL already emitted an integer claim count. | claim_countinteger claim count. | Modified | The dictionary now states the whole-number type already emitted by the Core SQL. | Documentation correction only: the fixed SQL column name or type did not change. |
encounterColumn-level | inst_claim_countDocumented as generic number; SQL already emitted an integer institutional-claim count. | inst_claim_countinteger institutional-claim count. | Modified | The dictionary now states the whole-number type already emitted by the Core SQL. | Documentation correction only: the fixed SQL column name or type did not change. |
encounterColumn-level | prof_claim_countDocumented as generic number; SQL already emitted an integer professional-claim count. | prof_claim_countinteger professional-claim count. | Modified | The dictionary now states the whole-number type already emitted by the Core SQL. | Documentation correction only: the fixed SQL column name or type did not change. |
encounterColumn-level | _dbt_source_relationDeclared in the v0.18 dictionary but never emitted by the fixed Core SQL. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | Removed a phantom internal field from the public dictionary. | No physical SQL column is dropped. Remove any schema expectation based only on the former dictionary entry. |
encounterColumn-level | patient_data_source_idDeclared in the v0.18 dictionary but never emitted by the fixed Core SQL. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | Removed a phantom internal grouper key from the public dictionary. | No physical SQL column is dropped. Use person_id and data_source for source-scoped analysis. |
encounterColumn-level | Not presentNot present in the v0.18.0 fixed Core output | ingest_datetimenullable timestamp from the originating clinical encounter; null for claims-derived encounters assembled from multiple claim lines. | Added | Adds source-record provenance where one source encounter exists and avoids attributing an arbitrary line timestamp to grouped claims encounters. | Add the nullable timestamp to downstream schemas and selects. Use it only for clinical-source provenance; claims-derived encounter rows publish null. |
immunizationModel-level | immunizationOne row per globally unique immunization_id. | immunizationOne row per (immunization_id, data_source). | Modified | Clinical source identifiers are scoped to their source system rather than required to be globally unique. | Fully refresh core.immunization and include data_source in downstream uniqueness tests and joins. |
immunizationColumn-level | normalized_code_typeConnector-supplied normalized value passed through. | normalized_code_typeDerived as cvx only when source_code_type and source_code match Tuva CVX terminology; otherwise null. | Modified | Tuva now owns the normalized immunization coding contract instead of honoring manual or custom normalized values. | Expect unsupported or unmatched source codes to produce null; remove connector logic that supplied this Core value. |
immunizationColumn-level | normalized_codeConnector-supplied normalized value passed through. | normalized_codeCVX code derived from Tuva terminology when the source CVX code matches; otherwise null. | Modified | Tuva now owns the normalized immunization coding contract. | Expect unsupported or unmatched source codes to produce null and refresh cached normalized codes. |
immunizationColumn-level | normalized_descriptionConnector-supplied normalized description passed through. | normalized_descriptionCVX long description derived from Tuva terminology when the code matches; otherwise null. | Modified | The display text is now reproducible from the package terminology asset. | Refresh cached labels and expect custom descriptions to be replaced or become null. |
immunizationColumn-level | normalized_doseConnector-supplied normalized dose passed through. | normalized_dosevarchar, currently always null; source_dose remains available. | Modified | Tuva 1.0 does not claim a canonical dose normalization that the package cannot support consistently. | Use source_dose or implement project-specific dose normalization downstream. |
immunizationColumn-level | mapping_methodvarchar normalization provenance. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | Normalization is package-owned and no longer exposes the legacy manual, automatic, or custom method label. | Remove downstream references to mapping_method. |
immunizationColumn-level | Not presentNot present in the v0.18.0 fixed Core output | ingest_datetimenullable timestamp for the source immunization warehouse load time. | Added | Adds source-record ingestion provenance to the public immunization output. | Add the nullable timestamp to downstream schemas and selects. Existing immunization grain and identifiers do not change. |
lab_resultModel-level | lab_resultOne row per globally unique lab_result_id. | lab_resultOne row per (lab_result_id, data_source). | Modified | Clinical source identifiers are scoped to their source system rather than required to be globally unique. | Fully refresh core.lab_result and include data_source in downstream uniqueness tests and joins. |
lab_resultColumn-level | normalized_order_typeConnector-supplied normalized order code system passed through. | normalized_order_typeDerived as loinc or snomed-ct only when the source order code matches the corresponding Tuva terminology asset. | Modified | Tuva now owns normalized order coding rather than honoring manual or custom normalized values. | Expect null for unsupported or unmatched codes and remove connector-supplied normalization dependencies. |
lab_resultColumn-level | normalized_order_codeConnector-supplied normalized order code passed through. | normalized_order_codeLOINC or SNOMED CT code derived from the matching Tuva terminology asset. | Modified | Normalization is reproducible and package-owned. | Refresh cached codes and expect custom or unmatched mappings to become null. |
lab_resultColumn-level | normalized_order_descriptionConnector-supplied normalized order description passed through. | normalized_order_descriptionLOINC long common name or SNOMED CT description derived from Tuva terminology. | Modified | Display text now follows the package terminology version. | Refresh cached labels and equality-based tests that used connector descriptions. |
lab_resultColumn-level | normalized_component_typeConnector-supplied normalized component code system passed through. | normalized_component_typeDerived as loinc or snomed-ct only when the source component code matches the corresponding terminology asset. | Modified | Tuva now owns normalized component coding rather than honoring manual or custom normalized values. | Expect null for unsupported or unmatched codes and remove connector-supplied normalization dependencies. |
lab_resultColumn-level | normalized_component_codeConnector-supplied normalized component code passed through. | normalized_component_codeLOINC or SNOMED CT code derived from the matching Tuva terminology asset. | Modified | Normalization is reproducible and package-owned. | Refresh cached codes and expect custom or unmatched mappings to become null. |
lab_resultColumn-level | normalized_component_descriptionConnector-supplied normalized component description passed through. | normalized_component_descriptionLOINC long common name or SNOMED CT description derived from Tuva terminology. | Modified | Display text now follows the package terminology version. | Refresh cached labels and equality-based tests that used connector descriptions. |
lab_resultColumn-level | source_abnormal_flagvarchar categorical interpretation named source_abnormal_flag. | source_abnormal_codevarchar source abnormal-result code or interpretation. | ModifiedRenamed | Renamed the field because values such as high, low, or abnormal are categorical rather than binary flags. | Replace source_abnormal_flag with source_abnormal_code in selects, schemas, and applications. |
lab_resultColumn-level | normalized_abnormal_flagvarchar categorical interpretation named normalized_abnormal_flag. | normalized_abnormal_codevarchar normalized abnormal-result code or interpretation. | ModifiedRenamed | Renamed the field because the domain is categorical rather than a 1/0/null flag. | Replace normalized_abnormal_flag with normalized_abnormal_code in selects, schemas, and applications. |
lab_resultColumn-level | mapping_methodvarchar normalization provenance. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | Normalization is package-owned and no longer exposes the legacy manual, automatic, or custom method label. | Remove downstream references to mapping_method. |
lab_resultColumn-level | Not presentNot present in the v0.18.0 fixed Core output | ingest_datetimenullable timestamp for the source lab-result warehouse load time. | Added | Adds source-record ingestion provenance to the public lab-result output. | Add the nullable timestamp to downstream schemas and selects. Existing lab-result grain and identifiers do not change. |
locationModel-level | locationClaims-derived rows were collapsed to one row per organization NPI across all medical and pharmacy claim sources, published data_source as null, and asserted location_id as globally unique. | locationOne row per (location_id, data_source). Clinical rows retain their mapped source; claims-derived rows retain the medical or pharmacy claim source and are deduplicated by organization NPI within that source. When clinical and claims-derived rows share the exact key, the clinical row takes precedence. | Modified | Source location identifiers require source context, and the source-native Core contract preserves every feed in which a claims provider NPI is observed. Clinical precedence preserves the richer source record without violating the composite key. | Fully refresh core.location and every dependent relation. Include data_source in downstream keys and joins: location_id alone is no longer unique and ID-only joins can fan out when the same NPI appears in multiple claim sources. Row counts can increase across sources, while an exact same-source clinical and claims overlap resolves to the clinical row. |
locationColumn-level | Not presentNot present in the v0.18.0 fixed Core output | ingest_datetimenullable timestamp from the originating clinical location; null for claims-derived locations assembled from provider and claim data. | Added | Adds source-record provenance where one clinical location record exists without assigning a synthetic timestamp to claims-derived locations. | Add the nullable timestamp to downstream schemas and selects. Claims-derived location rows publish null. |
medical_claimModel-level | medical_claimOne row per medical_claim_id; encounter and service-category enrichment joined on claim_id and claim_line_number without consistently including data_source, and contract-valid claim_type = 'undetermined' lines were omitted. | medical_claimThe same medical_claim_id grain, with enrichment joined on claim_id, claim_line_number, and data_source. Contract-valid claim_type = 'undetermined' lines are retained with other / other / other service categories and a source-scoped orphaned claim encounter. | Modified | Source-scoped enrichment prevents claims feeds that reuse identifiers from contaminating one another, while the conservative fallback preserves undetermined claims without guessing professional or institutional semantics. | Fully refresh core.medical_claim and revalidate cross-source identifier collisions. Row counts and amounts can increase for undetermined claims, affecting downstream practitioner, location, attribution, cost, and utilization outputs. The medical_claim_id algorithm itself is unchanged. |
medical_claimColumn-level | claim_line_numberDocumented as generic number; SQL already emitted an integer claim line number. | claim_line_numberinteger claim line number. | Modified | The dictionary now states the whole-number type already emitted by the Core SQL. | Documentation correction only: the fixed SQL column name or type did not change. |
medical_claimColumn-level | encounter_idJoined to encounter outputs by claim_id and claim_line_number without data_source. | encounter_idJoined by claim_id, claim_line_number, and data_source; claim_type = 'undetermined' lines receive the source-scoped orphaned claim encounter ID. | Modified | Source scoping prevents an identically keyed line from another claims feed from supplying the encounter assignment, and the orphan fallback avoids guessing a classified encounter. | Fully refresh core.medical_claim; encounter assignments can change for cross-source identifier collisions and previously omitted undetermined lines are added. |
medical_claimColumn-level | encounter_typeJoined to encounter outputs without data_source isolation. | encounter_typeTaken from the source-scoped encounter assignment; claim_type = 'undetermined' lines use orphaned claim. | Modified | The type belongs to the same source claim line without inferring a professional or institutional classification. | Revalidate rows where multiple data sources reuse claim identifiers and logic that filters orphaned claims. |
medical_claimColumn-level | encounter_groupJoined to encounter outputs without data_source isolation. | encounter_groupTaken from the source-scoped encounter assignment; claim_type = 'undetermined' lines use other. | Modified | The group belongs to the same source claim line without inferring a professional or institutional classification. | Revalidate rows where multiple data sources reuse claim identifiers and logic that filters the other encounter group. |
medical_claimColumn-level | claim_start_dateNative DATE was normalized through membership in the bounded published daily calendar. | claim_start_dateNative DATE passes through without a terminology-calendar membership join. | Modified | Logical Data Quality reports unreasonable values without normalization erasing the source date. | Out-of-calendar dates remain visible instead of becoming null; refresh tests or filters that expected null. |
medical_claimColumn-level | claim_end_dateNative DATE was normalized through membership in the bounded published daily calendar. | claim_end_dateNative DATE passes through without a terminology-calendar membership join. | Modified | Logical Data Quality reports unreasonable values without normalization erasing the source date. | Out-of-calendar dates remain visible instead of becoming null; refresh tests or filters that expected null. |
medical_claimColumn-level | claim_line_start_dateNative DATE was normalized through membership in the bounded published daily calendar. | claim_line_start_dateNative DATE passes through without a terminology-calendar membership join. | Modified | Logical Data Quality reports unreasonable values without normalization erasing the source date. | Out-of-calendar dates remain visible instead of becoming null; refresh tests or filters that expected null. |
medical_claimColumn-level | claim_line_end_dateNative DATE was normalized through membership in the bounded published daily calendar. | claim_line_end_dateNative DATE passes through without a terminology-calendar membership join. | Modified | Logical Data Quality reports unreasonable values without normalization erasing the source date. | Out-of-calendar dates remain visible instead of becoming null; refresh tests or filters that expected null. |
medical_claimColumn-level | admission_dateNative DATE was normalized through membership in the bounded published daily calendar. | admission_dateNative DATE passes through without a terminology-calendar membership join. | Modified | Logical Data Quality reports unreasonable values without normalization erasing the source date. | Out-of-calendar dates remain visible instead of becoming null; refresh tests or filters that expected null. |
medical_claimColumn-level | discharge_dateNative DATE was normalized through membership in the bounded published daily calendar. | discharge_dateNative DATE passes through without a terminology-calendar membership join. | Modified | Logical Data Quality reports unreasonable values without normalization erasing the source date. | Out-of-calendar dates remain visible instead of becoming null; refresh tests or filters that expected null. |
medical_claimColumn-level | service_category_1Joined to the service-category grouper without data_source isolation. | service_category_1Joined by claim_id, claim_line_number, and data_source; claim_type = 'undetermined' lines use other. | Modified | The category belongs to the same source claim line, and the fallback preserves undetermined claims without guessing their billing form. | Fully refresh and revalidate cross-source identifier collisions and downstream category totals, which can increase for other. |
medical_claimColumn-level | service_category_2Joined to the service-category grouper without data_source isolation. | service_category_2Joined by claim_id, claim_line_number, and data_source; claim_type = 'undetermined' lines use other. | Modified | The category belongs to the same source claim line, and the fallback preserves undetermined claims without guessing their billing form. | Fully refresh and revalidate cross-source identifier collisions and downstream category totals, which can increase for other. |
medical_claimColumn-level | service_category_3Joined to the service-category grouper without data_source isolation. | service_category_3Joined by claim_id, claim_line_number, and data_source; claim_type = 'undetermined' lines use other. | Modified | The category belongs to the same source claim line, and the fallback preserves undetermined claims without guessing their billing form. | Fully refresh and revalidate cross-source identifier collisions and downstream category totals, which can increase for other. |
medical_claimColumn-level | in_network_flagDocumented as generic number; SQL already emitted an integer in-network flag. | in_network_flaginteger in-network flag; 1 true, 0 false, null unknown or not applicable. | Modified | The dictionary now applies the public integer binary-flag contract to the existing SQL output. | No Core SQL type expression changed. Validate downstream domains that previously accepted values outside 1, 0, and null. |
medical_claimColumn-level | enrollment_flagDocumented as number; set from eligibility matching that depended on the bounded calendar-derived member-month output. | enrollment_flaginteger binary flag; source-scoped eligibility matching uses the complete 1900-2100 month spine and stops at the tuva_last_run month. | Modified | The field follows the public 1/0/null flag contract, and valid matching spans no longer disappear because of the published daily calendar boundary. | Fully refresh. Flags can change where prior enrollment matching was lost to calendar bounds or cross-source collisions. |
medical_claimColumn-level | member_month_keyColumn named member_month_key; v0.18 dictionary said number although SQL emitted the six-component string key. | member_month_idvarchar member-month identifier matched on person, member, payer, plan, source, and service month. | ModifiedRenamed | Renamed the key to the package-wide _id convention and corrected its declared string type. | Replace member_month_key with member_month_id and fully refresh claim and member-month relations. |
medical_claimColumn-level | file_datetimestamp. | file_dateNative SQL DATE; YYYY-MM-DD when serialized. | Modified | A file date is a calendar date and does not carry a time of day. | Fully refresh core.medical_claim and update downstream timestamp casts or schemas to DATE. |
medical_claimColumn-level | file_namePhysically emitted by v0.18 SQL but omitted from its Core dictionary. | file_nameDeclared varchar source file name. | Modified | The dictionary now documents the existing lineage column. | Documentation correction only: the fixed SQL column name or type did not change. |
medicationModel-level | medicationClinical medication records only; one row per globally unique medication_id. | medicationClinical medication records plus adjudicated pharmacy-claim lines; one row per (medication_id, source_type, data_source). Clinical and claims identifiers remain source-native and can overlap within a data source. | Modified | A unified medication table supports medication analysis across clinical and claims sources while preserving source-specific linkage fields. | Fully refresh core.medication. Expect materially more rows when claims are enabled, add source_type filters where source population matters, and include source_type and data_source in key joins. |
medicationColumn-level | medication_idSource clinical medication identifier treated as globally unique. | medication_idClinical source identifier scoped by data_source; claims rows reuse pharmacy_claim_id. | Modified | The identifier remains traceable to its source while supporting the new claims population. | Use (medication_id, source_type, data_source) as the key. Include source_type in downstream joins and uniqueness tests so a clinical identifier cannot collide with a pharmacy_claim_id. |
medicationColumn-level | Not presentNot present in the v0.18.0 fixed Core output | source_typevarchar with claims or clinical. | Added | Identifies which source population supplied each row in the unified model. | Use source_type when an analysis should include only clinical orders/administrations or only adjudicated pharmacy claims. |
medicationColumn-level | Not presentNot present in the v0.18.0 fixed Core output | member_idvarchar payer member identifier on claims rows; null on clinical rows. | Added | Carries payer-member linkage from core.pharmacy_claim. | Claims medication rows can now join to member-level claims outputs; handle null for clinical rows. |
medicationColumn-level | Not presentNot present in the v0.18.0 fixed Core output | claim_idvarchar pharmacy claim identifier on claims rows; null on clinical rows. | Added | Preserves the adjudicated claim linkage in the unified model. | Use with data_source and claim_line_number for claims reconciliation; handle null for clinical rows. |
medicationColumn-level | Not presentNot present in the v0.18.0 fixed Core output | claim_line_numberinteger pharmacy claim line number on claims rows; null on clinical rows. | Added | Preserves line-level adjudicated claim linkage in the unified model. | Use with claim_id and data_source for claims reconciliation; update fixed schemas for the new integer column. |
medicationColumn-level | Not presentNot present in the v0.18.0 fixed Core output | payervarchar payer on claims rows; null on clinical rows. | Added | Carries payer context from core.pharmacy_claim. | Claims medication rows can be segmented by payer; handle null for clinical rows. |
medicationColumn-level | Not presentNot present in the v0.18.0 fixed Core output | planvarchar plan on claims rows; null on clinical rows. | Added | Carries health-plan context from core.pharmacy_claim. | Claims medication rows can be segmented by plan; handle null for clinical rows. |
medicationColumn-level | ndc_codeClinical-only value supplied upstream or derived from source NDC terminology. | ndc_codeClinical values pass through or derive from a matching CodeRx package; claims rows use pharmacy_claim.ndc_code. CodeRx Open is the default, or all lookups use user-managed CodeRx Enterprise relations when enabled. | Modified | The same field now covers both source populations through one selected CodeRx interface. | Review counts and null rates by source_type. Fully refresh after selecting Open or Enterprise; Enterprise mode does not fall back to the bundled Open assets. |
medicationColumn-level | ndc_descriptionClinical-only NDC description enriched from Tuva terminology when available. | ndc_descriptionCodeRx package drug_name for a matched NDC on clinical and claims rows; unmatched values remain null. CodeRx Open is the default, or the user-managed Enterprise packages relation supplies all values when enabled. | Modified | The unified model now uses the selected CodeRx package interface instead of the legacy NDC terminology relation. | Fully refresh and review descriptions and null rates. Values can change with the CodeRx snapshot, and Enterprise mode does not fall back to Open data. |
medicationColumn-level | rxnorm_codeClinical-only value supplied upstream or derived through NDC/RxNorm mappings. | rxnorm_codeClinical values pass through or derive from the selected CodeRx drug; claims rows derive through a matching CodeRx package when available. | Modified | The same field now covers both populations through the shared CodeRx package and drug interfaces. | Fully refresh and review counts and null rates by source_type; unmatched NDCs and RxNorm concepts remain null. |
medicationColumn-level | rxnorm_descriptionClinical-only RxNorm description enriched from terminology when available. | rxnorm_descriptionCodeRx drug_name for a matched RxNorm concept, or the matched package drug_name when that is the available claims mapping. | Modified | The unified claims population receives the same selected CodeRx display contract as clinical data. | Fully refresh cached values and review CodeRx-version text and null changes. |
medicationColumn-level | atc_codeClinical-only value supplied upstream or derived through RxNorm-to-ATC mappings. | atc_codeClinical values pass through when supplied; otherwise clinical and claims rows derive the deterministic level-3 ATC code from the selected CodeRx classes relation. | Modified | The same field now covers both source populations through one CodeRx class hierarchy. | Fully refresh and review counts and null rates. When a drug has multiple class rows, Tuva selects the lexicographically first non-null level-3 code. |
medicationColumn-level | atc_descriptionClinical-only ATC description enriched from terminology when available. | atc_descriptionDescription from the matching level in the selected CodeRx class hierarchy; derived rows use the deterministic level-3 class name. | Modified | The unified claims population receives the same selected CodeRx class contract as clinical data. | Fully refresh cached values and review CodeRx-version text and classification changes. |
medicationColumn-level | quantityDocumented as generic number; SQL already emitted an integer dispensed quantity. | quantityinteger dispensed quantity. | Modified | The dictionary now states the whole-number type already emitted by the Core SQL. | Documentation correction only: the fixed SQL column name or type did not change. |
medicationColumn-level | days_supplyDocumented as generic number; SQL already emitted an integer days-supply value. | days_supplyinteger days-supply value. | Modified | The dictionary now states the whole-number type already emitted by the Core SQL. | Documentation correction only: the fixed SQL column name or type did not change. |
medicationColumn-level | ndc_mapping_methodvarchar NDC mapping provenance. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | Removed the legacy manual, automatic, or custom method label. | Remove downstream references; inspect ndc_code presence and package terminology lineage instead. |
medicationColumn-level | rxnorm_mapping_methodvarchar RxNorm mapping provenance. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | Removed the legacy manual, automatic, or custom method label. | Remove downstream references; inspect rxnorm_code presence and package terminology lineage instead. |
medicationColumn-level | atc_mapping_methodvarchar ATC mapping provenance. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | Removed the legacy manual, automatic, or custom method label. | Remove downstream references; inspect atc_code presence and package terminology lineage instead. |
medicationColumn-level | Not presentNot present in the v0.18.0 fixed Core output | ingest_datetimenullable timestamp from the originating clinical medication or adjudicated pharmacy-claim line. | Added | Carries source-record ingestion provenance across both populations in the unified medication model. | Add the nullable timestamp to downstream schemas and selects. Review null handling for source records whose ingestion time is unavailable. |
member_monthModel-level | member_monthsModel member_months expanded eligibility through the bounded published daily calendar, projected eligibility extension columns into member months, and tested the key with data_source. | member_monthModel member_month uses a complete package-owned 190001-210012 month spine, caps finite and open spans at the tuva_last_run month, joins payer/custom/Tuva attribution, and is keyed by member_month_id. Eligibility extension columns do not propagate to this different-grain output. | ModifiedRenamed | The singular name follows Core conventions, removes data loss at the daily-calendar boundary, prevents future member months, centralizes attribution context, and limits extensions to their supported same-named Core table. | Replace refs to member_months with member_month, fully refresh member-month and claim enrollment outputs, and rebuild persisted keys and attribution consumers. Move any eligibility-extension enrichment into an explicit downstream join or aggregation with a documented grain rule. |
member_monthColumn-level | member_month_keyColumn named member_month_key; v0.18 dictionary said number although SQL emitted a string from person_id, member_id, year_month, payer, plan, and data_source. | member_month_idvarchar primary key built from the same six components. | ModifiedRenamed | Renamed the field to the package-wide _id convention, corrected its declared type, and made the single generated key the declared grain. | Replace member_month_key with member_month_id in joins, tests, schemas, and stored downstream outputs. |
member_monthColumn-level | Not presentNot present in the v0.18.0 fixed Core output | tuva_attributed_providervarchar provider assigned by Tuva claims-based yearly attribution for the same person, data source, and calendar year. | Added | Makes Tuva provider assignment available at member-month grain alongside payer and custom attribution. | Adopt when useful and handle null when attribution is disabled or no assignable history exists. |
member_monthColumn-level | Not presentNot present in the v0.18.0 fixed Core output | tuva_attributed_provider_bucketvarchar attribution classification such as PCP, NPP, specialist, or no eligible history. | Added | Exposes the provider-selection bucket that explains the Tuva assignment. | Adopt when useful and handle null when attribution is not available. |
member_monthColumn-level | Not presentNot present in the v0.18.0 fixed Core output | tuva_attributed_provider_specialtyvarchar specialty description for the Tuva-attributed provider. | Added | Carries attribution specialty context directly to member-month analyses. | Adopt when useful and handle null when provider specialty or attribution is unavailable. |
observationModel-level | observationOne row per globally unique observation_id. | observationOne row per (observation_id, data_source). | Modified | Clinical source identifiers are scoped to their source system rather than required to be globally unique. | Fully refresh core.observation and include data_source in downstream uniqueness tests and joins. |
observationColumn-level | normalized_code_typeCould honor connector-supplied normalized values or legacy manual/custom mappings. | normalized_code_typeDerived only from source_code_type and source_code using supported Tuva terminology; ICD-9-PCS correctly yields icd-9-pcs. | Modified | Package-owned normalization is reproducible and fixes the former ICD-9-PCS code-system label defect. | Expect custom or unmatched mappings to become null and update any logic that compensated for the former ICD-10-PCS mislabel. |
observationColumn-level | normalized_codeCould honor connector-supplied normalized values or legacy manual/custom mappings. | normalized_codeDerived from supported ICD, HCPCS, SNOMED CT, or LOINC terminology using source coding. | Modified | Tuva now owns one reproducible normalized-code path. | Refresh cached codes and expect unsupported or unmatched values to be null. |
observationColumn-level | normalized_descriptionCould honor connector-supplied descriptions or legacy manual/custom mappings. | normalized_descriptionDerived from the package terminology description for normalized_code. | Modified | Display text now follows the installed Tuva terminology snapshot. | Refresh cached labels and equality-based tests; unmatched codes yield null. |
observationColumn-level | mapping_methodvarchar normalization provenance. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | Normalization is package-owned and no longer exposes the legacy manual, automatic, or custom method label. | Remove downstream references to mapping_method. |
observationColumn-level | Not presentNot present in the v0.18.0 fixed Core output | ingest_datetimenullable timestamp for the source observation warehouse load time. | Added | Adds source-record ingestion provenance to the public observation output. | Add the nullable timestamp to downstream schemas and selects. Existing observation grain and identifiers do not change. |
patientModel-level | patientOne row per globally unique person_id; eligibility extension columns could be copied onto claims-derived patient rows. | patientOne row per (person_id, data_source), with source-scoped deduplication; a claims row takes precedence over a clinical row for the same person and source. Only extensions from the same-named patient input are supported, and only on retained clinical patient rows; eligibility extensions do not propagate. | Modified | The same person can legitimately have one record in multiple source systems, duplicate representations inside one source resolve deterministically, and extensions remain at the grain of their supported same-named Core table. | Fully refresh core.patient. Include data_source in uniqueness tests and joins, review results where claims and clinical records share person_id and data_source, and move any eligibility-extension enrichment into an explicit downstream join with a documented selection rule. |
patientColumn-level | birth_dateNative DATE, but normalization required the value to exist in the bounded published daily calendar. | birth_dateNative DATE passed through without a terminology-calendar membership join. | Modified | Logical Data Quality reports unreasonable values without normalization erasing the source date. | Out-of-calendar values remain visible rather than becoming null; age can therefore change for affected rows after refresh. |
patientColumn-level | death_dateNative DATE, but normalization required the value to exist in the bounded published daily calendar. | death_dateNative DATE passed through without a terminology-calendar membership join. | Modified | Logical Data Quality reports unreasonable values without normalization erasing the source date. | Out-of-calendar values remain visible rather than becoming null; update tests that expected the former null. |
patientColumn-level | Not presentNot present in the v0.18.0 fixed Core output | ingest_datetimenullable timestamp from the selected clinical patient record; null for patient rows derived from claims eligibility. | Added | Adds source-record provenance when a clinical patient record supplies the Core row while keeping claims-derived patient provenance honest. | Add the nullable timestamp to downstream schemas and selects. Do not expect eligibility ingest_datetime to populate claims-derived Core patient rows. |
patientColumn-level | death_flagDocumented as generic number; SQL already emitted an integer deceased flag. | death_flaginteger deceased flag; 1 true, 0 false, null unknown or not applicable. | Modified | The dictionary now applies the public integer binary-flag contract to the existing SQL output. | No Core SQL type expression changed. Validate downstream domains that previously accepted values outside 1, 0, and null. |
patientColumn-level | ageDocumented as generic number; SQL already emitted an integer age in completed years. | ageinteger age in completed years. | Modified | The dictionary now states the whole-number type already emitted by the Core SQL. | Documentation correction only: the fixed SQL column name or type did not change. |
pharmacy_claimColumn-level | claim_line_numberDocumented as generic number; SQL already emitted an integer claim line number. | claim_line_numberinteger claim line number. | Modified | The dictionary now states the whole-number type already emitted by the Core SQL. | Documentation correction only: the fixed SQL column name or type did not change. |
pharmacy_claimColumn-level | quantityDocumented as generic number; SQL already emitted an integer dispensed quantity. | quantityinteger dispensed quantity. | Modified | The dictionary now states the whole-number type already emitted by the Core SQL. | Documentation correction only: the fixed SQL column name or type did not change. |
pharmacy_claimColumn-level | days_supplyDocumented as generic number; SQL already emitted an integer days-supply value. | days_supplyinteger days-supply value. | Modified | The dictionary now states the whole-number type already emitted by the Core SQL. | Documentation correction only: the fixed SQL column name or type did not change. |
pharmacy_claimColumn-level | refillsDocumented as generic number; SQL already emitted an integer refill count. | refillsinteger refill count. | Modified | The dictionary now states the whole-number type already emitted by the Core SQL. | Documentation correction only: the fixed SQL column name or type did not change. |
pharmacy_claimColumn-level | in_network_flagDocumented as generic number; SQL already emitted an integer in-network flag. | in_network_flaginteger in-network flag; 1 true, 0 false, null unknown or not applicable. | Modified | The dictionary now applies the public integer binary-flag contract to the existing SQL output. | No Core SQL type expression changed. Validate downstream domains that previously accepted values outside 1, 0, and null. |
pharmacy_claimColumn-level | ndc_descriptionDerived from the legacy NDC terminology relation when ndc_code matched. | ndc_descriptionDerived from drug_name in the selected CodeRx packages relation when ndc_code matches. CodeRx Open is the default; optional Enterprise mode reads only the user-managed coderx.packages source. | Modified | Replaces the legacy NDC asset with the shared CodeRx interface used by pharmacy normalization, medication enrichment, Data Quality, and dependent packages. | Fully refresh core.pharmacy_claim and medication consumers. Descriptions and null rates can change; Enterprise mode requires complete user-managed relations and does not fall back to Open assets. |
pharmacy_claimColumn-level | enrollment_flagDocumented as number; set from eligibility matching that depended on the bounded calendar-derived member-month output. | enrollment_flaginteger binary flag; source-scoped eligibility matching uses the complete 1900-2100 month spine and stops at the tuva_last_run month. | Modified | The field follows the public 1/0/null flag contract, and valid matching spans no longer disappear because of the published daily calendar boundary. | Fully refresh. Flags can change where prior enrollment matching was lost to calendar bounds or cross-source collisions. |
pharmacy_claimColumn-level | member_month_keyColumn named member_month_key; v0.18 dictionary said number although SQL emitted the six-component string key. | member_month_idvarchar member-month identifier matched on person, member, payer, plan, source, and dispensing month. | ModifiedRenamed | Renamed the key to the package-wide _id convention and corrected its declared string type. | Replace member_month_key with member_month_id and fully refresh claim and member-month relations. |
pharmacy_claimColumn-level | file_datetimestamp. | file_dateNative SQL DATE; YYYY-MM-DD when serialized. | Modified | A file date is a calendar date and does not carry a time of day. | Fully refresh core.pharmacy_claim and update downstream timestamp casts or schemas to DATE. |
pharmacy_claimColumn-level | file_namePhysically emitted by v0.18 SQL but omitted from its Core dictionary. | file_nameDeclared varchar source file name. | Modified | The dictionary now documents the existing lineage column. | Documentation correction only: the fixed SQL column name or type did not change. |
practitionerModel-level | practitionerClaims-derived rows were collapsed to one row per individual NPI across all medical and pharmacy claim sources, published data_source as null, and asserted practitioner_id as globally unique. | practitionerOne row per (practitioner_id, data_source). Clinical rows retain their mapped source; claims-derived rows retain the medical or pharmacy claim source and are deduplicated by practitioner NPI within that source. When clinical and claims-derived rows share the exact key, the clinical row takes precedence. | Modified | Source practitioner identifiers require source context, and the source-native Core contract preserves every feed in which a claims provider NPI is observed. Clinical precedence preserves the richer source record without violating the composite key. | Fully refresh core.practitioner and every dependent relation. Include data_source in downstream keys and joins: practitioner_id alone is no longer unique and ID-only joins can fan out when the same NPI appears in multiple claim sources. Row counts can increase across sources, while an exact same-source clinical and claims overlap resolves to the clinical row. |
practitionerColumn-level | provider_first_namev0.18 dictionary named the field provider_first_name, but both v0.18 and 1.0 SQL emitted first_name. | first_nameDeclared varchar first_name matching the physical Core output. | ModifiedRenamed | Corrected the public dictionary to the long-standing SQL column name; this is not a runtime rename. | If schemas were generated from v0.18 YAML, replace provider_first_name with first_name. Existing SQL selecting first_name is unchanged. |
practitionerColumn-level | provider_last_namev0.18 dictionary named the field provider_last_name, but both v0.18 and 1.0 SQL emitted last_name. | last_nameDeclared varchar last_name matching the physical Core output. | ModifiedRenamed | Corrected the public dictionary to the long-standing SQL column name; this is not a runtime rename. | If schemas were generated from v0.18 YAML, replace provider_last_name with last_name. Existing SQL selecting last_name is unchanged. |
practitionerColumn-level | Not presentNot present in the v0.18.0 fixed Core output | ingest_datetimenullable timestamp from the originating clinical practitioner; null for claims-derived practitioners assembled from provider and claim data. | Added | Adds source-record provenance where one clinical practitioner record exists without fabricating a timestamp for claims-derived rows. | Add the nullable timestamp to downstream schemas and selects. Claims-derived practitioner rows publish null. |
procedureColumn-level | procedure_idClinical source ID passed through; claims used delimiter concatenation with less explicit domain and component handling. | procedure_idTuva-generated collision-safe 32-character lowercase hash: clinical identity uses the clinical domain, data_source, and source procedure ID; claims identity includes source, claim, encounter, sequence, code system/code, date, modifiers, and practitioner when present. | Modified | Clinical and claims procedures have explicit domain-separated identities with unambiguous component and null encoding; claims components distinguish otherwise similar procedures. | Fully refresh core.procedure and every persisted downstream key or join; do not join refreshed rows to pre-refresh procedure_id values. |
procedureColumn-level | encounter_idClaims procedures joined to a distinct claim encounter by claim_id without data_source; clinical values passed through. | encounter_idClaims HCPCS rows use the source-scoped claim-line encounter assignment; claim-header procedures use a source-scoped claim encounter; clinical values pass through. | Modified | The encounter link can no longer come from an identically keyed claim in another source and is more precise for line procedures. | Fully refresh and revalidate procedures where claim identifiers repeat across sources or a claim spans multiple encounters. |
procedureColumn-level | claim_idClaims rows retained claim_id; clinical rows could pass through an Input Layer claim_id. | claim_idClaims rows retain claim_id; clinical rows are null because clinical procedure input no longer carries a claim link. | Modified | This keeps source clinical procedures separate from procedures derived from medical claims. | Remove clinical workflows that relied on input_layer.procedure.claim_id; use claim_id only for claims-derived rows. |
procedureColumn-level | procedure_dateDictionary declared varchar although SQL emitted DATE; claims normalization required header procedure dates to exist in the bounded daily calendar. | procedure_dateDeclared native SQL DATE; typed claim procedure dates pass through without a terminology-calendar membership join. | Modified | The dictionary now matches SQL, and Logical Data Quality can report unreasonable dates without normalization erasing them. | No type expression changes for ordinary rows, but out-of-calendar claim procedure dates can now remain populated after full refresh. |
procedureColumn-level | source_code_typevarchar source code-system field named source_code_type. | code_systemvarchar source code system for clinical and claims-derived procedures. | ModifiedRenamed | Renamed the field to the package-wide code_system convention. | Replace source_code_type with code_system in downstream selects and joins. |
procedureColumn-level | normalized_codeCould honor connector-supplied values or legacy manual/custom mappings in Core. | normalized_codeDerived in the Normalized Layer from source coding with supported ICD-10-PCS, ICD-9-PCS, HCPCS, and SNOMED CT terminology. | Modified | Tuva now owns one reproducible procedure normalization path. | Refresh cached codes and expect unsupported, custom-only, or unmatched mappings to become null. |
procedureColumn-level | normalized_descriptionCould honor connector-supplied descriptions or legacy manual/custom mappings in Core. | normalized_descriptionDerived from the package terminology description for normalized_code. | Modified | Display text now follows the installed terminology snapshot. | Refresh cached labels and equality-based tests; unmatched codes yield null. |
procedureColumn-level | Not presentNot present in the v0.18.0 fixed Core output | procedure_familyvarchar analytic family from the Tuva Procedure Grouper for mapped ICD-10-PCS codes. | Added | Provides a reusable higher-level grouping without duplicating the mapping downstream. | Adopt when useful; unsupported or unmapped code systems remain null. |
procedureColumn-level | Not presentNot present in the v0.18.0 fixed Core output | procedure_namevarchar mutually exclusive analytic procedure from the Tuva Procedure Grouper for mapped ICD-10-PCS codes. | Added | Exposes a reusable procedure label alongside procedure_family. | Adopt when useful and handle null for unsupported or unmapped codes. |
procedureColumn-level | normalized_code_typevarchar normalized procedure code system. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | The normalized code system duplicated code_system after terminology matching. | Use code_system with normalized_code. |
procedureColumn-level | mapping_methodvarchar normalization provenance. | Not presentRemoved from the fixed Tuva 1.0 Core contract | Removed | Normalization is package-owned and no longer exposes the legacy manual, automatic, or custom method label. | Remove downstream references to mapping_method. |
procedureColumn-level | Not presentNot present in the v0.18.0 fixed Core output | ingest_datetimenullable timestamp from the originating clinical procedure or medical-claim line; null when a claims-derived procedure cannot be tied reliably to one claim line. | Added | Preserves source-record provenance for clinical and line-level HCPCS procedures without assigning an arbitrary timestamp to claim-header procedures. | Add the nullable timestamp to downstream schemas and selects. Handle null for claim-header and other claims-derived procedures without reliable line provenance. |
utilizationModel-level | Not presentNo fixed Core model | utilizationOne row per (person_id, member_id, year_month, payer, plan, data_source), with 56 fixed columns and member_month_id as the primary key; encounter counts by analytic category plus provider attribution. | Added | Moves foundational member-month utilization concepts formerly embedded in Financial PMPM into Core without reproducing every legacy PMPM summary. | Build the new model if needed and point analyses at its documented measures. Do not assume it is a drop-in replacement for every Financial PMPM relation. |
Cross-cutting Core upgrade effects
- Rebuild as one coordinated migration. Build 1.0 into the separate output
location described in the upgrade steps. Identity changes in eligibility,
claims encounters, patient-source records, conditions, and procedures flow into foreign keys,
standalone packages, FHIR resources, exports, and application joins. Rebuild
every persisted dependent relation after Core. dbt does not automatically
drop a relation when a model is renamed, so remove the stale
core.member_monthsrelation only after consumers usecore.member_month. - Use source-scoped provider keys.
core.locationandcore.practitionernow use source-scoped composite keys:(location_id, data_source)and(practitioner_id, data_source). Claims-derived rows retain the medical or pharmacy claim source instead of collapsing the same NPI across all sources; when an exact source key also has a clinical row, the clinical row wins. Fully refresh these models and their dependents, and includedata_sourcein downstream keys and joins. ID-only joins can fan out when the same provider NPI appears in multiple sources, and provider-dimension row counts can rise. - Terminology-derived normalization. For the affected clinical concepts,
1.0 derives supported normalized values from Tuva terminology rather than
accepting connector, manual, or custom Normalize-engine values. The related
mapping_methodfields are removed. Review custom mappings and any consumer that expects a normalized value to remain populated. - Dates and calendars. All 28 Core calendar-date fields are native SQL
DATEvalues and useYYYY-MM-DDonly when serialized. The physical type changes are the threefile_datefields in eligibility, medical claim, and pharmacy claim; other v0.18 type discrepancies were documentation metadata. Already-typed claim, eligibility, patient, and procedure dates no longer become null merely because they fall outside the daily calendar. Member-month expansion uses its own complete190001through210012month spine and never emits months aftertuva_last_run. - Open eligibility spans and member months. A null
enrollment_end_daterepresents open coverage, and the accepted ingestion alias9999-12-31is published as null. Cost, utilization, and attribution share the member-month coverage grain; concurrent coverage rows remain distinct by member, payer, plan, and data source. Utilization counts are calculated by person, month, and source and repeat across concurrent coverage rows; select the intended coverage population before summing across plans. - Binary flags and categorical codes. Public binary
_flagfields use the integer1/0/null contract. Lab abnormal interpretations are categorical varchar codes and are therefore renamed from_flagto_codefields. - Medication key. Clinical and claims medication rows keep their source
identifiers. The public key is
(medication_id, source_type, data_source); include all three columns so identical values from the clinical and claims domains cannot collide. Nosource_medication_idcolumn is introduced. - Final grouper names. Use
core.condition.condition_nameandcore.procedure.procedure_namein queries, semantic models, and extracts. Procedure IDs use a collision-safe 32-character lowercase hash; full-refresh stored procedure keys and their consumers. - Cost categories. Cost now includes paid and allowed amounts for inpatient
long-term acute care, inpatient substance use, and outpatient substance use.
Join both cost and utilization to member months using
member_month_id. Preserve their six-field coverage grain when aggregating measures. - Hospice attribution. Inpatient hospice professional claims are considered before outpatient encounter candidates. Rebuild encounter assignments and validate affected downstream hospice and utilization reporting.
- New foundational outputs.
costandutilizationbring member-month paid, allowed, and claims-derived encounter-count concepts into Core. They are not field-for-field replacements for every former Financial PMPM output.
Owners of AHRQ Quality Indicators, CCSR, CMS HCC, Quality Measures, FHIR
Preprocessing, and custom packages must rebuild and validate outputs that
depend on changed Core identifiers or semantics. CMS HCC recapture now accepts
billing_diagnosis for claims-derived conditions and
discharge_diagnosis for clinical conditions; custom or forked recapture logic
needs the same compatibility update.
Tuva 1.0 retains populated diagnoses from medical-claim lines whose
claim_type is undetermined instead of discarding them during normalization.
It also retains those contract-valid lines in core.medical_claim.
The claim classification itself is not changed or guessed: each line receives
other / other / other service categories and a source-scoped
orphaned claim encounter instead of entering a professional or institutional
encounter algorithm. Each populated diagnosis flows to core.condition as a
billing_diagnosis; its encounter_id remains null because no classified
claim-line encounter was selected.
Fully refresh core.medical_claim, core.condition, and every dependent
relation, package, export, metric, or application. Medical-claim and condition
row counts can increase, as can medical-claim amounts and downstream
practitioner, location, attribution, cost, and utilization outputs.
Explore the tables and column dictionaries in the Core Data Model documentation.
Data Assets
Tuva 1.0 gives each package one explicit, versioned Data Asset snapshot:
- Package ownership: Tuva Core owns its complete snapshot under
tuva-core/<asset-version>/. Every asset-bearing standalone package owns its snapshot underdata-marts/<package>/<asset-version>/. - Independent versions: Each package has one namespaced Data Asset version variable that is used directly in its storage path. Package code and asset versions are intentionally independent and are coordinated manually; a code release can keep using the prior asset version when the assets did not change.
- Cloud metadata:
_manifest.jsoninventories the payloads and records row counts, byte counts, checksums, and source provenance._release.jsonrecords whether the snapshot is a mutablecandidateor a normally immutablereleasedversion. dbt loads the configured path and does not read either metadata file. - One release source: S3 is the source of truth for released assets, with byte-identical mirrors in Google Cloud Storage and Azure. This replaces the DoltHub-to-object-storage handoff, removing an extra synchronization step that made automated and agent-assisted maintenance more brittle.
The result is one complete snapshot per package without separate asset-family
versions. Fresh installations and upgrades load the package's configured
snapshot by running dbt seed or dbt build.
See Data Assets for the catalog and Seed Loading for configuration.
CodeRx assets
Tuva 1.0 replaces the legacy ndc, rxnorm_to_atc, and
rxnorm_brand_generic relations with three CodeRx Open assets:
coderx_packages, coderx_drugs, and coderx_classes. Packages map NDCs to
RxNorm concepts, drugs provide RxNorm names and brand attributes, and classes
provide the ATC hierarchy. These bundled Open assets are the default source for
pharmacy-claim descriptions, medication enrichment, NDC Data Quality checks,
and dependent packages.
Set use_coderx_enterprise: true only when the target database contains
user-managed packages, drugs, and classes relations in the coderx
schema. The switch applies to the complete shared CodeRx interface; Enterprise
mode does not fall back to the bundled Open assets for unmatched values.
Remove direct references to the three legacy terminology relations, fully refresh pharmacy and medication outputs, and review descriptions, null rates, brand attributes, and ATC classifications. See the Data Asset catalog for the CodeRx Open source metadata and previews.
Data Marts
In Tuva 0.18, Data Marts were included in Tuva Core under models/data_marts. In Tuva 1.0, each retained Data Mart is an independently installable package, while selected foundational capabilities moved into Tuva Core and capabilities without a 1.0 successor were removed.
The following table shows where each Tuva 0.18 Data Mart or related capability is located in Tuva 1.0:
| Tuva 0.18 location | Tuva 1.0 location | What changed |
|---|---|---|
models/data_marts/ahrq_measures/pqi | Standalone ahrq_quality_indicators package | Retained AHRQ quality-indicator and Prevention Quality Indicator functionality moved into the new canonical package. The former ahrq_measures package identity is retired. |
models/data_marts/ccsr | Standalone ccsr package | Diagnosis and procedure CCSR functionality moved into the canonical ccsr package. The duplicate tuva_ccsr package identity is retired. |
models/data_marts/chronic_conditions | Standalone cms_chronic_conditions package | CMS-defined chronic conditions moved into the standalone package. Tuva-defined chronic conditions were removed, and the duplicate tuva_cms_chronic_conditions identity is retired. |
models/data_marts/cms_hcc, models/data_marts/hcc_recapture, and models/data_marts/hcc_suspecting | Standalone cms_hcc package | CMS HCC scoring, HCC recapture, and HCC suspecting were combined into one package. |
models/data_marts/ed_classification | Standalone nyu_ed_classification package | NYU emergency-department classification moved into its own package. |
models/data_marts/quality_measures and models/data_marts/readmissions | Standalone quality_measures package | Quality measures and retained readmissions functionality were combined into one package. The former readmissions package identity is retired. |
models/data_marts/semantic_layer | Standalone semantic-layer repository; dbt package name semantic_layer | The Semantic Layer moved out of Tuva Core and now provides eight dimensions and eleven facts over Tuva Core and selected Data Marts. |
models/data_marts/fhir_preprocessing | Standalone fhir_preprocessing extension package | FHIR preprocessing moved out of Tuva Core into an independently installable, seedless package. |
models/data_marts/provider_attribution | Tuva Core models/claims_preprocessing/provider_attribution | Provider attribution moved from a Data Mart into Claims Preprocessing. |
models/data_marts/financial_pmpm | No standalone successor; foundational cost and utilization models are in Tuva Core | The Financial PMPM Data Mart was removed. Core cost and utilization do not reproduce every former PMPM summary. |
models/data_marts/pharmacy | No standalone successor; pharmacy-claim and medication functionality remains in Tuva Core | The expanded Pharmacy Data Mart relations were removed. |
models/data_marts/benchmarks and the former key_metrics package identity | No Tuva 1.0 successor | Benchmarks and key_metrics were removed. |
models/data_marts/normalize | Tuva Core Normalized Layer | The normalization boundary remains in Core, but the former unmapped-code reports were removed. |
models/data_marts/clinical_concept_library | No Tuva 1.0 successor | The clinical-concept helper was removed. |
The 1.0 scope retains CCSR's reviewed 2023.1 mapping assets, including the restored source-scoped procedure summary. The CCSR 2026 refresh is outside this release. CMS Chronic Conditions identifies condition evidence from Core diagnoses and encounters; it does not implement the full CMS claim-type, claim-count, and lookback qualification methodology. That work is tracked separately in CMS Chronic Conditions #48 and is also outside 1.0.
Migrating Data Mart dependencies
Before replacing a Tuva 0.18 Data Mart, verify the standalone package's Git repository and dbt package name, model and relation names or aliases, selectors, package variables, package-owned seeds and Data Assets, and downstream dependencies. Moving a capability into a standalone repository does not guarantee that every legacy output or configuration name is retained. Repository and dbt identifiers can differ—for example, the semantic-layer repository declares the dbt package name semantic_layer.
Rebuild affected relations with a full refresh, then validate expected package outputs and every downstream query, dashboard, extract, and application before promotion. Review the Data Mart overview and package-specific documentation before changing dependencies or downstream queries.
dbt Compatibility
Tuva Core and the standalone packages require dbt >=1.10.5,<3.0.0.
Versions 1.10.0 through 1.10.4 are below the supported floor.
The 1.0 five-warehouse validation passed with dbt Core 1.11.14 on Snowflake, BigQuery, Databricks, Microsoft Fabric, and Redshift. All five builds used the same exact Core and eight-package commit lock and the 1.0 Data Asset snapshots. Each built 578 models and 127 seeds, ran 173 unit tests, and enabled Structural and Logical Data Quality with failure keys. Snowflake, BigQuery, Databricks, and Redshift each ran 584 data tests; Fabric ran 583 because the regex contract test is deliberately disabled for that adapter. No result records reported errors, failures, skips, or warnings.
The tagged-package Snowflake build
independently installed all eight standalone v1.0.0 tags and verified their
exact Git commits, installed versions, and successful model coverage alongside
Core. All 1,463 result records succeeded, including the full Data Quality
surface and failure keys.
The separate DuckDB compatibility validation covered Core 1.10.5 and 1.11.2, Core 2.0.0-beta.2, and Fusion 2.0.0-preview.218. These are distinct runtime and warehouse results; a permissive package version range does not establish every combination.
SQL Server and Athena portability work does not add either adapter to the end-to-end supported warehouse set. Use the adapter and runtime combination validated for your deployment.
Testing Framework
Unit and data testing foundation
Tuva 1.0 establishes a simple dbt-native structure for unit and data tests. Unit tests live with the models they protect and validate model logic using small, controlled inputs and expected outputs. Generic and singular data tests validate invariants on built relations, including grain, keys, relationships, accepted values, reconciliation, and source isolation.
Confirmed logic bugs receive the smallest deterministic unit or data test that reproduces the defect. The test must fail without the fix and pass with it, then remain in the project to prevent the same regression from returning.
The encounter regression coverage verifies that a claim-line match in one data_source cannot suppress or alter an otherwise identical claim-line key from another source.
Claims parity metric catalog
Tuva Core now includes an optional parity metric table for detecting analytical drift across versions. It is disabled by default and produces exactly three fields when enabled: metric_id, metric_name, and result.
The first catalog contains 101 claims-focused metrics covering patients and coverage, medical and pharmacy claim volume and amounts, service categories, claim encounters, claims-derived conditions and procedures, member months, and Claims Preprocessing reconciliation. Metric IDs are immutable zero-padded numbers from 0001 through 0101; new metrics append new IDs, and an existing calculation is never silently redefined under the same ID.
Cross-version comparison is a manually executed release-validation step. The producer materializes one version's measurements. A separate manual comparison detects differences; producing the table alone does not establish parity with an earlier release.
Release validation
The release was validated across the combined Core and standalone-package graph with Structural and Logical Data Quality and failure keys enabled. The five-warehouse run used one resolved source lock; a subsequent Snowflake build verified all eight released mart tags. See dbt compatibility for the exact runtime and warehouse coverage.
The release parity and performance acceptance checks are complete. Deployment-specific reconciliation remains part of the upgrade process described above.
The modular architecture is designed to reduce unnecessary work by keeping optional packages out of Core builds. Actual runtime changes depend on warehouse, data volume, enabled domains, and selected packages; this release does not publish one universal performance benchmark.
Miscellaneous
- Provider attribution is now part of Claims Preprocessing and can combine mapped attribution with Tuva provider data for downstream member-month outputs.
- Package-owned data assets can be loaded independently of claims or clinical domain enablement, so
dbt seedproduces the complete asset set for the installed package. - Data Asset metadata now identifies maintainers, source URLs, update cadence, and usage so users can understand where reference data comes from.
- Archived package repositories remain available for historical installations and migration references even though they are no longer active Tuva 1.0 package identities.
- Documentation routes and migration guidance point users from retired Data Mart identities to their retained package or Core successor where one exists.
Additional Improvements
The migration catalogs above describe the final public contracts. For the complete implementation changes, compare Tuva Core v0.18.0 with v1.0.0.
The pull requests below are included in the v1.0.0 release of Tuva Core or the named standalone package. Core entries cover changes after v0.18.0; package entries cover the 1.0 extraction, integration, and hardening work. Earlier standalone-package history and changes merged after the release tags are excluded. Titles describe the individual changes when they were implemented; use the final contracts and upgrade guidance above when migrating. Maintenance-only changes labeled ignore-for-release are excluded.
tuva-core
- #1283: Fixing unique encounter ID failure
- #1320: Update HCC recapture
- #1323: Fix BigQuery field description limits for input layer
- #1327: Consolidate Tuva agent workflow context
- #1328: Fix CMS HCC missing OREC age fallback
- #1329: Rename ICD-10-CM billable flag
- #1330: Document dbt ref behavior flag
- #1331: [codex] Add docs release channels
- #1336: fix: correct hcc recapture YAML description key
- #1338: [codex] Add DAG viewer and update docs release references
- #1339: [codex] Polish DAG viewer header controls
- #1340: [codex] Polish DAG viewer metadata and previews
- #1342: Refactor DAG viewer and data dictionaries
- #1346: Fix proxied blog post links
- #1355: Add columns to HCC recapture
- #1358: Update HCC recapture gap status logic for closed - high/low coefficient
- #1363: Adding missing tag for HCC recapture dependency
- #1367: Adding missing tag for Chronic Conditions mart dependency
- #1378: Integrate the Tuva Core 1.0 architecture into main
- #1380: Align 1.0 data assets with package releases
- #1381: Make package assets independent of domain vars
- #1385: Finalize the Structural Data Quality readiness contract
- #1386: Finalize the Logical Data Quality contract
- #1398: Replace legacy drug terminology with CodeRx Open
- #1399: Add ingest_datetime across Input Layer and Core
- #1400: Update CMS assignment windows for 2026
- #1402: Define and harden the Tuva 1.0 extension-column contract
- #1403: Fix portable office-based surgery HCPCS casting
- #1404: Fix BigQuery type family macro test
- #1406: Fix minimum dbt version requirement
- #1407: Validate Tuva Core boolean feature variables
- #1408: Finalize Tuva 1.0 Input Layer and Core contracts
- #1409: Retain undetermined medical claims in Core
- #1410: Fix clinical-only person crosswalk enablement
- #1411: Remove orphaned present-on-admission models
- #1412: Fix cross-warehouse regex portability
- #1413: Make practitioner and location source-native
- #1414: Clean up repository structure for Tuva 1.0
- #1415: Add explicit package version contract for dbt v2
- #1416: Add cross-database function layer
- #1417: Add a portability linter for non-portable SQL in models
- #1424: Remove preliminary Output Data Quality
- #1427: Fix all-warehouse CI failures
- #1428: Fix Fabric and Redshift CI connections
- #1430: Refresh Core 1.0 terminology assets
- #1431: Simplify Core data asset architecture
- #1433: Harden extension column handling
- #1434: Align Core with refreshed condition and procedure groupers
- #1435: Complete Core cost and utilization coverage
- #1438: Make Core identities collision-safe and restore hospice attribution
- #1439: Fix final cross-warehouse portability blockers
- #1440: Add SQL Server and Athena support to Tuva Core
- #1442: Clarify condition lineage and Core dictionary references
- #1443: Make the SQL Server seed data source creation race safe
- #1444: Scope medication unit tests to their required input domains
- #1445: Clarify condition code system normalization
- #1448: Finalize Core 1.0 release checks and tagged mart integration
ahrq_quality_indicators
- #2: Align 1.0 data assets with package releases
- #3: Keep package data assets enabled on import
- #4: Add explicit package version contract for dbt v2
- #5: Use independent data asset version
- #6: Fix PQI identifier type consistency
- #7: Add the Apache 2.0 repository license
- #8: Prepare v0.1.0 for dbt Hub onboarding
- #9: Release ahrq_quality_indicators 1.0.0
ccsr
- #7: Align 1.0 data assets with package releases
- #8: Canonicalize the CCSR package identity
- #9: Rebaseline CCSR at 1.0.0
- #10: Make GCS release receipt verification cache-safe
- #12: Add explicit package version contract for dbt v2
- #13: Tuva 1.0: license, dependencies, adapter dispatch, and dbt range for ccsr
- #14: Use independent data asset version
- #15: Fix CCSR SQL portability on Fabric
- #16: Preserve source-scoped CCSR record grains
- #17: Restore the source-scoped CCSR procedure summary
- #18: Fix Redshift procedure map unit fixture
- #19: Point integration tests at Core with SQL Server and Athena support
- #20: Preserve procedure summary grain across description variants
- #21: Prepare CCSR for initial dbt Hub release
- #22: Release ccsr 1.0.0
cms_chronic_conditions
- #39: Align 1.0 data assets with package releases
- #40: Run CMS chronic conditions when imported
- #43: Add explicit package version contract for dbt v2
- #44: Tuva 1.0: license, dependencies, and dbt range for cms_chronic_conditions
- #45: Use independent data asset version
- #46: Fix CMS Chronic Conditions SQL portability on Fabric
- #47: Fix duplicate-eliminating unions on BigQuery
- #49: Fix source-scoped chronic condition logic
- #50: Support dbt Core 2 in CMS Chronic Conditions
- #51: Fix BigQuery empty CMS Chronic unit fixtures
- #52: Fix Redshift typing in empty OUD unit fixtures
- #53: Add SQL Server and Athena compatibility
- #54: Prepare v0.2.0 for dbt Hub onboarding
- #55: Release cms_chronic_conditions 1.0.0
cms_hcc
- #18: Fix HCC recapture's default chronic HCC dependency
- #20: Align 1.0 data assets with package releases
- #21: Keep package data assets enabled on import
- #24: Fix HCC recapture reason grain
- #25: Fix clinical-only HCC Suspecting enablement
- #26: Align CMS HCC with Tuva Core eligibility and condition contracts
- #27: Use portable numeric validation in HCC suspecting
- #28: Fix HCC recapture hierarchy gap status
- #29: Add explicit package version contract for dbt v2
- #31: Fix BigQuery empty test relation
- #32: Type suspect HCC claim ID for BigQuery
- #33: Fix Databricks unit fixture string types
- #34: Use independent data asset version
- #35: Fix CMS HCC Fabric test and SQL portability
- #36: Fix HCC status window frame on Redshift
- #37: Fix source-scoped CMS HCC grains
- #38: Correct CMS HCC factors and add official validation
- #39: Fix Redshift CMS HCC overlap unit fixture
- #40: Fix CMS HCC cross-warehouse unit-test portability
- #41: Add SQL Server and Athena compatibility
- #42: Exclude null normalized diagnoses from HCC eligibility
- #43: Prepare v0.1.0 dbt Hub bootstrap release
- #44: Release cms_hcc 1.0.0
fhir_preprocessing
- #1: Fix FHIR preprocessing for the Core 1.0 code-system contract
- #2: Run FHIR preprocessing when imported
- #3: Start FHIR preprocessing at 1.0.0
- #4: Align FHIR preprocessing with Core eligibility and flag contracts
- #5: Declare the dbt 1.10.5 through 2.x compatibility range
- #7: Fix Databricks unit fixture string types
- #9: Fix FHIR claim source scoping
- #10: Fix FHIR coverage mapping and EOB identifiers
- #11: Complete FHIR packaging and source-aware medication IDs
- #12: Fix Fabric coverage unit fixture
- #13: Prepare v0.1.0 dbt Hub bootstrap release
- #14: Release fhir_preprocessing 1.0.0
nyu_ed_classification
- #2: Align 1.0 data assets with package releases
- #3: Run NYU ED classification when imported
- #4: Add explicit package version contract for dbt v2
- #5: Use independent NYU data asset version
- #6: Preserve source scope in ED classification
- #7: Add the Apache 2.0 repository license
- #8: Prepare v0.1.0 dbt Hub bootstrap release
- #9: Release nyu_ed_classification 1.0.0
quality_measures
- #2: Align 1.0 data assets with package releases
- #3: Keep package data assets enabled on import
- #4: Use portable numeric validation in CQM438
- #5: Fix fanout in quality measure result assembly
- #6: Add explicit package version contract for dbt v2
- #7: Use independent Quality Measures data asset version
- #8: Use portable UNION syntax for readmissions
- #9: Fix duplicate-eliminating unions on BigQuery
- #10: Fix source scoping in quality measures
- #11: Add the Apache 2.0 repository license
- #12: Fix BigQuery empty SQL fixtures
- #13: Fix Quality Measures Fabric and Redshift portability
- #14: Prepare Quality Measures v0.1.0 for dbt Hub
- #15: Release quality_measures 1.0.0
semantic-layer
- #1: Align CCSR dependency with 1.0.0
- #2: Add package-owned Semantic Layer seed assets
- #3: Remove obsolete Core extension passthrough tests
- #4: Migrate Semantic Layer pharmacy facts to CodeRx
- #5: Align appointment and lab contracts with Tuva Core
- #6: Add explicit package version contract for dbt v2
- #8: Remove retired output data quality configuration
- #9: Use independent Semantic Layer data asset version
- #10: Preserve source-scoped semantic grains
- #11: Validate the source-scoped Semantic Layer dependency lock
- #12: Refresh the merged 1.0 ecosystem lock
- #13: Fix Redshift member-month risk unit expectation scales
- #14: Add SQL Server and Athena compatibility
- #15: Prepare Semantic Layer v0.1.0 for dbt Hub
- #16: Release semantic-layer 1.0.0