Skip to content

feat(ingestion): bronze shape comes from Airbyte — append_dedup, retire RMT promotion - #2882

Open
cyberantonz wants to merge 4 commits into
constructorfabric:mainfrom
cyberantonz:feat/2877-bronze-append-dedup
Open

feat(ingestion): bronze shape comes from Airbyte — append_dedup, retire RMT promotion#2882
cyberantonz wants to merge 4 commits into
constructorfabric:mainfrom
cyberantonz:feat/2877-bronze-append-dedup

Conversation

@cyberantonz

Copy link
Copy Markdown
Contributor

Implements #2877 — bronze table shape moves from our promotion machinery to the Airbyte destination itself.

What changed

  • Reconcile builds catalogs with destinationSyncMode=append_dedup + primaryKey=[["unique_key"]] for every stream whose schema carries unique_key (plain append fallback + stderr warning for keyless streams). normalize_catalog_to_append.pynormalize_catalog.py; the ab_create_connection contract comment and the dev-tool generate-catalog.sh follow the same rule (overwrite is gone everywhere).
  • bootstrap-db generation mirrors the same catalog rule and drops its promotion step, so the committed snapshot is byte-identical to what a real sync creates.
  • Promotion machinery deleted: promote_bronze_to_rmt macro, all 21 <connector>__bronze_promoted bootstrap models, ~120 -- depends_on lines, schema.yml entries, README/comment references. The obsolete Jira enrich crashes on every real sync (FINAL on a MergeTree bronze table) — no task metrics ever appear #1886 promotion-selector regression test goes with the model it guarded.
  • Snapshot regenerated (full bootstrap pipeline + dump-ddl.sh): unique_key becomes NOT NULL String on all 162 bronze tables (the destination strips PK nullability), allow_nullable_key is dropped, engines/ORDER BY otherwise byte-identical — and the two previously-unpromoted tables (bronze_claude_team.claude_team_invites, bronze_zendesk.support_ticket_ids) converge to the uniform ReplacingMergeTree(_airbyte_extracted_at) ORDER BY unique_key shape.
  • audit_rmt_read_dedup.py now treats every bronze_* source read as RMT (behavior verified identical against main: same advisory findings) + pathlib/ruff cleanup.
  • Conventions updated: architecture rules 4 & 8, check-dbt-conventions checks 4 & 5, connector-authoring validate workflow.

Why it's safe

All four prerequisite audits/verifications are recorded on #2877 (no connector emits a null unique_key; every stream's version column falls back to _airbyte_extracted_at exactly as promotion pinned; all 1220 test fixture rows already comply). Warm environments converge on the first sync after the switch: the destination detects the primary-key nullability change and rebuilds the table itself (temp + copy + EXCHANGE) — verified lossless on a disposable ClickHouse 25.7.5 with the stock destination image.

  • dbt parse green; field parity: 0 failures; pre-commit green.
  • The connectors-ddl workflow re-runs the exact generation pipeline and gates on snapshot convergence.

Closes #2877

🤖 Generated with Claude Code

@cyberantonz
cyberantonz requested a review from a team as a code owner August 26, 2026 17:30
@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 210 files, which is 110 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review ran on the open-source allowance, not this organization's plan, because the pull request author doesn't have an assigned seat. Waiting won't change this — ask an organization admin to assign them a seat, or add seats in Billing if every seat is already assigned, then retry.

Check out review usage here.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: 82dabc06-1a0e-4ada-9d60-eb131835705c

📥 Commits

Reviewing files that changed from the base of the PR and between 94a33c3 and ae3318a.

