# Register Shifts Foundation v31

## Purpose

v31 introduces register-based cashier shifts on top of the cash account ledger.

A shift is device-independent and belongs to:
- tenant
- register
- linked cashbox account
- business date

## Lifecycle

Open
→ Operational cash movements
→ Blind close
→ Closed

Only one open shift is allowed per register and per linked cashbox account.

## Opening float

Opening a shift can post an opening float.

The opening float:
- increases the linked cashbox balance
- creates immutable shift entry
- becomes initial expected shift cash

## Shift cash movements

Manual cash in/out are supported during an open shift.

Each operation:
- posts immutable cash account movement
- posts immutable shift entry
- updates expected shift cash
- is idempotent

## Blind close

While the shift is open, the public shift resource does not expose expected cash.

Cashier submits counted cash without seeing system expected cash.

On close:
- expected cash is captured
- counted cash is captured
- variance = counted - expected
- variance adjustment is posted to the cash account
- shift becomes closed
- expected/count/variance are revealed

## Immutability

`cash.shift_entries` are append-only at model and PostgreSQL trigger level.

## APIs

- POST /api/v1/cash/shifts
- GET  /api/v1/cash/shifts/{shiftId}
- POST /api/v1/cash/shifts/{shiftId}/movements
- POST /api/v1/cash/shifts/{shiftId}/close

## Permissions

- cash.shift.view
- cash.shift.open
- cash.shift.move
- cash.shift.close

## Next

v32:
- connect cash sales/refunds to open register shift
- expected shift cash from actual checkout payments
- cash drop / safe transfer
- shift variance approval threshold
