Product/security integrity gap
Protected develop@622e5e6c3d534f230c390f10e3832efadfc01825 has the same silent replacement pattern now being repaired for CDC in #200/#201 at a separate ETL registry boundary:
public final void register(TargetConnector connector) {
byId.put(connector.id(), connector);
}
TargetConnectorRegistry is a production Spring component and connector ID is the lookup/catalog authority. A later in-process registration with the same ID silently replaces the earlier target implementation. This is distinct from #200, which intentionally scopes itself to CDC registries.
Status: known_gap, source mutation defer_until_trigger while active Qlik scaffold-retirement PR #156 owns TargetConnectorRegistry and its catalog/config surface. Do not race #156 or broaden #200/#201.
RCA
- Immediate cause: ordinary
LinkedHashMap.put replacement semantics.
- Technical root cause: target connector identity uniqueness is not an explicit validated registry invariant.
- Control failure: current tests exercise lookup/catalog behavior but do not prove duplicate or blank IDs fail closed.
- Risk: registration order can silently change which implementation owns a configured connector ID, making execution/discovery authority ambiguous. This becomes more material as scaffold connectors are removed or real provider plugins are introduced.
Bounded remediation after #156 stabilizes/integrates
- Re-read the exact protected/current registry after Qlik retirement and preserve its accepted connector set/order.
- Add fail-first tests against the real
TargetConnectorRegistry requiring null/blank IDs and duplicate IDs to fail before mutation.
- Use explicit validation plus
putIfAbsent or an equivalent deterministic duplicate check; never silently choose first/last or add priority semantics without an ADR.
- Keep errors bounded to the non-secret connector ID; never include config maps, credentials, payloads, endpoints or provider exception text.
- Preserve unique registration order and existing lookup/catalog behavior.
Acceptance
Relationship: #153 connector scaffold lifecycle; #156 Qlik registry retirement; #200/#201 analogous CDC identity repair; #159 canonical traceability.
Product/security integrity gap
Protected
develop@622e5e6c3d534f230c390f10e3832efadfc01825has the same silent replacement pattern now being repaired for CDC in #200/#201 at a separate ETL registry boundary:TargetConnectorRegistryis a production Spring component and connector ID is the lookup/catalog authority. A later in-process registration with the same ID silently replaces the earlier target implementation. This is distinct from #200, which intentionally scopes itself to CDC registries.Status:
known_gap, source mutationdefer_until_triggerwhile active Qlik scaffold-retirement PR #156 ownsTargetConnectorRegistryand its catalog/config surface. Do not race #156 or broaden #200/#201.RCA
LinkedHashMap.putreplacement semantics.Bounded remediation after #156 stabilizes/integrates
TargetConnectorRegistryrequiring null/blank IDs and duplicate IDs to fail before mutation.putIfAbsentor an equivalent deterministic duplicate check; never silently choose first/last or add priority semantics without an ADR.Acceptance
Relationship: #153 connector scaffold lifecycle; #156 Qlik registry retirement; #200/#201 analogous CDC identity repair; #159 canonical traceability.