Spensara Spensara Knowledge Base & Documentation Repository

Repository Docs & Knowledge Base

Consolidated Spensara documentation repository (722 Markdown & architecture documents in ../repository)
Built Word Documents (.docx): Spensara Overview (.docx) Capability Assessment (.docx) Brink POS Ingestion Analysis (.docx) The Borg Ingestion Architecture (.docx)

Implementation Specs (157)

Detailed engineering and feature implementation specifications.
implementation-specs/specs/KdsCdcDebeziumIntegration/TASK2.md 6,099 bytes · Updated Oct 23, 2026 10:44 AM EDT
Raw File

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:

  • KdsCdcTenantResolver currently requires message.SourceAccountId and message.StoreGuid.
  • IKdsCdcSourceTenantMappingRepository and EfKdsCdcSourceTenantMappingRepository are keyed by (sourceType, sourceAccountId, storeGuid).
  • sample order and customer Debezium payloads include store_guid directly.
  • sample item Debezium payloads do not include store_guid; they include order_guid and item_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.cs
  • backend/Kds.Ai.Data/Repositories/IKdsCdcSourceTenantMappingRepository.cs
  • backend/Kds.Ai.Data/Repositories/EfKdsCdcSourceTenantMappingRepository.cs
  • backend/Kds.Ai.Data/Entities/KdsCdcSourceTenantMapping.cs
  • backend/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_id is 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_guid where 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_unresolved state 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_guid and, 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_unresolved landing 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:

  1. keep a slim mapping table keyed by (sourceType, storeGuid) for companyId + tenantId, or
  2. 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_guid relation,
  • item-bump payload resolves via relation data,
  • child payload without available relation is marked tenant_unresolved and 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_guid mappings 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_guid resolution 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_unresolved state
  • [ ] 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.