You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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
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.
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.
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:
add fail-first tests against the real CdcSourceRegistry and CdcTargetRegistry before production changes;
prove direct clear/remove or iterator mutation on an all() result cannot alter registry contents;
prove an already-returned snapshot does not change when a later legitimate registration occurs;
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.
Product / integrity gap
Fresh protected-source inspection at
develop@c2511f6b9d716ef9ab8de60a91fffd826714a4c5shows that bothCdcSourceRegistry.all()andCdcTargetRegistry.all()returnbyId.values()directly.Map.values()is a live mutable collection view: in-process callers can remove entries throughclear(),remove(...),removeIf(...), or iterator removal and mutate connector discovery/execution authority without passing throughregister(...)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
all()exposes the backing map's mutable values view.all()result can silently delete connector authority, alter subsequent/api/cdc/sourcesor/api/cdc/targetsdiscovery, and make runtime behavior depend on mutation of a supposedly observational API.Distinct remedies / feasibility
List.copyOf(byId.values())or an equivalent immutable snapshot that preserves deterministic registration order and connector object identity.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.UnsupportedOperationExceptionat 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:
CdcSourceRegistryandCdcTargetRegistrybefore production changes;clear/removeor iterator mutation on anall()result cannot alter registry contents;Current classification / writer safety
known_gap / defer_until_triggerfor source mutation. Live Draft PR #201 is still open at exact head1ba5527effcc4605b44d53effd0dfb3be3618164and owns both registry files. Protecteddevelopremains exactlyc2511f6b9d716ef9ab8de60a91fffd826714a4c5. 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.