📒 Files selected for processing (210)
  • .cf-studio/config/rules/architecture.md
  • .claude/skills/check-dbt-conventions/SKILL.md
  • .claude/skills/connector/workflows/create.md
  • .claude/skills/connector/workflows/validate.md
  • src/ingestion/connectors/ai/chatgpt-team/README.md
  • src/ingestion/connectors/ai/chatgpt-team/dbt/chatgpt_team__ai_assistant_usage.sql
  • src/ingestion/connectors/ai/chatgpt-team/dbt/chatgpt_team__ai_dev_usage.sql
  • src/ingestion/connectors/ai/chatgpt-team/dbt/chatgpt_team__bronze_promoted.sql
  • src/ingestion/connectors/ai/chatgpt-team/dbt/schema.yml
  • src/ingestion/connectors/ai/claude-enterprise/dbt/claude_enterprise__ai_assistant_usage.sql
  • src/ingestion/connectors/ai/claude-enterprise/dbt/claude_enterprise__ai_dev_usage.sql
  • src/ingestion/connectors/ai/claude-enterprise/dbt/claude_enterprise__bronze_promoted.sql
  • src/ingestion/connectors/ai/claude-team-invoices/dbt/claude_team__ai_invoice.sql
  • src/ingestion/connectors/ai/claude-team-invoices/dbt/claude_team_invoices__bronze_promoted.sql
  • src/ingestion/connectors/ai/claude-team-invoices/dbt/schema.yml
  • src/ingestion/connectors/ai/claude-team/dbt/claude_team__ai_dev_usage.sql
  • src/ingestion/connectors/ai/claude-team/dbt/claude_team__ai_overage.sql
  • src/ingestion/connectors/ai/claude-team/dbt/claude_team__ai_overage_daily.sql
  • src/ingestion/connectors/ai/claude-team/dbt/claude_team__bronze_promoted.sql
  • src/ingestion/connectors/ai/cursor/dbt/cursor__ai_dev_usage.sql
  • src/ingestion/connectors/ai/cursor/dbt/cursor__bronze_promoted.sql
  • src/ingestion/connectors/ai/cursor/dbt/cursor__members_snapshot.sql
  • src/ingestion/connectors/ai/cursor/dbt/cursor__usage_events.sql
  • src/ingestion/connectors/collaboration/m365/dbt/m365__bronze_promoted.sql
  • src/ingestion/connectors/collaboration/m365/dbt/m365__collab_chat_activity.sql
  • src/ingestion/connectors/collaboration/m365/dbt/m365__collab_document_activity_onedrive.sql
  • src/ingestion/connectors/collaboration/m365/dbt/m365__collab_document_activity_sharepoint.sql
  • src/ingestion/connectors/collaboration/m365/dbt/m365__collab_email_activity.sql
  • src/ingestion/connectors/collaboration/m365/dbt/m365__collab_meeting_activity.sql
  • src/ingestion/connectors/collaboration/slack/dbt/slack__bronze_promoted.sql
  • src/ingestion/connectors/collaboration/slack/dbt/slack__collab_chat_activity.sql
  • src/ingestion/connectors/collaboration/slack/dbt/slack__users_latest.sql
  • src/ingestion/connectors/collaboration/zoom/dbt/zoom__bronze_promoted.sql
  • src/ingestion/connectors/collaboration/zoom/dbt/zoom__users_snapshot.sql
  • src/ingestion/connectors/collaboration/zulip-proxy/README.md
  • src/ingestion/connectors/collaboration/zulip-proxy/dbt/schema.yml
  • src/ingestion/connectors/collaboration/zulip-proxy/dbt/zulip_proxy__bronze_promoted.sql
  • src/ingestion/connectors/collaboration/zulip-proxy/dbt/zulip_proxy__collab_chat_activity.sql
  • src/ingestion/connectors/collaboration/zulip-proxy/dbt/zulip_proxy__users_snapshot.sql
  • src/ingestion/connectors/crm/hubspot/dbt/hubspot__bronze_promoted.sql
  • src/ingestion/connectors/crm/hubspot/dbt/hubspot__crm_accounts.sql
  • src/ingestion/connectors/crm/hubspot/dbt/hubspot__crm_activities.sql
  • src/ingestion/connectors/crm/hubspot/dbt/hubspot__crm_contacts.sql
  • src/ingestion/connectors/crm/hubspot/dbt/hubspot__crm_deals.sql
  • src/ingestion/connectors/crm/hubspot/dbt/hubspot__crm_users.sql
  • src/ingestion/connectors/dev-portal/compass/dbt/compass__bronze_promoted.sql
  • src/ingestion/connectors/dev-portal/compass/dbt/schema.yml
  • src/ingestion/connectors/git/bitbucket-cloud/dbt/bitbucket_cloud__account_emails.sql
  • src/ingestion/connectors/git/bitbucket-cloud/dbt/bitbucket_cloud__bronze_promoted.sql
  • src/ingestion/connectors/git/bitbucket-cloud/dbt/bitbucket_cloud__commits.sql
  • src/ingestion/connectors/git/bitbucket-cloud/dbt/bitbucket_cloud__file_changes.sql
  • src/ingestion/connectors/git/bitbucket-cloud/dbt/bitbucket_cloud__item_events.sql
  • src/ingestion/connectors/git/bitbucket-cloud/dbt/bitbucket_cloud__pr_review_events.sql
  • src/ingestion/connectors/git/bitbucket-cloud/dbt/bitbucket_cloud__pull_requests.sql
  • src/ingestion/connectors/git/bitbucket-cloud/dbt/bitbucket_cloud__pull_requests_comments.sql
  • src/ingestion/connectors/git/bitbucket-cloud/dbt/bitbucket_cloud__pull_requests_commits.sql
  • src/ingestion/connectors/git/bitbucket-cloud/dbt/bitbucket_cloud__pull_requests_reviewers.sql
  • src/ingestion/connectors/git/bitbucket-cloud/dbt/bitbucket_cloud__repositories.sql
  • src/ingestion/connectors/git/bitbucket-cloud/dbt/bitbucket_cloud__repository_branches.sql
  • src/ingestion/connectors/git/bitbucket-cloud/dbt/bitbucket_cloud__unowned_commit_emails.sql
  • src/ingestion/connectors/git/bitbucket-cloud/dbt/schema.yml
  • src/ingestion/connectors/git/github-directory/dbt/github_directory__bronze_promoted.sql
  • src/ingestion/connectors/git/github-directory/dbt/github_directory__org_members_fields_history.sql
  • src/ingestion/connectors/git/github-directory/dbt/github_directory__org_members_snapshot.sql
  • src/ingestion/connectors/git/github-directory/dbt/schema.yml
  • src/ingestion/connectors/git/github/dbt/github__account_emails.sql
  • src/ingestion/connectors/git/github/dbt/github__bronze_promoted.sql
  • src/ingestion/connectors/git/github/dbt/github__ci_runs.sql
  • src/ingestion/connectors/git/github/dbt/github__commits.sql
  • src/ingestion/connectors/git/github/dbt/github__deployment_events.sql
  • src/ingestion/connectors/git/github/dbt/github__deployments.sql
  • src/ingestion/connectors/git/github/dbt/github__file_changes.sql
  • src/ingestion/connectors/git/github/dbt/github__issue_link_events.sql
  • src/ingestion/connectors/git/github/dbt/github__issue_links_snapshot.sql
  • src/ingestion/connectors/git/github/dbt/github__item_events.sql
  • src/ingestion/connectors/git/github/dbt/github__pr_review_events.sql
  • src/ingestion/connectors/git/github/dbt/github__project_fields_history.sql
  • src/ingestion/connectors/git/github/dbt/github__project_fields_snapshot.sql
  • src/ingestion/connectors/git/github/dbt/github__project_items_snapshot.sql
  • src/ingestion/connectors/git/github/dbt/github__pull_requests.sql
  • src/ingestion/connectors/git/github/dbt/github__pull_requests_comments.sql
  • src/ingestion/connectors/git/github/dbt/github__pull_requests_commits.sql
  • src/ingestion/connectors/git/github/dbt/github__pull_requests_reviewers.sql
  • src/ingestion/connectors/git/github/dbt/github__repositories.sql
  • src/ingestion/connectors/git/github/dbt/github__repository_branches.sql
  • src/ingestion/connectors/git/github/dbt/github__task_field_history.sql
  • src/ingestion/connectors/git/github/dbt/github__task_field_metadata.sql
  • src/ingestion/connectors/git/github/dbt/github__task_issuetypes.sql
  • src/ingestion/connectors/git/github/dbt/github__task_links.sql
  • src/ingestion/connectors/git/github/dbt/github__task_projects.sql
  • src/ingestion/connectors/git/github/dbt/github__task_statuses.sql
  • src/ingestion/connectors/git/github/dbt/github__task_users.sql
  • src/ingestion/connectors/git/github/dbt/github__unowned_commit_emails.sql
  • src/ingestion/connectors/git/github/dbt/schema.yml
  • src/ingestion/connectors/git/gitlab/dbt/gitlab__bronze_promoted.sql
  • src/ingestion/connectors/git/gitlab/dbt/gitlab__commits.sql
  • src/ingestion/connectors/git/gitlab/dbt/gitlab__file_changes.sql
  • src/ingestion/connectors/git/gitlab/dbt/gitlab__pull_requests.sql
  • src/ingestion/connectors/git/gitlab/dbt/gitlab__pull_requests_comments.sql
  • src/ingestion/connectors/git/gitlab/dbt/gitlab__pull_requests_commits.sql
  • src/ingestion/connectors/git/gitlab/dbt/gitlab__pull_requests_reviewers.sql
  • src/ingestion/connectors/git/gitlab/dbt/gitlab__repositories.sql
  • src/ingestion/connectors/git/gitlab/dbt/gitlab__repository_branches.sql
  • src/ingestion/connectors/hr-directory/active-directory/dbt/active_directory__bronze_promoted.sql
  • src/ingestion/connectors/hr-directory/active-directory/dbt/active_directory__person_attribute_claims.sql
  • src/ingestion/connectors/hr-directory/active-directory/dbt/active_directory__to_class_people.sql
  • src/ingestion/connectors/hr-directory/active-directory/dbt/active_directory__users_snapshot.sql
  • src/ingestion/connectors/hr-directory/active-directory/dbt/schema.yml
  • src/ingestion/connectors/hr-directory/bamboohr/dbt/bamboohr__bronze_promoted.sql
  • src/ingestion/connectors/hr-directory/bamboohr/dbt/bamboohr__employees_fields_history.sql
  • src/ingestion/connectors/hr-directory/bamboohr/dbt/bamboohr__employees_snapshot.sql
  • src/ingestion/connectors/hr-directory/bamboohr/dbt/bamboohr__hr_events.sql
  • src/ingestion/connectors/hr-directory/bamboohr/dbt/bamboohr__person_attribute_claims.sql
  • src/ingestion/connectors/hr-directory/bamboohr/dbt/bamboohr__to_class_people.sql
  • src/ingestion/connectors/hr-directory/bamboohr/dbt/bamboohr__working_hours.sql
  • src/ingestion/connectors/hr-directory/ms-entra/README.md
  • src/ingestion/connectors/hr-directory/ms-entra/dbt/ms_entra__bronze_promoted.sql
  • src/ingestion/connectors/hr-directory/ms-entra/dbt/ms_entra__person_attribute_claims.sql
  • src/ingestion/connectors/hr-directory/ms-entra/dbt/ms_entra__to_class_people.sql
  • src/ingestion/connectors/hr-directory/ms-entra/dbt/ms_entra__users_snapshot.sql
  • src/ingestion/connectors/hr-directory/ms-entra/dbt/schema.yml
  • src/ingestion/connectors/support/zendesk/dbt/schema.yml
  • src/ingestion/connectors/support/zendesk/dbt/zendesk__bronze_promoted.sql
  • src/ingestion/connectors/support/zendesk/dbt/zendesk__support_activity.sql
  • src/ingestion/connectors/support/zendesk/dbt/zendesk__support_agent.sql
  • src/ingestion/connectors/support/zendesk/dbt/zendesk__support_event.sql
  • src/ingestion/connectors/support/zendesk/dbt/zendesk__support_ticket.sql
  • src/ingestion/connectors/support/zendesk/descriptor.yaml
  • src/ingestion/connectors/task-tracking/jira/connector.yaml
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__availability_events.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__bronze_promoted.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__changelog_items.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__comment_lifecycle_events.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__comment_lifecycle_history.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__comment_snapshot.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__comment_state.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__identity_inputs.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__issue_availability_history.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__issue_availability_snapshot.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__issue_availability_state.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__issue_field_snapshot.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__project_visibility_history.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__project_visibility_snapshot.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__project_visibility_state.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__task_comments.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__task_field_history.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__task_field_metadata.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__task_issuetypes.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__task_projects.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__task_sprints.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__task_statuses.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__task_users.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__task_worklogs.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__users_fields_history.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__users_snapshot.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__worklog_lifecycle_events.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__worklog_lifecycle_history.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__worklog_snapshot.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/jira__worklog_state.sql
  • src/ingestion/connectors/task-tracking/jira/dbt/schema.yml
  • src/ingestion/connectors/wiki/confluence/dbt/confluence__bronze_promoted.sql
  • src/ingestion/connectors/wiki/confluence/dbt/confluence__wiki_activity.sql
  • src/ingestion/connectors/wiki/confluence/dbt/confluence__wiki_engagement.sql
  • src/ingestion/connectors/wiki/confluence/dbt/confluence__wiki_pages.sql
  • src/ingestion/connectors/wiki/outline/dbt/outline__bronze_promoted.sql
  • src/ingestion/connectors/wiki/outline/dbt/outline__users_snapshot.sql
  • src/ingestion/connectors/wiki/outline/dbt/outline__wiki_activity.sql
  • src/ingestion/connectors/wiki/outline/dbt/outline__wiki_engagement.sql
  • src/ingestion/connectors/wiki/outline/dbt/outline__wiki_pages.sql
  • src/ingestion/dbt/audit_rmt_read_dedup.py
  • src/ingestion/dbt/dbt_project.yml
  • src/ingestion/dbt/macros/promote_bronze_to_rmt.sql
  • src/ingestion/reconcile-connectors/lib/airbyte.sh
  • src/ingestion/reconcile-connectors/lib/reconcile.sh
  • src/ingestion/reconcile-connectors/python/normalize_catalog.py
  • src/ingestion/scripts/bootstrap-db/README.md
  • src/ingestion/scripts/bootstrap-db/bootstrap-db.sh
  • src/ingestion/scripts/bootstrap-db/connectors-config.yaml
  • src/ingestion/scripts/bootstrap-db/create-connector-tables.sh
  • src/ingestion/scripts/bootstrap-db/pins.env
  • src/ingestion/scripts/connectors-ddl/active-directory.sql
  • src/ingestion/scripts/connectors-ddl/bamboohr.sql
  • src/ingestion/scripts/connectors-ddl/bitbucket-cloud.sql
  • src/ingestion/scripts/connectors-ddl/chatgpt-team.sql
  • src/ingestion/scripts/connectors-ddl/claude-enterprise.sql
  • src/ingestion/scripts/connectors-ddl/claude-team-invoices.sql
  • src/ingestion/scripts/connectors-ddl/claude-team.sql
  • src/ingestion/scripts/connectors-ddl/compass.sql
  • src/ingestion/scripts/connectors-ddl/confluence.sql
  • src/ingestion/scripts/connectors-ddl/cursor.sql
  • src/ingestion/scripts/connectors-ddl/github-directory.sql
  • src/ingestion/scripts/connectors-ddl/github.sql
  • src/ingestion/scripts/connectors-ddl/gitlab.sql
  • src/ingestion/scripts/connectors-ddl/hubspot.sql
  • src/ingestion/scripts/connectors-ddl/insight.sql
  • src/ingestion/scripts/connectors-ddl/jira.sql
  • src/ingestion/scripts/connectors-ddl/m365.sql
  • src/ingestion/scripts/connectors-ddl/ms-entra.sql
  • src/ingestion/scripts/connectors-ddl/outline.sql
  • src/ingestion/scripts/connectors-ddl/silver.sql
  • src/ingestion/scripts/connectors-ddl/slack.sql
  • src/ingestion/scripts/connectors-ddl/zendesk.sql
  • src/ingestion/scripts/connectors-ddl/zoom.sql
  • src/ingestion/scripts/connectors-ddl/zulip-proxy.sql
  • src/ingestion/tests/e2e/lib/ch_seeder.py
  • src/ingestion/tests/e2e/lib/dbt_runner.py
  • src/ingestion/tests/e2e/lib/tracked_models.py
  • src/ingestion/tests/e2e/meta/test_dbt_runner.py
  • src/ingestion/tests/e2e/metrics/test_fixtures.py
  • src/ingestion/tools/declarative-connector/generate-catalog.sh

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Review on demand using usage pricing

