MK Physical Scale Capability Rebuild Packet¶
- Packet status:
DETAILED SOURCE-RECONCILED REBUILD INPUT / POLICY, DEVICE, TARGET-ROLE AND RUNTIME REVIEW REQUIRED - Capability: physical Scale Check-in, Check-out, reweigh, ticket lineage and owner handoff
- Process owner:
PROC-YMS-SCALE-TICKET-EXECUTION-MK - Operating profile:
mk-order - Current module:
yms.scale - Current primary records:
T_SCALE_TICKET,T_SCALE_TICKET_EVENT - Current links:
T_LOAD.TICKET_NUMBER,T_TRANSLOAD.SCALE_TICKET_ID,T_EQUIPMENT_LOAD.SCALE_TICKET_ID - Related owners: MK Inbound Purchase, MK Outbound Sales, Transload, Equipment, Inventory, Allocation and document outputs
- Current source authority:
MK_PHYSICAL_SCALE_SOURCE_AUTHORITY.md - Current Process contract:
MK_SCALE_TICKET_EXECUTION_WORKFLOW.md - Target stack: React + Next.js + framework-independent TypeScript application/domain/repository contracts + MySQL first
- Device status: no accepted physical-device adapter is established by current repository source
- Worker requirement: none for the synchronous core ticket transaction; a worker is optional only for a separately approved asynchronous device/provider channel
- Later database target: PostgreSQL after accepted React + Next.js + TypeScript + MySQL stabilization
- Important: this packet does not approve the unresolved Gross/Tare flow contract, device policy, role policy, zero-weight policy or cross-surface BMS ownership.
1. Capability Outcome¶
1.1 Business problem¶
Physical vehicle/equipment movement can require two trusted Scale stages. The system must capture the correct stage, preserve the exact accepted values and actor/time provenance, connect the ticket to the correct business record, distinguish Scale completion from downstream business completion and recover safely from timeout, duplicate, correction or reversal.
The capability must preserve:
physical movement
+ operator-selected flow
+ stage direction
+ accepted reading
+ ticket identity
+ order/transload/equipment link
+ correction/reversal lineage
+ exact readback
without collapsing these separate outcomes:
Scale Check-in
!= Scale Check-out
!= Purchase receipt finalize
!= Inventory Lot materialization
!= Outbound order close
!= Packing / Delivery
!= document print
1.2 Required user-visible result¶
An authorized Scale operator can:
- enter the Scale Workspace through the assigned menu;
- identify the exact intended business flow and physical movement;
- distinguish Purchase, Doortrade, Sales and Export direction;
- verify the exact order, equipment, company, commodity, quantity and current ticket state;
- capture or manually enter a first-stage reading;
- submit Check-in once and receive exact ticket/order/link readback;
- reopen the active ticket by stable identity;
- correct the first stage before Check-out only through a reasoned reweigh command;
- capture and submit the second stage once;
- verify both stages and net calculation;
- see independent downstream child dispositions;
- continue to Purchase finalize or Outbound close only through the owning process;
- recover from a timeout without blind replay;
- void/reverse only through an authorized, reasoned and downstream-safe command;
- print the intended active ticket without treating print as completion;
- retain the same Wiki topic when the PHP page later becomes React + Next.js.
1.3 Non-goals¶
This packet does not approve:
- one generic Scale lifecycle status stored on unrelated business records;
- all-flow Gross Check-in;
- all-flow Tare Check-in;
- numeric-client or numeric-role policy;
- device text injected directly into a business table;
- browser time as authoritative physical event time;
- BMS generic mutation as a second YMS ticket owner;
- ticket deletion as ordinary Undo;
- hidden Purchase receipt or Outbound close inside a Scale success message;
- blind retry after timeout;
- a generic table mutation API;
- durable print status;
- PostgreSQL in the first Scale migration wave.
2. Current Truth Table¶
| Statement | Current source-reconciled truth |
|---|---|
| YMS Schedule/ticket/detail/event reads are tenant scoped | Yes |
| YMS write routes require module/menu entry | Yes |
| Integrated Check-in saves order/items/ticket/link in one local transaction | Yes |
| Check-out saves all header/items/ticket/downstream state in one transaction | No |
| Current client request timeout | 30 seconds |
| Client abort cancels server commit | No |
| YMS reweigh requires reason | Yes, before second stage |
| YMS reweigh records immutable event | Yes |
| YMS stage update uses compare-and-swap snapshot | Yes |
| YMS second stage requires first stage | Yes |
| YMS duplicate identical completed stage is idempotent in-process | Yes |
| Durable request token across lost responses | No |
| YMS delete/reversal checks downstream execution | Yes |
| YMS delete/reversal records reason/event | Yes |
| BMS PATCH/delete uses the full YMS stage/reversal contract | No |
| Current physical print is tenant/active scoped | Yes |
| Current physical print is a durable effect | No |
| Current page has an accepted device adapter | No |
Current page starts with 00000 lb |
Yes |
| Purchase/Doortrade UI schema is Gross-in/Tare-out | Yes |
| Sales/Export UI schema is Tare-in/Gross-out | Yes |
| Integrated Check-in writes Tare for Sales/Export | No; it currently writes Gross for every flow |
| Existing static contract test detects Sales/Export direction mismatch | No; it requires the all-flow Gross behavior |
| Existing local smoke covers Purchase Gross-in/Tare-out | Yes, when run locally |
| Existing local smoke covers Sales/Export Tare-in/Gross-out | No source-confirmed coverage found |
3. Actors, Capabilities And Denied Behavior¶
3.1 Actors¶
Scale Operator¶
Responsible for:
- selecting the correct flow and record;
- verifying physical and system identity;
- entering/accepting stage values;
- Check-in and Check-out;
- exact readback;
- stopping on mismatch or unknown result.
Must not:
- bypass menu/record scope with copied IDs;
- change an already completed stage through generic edit;
- repeat Check-in/Check-out after timeout without reread;
- finalize Purchase receipt by direct table edit;
- repair Outbound close through Scale resubmission;
- directly delete or restore ticket/link rows.
Receiving / Inbound Purchase Operator¶
Responsible for:
- Purchase order and item source values;
- Scale-to-receipt finalize;
- receipt/Transload/Lot reconciliation;
- post-receipt correction.
Must not classify Scale stage completion as receipt completion.
Shipping / Outbound Sales Operator¶
Responsible for:
- Outbound order/items/equipment context;
- Outbound close/status after accepted Scale evidence;
- downstream Packing/Delivery continuation.
Must not use ordinary Outbound Save to overwrite Scale-owned stage evidence.
Scale Recovery Manager¶
Responsible for:
- reweigh/reversal authorization where policy requires;
- unknown-result reconciliation;
- event timeline review;
- competing-writer escalation;
- fixture/recovery cleanup in non-Production environments.
Support / Migration Operator¶
Responsible for:
- request/ticket/order/link trace;
- current-versus-target parity;
- one-writer cutover and rollback;
- caller-zero evidence.
Device Integration Owner — future/optional¶
Responsible for:
- device identity and connection;
- reading session and provenance;
- transport/reconnect behavior;
- device health and diagnostics.
Must not mutate ticket/order tables directly.
3.2 Proposed semantic capabilities¶
yms.scale.view
yms.scale.check-in
yms.scale.check-out
yms.scale.reweigh
yms.scale.reverse
yms.scale.events.view
yms.scale.print
yms.scale.reconcile
yms.scale.device.use
These are target semantic names. Current role/menu mapping must be characterized before activation.
3.3 Authorization dimensions¶
Every query/command evaluates:
authenticated actor
+ tenant/profile
+ capability
+ current menu/page compatibility
+ record tenant
+ record state
+ flow/stage eligibility
+ downstream lock
The client never sends an actor or tenant ID to gain access.
4. Flow And Stage Contract¶
4.1 Current intended UI matrix¶
| Flow | Business direction | UI Check-in | UI Check-out | Related owner |
|---|---|---|---|---|
| Purchase | inbound | Gross | Tare | Inbound Purchase |
| Doortrade | inbound local | Gross | Tare | Inbound Purchase |
| Sales | outbound local | Tare | Gross | Outbound Sales |
| Export | outbound ocean | Tare | Gross | Outbound Sales / Booking |
Other is not an approved long-term MK business flow. Current fallback behaves as Tare-in/Gross-out but requires Product disposition.
4.2 Current implementation contradiction¶
Integrated Check-in currently forces Gross for all flows. Therefore the accepted target matrix is not established by current source alone.
Activation blocker:
SCALE-POL-010 must be accepted
and
SCALE-SCN-010 through SCALE-SCN-040 must pass
before a target write cutover
4.3 Target policy representation¶
Do not hardcode the direction in React components or route handlers.
interface ScaleFlowPolicy {
flow: 'PURCHASE' | 'DOORTRADE' | 'SALES' | 'EXPORT';
entryStage: 'GROSS' | 'TARE';
exitStage: 'GROSS' | 'TARE';
requireOrder: boolean;
requireEquipment: boolean;
requireBooking: boolean;
requireContainerSize: boolean;
zeroWeightPolicy: 'FORBIDDEN' | 'EXPLICIT_EXCEPTION';
}
Policy is selected through Operating Profile and typed configuration, never numeric Client ID.
5. State Model¶
5.1 Persisted ticket evidence¶
Persisted evidence is the two stage timestamps/axle snapshots plus lifecycle deletion.
GROSS stage
TARE stage
DELETED_AT
5.2 Derived ticket states¶
NOT_STARTED
ENTRY_RECORDED
COMPLETED
VOIDED
REVERSED
CONFLICT
UNKNOWN
Derivation requires the selected flow policy.
| State | Derivation |
|---|---|
NOT_STARTED |
neither accepted entry nor exit stage exists |
ENTRY_RECORDED |
accepted entry exists and exit does not |
COMPLETED |
accepted entry and exit exist and Gross/Tare validation passes |
VOIDED |
non-completed ticket soft-deleted with TICKET_VOID event |
REVERSED |
completed ticket soft-deleted with TICKET_REVERSAL event |
CONFLICT |
stages, links, flow or events disagree |
UNKNOWN |
request outcome cannot yet be classified |
Do not infer ENTRY_RECORDED merely from “exactly one timestamp” without the flow policy.
5.3 Composite process state¶
Scale ticket state remains separate from:
Order state
Transload/receipt state
Inventory Lot state
Equipment Load state
Outbound close state
Packing/Delivery state
Print state
Target UI displays independent child dispositions rather than one “Complete” status.
6. Identity Model¶
6.1 Required stable identities¶
| Identity | Purpose |
|---|---|
tenantId / tenant UUID |
tenant scope |
scaleTicketId |
current local relational identity |
scaleTicketUuid |
durable ticket identity when exposed safely |
ticketNumber |
operator-facing reference, not sole relational key |
scaleRequestToken |
idempotency across duplicate/response loss |
flow |
accepted business flow |
orderId |
Purchase or Sales owner record |
orderItemIds[] |
exact source item context |
transloadId |
Purchase ticket link/receipt handoff |
equipmentLoadId |
Sales ticket link |
deviceId |
future physical device identity |
deviceSessionId |
future connected weighing session |
deviceReadingId |
future immutable source reading |
ticketEventId / UUID |
reweigh/void/reversal lineage |
requestId |
request tracing; not sufficient alone for business idempotency |
6.2 Ticket number¶
Ticket number is human-facing and must be unique in the accepted tenant scope. Target generation must not rely on an unguarded “latest + 1” read.
Accepted target alternatives:
- tenant-scoped DB sequence table with conditional update;
- UUID identity plus separately reserved display number;
- retry-safe unique insert bound to
scaleRequestToken.
Final choice is a DB/application decision, not a React concern.
6.3 Business link identity¶
Exactly one accepted link path per flow:
Purchase/Doortrade:
Scale Ticket -> Transload -> Inbound Purchase
Sales/Export:
Scale Ticket -> Equipment Load -> Outbound Sales
T_LOAD.TICKET_NUMBER is a compatibility projection. It is not the target canonical relationship.
7. Device And Reading Envelope¶
7.1 Current status¶
No accepted device adapter is source-confirmed. Current operation is manual-entry capable and the “Live Weight” display is not authority.
7.2 Target device-neutral envelope¶
interface ScaleReadingEnvelope {
deviceId: string;
deviceSessionId: string;
readingId: string;
source: 'DEVICE' | 'MANUAL';
capturedAt: string;
receivedAt: string;
inputUom: 'LB';
canonicalUom: 'LB';
value: string;
stability: 'STABLE' | 'UNSTABLE' | 'UNKNOWN';
rawReference?: string;
}
The application records which reading the operator accepted.
interface AcceptedScaleStageInput {
flow: ScaleFlow;
stage: 'GROSS' | 'TARE';
axles: {
steering: string;
drive: string;
rear: string;
fourth: string;
fifth: string;
};
acceptedReadingId?: string;
acceptedAt: string;
acceptedBy: string;
reason?: string;
}
7.3 Device rules¶
- Device disconnect does not erase a captured business ticket.
- Unstable reading is not silently accepted.
- Device time and server receive time remain distinguishable.
- Manual fallback is explicit and auditable.
- One reading may be displayed many times but accepted once per stage/version.
- Device adapter never owns tenant, order, ticket or role policy.
- Raw device payload retention is a separate security/retention decision.
8. Data Field Dictionary¶
8.1 T_SCALE_TICKET¶
| Field | Current meaning | Target rule |
|---|---|---|
ID |
local ticket identity | immutable |
UUID |
row identity | immutable, unique per accepted schema |
CLIENT_ID |
current tenant scope | resolved server-side |
TICKET_NUMBER |
operator reference | tenant-scoped unique reservation; immutable after create unless a separate correction policy exists |
REFERENCE_NUMBER |
business reference snapshot | bounded text; source and mutability policy required |
COMPANY_NAME |
company snapshot | not a company master key |
TRACTOR_NUMBER |
vehicle snapshot | bounded text |
EQUIPMENT_NUMBER |
equipment/container snapshot | must agree with accepted link when required |
DRIVER_NAME |
operator-entered driver snapshot | bounded text |
WEIGHER_NAME |
operator-entered weigher snapshot | actor identity remains separate |
COMMODITY_NAME |
ticket commodity summary | derived/validated from exact item set where linked |
COMMODITY_QUANTITY |
ticket quantity snapshot | UOM/quantity authority policy required |
GROSS_TIME |
accepted Gross stage server time | immutable except reasoned pre-completion correction policy |
GROSS_*_WEIGHT |
accepted Gross axle snapshot | integer LB in current schema; exact target precision required |
TARE_TIME |
accepted Tare stage server time | immutable except reasoned pre-completion correction policy |
TARE_*_WEIGHT |
accepted Tare axle snapshot | integer LB in current schema |
REMARK |
operator/support note | not the only correction lineage |
DRIVER_SIGNATURE |
legacy signature payload | ownership/retention/security review required |
WEIGHER_SIGNATURE |
legacy signature payload | ownership/retention/security review required |
BAD_BALE_* |
legacy quality fields | separate Product owner/disposition required |
DELETED_AT |
soft-delete/void/reversal marker | only through owner command |
CREATED_AT, UPDATED_AT |
row timestamps | not physical stage timestamps |
8.2 Derived totals¶
Gross = sum Gross axles
Tare = sum Tare axles
Net = Gross - Tare
Rules:
- no negative axle value;
- Gross and Tare each follow accepted zero-weight policy;
- completed ticket requires Gross >= Tare unless an explicit exceptional process exists;
- all calculations use exact decimal/integer rules, not JavaScript floating inference;
- canonical UOM is explicit.
8.3 T_SCALE_TICKET_EVENT¶
| Field group | Meaning |
|---|---|
SCALE_TICKET_ID, TICKET_NUMBER |
parent identity snapshot |
EVENT_TYPE |
REWEIGH_CORRECTION, TICKET_VOID, TICKET_REVERSAL |
WEIGHT_PREFIX |
affected stage or NONE |
| input/canonical/display UOM | unit provenance |
| before/after stage time and axles | immutable transition evidence |
REASON_TEXT |
required human reason |
| actor ID/username | action actor |
REQUEST_ID |
request trace |
| lifecycle/UUID | immutable event identity and soft-delete infrastructure |
Target event rules:
- append only;
- no event overwrite;
- stable event UUID;
- reason required for every corrective/destructive action;
- event and ticket update commit in the same local transaction;
- correction event is not a substitute for business idempotency token.
8.4 Link fields¶
| Field | Meaning | Target disposition |
|---|---|---|
T_TRANSLOAD.SCALE_TICKET_ID |
Purchase/Transload link | typed repository relation |
T_EQUIPMENT_LOAD.SCALE_TICKET_ID |
Sales/Equipment link | typed repository relation |
T_LOAD.TICKET_NUMBER |
compatibility display pointer | retire after caller-zero or retain as projection only |
9. Semantic Query Contracts¶
9.1 GetScaleSchedule¶
Input:
{
dateFrom?: string;
dateTo?: string;
keyword?: string;
}
Returns:
- exact order/flow identity;
- accepted flow projection and reason;
- linked ticket ID/number;
- entry/exit stage disposition;
- order/transload/equipment child disposition;
- allowed actions;
- warnings/conflicts.
No mutation.
9.2 GetOpenScaleTickets¶
Returns active tickets whose accepted flow has entry stage and lacks exit stage.
Do not implement as “exactly one timestamp” without flow policy.
9.3 GetScaleTicketDetail¶
Returns:
- ticket identity;
- accepted flow and link;
- both stage snapshots;
- computed totals;
- order/item/equipment summary;
- correction/reversal eligibility;
- exact child dispositions;
- current version/freshness;
- stable errors/warnings.
9.4 GetScaleTicketTimeline¶
Returns ordered immutable events and ticket creation/completion references.
Normal user UI may summarize; support UI can show full bounded evidence.
9.5 GetScaleCommandResultByToken¶
Input:
{ scaleRequestToken: string }
Returns:
NOT_FOUND
IN_PROGRESS
COMMITTED
FAILED_DEFINITE
UNKNOWN_REVIEW
with exact ticket/order/link IDs when known.
9.6 GetDeviceSessionState — future/optional¶
Returns device connection, last stable reading, reading age and diagnostic state. It never implies a business stage was accepted.
10. Semantic Command Contracts¶
10.1 ExecuteScaleCheckIn¶
Purpose: submit the accepted first stage exactly once.
Input:
interface ExecuteScaleCheckInCommand {
scaleRequestToken: string;
flow: ScaleFlow;
orderContext:
| { mode: 'EXISTING'; orderId: string; expectedVersion: string }
| { mode: 'WALK_IN'; orderDraft: WalkInOrderDraft };
itemSnapshot: ScaleOrderItemInput[];
stage: AcceptedScaleStageInput;
ticketMetadata: ScaleTicketMetadataInput;
}
Server behavior:
- authenticate and resolve tenant/profile/capability;
- resolve accepted flow policy;
- verify command stage equals policy entry stage;
- claim request token;
- validate order/items/references;
- save/create order through the owning application contract;
- create ticket and typed link;
- exact ticket/order/link readback;
- commit once;
- return stable result.
Current integrated Check-in provides a useful one-transaction baseline. Target implementation must correct the flow-stage contradiction and add durable idempotency/freshness.
10.2 CorrectScaleEntryStage¶
Preconditions:
- ticket active;
- exit stage absent;
- actor authorized;
- reason present;
- expected ticket version matches;
- new values satisfy flow/UOM/weight policy.
Transaction:
conditional ticket stage update
+ correction event
+ exact readback
Do not update through generic table PATCH.
10.3 PrepareScaleCheckOut¶
This command belongs to the relevant Order owner, not the Scale ticket.
Purpose:
- validate/edit allowed header and item values before Scale Out;
- save all intended owner changes atomically where approved;
- return exact order/item snapshot and version.
Current browser-sequenced header/item writes are not the target contract.
10.4 CompleteScaleCheckOut¶
Input:
interface CompleteScaleCheckOutCommand {
scaleRequestToken: string;
scaleTicketId: string;
expectedTicketVersion: string;
expectedOrderSnapshotVersion?: string;
stage: AcceptedScaleStageInput;
}
Behavior:
- verify entry stage exists and matches flow;
- verify submitted stage equals exit stage;
- verify ticket/link/record scope;
- claim request token;
- conditional stage update;
- exact totals and readback;
- commit;
- return child handoff requirements.
Result does not claim Purchase receipt or Outbound close.
10.5 FinalizePurchaseReceiptFromScale — referenced owner command¶
Owned by Inbound Purchase.
Input references completed Scale ticket and exact Purchase/Transload/item versions. It may update item/transload/lot state in its own accepted transaction.
Scale UI can invoke an explicit handoff, but the result remains separately labeled.
10.6 CloseOutboundFromScale — referenced owner command¶
Owned by Outbound Sales.
It updates accepted Outbound completion fields under Outbound policy and returns its own readback. A failure after Scale Out leaves Scale completed and Outbound close incomplete.
10.7 VoidOrReverseScaleTicket¶
Input:
{
scaleRequestToken: string;
scaleTicketId: string;
expectedVersion: string;
action: 'VOID' | 'REVERSE';
reason: string;
}
Behavior:
- authorize recovery capability;
- classify ticket as incomplete/completed;
- verify downstream blockers across all accepted link owners;
- conditional soft delete;
- event append;
- link/projection cleanup;
- exact residual readback;
- commit once.
Target does not call this command DELETE in operator UI.
10.8 ReconcileScaleUnknownResult¶
Input: request token and any known ticket/order/link identifiers.
Result:
FOUND_COMMITTED
CONFIRMED_ABSENT_RETRY_ALLOWED
CONFLICT_MANUAL_REVIEW
UNKNOWN_MANUAL_REVIEW
It does not repeat the business command automatically.
11. Target HTTP Adapter Shape¶
Routes are illustrative adapters, not domain authority.
GET /api/scale/schedule
GET /api/scale/tickets?state=open
GET /api/scale/tickets/{ticketId}
GET /api/scale/tickets/{ticketId}/events
GET /api/scale/requests/{requestToken}
POST /api/scale/check-ins
POST /api/scale/tickets/{ticketId}/entry-corrections
POST /api/scale/tickets/{ticketId}/check-outs
POST /api/scale/tickets/{ticketId}/reversals
POST /api/scale/requests/{requestToken}/reconcile
Referenced owner adapters:
POST /api/inbound-purchases/{orderId}/finalize-from-scale
POST /api/outbound-sales/{orderId}/close-from-scale
Next.js Route Handlers own authentication/context/validation/error mapping only. They do not own Scale policy or SQL.
12. Stable Result DTOs¶
12.1 Check-in result¶
interface ScaleCheckInResult {
requestToken: string;
ticket: {
id: string;
uuid?: string;
ticketNumber: string;
flow: ScaleFlow;
state: 'ENTRY_RECORDED';
entryStage: 'GROSS' | 'TARE';
entryAt: string;
grossLb: string;
tareLb: string;
netLb: string;
};
order: { id: string; type: 'PURCHASE' | 'SALES'; version: string };
link: { transloadId?: string; equipmentLoadId?: string };
}
12.2 Check-out result¶
interface ScaleCheckOutResult {
requestToken: string;
ticket: {
id: string;
ticketNumber: string;
state: 'COMPLETED';
completedAt: string;
grossLb: string;
tareLb: string;
netLb: string;
};
downstream: {
purchaseFinalize: 'NOT_APPLICABLE' | 'REQUIRED' | 'COMPLETED' | 'FAILED' | 'UNKNOWN';
outboundClose: 'NOT_APPLICABLE' | 'REQUIRED' | 'COMPLETED' | 'FAILED' | 'UNKNOWN';
};
}
12.3 Reversal result¶
interface ScaleReversalResult {
requestToken: string;
ticketId: string;
action: 'VOIDED' | 'REVERSED';
eventId: string;
detachedLinks: Array<{ type: string; id: string }>;
residualConflicts: Array<{ code: string; owner: string }>;
}
13. Stable Error Catalog¶
| Code | Meaning | Safe user action |
|---|---|---|
SCALE_UNAUTHENTICATED |
no authenticated actor | sign in through normal entry |
SCALE_FORBIDDEN |
capability denied | stop; do not use copied URL/ID |
SCALE_PROFILE_NOT_APPLICABLE |
flow/profile unavailable | return to assigned profile |
SCALE_FLOW_INVALID |
unsupported/unresolved flow | confirm Purchase/Doortrade/Sales/Export |
SCALE_STAGE_DIRECTION_CONFLICT |
submitted stage contradicts flow | stop; do not write opposite stage |
SCALE_ORDER_NOT_FOUND |
owner order absent | reopen/search exact order |
SCALE_ORDER_STALE |
owner snapshot changed | refresh order/items |
SCALE_ITEM_INVALID |
commodity/quantity/weight invalid | correct item lines |
SCALE_TICKET_NOT_FOUND |
ticket absent/inactive | reread schedule/ticket |
SCALE_TICKET_STALE |
ticket changed after open | refresh detail/timeline |
SCALE_ENTRY_REQUIRED |
Check-out lacks valid entry | reconcile flow and first stage |
SCALE_ENTRY_ALREADY_EXISTS |
duplicate/different entry | reread; use correction command if allowed |
SCALE_EXIT_ALREADY_EXISTS |
ticket already complete | reread; do not reweigh through Check-out |
SCALE_REWEIGH_REASON_REQUIRED |
correction reason missing | provide bounded reason |
SCALE_REWEIGH_AFTER_EXIT_FORBIDDEN |
completed ticket immutable | use approved reversal/recovery |
SCALE_WEIGHT_NEGATIVE |
negative axle/total | correct input |
SCALE_WEIGHT_ZERO_FORBIDDEN |
zero rejected by policy | capture valid reading or approved exception |
SCALE_TARE_EXCEEDS_GROSS |
invalid completed totals | stop and verify physical values |
SCALE_UOM_MISMATCH |
unsupported unit/context | resolve canonical unit |
SCALE_REQUEST_DUPLICATE |
same token already handled | display existing result |
SCALE_REQUEST_PAYLOAD_CONFLICT |
same token/different payload | stop and reconcile |
SCALE_RESULT_UNKNOWN |
timeout/connection loss | read request/ticket/order/link before retry |
SCALE_TICKET_NUMBER_CONFLICT |
number reservation collision | server retries or returns stable conflict |
SCALE_DOWNSTREAM_LOCKED |
reversal blocked by later work | escalate to owning process |
SCALE_LINK_CONFLICT |
ticket/order/transload/equipment disagree | stop; support reconciliation |
SCALE_BMS_OWNER_CONFLICT |
competing BMS mutation detected | stop; reconcile current writer |
SCALE_DEVICE_UNAVAILABLE |
approved device path unavailable | explicit manual fallback or stop |
SCALE_DEVICE_READING_UNSTABLE |
reading not stable | wait/reacquire; do not accept silently |
SCALE_SCHEMA_NOT_READY |
required event/idempotency schema absent | no write activation |
SCALE_DATA_CONFLICT |
persisted evidence disagrees | support/manual review |
SCALE_UNEXPECTED_ERROR |
unclassified error | preserve correlation/request IDs |
Raw SQL, credentials, stack traces and unrestricted device payloads are not user errors.
14. Transaction, Concurrency And Idempotency¶
14.1 Check-in¶
Target transaction:
request-token claim
+ order/create-or-save through owner contract
+ ticket insert/update
+ typed business link
+ exact readback
= one local transaction
14.2 Entry correction¶
expected ticket version
+ exit-stage-absent predicate
+ conditional stage update
+ correction event
+ readback
= one local transaction
14.3 Check-out¶
Preferred target structure:
Owner Prepare command
-> exact owner snapshot
-> Scale Check-out transaction
-> explicit owner finalize/close command
The UI may present this as one guided flow but must display independent child outcomes.
14.4 Reversal¶
expected ticket version
+ downstream blocker checks
+ conditional ticket soft delete
+ event append
+ link/projection cleanup
+ exact residual readback
= one local transaction
14.5 Locks and conditional writes¶
Current DB rules forbid FOR UPDATE. Use:
- tenant-scoped conditional
UPDATEpredicates; - version/freshness columns or full snapshot CAS;
- unique request token;
- unique ticket identity/number constraints;
- transaction boundaries;
- bounded advisory lock only if accepted and not nested across helper owners.
14.6 Idempotency¶
Key:
tenant + command kind + scaleRequestToken
Same token/same payload returns the committed result. Same token/different payload returns conflict.
Ticket-stage local same-value repeat is useful but is not enough when a lost response could also include order/link/finalize effects.
15. Exception And Recovery Matrix¶
| ID | Situation | Required reread | Safe recovery | Must not repeat |
|---|---|---|---|---|
SCALE-EXC-010 |
Check-in response lost | request token, ticket by order/link, order/items, link | return existing result or retry only if confirmed absent | complete Check-in payload blindly |
SCALE-EXC-020 |
Check-in local transaction rejected | order/items/ticket/link | correct input and submit new/approved request | assume partial commit without evidence |
SCALE-EXC-030 |
Sales/Export Gross/Tare direction mismatch | flow, ticket stages, board, detail | stop; characterize and fix flow contract | Check-out using guessed opposite stage |
SCALE-EXC-040 |
Reweigh response lost | ticket stage, event timeline, request token | return existing correction or retry confirmed absent | second correction with new reason automatically |
SCALE-EXC-050 |
Header saved, later Check-out item save failed | header and every item | correct/resume owner Save only | Scale Out |
SCALE-EXC-060 |
Owner Save complete, Scale Out absent | order/items, ticket stages | submit Scale Out if confirmed absent and still intended | owner Save batch |
SCALE-EXC-070 |
Scale Out committed, Outbound close failed | ticket detail, Outbound order | Outbound owner resumes close | Scale Out |
SCALE-EXC-080 |
Scale Out committed, Purchase finalize failed | ticket detail, Purchase/Transload/Lot | Inbound owner resumes finalize | Check-out |
SCALE-EXC-090 |
30-second timeout | request token, ticket/detail, links, owner rows | classify committed/absent/conflict | timed-out command before reread |
SCALE-EXC-100 |
Ticket-number collision | request result and existing ticket by token | server reservation retry or manual review | client-generated alternate number |
SCALE-EXC-110 |
BMS PATCH changed YMS ticket | ticket, event timeline, BMS audit, links | freeze writes; reconcile owner | YMS correction until classified |
SCALE-EXC-120 |
BMS delete detached only part of links | ticket lifecycle, Transload, Equipment Load, Order | controlled reconciliation | generic recreate/delete |
SCALE-EXC-130 |
Device disconnect before acceptance | device session/readings | reconnect or explicit manual input | assume displayed stale value |
SCALE-EXC-140 |
Device disconnect after accepted command | request/ticket readback | use committed business evidence | repeat device/business submission |
SCALE-EXC-150 |
Completed ticket omitted from board | known ID, exact detail/events | show completed readback | infer deletion/failure from absence |
SCALE-EXC-160 |
Reversal blocked by downstream work | all blocker records | escalate to owner-specific correction plan | direct soft delete/link clear |
SCALE-EXC-170 |
Demo card mistaken for operational record | ticket/order IDs and demo flag | close demo UI; no business action | submit Production-like recovery |
SCALE-EXC-180 |
Print wrong/missing | ticket detail and print URL | reprint same verified ticket | mutate ticket/order to fix print |
16. UI / UX Contract¶
16.1 React Scale Workspace areas¶
Schedule / Search
Active Tickets
Check-in Workspace
Check-out Workspace
Completed Ticket Readback
Timeline / Recovery
Device Status (only when approved)
16.2 Required visible states¶
Loading
Empty — no operational rows
Denied
Profile unavailable
Device unavailable
Device unstable
Record stale
Flow/stage conflict
Check-in submitting
Check-in result unknown
Entry recorded
Reweigh reason required
Check-out preparation partial
Check-out submitting
Scale completed / downstream pending
Scale completed / Outbound close failed
Scale completed / Purchase finalize failed
Reversal blocked
Void/Reversal completed
Completed detail
16.3 Demo behavior¶
Demo content must be an explicit test/demo mode, not silently injected into an empty operational board.
Operational empty state
!= interactive demo ticket
16.4 Readback panel¶
After each write, show:
- ticket ID/number;
- flow;
- stage and time;
- Gross/Tare/Net;
- order ID/number;
- Transload or Equipment Load link;
- event ID for correction/reversal;
- downstream disposition;
- request/correlation reference;
- next safe action.
16.5 Accessibility and mobile¶
- stage/flow not color-only;
- input labels and validation are field-local;
- keyboard submission does not double-submit;
- readback is screen-reader announced;
- unknown result is not displayed as generic failure;
- no required hover-only controls;
- completed/reversal history is readable on narrow screens.
17. Current Caller And Consumer Map¶
17.1 Current writers¶
YMS Scale Portal
-> /api/yms/scale/check-in/execute
-> /api/yms/scale/check-in
-> /api/yms/scale/check-out
-> /api/yms/scale/purchase-inbound/finalize
-> /api/yms/scale/tickets/{id} DELETE
BMS Scale Ticket
-> generic create
-> PATCH
-> DELETE
-> Closing
-> Outbound Weight Apply
17.2 Current readers/consumers¶
- YMS Schedule and active board;
- YMS exact detail and event timeline;
- Inbound Purchase and Transload link;
- Outbound Equipment Load and order ticket projection;
- Inventory receipt/finalize;
- BMS billing/transaction surfaces;
- physical-ticket print;
- Sales Weight Ticket output;
- reports/history and operational support.
17.3 Caller-zero requirement¶
Before PHP retirement:
- all YMS read/write callers route through accepted application contracts;
- BMS generic create/PATCH/delete no longer mutates YMS-owned MK tickets or has an explicit separate scope proven by caller/record rules;
- direct physical print uses target read adapter or accepted stable compatibility route;
- no direct
T_SCALE_TICKETbusiness mutation remains outside owner repositories; - no current UI relies on demo injection or hidden string actions;
- Process/Runbook/Wiki point to target routes.
18. Target Component Map¶
React Scale Workspace
├─ ScheduleView
├─ ActiveTicketBoard
├─ CheckInForm
├─ CheckOutForm
├─ CompletedTicketReadback
├─ TicketTimeline
└─ DeviceStatusPanel (optional)
↓
Next.js Server Components / Route Handlers
↓
ScaleQueryApplication
ScaleCheckInApplication
ScaleCheckOutApplication
ScaleCorrectionApplication
ScaleReversalApplication
↓
ScaleFlowPolicy
ScaleWeightPolicy
ScaleRecoveryPolicy
↓
ScaleTicketRepository
ScaleTicketEventRepository
ScaleRequestRepository
OrderLinkAdapters
↓
MySQL
Optional device path:
Device Adapter
-> Device Session/Reading Store or bounded in-memory channel
-> accepted reading DTO
-> Scale Application
React owns presentation and interaction. It does not own stage direction, weight policy, idempotency or SQL.
19. Migration And Cutover¶
19.1 Waves¶
SCALE-W0 Source/schema/role/device/caller characterization
SCALE-W1 Flow-stage policy acceptance and regression repair
SCALE-W2 TypeScript read models and completed timeline
SCALE-W3 React + Next.js read-only Workspace
SCALE-W4 Request identity and integrated Check-in one-writer
SCALE-W5 Checkout preparation and Scale Out one-writer
SCALE-W6 Explicit Purchase finalize / Outbound close dispositions
SCALE-W7 Reweigh and reversal one-writer
SCALE-W8 Device adapter, only if approved
SCALE-W9 BMS competing-writer retirement
SCALE-W10 Target-role stabilization, Wiki and observation
SCALE-W11 PHP caller-zero
SCALE-W12 PostgreSQL later
19.2 One-writer rule¶
For one ticket/request/cohort:
one authoritative Scale writer
No PHP/TypeScript dual write. No YMS/BMS concurrent owner ambiguity.
19.3 Read shadow¶
Before write cutover compare:
- Schedule rows;
- flow classification;
- open ticket classification;
- completed detail;
- Gross/Tare/Net;
- order/transload/equipment links;
- event timeline;
- allowed actions and blockers.
19.4 Rollback¶
Rollback may:
- route new writes back to the prior accepted writer;
- stop new target writes;
- preserve committed tickets/events/links;
- reconcile in-flight request tokens;
- keep target read-only diagnostics.
Rollback must not:
- delete or recreate committed tickets;
- replay unknown stages;
- erase correction/reversal events;
- manually swap Gross/Tare values;
- restore BMS generic writer without reconciling ownership;
- dual-write.
20. PostgreSQL Preservation¶
Later PostgreSQL design preserves:
- tenant-first identity and uniqueness;
- ticket UUID and display number distinction;
- exact numeric/weight precision;
- explicit canonical UOM;
- stage snapshots and physical event times;
- immutable correction/reversal events;
- request-token idempotency;
- conditional/versioned writes;
- typed Purchase/Transload and Sales/Equipment links;
- soft delete and retention;
- no generic table mutation authority.
Do not infer PostgreSQL types from current PHP casts alone.
21. Policy Decision Register¶
| ID | Decision required | Current source | Recommended direction | Blocks |
|---|---|---|---|---|
SCALE-POL-010 |
Gross/Tare direction per flow | UI and Check-in endpoint conflict | accept explicit profile policy and fix all callers/tests | every write wave |
SCALE-POL-020 |
Other/Walk-In flow | fallback only | remove from MK normal path or define explicit policy | UI/API/Wiki |
SCALE-POL-030 |
zero-weight policy | currently false | forbid by default; explicit exceptional command only if business requires | validation |
SCALE-POL-040 |
manual versus device reading | manual current | preserve manual; add device only with provenance/session | device wave |
SCALE-POL-050 |
physical event time | DB NOW current | server accepted time + optional device captured time | data model |
SCALE-POL-060 |
Check-out owner pre-save | sequential current | atomic owner preparation command | checkout migration |
SCALE-POL-070 |
Outbound close after Scale | separate current | explicit child result/recovery | UI/Runbook |
SCALE-POL-080 |
Purchase finalize after Scale | separate current | explicit owner handoff/result | UI/Runbook |
SCALE-POL-090 |
reweigh authority | same menu currently | separate semantic capability and reason | access |
SCALE-POL-100 |
void/reversal authority | YMS guarded, BMS unguarded | YMS owner command only; BMS disposition required | recovery |
SCALE-POL-110 |
BMS generic writer | competing owner | retire for MK YMS tickets or strictly separate record scope | caller-zero |
SCALE-POL-120 |
ticket number reservation | latest+1 | request-bound atomic reservation | concurrency |
SCALE-POL-130 |
completed ticket UX | leaves board | durable completed detail/timeline | UI/Wiki |
SCALE-POL-140 |
demo rows | auto-injected | explicit demo mode only | operator safety |
SCALE-POL-150 |
signatures/bad-bale fields | legacy shared table | separate owner/retention decision | schema/UI |
SCALE-POL-160 |
per-action role matrix | module/menu current | semantic capabilities plus current compatibility mapping | activation |
No recommendation is Product approval.
22. Stable Verification Scenarios¶
22.1 Flow direction¶
SCALE-SCN-010 Purchase Gross Check-in -> Tare Check-out
SCALE-SCN-020 Doortrade Gross Check-in -> Tare Check-out
SCALE-SCN-030 Sales Tare Check-in -> Gross Check-out
SCALE-SCN-040 Export Tare Check-in -> Gross Check-out
SCALE-SCN-050 Opposite-stage Check-in rejected
SCALE-SCN-060 Opposite-stage Check-out rejected
22.2 Check-in¶
SCALE-SCN-110 Existing order integrated Check-in
SCALE-SCN-120 Walk-in order + Check-in atomic success
SCALE-SCN-130 Middle item validation failure rolls back all
SCALE-SCN-140 Ticket insert failure rolls back order/items
SCALE-SCN-150 Duplicate request token returns same result
SCALE-SCN-160 Response lost after commit
SCALE-SCN-170 Concurrent ticket-number reservation
SCALE-SCN-180 Foreign tenant / denied role / direct URL
22.3 Reweigh¶
SCALE-SCN-210 Same entry repeat returns existing result
SCALE-SCN-220 Changed entry requires reason
SCALE-SCN-230 Correction records event and before/after snapshot
SCALE-SCN-240 Concurrent stale correction rejected
SCALE-SCN-250 Reweigh after exit rejected
SCALE-SCN-260 Correction response loss reconciled
22.4 Check-out and downstream¶
SCALE-SCN-310 Normal completed ticket
SCALE-SCN-320 Missing entry rejected
SCALE-SCN-330 Negative/zero/Tare>Gross rejected
SCALE-SCN-340 Sequential owner Save middle failure; no Scale Out
SCALE-SCN-350 Scale Out success / Outbound close failure
SCALE-SCN-360 Scale Out success / Purchase finalize failure
SCALE-SCN-370 Check-out response loss
SCALE-SCN-380 Completed ticket exact detail/timeline
22.5 Reversal and competing writers¶
SCALE-SCN-410 Void uncompleted ticket
SCALE-SCN-420 Reverse completed ticket without downstream work
SCALE-SCN-430 Reversal blocked by Transload/Inventory/Delivery
SCALE-SCN-440 Reversal response loss
SCALE-SCN-450 BMS PATCH conflict detected
SCALE-SCN-460 BMS delete residual-link detection
22.6 Device and print¶
SCALE-SCN-510 Manual entry normal
SCALE-SCN-520 Device stable reading accepted
SCALE-SCN-530 Device unstable reading blocked
SCALE-SCN-540 Device disconnect before acceptance
SCALE-SCN-550 Device disconnect after commit
SCALE-SCN-560 Physical ticket tenant/active scope
SCALE-SCN-570 Print failure does not mutate ticket
SCALE-SCN-580 Empty operational board has no interactive demo rows
Device scenarios remain NOT APPLICABLE / NOT RUN until a device contract is approved.
22.7 Migration¶
SCALE-MIG-SCN-010 Schedule read parity
SCALE-MIG-SCN-020 Flow classification parity
SCALE-MIG-SCN-030 Ticket/detail/event parity
SCALE-MIG-SCN-040 Integrated Check-in one-writer
SCALE-MIG-SCN-050 Check-out one-writer
SCALE-MIG-SCN-060 Downstream child result parity
SCALE-MIG-SCN-070 Reweigh/reversal parity
SCALE-MIG-SCN-080 Unknown-result rollback/reconcile
SCALE-MIG-SCN-090 BMS competing-writer caller-zero
SCALE-MIG-SCN-100 PHP caller-zero
SCALE-MIG-SCN-110 PostgreSQL parity
23. Evidence Template¶
For each scenario record:
scenario ID
source/release SHA
environment and DB identity
tenant/profile
actor/role/capability
normal menu entry
flow and expected stage direction
order/item/transload/equipment/ticket IDs
request token and request/correlation ID
device/manual source
before ticket/order/link/event state
submitted stage values and UOM
API status/result
exact ticket/detail/event readback
exact owner/link/downstream readback
UI visible result
console/network evidence
cleanup and zero residue
result: PASS / FAIL / BLOCKED / NOT RUN
Do not use Production for destructive, cross-tenant or device-fault injection.
24. Definition Of Ready¶
A Scale implementation wave is not ready until:
SCALE-POL-010flow direction is accepted;- current Sales/Export contradiction is characterized and resolved in plan;
- target roles/capabilities/record scope are accepted;
- exact schema and indexes are verified;
- request identity/version strategy is accepted;
- ticket number reservation is defined;
- BMS competing-writer disposition is accepted;
- Check-out owner-preparation boundary is defined;
- Purchase finalize and Outbound close child contracts are accepted;
- reversal/downstream-lock policy is accepted;
- device work is explicitly in or out;
- rollback and evidence fixtures exist;
- CTC regression scope is defined.
25. Definition Of Complete¶
The capability is not complete until:
- all four accepted flows pass normal and negative scenarios;
- exact Check-in/Check-out readback is visible;
- timeout/duplicate does not duplicate business state;
- reweigh/reversal lineage is immutable and visible;
- no competing BMS writer remains for the same MK ticket scope;
- Purchase/Outbound child failures are recoverable without Scale replay;
- target roles pass menu/page/API/record tests;
- current Wiki is updated and field-reviewed;
- one writer and rollback are proven;
- PHP caller-zero is proven;
- Production observation is separately authorized and completed;
- PostgreSQL remains a later separately accepted wave.
---¶
Source:
docs/reconstruction/MK_PHYSICAL_SCALE_CAPABILITY_REBUILD_PACKET.md— ctc repository · This page is an English translation of the source document. Identifiers, file paths and code symbols are unchanged.