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 2: Simplify Tenant Identity To store_guid And Define Durable Routing Resolution For Child Entities
Summary
Shift KDS CDC tenant identity from composite source_account_id + store_guid to store_guid == tenant_id, and add a durable routing-resolution path for entities that do not include store_guid directly.
Current Codebase Findings
Repository analysis shows:
KdsCdcTenantResolvercurrently requiresmessage.SourceAccountIdandmessage.StoreGuid.IKdsCdcSourceTenantMappingRepositoryandEfKdsCdcSourceTenantMappingRepositoryare keyed by(sourceType, sourceAccountId, storeGuid).- sample order and customer Debezium payloads include
store_guiddirectly. - sample item Debezium payloads do not include
store_guid; they includeorder_guidanditem_bump_guid.
This means direct tenant resolution can work for orders/customers, but items require a second identity path.
Dependencies
- TASK 1
docs/features/ETL/kds-cdc/debezium-payload-compatibility-notes.md
Source References
../../docs/features/ETL/kds-cdc/debezium-payload-compatibility-notes.md../../docs/features/ETL/kds-cdc/payloads/item_update.json../../docs/features/ETL/kds-cdc/payloads/order_create.json../../docs/features/ETL/kds-cdc/payloads/order_update.json
Scope From Breakdown
This task covers:
- simplified tenant identity contract,
- repository/resolver updates,
- child-entity correlation for tenant resolution,
- durable relation-index seam owned by ETL state,
- failure behavior when relation-based resolution is unavailable.
Files to Modify
backend/Kds.Ai.Integrations/KdsCdc/KdsCdcTenantResolver.csbackend/Kds.Ai.Data/Repositories/IKdsCdcSourceTenantMappingRepository.csbackend/Kds.Ai.Data/Repositories/EfKdsCdcSourceTenantMappingRepository.csbackend/Kds.Ai.Data/Entities/KdsCdcSourceTenantMapping.csbackend/Kds.Ai.Data/Configurations/KdsCdcSourceTenantMappingConfiguration.cs- related migrations if schema changes are chosen now
backend/tests/Kds.Ai.Integrations.Tests/KdsCdc/KdsCdcTenantResolverTests.cs
Potential new helper seams if needed:
- relation cache or repository for
order_guid -> store_guid - relation cache or repository for
item_guid -> store_guid - durable/shared state abstraction if relation lookup must survive worker boundaries
Required Behavior
Direct tenant resolution
For entities whose effective row image includes store_guid:
- tenant identity comes from
store_guid, - tenant id is
store_guid, - no
source_account_idis required for resolution.
Child-entity relation resolution
For items and item_bumps when store_guid is absent:
- resolver must use relation data, most likely
order_guid -> store_guid, - resolver may also use
item_guid -> store_guidwhere that is more direct, - relation data must come from durable/shared ETL state rather than process memory only,
- unresolved relation must not silently assign wrong tenant.
Required failure behavior:
- if relation lookup fails for an otherwise valid Debezium payload, record durable
tenant_unresolvedstate and schedule retry, - do not quarantine valid child payloads only because relation indexes are temporarily incomplete,
- quarantine only when the payload is malformed, unsupported, explicitly non-retryable, or an exhaustion policy decides retry can no longer succeed,
- diagnostics clearly state that child payload lacked direct
store_guid, relation resolution failed, and whether the result is retryable or final.
Relation-index lifecycle
Relation indexes must have one durable owner and one clear update path.
Required behavior:
- order staging/load success updates
order_guid -> store_guid, - item staging/load success updates
item_guid -> store_guidand, if useful,item_guid -> order_guid, - promotion/resolution reads the same durable relation state used by later retry attempts,
- when relation state changes, previously
tenant_unresolvedlanding records can be re-evaluated without re-reading SQS, - relation updates are idempotent and safe to replay.
Mapping storage shape
At minimum, source mapping lookup must stop requiring source_account_id.
Acceptable end states:
- keep a slim mapping table keyed by
(sourceType, storeGuid)forcompanyId + tenantId, or - replace that with tenant lookup if the codebase already has a better authoritative seam.
Whichever path is used, source_account_id must not remain a required KDS CDC resolution input.
Testing
Add tests for:
- order payload resolves tenant directly from
store_guid, - customer payload resolves tenant directly from
store_guid, - item payload resolves tenant via
order_guidrelation, - item-bump payload resolves via relation data,
- child payload without available relation is marked
tenant_unresolvedand scheduled for retry, - child payload resolves after relation index is populated later,
- malformed or unsupported child payload is quarantined rather than retried forever,
- duplicate active
store_guidmappings remain ambiguous and fail clearly if a mapping table is retained, - resolver no longer requires
source_account_id.
Acceptance Criteria
- [ ] KDS CDC tenant resolution no longer requires
source_account_id - [ ] Direct
store_guidresolution works for orders/customers - [ ] Child entities have an explicit durable relation-based resolution path
- [ ] Missing relation data for otherwise valid child entities creates durable retryable
tenant_unresolvedstate - [ ] Relation-index updates allow unresolved landing records to be promoted later without SQS replay
- [ ] Non-retryable tenant-resolution failures are quarantined with clear diagnostics
- [ ] Mapping/repository contract is updated away from composite source-account keying
- [ ] Tests cover direct and relation-based resolution behavior
Notes
- Do not silently infer tenant from weak heuristics other than explicit relation data.
- This task defines durable routing-state seam even if full ETL ownership of that state is wired in later task implementation.