Skip to content

[Connector integrity] Return immutable CDC registry snapshots from discovery APIs #246

Description

@seonghobae

Product / integrity gap

Fresh protected-source inspection at develop@c2511f6b9d716ef9ab8de60a91fffd826714a4c5 shows that both CdcSourceRegistry.all() and CdcTargetRegistry.all() return byId.values() directly. Map.values() is a live mutable collection view: in-process callers can remove entries through clear(), remove(...), removeIf(...), or iterator removal and mutate connector discovery/execution authority without passing through register(...) or its identity validation.

This is the CDC analogue of #231 for TargetConnectorRegistry, but it affects separate production registries and therefore needs separate source sequencing. PR #201 currently owns both CDC registry files for null/blank/duplicate-ID fail-closed validation; do not race that writer.

RCA

  • Immediate cause: all() exposes the backing map's mutable values view.
  • Technical root cause: read-only discovery semantics and mutable registry storage share one collection object.
  • Control failure: registry tests cover lookup/registration identity but do not assert that enumeration is immutable and snapshot-stable.
  • Impact: any injected in-process component or future plugin retaining the all() result can silently delete connector authority, alter subsequent /api/cdc/sources or /api/cdc/targets discovery, and make runtime behavior depend on mutation of a supposedly observational API.

Distinct remedies / feasibility

  1. Preferred after fix(cdc): fail closed on duplicate connector registry IDs #201 clears — immutable snapshot. Return List.copyOf(byId.values()) or an equivalent immutable snapshot that preserves deterministic registration order and connector object identity.
  2. Acceptable — explicit immutable collection type/API. Refactor discovery to a read-only descriptor collection only if public compatibility and [Product/API] Separate live CDC target capability discovery from unwired canonical-write SPI stubs #202's target-capability redesign justify the larger change.
  3. Reject — unmodifiable live view. Collections.unmodifiableCollection(byId.values()) prevents caller mutation but still changes retroactively when later registration occurs; snapshot semantics are easier to reason about for discovery and tests.
  4. Reject — catching UnsupportedOperationException at consumers. Mutation prevention belongs at the registry boundary, not every caller.

No secret, deployment authority, dependency, cross-repository change, or schema migration is required.

TDD acceptance

When #201 integrates/closes or otherwise hands off a stable exact parent:

  1. add fail-first tests against the real CdcSourceRegistry and CdcTargetRegistry before production changes;
  2. prove direct clear/remove or iterator mutation on an all() result cannot alter registry contents;
  3. prove an already-returned snapshot does not change when a later legitimate registration occurs;
  4. preserve deterministic registration order, connector object identity, empty-source fallback behavior, and fix(cdc): fail closed on duplicate connector registry IDs #201's null/blank/duplicate-ID validation;
  5. add beginner-readable public Javadoc documenting immutable snapshot semantics;
  6. coordinate with [Product/API] Separate live CDC target capability discovery from unwired canonical-write SPI stubs #202 so capability/execution refactoring does not reintroduce a mutable discovery surface;
  7. run focused/full CDC tests and regenerate exact-source CI/security/SBOM/SAST, non-vacuous owned-production coverage and independent review evidence before protected integration.

Current classification / writer safety

known_gap / defer_until_trigger for source mutation. Live Draft PR #201 is still open at exact head 1ba5527effcc4605b44d53effd0dfb3be3618164 and owns both registry files. Protected develop remains exactly c2511f6b9d716ef9ab8de60a91fffd826714a4c5. Re-read both identities and the final #201 diff before implementation; do not create a competing branch while that writer lane is active.

Relationships: #200/#201 registry identity validation; #202 target capability/execution truthfulness; #231 ETL target-registry analogue.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: authAuthentication, authorization, identity, or tenant isolationarea: ci-cdCI, GitHub Actions, checks, release, or supply chainarea: dependenciesDependency or lockfile maintenancearea: securitySecurity boundary, hardening, or vulnerability preventionmaintenancepriority: mediumNormal-priority or P2 workstatus: triagedOpen issue has an organization taxonomy assignmenttype: featureNew or expanded product capability

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions