Kanban Cards Module
Purpose
Section titled “Purpose”Kanban Cards manage physical and digital kanban cards used in lean manufacturing and inventory management. Cards signal the need to replenish inventory, initiate production, or trigger material movement between process steps.
Integrations
Section titled “Integrations”- Items Module: References the item a card represents
- Serial Number Service: Generates unique identifiers for physical cards
- Facilities Module: Tracks card location within warehouses and production areas
Main Entities
Section titled “Main Entities”The card’s item is an ItemReference (see Entity References) that, besides the item eId / rId / cached name, carries denormalized retired and provenance fields used to resolve and mark cards whose item has been deleted — see Deleted-Item Resolution.
OpenAPI specification: https://stage.alpha002.io.arda.cards/v1/kanban/docs/redoc/index.html#tag/v1
Query Locator Fields
Section titled “Query Locator Fields”Universes configured with EntityServiceConfiguration accept both JSON field paths (camelCase) and database column names (snake_case) as locators. The table below shows both forms. See Query DSL: EntityServiceConfiguration.
| JSON Field Path | Column Name | Type | Description |
|---|---|---|---|
eId | eid | uuid | Entity UUID |
serialNumber | kanban_card_sn | String | Card serial number |
itemReference.entityId | item_reference_entity_id | uuid | Associated item entity ID |
itemReference.itemName | item_reference_item_name | String | Associated item name |
itemReference.retired | item_reference_retired | boolean | Whether the referenced item is logically deleted |
cardQuantity.amount | card_quantity_amount | Decimal | Inventory quantity represented |
cardQuantity.unit | card_quantity_unit | String | Inventory unit of measure |
requestLocation.facility | physical_locator_facility | String | Current facility |
requestLocation.department | physical_locator_department | String | Current department |
requestLocation.location | physical_locator_location | String | Current location |
status | status | String | Current card status |
printStatus | print_status | String | Current print status |
| — | id | uuid | Record ID (bitemporal) |
| — | effective_as_of | TIMESTAMP | Bitemporal effective timestamp |
| — | recorded_as_of | TIMESTAMP | Bitemporal recorded timestamp |
| — | retired | BOOLEAN | Whether logically deleted |
| — | tenant_id | uuid | Owning tenant |
| — | last_event_* | various | Fields describing the most recent lifecycle event |
| — | last_print_event_* | various | Fields describing the most recent print event |
Service Layer
Section titled “Service Layer”KanbanCardService implements DataAuthorityService<KanbanCard, KanbanCardMetadata>.
Core Operations
Section titled “Core Operations”create,read,update,deletelist,count,historysummaryByStatus— aggregates cards by status with quantity totalslistWithDetails— returns cards with full item details
Lifecycle Management
Section titled “Lifecycle Management”Two specialized lifecycle interfaces:
KanbanCardLifecycle — operational state transitions:
REQUESTED -> ACCEPTED -> IN_PROCESS -> COMPLETED -> FULFILLED -> RECEIVED -> IN_USE -> DEPLETED -> WITHDRAWNMethods: request, accept, startProcessing, completeProcessing, fulfill, receive, use, deplete, withdraw
KanbanCardPrintLifecycle — print state management:
NOT_PRINTED -> PRINTED (print)PRINTED -> PRINTED (reprint)PRINTED -> NOT_PRINTED (unmark)PRINTED -> LOST (reportLost)PRINTED -> DEPRECATED (deprecate)PRINTED -> RETIRED (retire)DEPRECATED -> LOST (reportLost)DEPRECATED -> RETIRED (retire)LOST -> PRINTED (reprint)LOST -> RETIRED (retire)Methods: printCards, cardPrinted, reprint, reportLost, retire, unmarkPrinted
The unmarkPrinted method transitions a card from PRINTED to NOT_PRINTED. It is a no-op for cards not in PRINTED status (idempotent for NOT_PRINTED). Exposed via POST /kanban-card/{eId}/event/unmark.
Business Rules
Section titled “Business Rules”- Serial number uniqueness within tenant scope
- Valid lifecycle state transitions
- Item reference validation
- Location tracking on lifecycle transitions
- Print status management
Kanban cards support a free-text notes field (up to 8192 characters, nullable). Notes are initialized from the item’s defaults when a card is created and can be updated independently via a dedicated endpoint. See Kanban Card Notes for the feature specification.
Deleted-Item Resolution
Section titled “Deleted-Item Resolution”Items are soft-deleted — deletion writes a retired = true bitemporal row that keeps the full item payload — and a kanban card keeps its item reference after the item is gone. Resolving such a card no longer errors: as of PDEV-808 the card’s ItemReference carries the referenced item’s deletion state, and reads resolve the retained record so the card renders with the item’s last-known name and a deleted marker.
Denormalized reference fields
Section titled “Denormalized reference fields”The ItemReference gains two denormalized fields, synchronized from the item:
retired: Boolean— whether the referenced item is logically deleted (defaultfalse)provenance: { updatedBy, updatedAt } | null— who/when of the last sync (the deletion stamp whenretiredis true)
These are a routing hint and a convenience for consumers that do not re-resolve; the resolved item record is the source of truth.
Propagation (observer; async, best-effort)
Section titled “Propagation (observer; async, best-effort)”ItemListener (in the kanban service) observes Item Update / Delete events, published post-commit. On each event it copies rId, name, retired (= true on delete), and provenance onto every card referencing the item (cardsForItem). Dispatch is async and best-effort — a failed listener is logged at WARN, not retried — so the cache is eventually consistent.
Two-path resolution and coalesce
Section titled “Two-path resolution and coalesce”detailsFor and listWithDetails resolve each card’s item by the cached retired flag:
retired == false(believed live, and the legacy default) →getAsOf(eId, asOf, includeRetired = true)— include-retired is the safety net for the observer-lag window and for legacy cards.retired == true→getRecord(rId)— a direct primary-key fetch of the frozen tombstone,asOf-independent.
The response’s retired / provenance are coalesced from the resolved record, with the cache as a fallback. This makes the pre-existing backlog correct with no data backfill: a legacy card (retired = false) takes the believed-live path, include-retired resolves the tombstone, and the record marks it correctly.
On a single-card detail read where the cache is stale, the corrected reference is healed back to the card — best-effort and conflict-tolerant (swallows AppError.ConflictingState), effective-dated no earlier than the item change it reflects. List reads coalesce only (no inline heal writes, to avoid turning a page read into N writes). listWithDetails partitions its chunk (believed-live entries by eId, retired entries by rId) and skips a genuinely-absent (corrupt) item rather than failing the whole page.
API and printing
Section titled “API and printing”No endpoint or authentication changes. The card’s item reference gains retired and provenance additively; KanbanCardDetails gains no top-level fields (consumers read card.item.retired / card.item.provenance). The 500 (IncompatibleState) is removed for the deleted-item case on the detail / list / print routes (retained only for genuine internal inconsistency). The card print payload (KanbanCardPrintInfo) gains item_retired, item_last_updated_by, and item_last_updated_at, so a printed card marks a deleted item; the item Label/Breadcrumb print is handled in the Item Module.
Persistence Layer
Section titled “Persistence Layer”KanbanCardUniverse extends AbstractScopedUniverse<KanbanCard, KanbanCardMetadata, KANBAN_CARD_TABLE, KanbanCardRecord>().
The item reference is flattened into the kanban_card table via the shared ItemReferenceComponent. Alongside the existing item_reference_entity_id / item_reference_item_name / item_reference_record_id, it carries the denormalized deletion fields: item_reference_retired (boolean, NOT NULL DEFAULT false) and the nested provenance component item_reference_provenance_updated_by (varchar, nullable) / item_reference_provenance_updated_at (bigint, nullable, both-or-neither). Because the component is shared, the same columns also exist on order_line, where they are currently unused (see Item Module).
Event sourcing tables:
kanban_card_event— lifecycle state changeskanban_card_print_event— print lifecycle changes
Both tables record event_type, from_status, to_status, location, timestamps, and author.
QR Code Lookup URL
Section titled “QR Code Lookup URL”Physical cards include a QR code linking to:
https://{base-url}/kanban/cards/{kanban-card-id}?view=card&src=qrBase URLs by Environment
Section titled “Base URLs by Environment”| Environment | Base URL |
|---|---|
| Production | live.app.arda.cards |
| Staging | stage.app.arda.cards |
| Development | dev.app.arda.cards |
QR Code Physical Specification
Section titled “QR Code Physical Specification”| Property | Value |
|---|---|
| Encoding | URL string encoded as QR code |
| Error correction | Level M (15% recovery) — suitable for shop floor conditions where cards may be scratched or dirty |
| Minimum print size | 20 mm x 20 mm at 300 DPI for reliable scanning with mobile phone cameras |
| Label placement | Bottom-right quadrant of the card, with at least 4 mm quiet zone on all sides |
| Human-readable fallback | Card serial number printed below the QR code in OCR-B font for manual lookup when scanning fails |
Resolving a Card ID from the API
Section titled “Resolving a Card ID from the API”The card eId is available via the query endpoint:
POST /v1/kanban/kanban-card/queryAuthentication: Bearer token. Pass the tenant identifier in the X-Tenant-Id request header.
Pagination: Default page size is 20; maximum is 500. Use the pageSize query parameter to increase the limit within that bound.
Extracting the ID: The entity identifier is at results[*].payload.eId in the response body.
API documentation:
- OpenAPI:
https://prod.alpha001.io.arda.cards/v1/kanban/docs/openApi.json - Swagger UI:
https://prod.alpha001.io.arda.cards/v1/kanban/docs/openapi/index.html - Redoc:
https://prod.alpha001.io.arda.cards/v1/kanban/docs/redoc/index.html
Copyright: © Arda Systems 2025-2026, All rights reserved