Comment @coderabbitai help to get the list of available commands.

@hello1101n

Copy link
Copy Markdown
Contributor

Are we sure we want to do it in the current release?

@hello1101n hello1101n left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's review

cyberantonz and others added 4 commits September 1, 2026 13:20
…re RMT promotion (constructorfabric#2877)

The destination-clickhouse 2.x connector performs no destination-side
dedup work (upsertTable is a stub; append_dedup is the same append-only
insert path) — it just creates the table as ReplacingMergeTree ORDER BY
the primary key. So the bronze RMT shape moves to the connector:

- reconcile builds catalogs with destinationSyncMode=append_dedup and
  primaryKey=[[unique_key]] for every keyed stream (append fallback for
  keyless ones); normalize_catalog_to_append.py renamed to
  normalize_catalog.py accordingly
- bootstrap-db generation mirrors the same catalog rule, so the dumped
  snapshot is byte-identical to what a real sync creates
- the promote_bronze_to_rmt macro, all 21 <connector>__bronze_promoted
  bootstrap models, their depends_on lines, schema.yml entries and the
  generation-time promotion step are deleted
- snapshot regenerated: unique_key becomes NOT NULL String (the
  destination strips PK nullability), allow_nullable_key is gone, and
  the two previously-unpromoted tables (claude_team_invites,
  support_ticket_ids) converge to the uniform RMT shape
- audit_rmt_read_dedup treats every bronze_* source read as RMT
  (verified against main: identical findings)
- conventions updated (architecture rules 4 and 8, check-dbt-conventions
  checks 4 and 5, connector validate workflow); the obsolete constructorfabric#1886
  promotion-selector regression test is removed with the model it
  guarded

Warm environments converge on the first sync after the switch: the
destination detects the primary-key nullability change and rebuilds the
table itself (temp + copy + EXCHANGE), verified lossless on a disposable
instance. Prerequisite audits and verification are recorded on constructorfabric#2877.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Anton Zelenov <antonz@constructor.tech>
…ilder

A stream without a unique_key schema property would land as an
ever-duplicating bronze table — a defect, not a degraded mode. All three
catalog builders (reconcile normalize_catalog.py, bootstrap-db
create-connector-tables.sh, the declarative-connector dev tool) now fail
loudly naming the offending streams instead of falling back to plain
append; the append fallback is removed and the conventions text updated
to match. No current stream is affected: all 162 bronze tables carry
unique_key.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Anton Zelenov <antonz@constructor.tech>
The 2.1.29 destination is the version instances should run (it adds the
replicated-engine options needed for clustered ClickHouse). Snapshot
regenerated with it is byte-identical to the committed one, so the CDK
bump between 2.1.25 and 2.1.29 changed no type mappings and no snapshot
diff accompanies the pin.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Anton Zelenov <antonz@constructor.tech>
Tables added on main since the branch diverged (compass, the new github
streams and their silver/gold descendants) converge to the append_dedup
shape: unique_key NOT NULL, allow_nullable_key dropped. Also sweeps the
promotion references main introduced (compass__bronze_promoted and its
schema.yml entry, depends_on headers in the new github/bitbucket models,
connector-authoring skill instructions).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Anton Zelenov <antonz@constructor.tech>
@cyberantonz
cyberantonz force-pushed the feat/2877-bronze-append-dedup branch from 9934d56 to ae3318a Compare September 1, 2026 11:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bronze shape should come from Airbyte: switch connections to append_dedup, retire RMT promotion

3 participants