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 4: Raw To Load Normalization
Summary
Implement the first normalize_load ETL stage for the narrowed Brink v1 slice: one tenant-day raw -> load flow for Sales2.GetOrders only.
This task starts from the persisted extract_raw replay boundary from TASK2.md and the stage lifecycle contract from TASK3.md, and turns them into a real normalize_load execution step that:
- resolves one successful upstream
extract_rawbatch - reads persisted raw XML from S3
raw/ - normalizes
GetOrdersXML into the existingGetOrdersstaging/load contracts - writes Parquet artifacts to S3
load/ - records load-stage diagnostics, contract inventory, and upstream lineage
This task owns:
normalize_loadchild job contract and orchestration- upstream raw-batch resolution for one tenant-day run
GetOrdersnormalization catalog and context construction- relational decomposition of the
GetOrderspayload into load contracts - load artifact persistence and diagnostics
- unit tests and live E2E for the first
raw -> loadboundary
This task does not implement Redshift COPY, curated SQL, or curated export. Those belong to later tasks.
Dependencies
- TASK 0 - Module 0 decision record
- TASK 2 - extract raw XML
- TASK 3 - batch lifecycle, checkpoints, and failure packaging
Subtasks
- [x] TASK 4.1 - Implement normalize-load orchestration and upstream raw-batch resolution
- [x] TASK 4.2 - Implement
GetOrdersrelational decomposition and normalization catalog - [x] TASK 4.3 - Implement load artifact persistence and normalize-load diagnostics
- [x] TASK 4.4 - Add unit tests and live E2E validation for
normalize_load
Files to Create
1. Normalize-load orchestration contracts and services
Create or finalize the ETL/Warehouse-facing services that execute one tenant-day normalize_load run.
Required logical responsibilities:
- child normalize-load job entry
- upstream raw-batch resolver
- normalize-load orchestrator
- normalization catalog for the narrowed v1 scope
- normalization context factory
- load artifact writer
Recommended logical services:
BrinkPosNormalizeLoadJobsBrinkPosRawBatchResolverBrinkPosNormalizeLoadOrchestratorBrinkPosNormalizationCatalogBrinkPosNormalizationContextFactoryBrinkPosLoadArtifactWriter
2. Load-stage result and diagnostics models
Create or finalize the minimum models needed for one normalize_load endpoint execution and one full tenant-day load batch.
Required minimum details:
company_idtenant_idbusiness_datepipeline_stage = normalize_load- upstream
extract_rawbatch reference stream_nameoperation_nametarget_contract_group- emitted contracts with schema versions, row counts, and
load/URIs started_atcompleted_at- endpoint and batch status
3. Normalization contract inventory
Create or finalize the fixed v1 operation-to-contract inventory for Sales2.GetOrders based on the existing staging model under:
backend/integrations/Kds.Ai.Integrations.BrinkPos/Models/Staging/Sales2/GetOrders
This task should treat that existing staging model as the target contract and verify its completeness against:
- Brink portal semantics
temp/GetOrders_WithKnownBusinessDate_CallsRealBrinkEndpoint_2024-10-06.xml
Files to Modify
4. Shared normalization seam
Modify or finalize the shared normalization seam so the ETL job starts from persisted raw S3 objects and ETL context, not from in-memory DTO state from extraction.
Required responsibility split:
- shared ETL/Warehouse code owns upstream raw selection, context construction, stage lifecycle, and
load/artifact persistence Kds.Ai.Integrations.BrinkPosownsGetOrdersparsing, source-shaped mapping, and operation-specific normalization profiles
5. Brink GetOrders normalization profiles and mappers
Modify the Brink normalization path so Sales2.GetOrders emits the full existing staging-model contract set needed by this slice.
This task should not widen v1 scope to any non-GetOrders endpoint.
6. S3 load storage integration
Modify the shared ETL storage path so load artifacts are written to the standard S3 load/ layout from docs/ETL.md, and final URIs are recorded in normalize_load batch diagnostics.
7. Batch lifecycle touch points
Use the lifecycle contract from TASK3.md so normalize_load batches store current-state, checkpoint, rerun lineage, and upstream extract_raw batch references consistently.
Required Behavior
Scope rule
This task is strict v1 normalize_load only for:
Sales2.GetOrders
No kitchen or settings endpoint belongs to this task, even if older Brink groundwork documents describe a broader normalization catalog.
Upstream-batch rule
For one child normalize-load request:
- if
ExtractBatchIdis provided, resolve that successfulextract_rawbatch - otherwise resolve the current successful
extract_rawbatch for the same tenant and business date - use that upstream batch as the only normalization source for the full tenant-day load run
Failed or non-current upstream raw batches must not be used unless a later replay policy expands explicitly.
Input contract rule
The child normalize-load contract should follow this logical shape:
CompanyIdTenantId- required
BusinessDate - optional
ExtractBatchId TriggerForceReset- optional
RequestedBy
BusinessDate is required here because the effective date was already resolved by extract_raw.
Replay-boundary rule
- normalization starts from persisted
raw/artifacts only - this stage must not call Brink again
- this stage must not depend on typed DTOs carried across from
extract_raw - replay for
normalize_loadrebuildsload/artifacts from persisted upstream raw artifacts
Target-contract rule
The target contract for this task is the existing GetOrders staging model already present in code.
Required emitted contracts for v1 are:
staging.brink_sales2_ordersstaging.brink_sales2_order_entriesstaging.brink_sales2_order_entry_voidsstaging.brink_sales2_order_entry_taxesstaging.brink_sales2_order_entry_promotionsstaging.brink_sales2_order_entry_discountsstaging.brink_sales2_order_entry_modifiersstaging.brink_sales2_order_entry_modifier_taxesstaging.brink_sales2_order_entry_modifier_promotionsstaging.brink_sales2_order_paymentsstaging.brink_sales2_order_payment_detailsstaging.brink_sales2_order_payment_additional_datastaging.brink_sales2_order_taxesstaging.brink_sales2_order_discountsstaging.brink_sales2_order_promotionsstaging.brink_sales2_order_surchargesstaging.brink_sales2_order_surcharge_taxesstaging.brink_sales2_order_deposits
This list is derived from the current code-backed staging model and should be treated as the source of truth for this slice.
Relational decomposition rule
Sales2.GetOrdersmust not be normalized as one flat header contract only- nested collections must be decomposed into separate emitted contracts where the staging model already represents them relationally
- child contracts must preserve deterministic parent-child join keys and row ordinals where needed
- this stage remains source-shaped and technical; do not add curated logic or cross-endpoint enrichment here
Normalization boundary rule
- shared ETL/Warehouse code owns stage orchestration and load artifact persistence
- Brink normalization code owns XML parsing, payload traversal, and source-shaped mapping
- the job-level contract depends on
OperationName,TargetContractGroup,ParserVersion, andContractVersion - the job-level contract must not depend on concrete mapper class names
Metadata envelope rule
Every emitted contract must include the ETL metadata envelope needed by the staging plan, including at least:
_etl_batch_id_etl_source_type_etl_operation_name_etl_contract_name_etl_schema_version_etl_ingested_at_etl_raw_s3_path_etl_row_ordinal
Load artifact rule
- generated load artifacts must be written to S3
load/ - final
load/URIs, schema versions, row counts, and contract names must be recorded in batch details - if any required contract write fails, the endpoint fails and the full
normalize_loadbatch fails - already written
load/artifacts may remain for diagnostics and replay
Zero-row rule
- zero rows is not a failure by itself
- successful normalization may emit zero rows for one or more contracts
- the stage is still successful if parsing, mapping, and required persistence complete successfully
Lifecycle rule
- one child
normalize_loadjob executes one tenant-day stage boundary - the stage uses the batch, checkpoint,
is_current, rerun, and upstream-lineage contract fromTASK3.md - fail-fast behavior is acceptable because v1 contains one required upstream operation only
Testing
Unit tests
Unit tests are mandatory for this task.
Add unit tests for:
- upstream raw-batch resolution with explicit
ExtractBatchId - upstream raw-batch resolution through current successful
extract_rawbatch lookup - normalization catalog correctness for the narrowed v1 scope
NormalizationContextconstruction from persisted raw artifact metadataSales2.GetOrdersrelational decomposition into the full emitted contract set- ETL metadata envelope population on emitted rows
- deterministic parent-child key and ordinal behavior
- zero-row successful normalization behavior
- load artifact persistence and diagnostics recording
- failure handling when one required emitted contract write fails
Live E2E tests
This task ends at a real ETL boundary, so live E2E is required whenever Aspire-managed secrets and integrations are available.
Add live E2E coverage that verifies at least:
- one successful tenant-day
extract_rawbatch can be used as the upstream source fornormalize_load - the stage reads real persisted raw XML rather than re-calling Brink
Sales2.GetOrdersproduces Parquet artifacts in S3load/- emitted artifacts match the expected contract inventory for the selected real raw sample
- batch metadata points to the produced
load/artifacts and upstream raw batch correctly
Recommended live verification shape:
- run one real tenant-day
extract_rawbatch - start
normalize_loadfrom that raw batch - assert that expected Parquet artifacts exist in
load/ - assert that metadata records contract names, row counts, schema versions, and URIs
- assert that no secrets are written into load diagnostics or object metadata
Acceptance Criteria
- [x] Child normalize-load job entry exists for one tenant-day
normalize_loadstage - [x]
normalize_loadresolves a successful upstreamextract_rawbatch by explicit id or current-state lookup - [x]
normalize_loadstarts from persisted raw S3 artifacts only - [x]
Sales2.GetOrdersis the only normalization source in this task - [x] The existing
GetOrdersstaging model is reused as the target load contract - [x]
GetOrdersnormalization emits the full required relational contract set for the existing staging model - [x] Every emitted contract includes the ETL metadata envelope and deterministic lineage fields
- [x] Parquet load artifacts are written to S3
load/ - [x] Normalize-load diagnostics capture upstream batch, contract inventory, row counts, schema versions, and load URIs
- [x] Zero-row successful normalization is handled correctly
- [x] Unit tests cover orchestration, decomposition, metadata, and failure behavior
- [x] Live E2E verifies Parquet output from real persisted raw artifacts
- [x] Solution builds without errors
Notes
- Follow
TASK0.mdas the authoritative scope document when older Brink docs widen normalization scope. - Keep this task strict:
raw -> loadonly. - Reuse the existing code-backed staging model for
GetOrders; verify completeness rather than redesigning the stage shape. - Keep normalization source-shaped; curated semantics belong to later tasks.