Categories
Implementation Specs (157)
- specs/AnomalyDetection/TASK1.1.md
- specs/AnomalyDetection/TASK1.2.md
- specs/AnomalyDetection/TASK1.3.md
- specs/AnomalyDetection/TASK1.4.md
- specs/AnomalyDetection/TASK2.1.md
- specs/AnomalyDetection/TASK2.2.md
- specs/AnomalyDetection/TASK3.1.md
- specs/AnomalyDetection/TASK3.2.md
- specs/AnomalyDetection/TASK3.3.md
- specs/AnomalyDetection/TASK4.1.md
- specs/AnomalyDetection/TASK4.2.md
- specs/AnomalyDetection/TASK4.3.md
- specs/AnomalyDetection/TASK4.4.md
- specs/AnomalyDetection/TASK5.1.md
- specs/AnomalyDetection/TASK5.2.md
- specs/AnomalyDetection/TASK5.3.md
- specs/AnomalyDetection/TASK6.1.md
- specs/AnomalyDetection/TASK6.2.md
- specs/AnomalyDetection/TASK6.3.md
- specs/AnomalyDetection/TASKS.md
- specs/ApiServicePostgresTestStability/TASK.md
- specs/BackendDatabaseConsolidation/TASK.md
- specs/BackendDatabaseConsolidation/TASK1.1.md
- specs/BackendDatabaseConsolidation/TASK1.2.md
- specs/BackendDatabaseConsolidation/TASK1.3.md
- specs/BackendDatabaseConsolidation/TASK2.1.md
- specs/BackendDatabaseConsolidation/TASK2.2.md
- specs/BackendDatabaseConsolidation/TASK2.3.md
- specs/BackendDatabaseConsolidation/TASK3.1.md
- specs/BackendDatabaseConsolidation/TASK3.2.md
- specs/BackendDatabaseConsolidation/TASK4.1.md
- specs/BackendDatabaseConsolidation/TASK4.2.md
- specs/BackendDatabaseConsolidation/TASK4.3.md
- specs/BackendDatabaseConsolidation/TASK5.1.md
- specs/BackendDatabaseConsolidation/TASK5.2.md
- specs/BrinkLaborGetShiftsStaging/TASK.md
- specs/BrinkPosOrdersFirstEtlJob/TASK.md
- specs/BrinkPosOrdersFirstEtlJob/TASK0.md
- specs/BrinkPosOrdersFirstEtlJob/TASK1.md
- specs/BrinkPosOrdersFirstEtlJob/TASK2.1.md
- specs/BrinkPosOrdersFirstEtlJob/TASK2.2.md
- specs/BrinkPosOrdersFirstEtlJob/TASK2.3.md
- specs/BrinkPosOrdersFirstEtlJob/TASK2.4.md
- specs/BrinkPosOrdersFirstEtlJob/TASK2.md
- specs/BrinkPosOrdersFirstEtlJob/TASK3.1.md
- specs/BrinkPosOrdersFirstEtlJob/TASK3.2.md
- specs/BrinkPosOrdersFirstEtlJob/TASK3.3.md
- specs/BrinkPosOrdersFirstEtlJob/TASK3.4.md
- specs/BrinkPosOrdersFirstEtlJob/TASK3.md
- specs/BrinkPosOrdersFirstEtlJob/TASK4.1.md
- specs/BrinkPosOrdersFirstEtlJob/TASK4.2.md
- specs/BrinkPosOrdersFirstEtlJob/TASK4.3.md
- specs/BrinkPosOrdersFirstEtlJob/TASK4.4.md
- specs/BrinkPosOrdersFirstEtlJob/TASK4.md
- specs/BrinkPosOrdersFirstEtlJob/TASK5.1.md
- specs/BrinkPosOrdersFirstEtlJob/TASK5.2.md
- specs/BrinkPosOrdersFirstEtlJob/TASK5.3.md
- specs/BrinkPosOrdersFirstEtlJob/TASK5.4.md
- specs/BrinkPosOrdersFirstEtlJob/TASK5.md
- specs/BrinkPosOrdersFirstEtlJob/TASK6.1.md
- specs/BrinkPosOrdersFirstEtlJob/TASK6.2.md
- specs/BrinkPosOrdersFirstEtlJob/TASK6.3.md
- specs/BrinkPosOrdersFirstEtlJob/TASK6.4.md
- specs/BrinkPosOrdersFirstEtlJob/TASK6.md
- specs/BrinkPosOrdersFirstEtlJob/TASK7.md
- specs/BrinkPosOrdersFirstEtlJob/TASK8.md
- specs/BrinkPosOrdersFirstEtlJob/TASK9.md
- specs/BrinkSettings2ToStaging/TASK.MD
- specs/CuratedToS3Stage/TASK.md
- specs/CuratedToS3Stage/TASK0.md
- specs/CuratedToS3Stage/TASK1.md
- specs/CuratedToS3Stage/TASK2.md
- specs/CuratedToS3Stage/TASK3.md
- specs/CuratedToS3Stage/TASK4.md
- specs/CustomerCredentialCustomHeaders/TASK.md
- specs/CustomerCredentialCustomHeaders/TASK1.1.md
- specs/CustomerCredentialCustomHeaders/TASK1.2.md
- specs/CustomerCredentialCustomHeaders/TASK2.1.md
- specs/CustomerCredentialCustomHeaders/TASK2.2.md
- specs/CustomerCredentialCustomHeaders/TASK3.1.md
- specs/CustomerCredentialTriggeredProvisioning/TASK.md
- specs/CustomerCredentialTriggeredProvisioning/TASK1.1.md
- specs/CustomerCredentialTriggeredProvisioning/TASK1.2.md
- specs/CustomerCredentialTriggeredProvisioning/TASK2.1.md
- specs/CustomerCredentialTriggeredProvisioning/TASK2.2.md
- specs/CustomerCredentialTriggeredProvisioning/TASK3.1.md
- specs/CustomerCredentialTriggeredProvisioning/TASK3.2.md
- specs/CustomerCredentialTriggeredProvisioning/TASK4.1.md
- specs/EtlSourceAdapterFramework/TASK.md
- specs/EtlSourceAdapterFramework/TASK0.md
- specs/EtlSourceAdapterFramework/TASK1.md
- specs/EtlSourceAdapterFramework/TASK2.md
- specs/EtlSourceAdapterFramework/TASK3.md
- specs/EtlSourceAdapterFramework/TASK4.md
- specs/EtlSourceAdapterFramework/TASK5.md
- specs/EtlSourceAdapterFramework/TASK6.md
- specs/KdsCdcDebeziumIntegration/TASK.md
- specs/KdsCdcDebeziumIntegration/TASK1.md
- specs/KdsCdcDebeziumIntegration/TASK2.md
- specs/KdsCdcDebeziumIntegration/TASK3.md
- specs/KdsCdcDebeziumIntegration/TASK4.md
- specs/KdsCdcDebeziumIntegration/TASK5.md
- specs/KdsCdcDurableRelationRouting/TASK.md
- specs/KdsCdcDurableRelationRouting/TASK1.md
- specs/KdsCdcDurableRelationRouting/TASK2.md
- specs/KdsCdcDurableRelationRouting/TASK3.md
- specs/KdsCdcDurableRelationRouting/TASK4.md
- specs/KdsCdcDurableRelationRouting/TASK5.md
- specs/KdsCdcIngestion/TASK.md
- specs/KdsCdcIngestion/TASK1.md
- specs/KdsCdcIngestion/TASK2.md
- specs/KdsCdcIngestion/TASK3.md
- specs/KdsCdcIngestion/TASK4.md
- specs/KdsCdcIngestion/TASK5.md
- specs/KdsCdcIngestion/TASK6.md
- specs/KdsCdcIngestion/TASK7.md
- specs/KdsCdcIngestion/TASK8.md
- specs/KdsCdcIngestion/TASK9.md
- specs/KdsCdcReplayExecution/TASK.md
- specs/KdsCdcReplayExecution/TASK1.md
- specs/KdsCdcReplayExecution/TASK2.md
- specs/KdsCdcReplayExecution/TASK3.md
- specs/KdsCdcReplayExecution/TASK4.md
- specs/KdsMonitorServingContractMigration/TASK.md
- specs/KdsMonitorServingContractMigration/TASK1.1.md
- specs/KdsMonitorServingContractMigration/TASK1.2.md
- specs/KdsMonitorServingContractMigration/TASK2.1.md
- specs/KdsMonitorServingContractMigration/TASK2.2.md
- specs/KdsMonitorServingContractMigration/TASK3.1.md
- specs/KdsMonitorServingContractMigration/TASK3.2.md
- specs/RedshiftFoundation/TASK.md
- specs/RedshiftFoundation/TASK1.1.md
- specs/RedshiftFoundation/TASK1.2.md
- specs/RedshiftFoundation/TASK1.3.md
- specs/RedshiftFoundation/TASK1.4.md
- specs/RedshiftFoundation/TASK2.1.md
- specs/RedshiftFoundation/TASK2.2.md
- specs/RedshiftFoundation/TASK3.1.md
- specs/RedshiftFoundation/TASK3.2.md
- specs/RedshiftFoundation/TASK3.3.md
- specs/RedshiftSyntheticDataFeed/TASK.md
- specs/RedshiftSyntheticDataFeed/TASK1.1.md
- specs/RedshiftSyntheticDataFeed/TASK1.2.md
- specs/RedshiftSyntheticDataFeed/TASK1.3.md
- specs/RedshiftSyntheticDataFeed/TASK2.1.md
- specs/RedshiftSyntheticDataFeed/TASK2.2.md
- specs/RedshiftSyntheticDataFeed/TASK3.1.md
- specs/RedshiftSyntheticDataFeed/TASK3.2.md
- specs/SingleStoreRedshiftRuntimeReadPath/TASK.md
- specs/SingleStoreRedshiftRuntimeReadPath/TASK1.1.md
- specs/SingleStoreRedshiftRuntimeReadPath/TASK1.2.md
- specs/SingleStoreRedshiftRuntimeReadPath/TASK2.1.md
- specs/SingleStoreRedshiftRuntimeReadPath/TASK2.2.md
- specs/SingleStoreRedshiftRuntimeReadPath/TASK2.3.md
- specs/SingleStoreRedshiftRuntimeReadPath/TASK3.1.md
- specs/SingleStoreRedshiftRuntimeReadPath/TASK3.2.md
- specs/SingleStoreRedshiftRuntimeReadPath/TASK4.1.md
TASK 1: Establish KDS CDC Adapter Identity And Pipeline Integration
Summary
Establish the production KDS CDC adapter as a first-class ETL framework source.
This task creates the implementation seam for all later KDS CDC work by freezing:
- source identity,
- ingestion mode,
- stage list,
- adapter registration,
- runtime adapter resolution pattern,
- separation from synthetic KDS bootstrap code.
This task does not implement CDC message intake, tenant mapping, raw persistence, or Redshift logic yet.
Current Codebase Findings
Repository analysis shows the existing ETL framework already has the core runtime seam KDS CDC should reuse:
IEtlSourceAdapterexposesDescriptorplus orderedGetStages().EtlPipelineRunnerexecutes adapter-declared stages in order and carries prior stage outputs throughEtlStageContext.EtlStageNamesalready defines all five required stage names:extract_raw,normalize_load,load_to_staging,staging_to_curated, andcurated_to_s3.BrinkPosSourceAdapteris current reference implementation for a full five-stage adapter.DependencyInjectionExtensions.AddBrinkPosEtlModule()registers stage wrappers plusIEtlSourceAdapterusing DI.BrinkPosEtlJobsresolves the adapter bycandidate.Descriptor.SourceType == "brink_pos"and passes it intoIEtlPipelineRunner.
Repository analysis also shows why a new identity is required:
IngestionMode.Cdcalready exists and can be reused directly.IngestionSourceTypecurrently contains onlySyntheticKdsandBrinkOrders; no production KDS CDC enum exists yet.SyntheticKdsFeedServiceis a separate direct warehouse-feed path withIngestionMode.SyntheticFeedandIngestionSourceType.SyntheticKds.- synthetic KDS code writes directly through warehouse services and is not an ETL source adapter.
- tenant warehouse bootstrap currently ties KDS staging resources to Brink POS credential/service enablement in existing warehouse bootstrap code, so KDS CDC must introduce its own enablement path rather than relying on Brink onboarding.
This means Task 1 should add a new production identity and adapter registration rather than extend SyntheticKdsFeedService or reuse SyntheticKds enum/storage identity.
Dependencies
docs/features/ETL/kds-cdc/index.mddocs/features/ETL/kds-cdc/implementation-breakdown.md- existing ETL framework from
specs/EtlSourceAdapterFramework
Source References
../../docs/features/ETL/kds-cdc/implementation-breakdown.md#task-checklist../../docs/features/ETL/kds-cdc/index.md#selected-behavior-summary../../docs/features/ETL/kds-cdc/index.md#batch-lifecycle-and-lineage../../docs/features/ETL/kds-cdc/index.md#non-goals../../docs/features/ETL/etl-source-adapter-framework.md../../docs/features/ETL/how-to-add-etl-source-adapter.md
Scope From Breakdown
This task covers only the first implementation-breakdown item:
- introduce production source identity for KDS CDC and keep it separate from
SyntheticKds - register adapter in existing ETL framework with ingestion mode
Cdc - define stage list and adapter wiring so KDS CDC follows framework-native stage execution
Files to Create
1. KDS CDC adapter package
Create a dedicated KDS CDC adapter package under the ETL integration layer.
Recommended logical location:
backend/Kds.Ai.Integrations/KdsCdc/
Minimum logical types:
KdsCdcSourceAdapterKdsCdcExtractStageKdsCdcNormalizeLoadStageKdsCdcLoadToStagingStageKdsCdcStagingToCuratedStageKdsCdcCuratedToS3StageKdsCdcEtlStageConstantsonly if truly needed for source-local constants not already covered byEtlStageNames
Important rule:
- stage wrappers should use
EtlStageNamesfor stage names, - source-local constants should only hold KDS CDC identity values or contract-version details,
- do not duplicate shared stage-name literals in a new source-local constants class unless there is a concrete need beyond current framework contracts.
2. KDS CDC entrypoint seam
Create the first runtime entrypoint seam for KDS CDC pipeline invocation.
Exact host type may vary, but the code should make room for a CDC-native entrypoint such as:
- background worker,
- job host wrapper,
- poller orchestration service.
Recommended logical types:
IKdsCdcPipelineLauncherKdsCdcPipelineLauncher- or a KDS CDC worker/job class that owns adapter selection and
IEtlPipelineRunnerinvocation.
This seam should be distinct from Brink scheduler/manual jobs because KDS CDC runtime trigger semantics are different.
3. KDS CDC pipeline request/result models if needed
If current EtlPipelineRequest is too Brink-shaped for CDC caller clarity, add thin KDS CDC-specific request models that translate into the shared pipeline request.
Do not redesign the framework request shape in this task unless an actual blocker appears.
Files to Modify
4. Source identity enum
Modify:
backend/Kds.Ai.Data/Enums/IngestionSourceType.cs
Add a new production enum value for KDS CDC.
Expected value:
KdsCdc
Do not rename or repurpose SyntheticKds.
5. DI registration
Modify:
backend/Kds.Ai.Integrations/DependencyInjectionExtensions.cs
Add KDS CDC stage wrappers, adapter registration, and any first entrypoint or worker services needed for runtime composition.
Important DI rule:
- KDS CDC should register as another
IEtlSourceAdapter, alongside Brink, - do not replace the existing Brink adapter registration,
- do not collapse both sources into one adapter.
6. Adapter selection call sites
Review and update any call sites that assume only Brink exists.
Confirmed current call site:
backend/Kds.Ai.ApiService/Jobs/BrinkPosEtlJobs.cs
Current pattern is acceptable for Brink because it filters by Descriptor.SourceType == "brink_pos".
Task 1 should establish the same selection pattern for KDS CDC callers, typically by resolving sourceAdapters.Single(...) for "kds_cdc".
Do not force a premature generic source-dispatch registry unless a second caller already needs it in this task.
7. ETL framework tests
Modify or add tests under:
backend/tests/Kds.Ai.Integrations.Tests/Etl/backend/tests/Kds.Ai.Integrations.Tests/KdsCdc/if a new source-specific test folder is introduced
8. KDS CDC service/bootstrap enablement
Review warehouse/bootstrap enablement seams so KDS CDC can provision required KDS staging/curated resources without depending on CustomerCredentialService.BrinkPos.
Expected areas:
- customer credential/service enum or equivalent source enablement metadata,
- tenant warehouse bootstrap resource-prefix selection,
- AppHost/local configuration for enabling KDS CDC in development.
Preferred direction:
- add explicit KDS CDC service/source enablement, such as
CustomerCredentialService.KdsCdc, or another narrowly scoped warehouse bootstrap flag if credential-service enum is not the right abstraction.
Required Behavior
Source identity
KDS CDC must have both:
- storage/source string identity:
kds_cdc - typed enum identity:
IngestionSourceType.KdsCdc
These identities must flow consistently through:
EtlSourceDescriptor,- stage batch creation requests,
- checkpoint requests,
- failed package metadata,
- future curated
_etl_source_typewrites.
Ingestion mode
KDS CDC stage jobs must use IngestionMode.Cdc.
This is already supported by backend/Kds.Ai.Data/Enums/IngestionMode.cs and should not be emulated via ApiPull or SyntheticFeed.
Stage list
KDS CDC adapter must expose exactly five stages in framework order:
extract_rawnormalize_loadload_to_stagingstaging_to_curatedcurated_to_s3
This ordering must be returned from IEtlSourceAdapter.GetStages().
The stage list must match the main KDS CDC feature doc and the current framework capability.
Framework-native runtime execution
KDS CDC must execute through:
IEtlPipelineRunnerIEtlSourceAdapterIEtlStageEtlStageContextEtlStageResult
Do not implement a custom internal loop for stage chaining.
Separation from synthetic KDS
The new KDS CDC implementation must not:
- reuse
IngestionSourceType.SyntheticKds, - reuse
IngestionMode.SyntheticFeed, - extend
SyntheticKdsFeedServiceas its orchestration mechanism, - identify production CDC rows or batches as synthetic KDS.
The synthetic feed remains a separate bootstrap path.
Stage wrapper behavior for task 1
Because downstream CDC logic is not implemented yet, stage wrapper behavior may begin as one of two acceptable shapes:
- thin wrappers over not-yet-implemented KDS CDC job services that define final contracts and throw intentional
NotImplementedException, or - thin wrappers over placeholder services that return task-specific temporary results used only to prove registration and ordering in tests.
Preferred rule:
- define the final wrapper and job-service seams now,
- keep placeholder behavior minimal,
- avoid fake business logic that later tasks must delete.
Batch lifecycle alignment
Task 1 should freeze the expectation that each KDS CDC stage will own its own IngestionBatch and chain through UpstreamBatchId like the main feature doc requires.
Task 1 does not need to implement all stage job details, but the public seams and acceptance criteria must reflect that per-stage lifecycle model.
Business date rule
KDS CDC has no source business date. The adapter must plan for:
BusinessDate = DateOnly.FromDateTime(DateTime.UtcNow)This rule becomes authoritative for KDS CDC stage jobs.
Task 1 does not need full implementation, but it should not leave room for Brink-style business-date resolution semantics to leak into CDC.
Proposed Implementation Shape
Recommended descriptor:
public EtlSourceDescriptor Descriptor { get; } = new("kds_cdc", IngestionSourceType.KdsCdc);Recommended adapter shape:
internal sealed class KdsCdcSourceAdapter(
KdsCdcExtractStage extractStage,
KdsCdcNormalizeLoadStage normalizeLoadStage,
KdsCdcLoadToStagingStage loadToStagingStage,
KdsCdcStagingToCuratedStage stagingToCuratedStage,
KdsCdcCuratedToS3Stage curatedToS3Stage) : IEtlSourceAdapter
{
private readonly IReadOnlyList<IEtlStage> _stages =
[
extractStage,
normalizeLoadStage,
loadToStagingStage,
stagingToCuratedStage,
curatedToS3Stage
];
public EtlSourceDescriptor Descriptor { get; } = new("kds_cdc", IngestionSourceType.KdsCdc);
public IReadOnlyList<IEtlStage> GetStages() => _stages;
}Recommended entrypoint pattern:
var adapter = sourceAdapters.Single(static candidate =>
string.Equals(candidate.Descriptor.SourceType, "kds_cdc", StringComparison.Ordinal));
await pipelineRunner.RunAsync(
new EtlPipelineRequest(
companyId,
tenantId,
businessDate: null,
trigger,
forceReset,
requestedBy,
adapter),
ct);Important note:
businessDate: nullhere reflects that caller does not supply a business date.- stage-job implementations should derive processing date internally in later tasks.
- do not change the shared pipeline contract only to force a CDC business date placeholder into task 1.
Testing
Unit tests
Add unit tests for:
- new
IngestionSourceType.KdsCdcpresence and KDS CDC descriptor usage where practical, - KDS CDC adapter descriptor equals
("kds_cdc", IngestionSourceType.KdsCdc), - KDS CDC adapter returns five stages in correct order,
- each KDS CDC wrapper exposes correct
StageNamefromEtlStageNames, - DI resolves both Brink and KDS CDC
IEtlSourceAdapterregistrations together, - KDS CDC entrypoint resolves adapter by
"kds_cdc"and invokesIEtlPipelineRunnerwith that adapter, - no test path identifies KDS CDC as
SyntheticKds.
Integration or composition tests
Add at least one composition-focused test proving:
- host or service provider can resolve
IEnumerable<IEtlSourceAdapter>, - the KDS CDC adapter is present,
- stage ordering is stable,
- existing Brink adapter remains present.
Not required in task 1
This task does not require:
- live SQS integration,
- live AWS tests,
- Redshift tests,
- stage lifecycle persistence tests beyond what adapter identity requires.
Acceptance Criteria
- [ ]
IngestionSourceType.KdsCdcexists as new production source enum value - [ ] KDS CDC uses source string
kds_cdc - [ ] KDS CDC uses
IngestionMode.Cdc - [ ] A dedicated
KdsCdcSourceAdapterexists - [ ] KDS CDC adapter implements
IEtlSourceAdapter - [ ] KDS CDC adapter returns five framework stages
- [ ] KDS CDC stage order is
extract_raw -> normalize_load -> load_to_staging -> staging_to_curated -> curated_to_s3 - [ ] KDS CDC stage wrappers use shared
EtlStageNames - [ ] KDS CDC runtime composition is registered through DI
- [ ] DI resolves KDS CDC alongside Brink POS, not instead of Brink POS
- [ ] A KDS CDC pipeline entry seam exists for future worker/job invocation
- [ ] KDS CDC entry seam selects adapter by
Descriptor.SourceType == "kds_cdc" - [ ] KDS CDC warehouse/bootstrap enablement is separate from Brink POS credential/service enablement
- [ ] No production CDC path reuses
SyntheticKdsFeedServiceas its adapter runtime - [ ] No production CDC path uses
IngestionSourceType.SyntheticKds - [ ] No production CDC path uses
IngestionMode.SyntheticFeed - [ ] Tests cover adapter descriptor, stage ordering, DI registration, and source separation
- [ ] Solution builds without errors
Notes
- Follow
docs/features/ETL/kds-cdc/index.mdas source of truth for source identity and stage model. - Use Brink POS adapter as structural reference, not as semantic template for scheduling or business-date behavior.
- Keep Task 1 minimal: identity and integration seams only.
- Prefer thin placeholder job services over speculative CDC logic.
- Preserve room for a future CDC-native worker that polls SQS and then invokes the shared pipeline.