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 7: Implement Curated Transformation And Curated-To-S3 Export
Summary
Implement KDS CDC staging_to_curated and curated_to_s3 as framework-native downstream stages after successful source-shaped staging load. This task defines curated merge boundaries, source-identity and soft-delete handling, curated target and export catalogs, and Redshift UNLOAD export behavior for initial delivery. It excludes final checkpoint/replay orchestration beyond the durable details these stages must persist.
Current Codebase Findings
docs/features/ETL/kds-cdc/index.mdStage 8 requires idempotent staging-to-curated merges intocurated.kitchen_orders,curated.kitchen_order_items,curated.kitchen_item_status_events, andcurated.customerswhere applicable.- Stage 8 also fixes behavior: preserve production KDS CDC identity, apply source
is_deletedas soft-delete semantics, keep transaction sizes bounded by batch size, and do not advance checkpoint if curated merge fails. - Stage 9 requires
curated_to_s3from first delivery, using RedshiftUNLOADinto tenant/entity-partitioned curated Parquet under the existing ETL S3 layout. backend/Kds.Ai.Integrations/BrinkPos/BrinkPosStagingToCuratedJobs.csis current framework-native reference for curated-stage job orchestration:- resolve upstream successful
load_to_stagingbatch, - start a stage-scoped
IngestionBatch, - execute curated targets through
ICuratedTargetExecutor, - persist structured stage details,
- complete batch, then advance checkpoint,
- fail the batch through
StageExecutionSupport.FailStageBatchAsyncon exception. backend/Kds.Ai.Integrations/BrinkPos/BrinkPosCuratedToS3Jobs.csis current framework-native reference for export-stage orchestration:- resolve upstream successful
staging_to_curatedbatch, - start a stage-scoped
IngestionBatch, - execute export targets through
ICuratedExportExecutor, - persist structured export details,
- complete batch, then advance checkpoint,
- fail the batch on exception using warehouse-curated failure context.
backend/Kds.Ai.Integrations/Etl/CuratedTargetExecutor.csprovides a generic transactional executor that runs each target'sDeleteSqlthenWriteSqlinside one Redshift transaction usingtenant_id,business_date, andsnapshot_dateparameters.backend/Kds.Ai.Integrations/Etl/CuratedExportExecutor.csprovides a generic RedshiftUNLOADexecutor that:- builds curated S3 prefix URIs through
IEtlS3Storage.BuildCuratedUri(...), - uses explicit
SELECTSQL per target, - writes
PARQUET ALLOWOVERWRITE, - cleans up already-exported prefixes if a later export target fails.
backend/Kds.Ai.Integrations/BrinkPos/BrinkPosCuratedTargetCatalog.csshows repo pattern for curated-target catalogs: explicit target names, required staging tables, SQL template ids, delete SQL, insert SQL, and source-type filtering.backend/Kds.Ai.Integrations/BrinkPos/BrinkPosCuratedExportCatalog.csshows repo pattern for curated export catalogs: explicitSELECTprojection, export entity name, file-prefix naming, and source-type/date filters.backend/Kds.Ai.Warehouse/Services/Synthetic/RedshiftCuratedOrderWriter.csis current KDS-specific curated data reference, but it is a legacy synthetic runtime path. It directly mutatescurated.kitchen_orders,curated.kitchen_order_items, andcurated.kitchen_item_status_eventsusingSourceSystem = "synthetic_kds", id-based delete/reinsert logic, and post-write orphan validation. It is useful for KDS table relationships and field parity only, not for production CDC runtime shape.backend/Kds.Ai.Warehouse/Models/Curated/CuratedTableNames.csalready includesKitchenOrders,KitchenOrderItems,KitchenItemStatusEvents, andCustomers.- Repo evidence currently shows bootstrap/runtime coverage for
curated.kitchen_orders,curated.kitchen_order_items, andcurated.kitchen_item_status_events, but noCREATE TABLE curated.customersSQL or corresponding runtime/catalog/export/test path was found.
Current repo constraints this task must respect:
- Curated KDS production runtime must move through framework-native
staging_to_curatedandcurated_to_s3stages, not the old synthetic direct-writer path. - Existing generic curated executors are reusable, but KDS CDC needs its own catalogs, details models, and SQL semantics because CDC row deltas and soft deletes are not Brink snapshot semantics.
curated.customersis part of the documented target set, but repo does not show a finished schema/runtime/export path for it today, so Task 7 must make an explicit implementation-or-conditional-scope decision instead of assuming it already exists.
Dependencies
../../docs/features/ETL/kds-cdc/index.md../../docs/features/ETL/kds-cdc/implementation-breakdown.md../../docs/features/ETL/etl-source-adapter-framework.md./TASK6.md
Source References
../../docs/features/ETL/kds-cdc/implementation-breakdown.md#task-checklist../../docs/features/ETL/kds-cdc/index.md#stage-8-staging-to-curated-staging_to_curated../../docs/features/ETL/kds-cdc/index.md#stage-9-curated-to-s3-curated_to_s3../../docs/features/ETL/kds-cdc/index.md#selected-behavior-summary../../docs/features/ETL/kds-cdc/index.md#checkpointing-and-replay../../docs/features/ETL/kds-cdc/index.md#quarantine-and-failed-packages../../docs/features/ETL/kds-cdc/index.md#supported-corner-cases../../docs/features/ETL/etl-source-adapter-framework.md
Scope From Breakdown
- apply idempotent staging-to-curated merges for KDS warehouse targets
- preserve production KDS CDC source identity and soft-delete semantics in curated layer
- export curated data to tenant/entity-partitioned S3 Parquet with Redshift
UNLOAD - treat curated export as part of first delivery, not later follow-up work
Files to Create
- KDS CDC curated-stage jobs and details under
backend/Kds.Ai.Integrations/KdsCdc/and/Models/: IKdsCdcStagingToCuratedJobsKdsCdcStagingToCuratedJobsIKdsCdcCuratedToS3JobsKdsCdcCuratedToS3JobsKdsCdcStagingToCuratedDetailsKdsCdcCuratedTargetDiagnosticKdsCdcCuratedToS3DetailsKdsCdcCuratedExportDiagnostic
Responsibilities:
- resolve successful upstream batches from Task 6,
- select executable curated targets,
- run framework-native curated merge and export executors,
- persist structured details for replay and diagnostics,
- complete stage batches only after merge/export success.
- KDS CDC curated target catalog under
backend/Kds.Ai.Integrations/KdsCdc/: KdsCdcCuratedTargetCatalog- optional
KdsCdcCuratedTargetDefinition
Responsibilities:
- define curated targets for
kitchen_orders,kitchen_order_items,kitchen_item_status_events, andcustomerswhere applicable, - declare required staging tables,
- define SQL template ids,
- define idempotent delete/upsert SQL that preserves production source identity and soft-delete behavior.
- KDS CDC curated export catalog under
backend/Kds.Ai.Integrations/KdsCdc/: KdsCdcCuratedExportCatalog- optional
KdsCdcCuratedExportDefinition
Responsibilities:
- define explicit export targets and
SELECTprojections, - freeze export entity names and output-prefix naming,
- filter exported rows to production KDS CDC source identity,
- preserve tenant/entity partitioning for S3 curated exports.
- Optional KDS CDC curated SQL helpers under
backend/Kds.Ai.Integrations/KdsCdc/Sql/if query text becomes too large for one catalog file: - keep helper scope minimal,
- prefer explicit target-owned SQL over generic abstraction if only KDS CDC uses it.
Files to Modify
- KDS CDC adapter stage wrappers from Task 1 in
backend/Kds.Ai.Integrations/KdsCdc/andbackend/Kds.Ai.Integrations/DependencyInjectionExtensions.cssostaging_to_curatedandcurated_to_s3are real framework stages usingEtlStageNames.StagingToCuratedandEtlStageNames.CuratedToS3. - Task 6 load-to-staging details/contracts under
backend/Kds.Ai.Integrations/KdsCdc/so curated jobs can deterministically select executable targets from durable upstream staging results. - Shared curated executor/catalog seams only if additive capability is truly required:
backend/Kds.Ai.Integrations/Etl/CuratedTargetExecutor.csbackend/Kds.Ai.Integrations/Etl/CuratedExportExecutor.csbackend/Kds.Ai.Integrations/Etl/ICuratedTargetCatalog.csbackend/Kds.Ai.Integrations/Etl/ICuratedExportCatalog.cs
Guidance: prefer KDS CDC-specific catalogs and details rather than broadening shared abstractions unless a missing shared feature is clearly generic.
- Warehouse bootstrap/schema/runtime seams under
backend/Kds.Ai.Warehouse/Services/,backend/Kds.Ai.WarehouseDataModel/, and related tests ifcurated.customersor KDS CDC-specific curated columns do not already exist or are not yet asserted. - KDS CDC service/bootstrap enablement so curated dependencies for KDS CDC tenants are provisioned independently of Brink POS credentials.
- Tests under:
backend/tests/Kds.Ai.Integrations.Tests/KdsCdc/backend/tests/Kds.Ai.Data.Tests/- additive warehouse/bootstrap/export tests where needed.
Required Behavior
Staging-To-Curated Boundary
staging_to_curatedtransforms source-shaped KDS staging rows into curated warehouse tables after successful Task 6 load-to-staging.- Current curated target set for this task is:
curated.kitchen_orderscurated.kitchen_order_itemscurated.kitchen_item_status_eventscurated.customerswhere applicable- Stage execution must remain framework-native:
- resolve upstream
load_to_stagingbatch, - start a new
IngestionBatchforstaging_to_curated, - run curated SQL through
ICuratedTargetExecutoror a clearly justified additive extension, - persist structured details,
- complete batch,
- advance checkpoint only after completion.
Curated Merge Semantics
- Curated merges must be idempotent for retry from staging/load/raw after failures.
- Curated rows must preserve production source identity as
kds_cdc/KdsCdc, not synthetic KDS. - Source
is_deletedmust flow into curated soft-delete behavior. - Normal KDS CDC path must not physically delete curated rows as business behavior.
- Transaction sizes must remain bounded by micro-batch size and tenant/entity slice boundaries.
- If curated merge fails, checkpoint must not advance and
curated_to_s3must not run for that slice.
KDS Curated SQL Shape
- SQL should be explicit per curated target, following existing catalog style.
- Preferred direction is idempotent delete/reinsert or merge-like behavior scoped to keys present in the current CDC slice, not broad tenant-day replacement.
- Any delete step used for idempotence must preserve soft-delete semantics in final curated state.
- Relationship integrity between orders, items, and item status events must remain safe under partial row updates and retries.
RedshiftCuratedOrderWriter.csmay be used as field-parity and dependency-order reference for kitchen tables, especially parent/child delete ordering and orphan validation, but production KDS CDC runtime must not call that synthetic writer.
Customers Gap
curated.customersis part of documented target scope and must remain explicit in this task.- Since current repo evidence did not show
CREATE TABLE curated.customers, Task 7 must choose and document one of two outcomes: - implement
curated.customersDDL, target catalog, merge SQL, export projection, and tests now, - or mark KDS customer curated output as explicitly conditional with a documented blocker and ensure runtime skips only missing customer artifacts, not all customer support silently.
- If repo bootstrap/runtime support for
curated.customersis incomplete and no blocker is accepted, Task 7 must close that gap with additive schema/catalog/export work rather than silently excluding customers. - If customer events are absent for some tenants or early mock flows, the runtime may skip export/merge for missing upstream customer staging artifacts, but target definitions and stage behavior must still be designed now.
Curated-To-S3 Boundary
curated_to_s3is part of first delivery, not follow-up work.- Export must happen only after curated merge succeeds for the same tenant/entity slice lineage.
- Use Redshift
UNLOADto export curated data to S3 curated Parquet. - Preserve tenant/entity partitioning with conceptual key shape:
curated/company_id={company_id}/tenant_id={tenant_id}/entity={entity}/dt={date}/batch_id={batch_id}/...- Stage success is recorded only after export succeeds.
- On export failure, curated Redshift data remains committed, incomplete curated S3 artifacts should be cleaned up when possible, and retry should be possible from curated-stage output without re-reading SQS.
Source Filtering And Export Contract
- Curated merge and export queries must filter or stamp rows so production CDC rows are identifiable as KDS CDC, not synthetic KDS.
- Export projections should be explicit, not
SELECT *, matching current catalog style and keeping Parquet schema stable. - Export targets should include tenant identity as explicit projected data where repo export conventions already do so.
Durable Stage Details
staging_to_curateddetails should include at minimum:- upstream
load_to_stagingbatch id, - executed target names,
- required staging tables,
- SQL template ids,
- status per target,
- deleted/upserted row counts or equivalent diagnostics,
- start/completion timestamps,
- source identity marker used.
curated_to_s3details should include at minimum:- upstream
staging_to_curatedbatch id, - exported target names,
- entity names,
- output prefix URIs,
- status per target,
- start/completion timestamps.
- Details must be durable enough for Task 8 replay/checkpoint work to retry curated merge/export from staging/load/curated durable state.
Business Date Rule
- Preserve CDC processing-date rule established earlier:
BusinessDate = DateOnly.FromDateTime(DateTime.UtcNow)- Do not switch KDS CDC curated stages to synthetic feed or Brink snapshot semantics.
Proposed Implementation Shape
High-level flow:
Task 6 load_to_staging succeeds for tenant/entity slice
-> resolve upstream successful load_to_staging batch
-> select KDS curated targets whose required staging tables succeeded
-> start staging_to_curated batch
-> execute idempotent curated target SQL inside Redshift transaction(s)
-> persist curated target diagnostics
-> complete staging_to_curated batch
-> start curated_to_s3 batch
-> UNLOAD explicit curated projections to S3 curated prefix per entity
-> persist export diagnostics
-> complete curated_to_s3 batchRecommended stage job shape:
public interface IKdsCdcStagingToCuratedJobs
{
Task<KdsCdcStageJobResult> ExecuteAsync(
KdsCdcStagingToCuratedJobInput input,
CancellationToken ct = default);
}
public interface IKdsCdcCuratedToS3Jobs
{
Task<KdsCdcStageJobResult> ExecuteAsync(
KdsCdcCuratedToS3JobInput input,
CancellationToken ct = default);
}Recommended curated target mapping direction:
staging.kds_orders->curated.kitchen_ordersstaging.kds_items->curated.kitchen_order_itemsstaging.kds_item_bumps->curated.kitchen_item_status_eventsstaging.kds_customers->curated.customers
Recommended design notes:
- Prefer one
staging_to_curatedbatch and onecurated_to_s3batch per tenant/entity slice lineage, matching earlier KDS CDC boundaries. - Use
ICuratedTargetExecutorandICuratedExportExecutorunless a concrete KDS CDC need requires small additive extension. - Keep catalog SQL explicit and source-scoped by KDS CDC identity.
- Keep export projections explicit and stable.
- Keep synthetic KDS writer as reference only for dependency ordering, key-based idempotence, and soft-delete/orphan safety checks.
Testing
- Unit tests for curated target catalog definitions:
- required staging-table dependencies per target,
- target SQL/source-type identity uses KDS CDC rather than synthetic KDS,
- soft-delete semantics are preserved,
- customer target exists or is explicitly conditionally executable by upstream success.
- Unit tests for curated export catalog definitions:
- explicit target/entity naming,
- explicit projections instead of
SELECT *, - KDS CDC source filtering,
- expected curated S3 entity naming and output-prefix rules.
- Job orchestration tests proving:
staging_to_curatedresolves upstream successfulload_to_stagingbatch,- only executable targets run when required staging tables succeeded,
- stage batch completes only after merge/export success,
- checkpoint advancement happens after completion,
- curated merge failure stops export and marks batch failure,
- curated export failure leaves upstream curated merge committed but marks export batch failure.
- Data/warehouse tests for:
- idempotent re-run of same curated slice,
- soft-delete propagation into curated rows,
- safe order/item/status-event relationship handling under retry,
- bootstrap/schema coverage for
curated.customersif currently missing. - KDS CDC curated/bootstrap readiness does not rely on Brink POS service enablement.
- Export executor integration tests or additive tests proving:
- KDS CDC curated exports use Redshift
UNLOAD, - cleanup occurs for already-exported prefixes when a later target fails,
- exported prefixes use tenant/entity/date/batch partitioning.
- Regression tests ensuring Brink curated stages remain unchanged.
Not required in this task:
- full checkpoint/replay orchestration policy,
- new SQS behavior,
- raw/load normalization changes,
- downstream Athena/query-layer consumers.
Acceptance Criteria
- KDS CDC has dedicated
staging_to_curatedandcurated_to_s3job seams wired into framework-native ETL stages. - Curated merge is idempotent and retry-safe.
- Curated rows preserve production KDS CDC identity, not
synthetic_kds. - Source
is_deletedbecomes curated soft-delete behavior, not normal-path physical delete. curated_to_s3is included now and uses RedshiftUNLOAD.- Curated exports are partitioned by company, tenant, entity, and date using existing ETL curated layout.
- Curated export stage succeeds only after export succeeds and cleans up incomplete prefixes when possible.
- Stage details durably record enough merge/export diagnostics for later replay and checkpoint work.
- Kitchen order, order item, and item status event targets are covered.
curated.customersis explicitly addressed in schema/catalog/runtime scope rather than silently omitted.- If
curated.customersis not fully implemented, the conditional blocker is explicit and test-covered. - No KDS CDC runtime path calls
RedshiftCuratedOrderWriteror stamps curated rows withSourceSystem = "synthetic_kds"; production KDS CDC curated rows are identifiable askds_cdc/KdsCdc. - Tests cover target catalogs, export catalogs, stage orchestration, soft-delete behavior, retry behavior, and any required curated customer schema/runtime additions.
Notes
- Use
docs/features/ETL/kds-cdc/index.md#stage-8-staging-to-curated-staging_to_curatedand#stage-9-curated-to-s3-curated_to_s3as source of truth. - Use Brink curated jobs/catalogs as structural reference only; their day/snapshot-scoped SQL should not be copied blindly into CDC row-delta semantics.
- Use
RedshiftCuratedOrderWriter.csonly as KDS field-parity and dependency-order reference. Do not reuse it as production CDC runtime path. - Keep
curated.customersvisible in scope even if current repo support is incomplete.