# Tidemark Logistics — Product Requirements (v1.1)

Tidemark Logistics is a freight shipment console. Dispatchers sign in, browse and search shipments with status tabs and exception flags, open a detail page (route map, hub-local timeline, parcel weights, customs documents), cancel shipments, book new ones through a four-step wizard with service quotes and optional insurance, and print a shipping label. The console clock is fixed at 19 Oct 2026.

**Problem.** Dispatchers need to trust the tracking data they act on: which shipments are late or held, what a parcel is charged for, and what a booking will cost.

## Users
- **Dispatcher** — Find a shipment fast, see whether it is late or held and resolve customs holds.
- **Shipper** — Book a shipment and know the price, ETA and insurance before confirming.
- **Integration client** — Sign in with a service key instead of a person.

## Goals
- Weights, dimensional weight and prices are computed with one documented formula.
- Exceptions and Late flags appear only when they are actually open.
- The timeline always reads newest first, in each hub's local time.
- A booking cannot be made with invalid parties, parcels or insurance values.

## Sign-in (AUT)

Email and password, or an API key.

- **FR-AUT-01** (Must) Valid credentials open the Shipments page and show the signed-in identity in the sidebar.
  - Heading "Sign in to Tidemark" with Email, Password and Sign in
  - Sidebar shows "Mara Ellison" and "Dispatcher"
- **FR-AUT-02** (Should) Wrong credentials and blank submissions are refused without leaving the sign-in page.
  - "Email or password is incorrect"
  - "Enter your work email and password"
- **FR-AUT-03** (Could) "Use an API key instead" signs in with a valid key and rejects an unknown one.
  - "That API key was not recognised"
  - Valid key: sidebar shows "API client" and "Service key"
- **FR-AUT-04** (Could) Sign out returns to the sign-in page and Back does not reveal shipments.

## Shipments list (LST)

Tabs, search, sort and pagination over 30 seeded shipments.

- **FR-LST-01** (Must) The list opens on All with exact tab counts and a ten-row first page.
  - All 30, Booked 3, In transit 12, At customs 3, Out for delivery 3, Delivered 7, Cancelled 2, Exceptions 6
  - "Page 1 of 3"; columns Tracking, Route, Service, Status, ETA, Weight; first row TMK-480601 (ETA 13 Oct 2026)
- **FR-LST-02** (Should) A status tab narrows the table to that status.
  - Delivered: seven rows, all "Delivered", one page
  - Cancelled: TMK-480466 and TMK-480656
- **FR-LST-03** (Must) The Exceptions tab lists exactly the shipments with an open exception, each with its reason.
  - TMK-480377, TMK-480444, TMK-480523, TMK-480589, TMK-480623, TMK-480678
  - TMK-480377 flag: "Held at customs: Commercial invoice missing"
- **FR-LST-04** (Should) Search matches tracking number or consignee, case-insensitively; no match shows an empty state.
  - "480377" returns only TMK-480377 (At customs)
  - "oakmere" returns TMK-480477 and TMK-480612 (Oakmere Stores)
  - "zzz-none": "No shipments match your search"; clearing the box restores ten rows
- **FR-LST-05** (Could) The ETA header toggles ascending (default) and descending order.
  - Ascending first row TMK-480601 (13 Oct 2026)
  - Descending first row TMK-480433 (30 Oct 2026)
- **FR-LST-06** (Could) Pagination moves across three pages with Previous and Next disabled at the ends.
- **FR-LST-07** (Should) A shipment shows "Late" only when its ETA is before today and it is not delivered.
  - TMK-480444 (ETA 17 Oct) is Late
  - TMK-480589 (ETA 19 Oct, due today) is not Late

## Shipment detail (DET)

Summary, route map and timeline.

- **FR-DET-01** (Must) The detail page shows status, service, ETA, parties and a route map listing every hub with the current position marked.
  - TMK-480411: In transit, Standard, ETA 21 Oct 2026, Keiran to Brannhaven
  - Hubs in order KEI, QIN, SUN, HAL, ZEN, TAV, MRS, KLM, BRH; marker between ZEN and TAV
- **FR-DET-02** (Must) The timeline lists events newest first.
  - TMK-480411 first entry "Departed Zenith Dry Port" (16 Oct), last "Shipment booked" (11 Oct)
- **FR-DET-03** (Should) Each event shows the local time at its hub with the UTC offset.
  - "Departed Zenith Dry Port": 16 Oct, 14:00 UTC+03:00
  - "Shipment booked": 11 Oct, 15:00 UTC+09:00

## Weights (WGT)

kg/lb display and dimensional charging.

- **FR-WGT-01** (Must) The unit toggle converts kg to lb with 1 kg = 2.2046 lb, rounded (not truncated) to one decimal.
  - TMK-480411 kg: 12.5, 8.0, 2.4; total 22.9
  - lb: 27.6, 17.6, 5.3; total 50.5
- **FR-WGT-02** (Must) Dimensional weight is length x width x height (cm) / 5000; each parcel is charged at the greater of actual and dimensional weight, and the shipment shows the chargeable total.
  - 60x40x30 = 14.4 kg; 70x70x25 = 24.5 kg; 100x50x40 = 40.0 kg
  - Chargeable weight 78.9 kg; volumetric parcels tagged "Volumetric"

## Customs documents and exceptions (CUS)

Checklist, holds and exception lifecycle.

- **FR-CUS-01** (Should) The checklist separates required and optional documents with a received count and shows the exception banner.
  - TMK-480377: "2 of 3 required documents received"; Commercial invoice unchecked, Packing list and Certificate of origin checked, Dangerous goods declaration (optional) unchecked
  - Banner "Held at customs: Commercial invoice missing"
- **FR-CUS-02** (Must) Receiving the last required document clears the hold, logs an event and removes the shipment from Exceptions.
  - "3 of 3 required documents received"; banner gone
  - Newest timeline entry "Customs documents received, clearance resumed"
  - Exceptions tab shows five rows
- **FR-CUS-03** (Must) A delivered shipment carries no open exception and is excluded from the Exceptions tab; its past delay remains in the timeline.
  - TMK-480211: Delivered, no banner, timeline still lists "Delayed: Storm closed the berth for 14 hours"
  - Exceptions tab shows six rows without TMK-480211
- **FR-CUS-04** (Should) Documents of a delivered shipment are locked.
  - Checkboxes disabled; "Documents are locked once a shipment is delivered"

## Cancellation (CAN)

Cancel a shipment that has not been delivered.

- **FR-CAN-01** (Must) Cancelling asks for confirmation, then sets the status to Cancelled, logs the event and updates the tab counts.
  - Dialog with "Keep shipment" and "Yes, cancel shipment"
  - Status "Cancelled"; newest entry "Shipment cancelled by shipper"; Cancel button gone
  - TMK-480305: tabs Cancelled 3, In transit 11
- **FR-CAN-02** (Should) "Keep shipment" closes the dialog and leaves the status unchanged.
- **FR-CAN-03** (Should) A delivered shipment has no Cancel button.

## New shipment wizard (WIZ)

Four steps: sender, recipient, parcels, service.

- **FR-WIZ-01** (Must) A shipment can be booked end to end; it appears as Booked with the quoted ETA and a new tracking number.
  - Sender Brannhaven Port to recipient Halvard Terminal, one 5 kg 40x30x20 cm parcel, Standard
  - TMK-480901: Booked, route BRH, KLM, MRS, TAV, ZEN, HAL, ETA 23 Oct 2026, one entry "Shipment booked"
  - List shows All 31, Booked 4
- **FR-WIZ-02** (Should) Each step blocks Continue and names the missing field.
  - "Sender: name must be 2 to 60 characters"
  - "Sender: street address is required"
- **FR-WIZ-03** (Should) Origin and destination hubs must differ.
  - "Origin and destination hubs must differ"; no shipment created
- **FR-WIZ-04** (Should) A parcel may weigh at most 70 kg.
  - 70 kg accepted
  - 71 kg: "Parcel 1: weight exceeds the 70 kg limit"
- **FR-WIZ-05** (Should) Economy is unavailable when any parcel exceeds 30 kg.
  - 35 kg parcel: Economy disabled with "Parcel 1 is over 30 kg; Economy accepts up to 30 kg per parcel"; Standard and Express selectable

## Quotes and insurance (QUO)

Price per service with fuel surcharge and optional insurance.

- **FR-QUO-01** (Must) Each service shows an ETA and a total of freight plus an 8% fuel surcharge on freight.
  - 5 kg 40x30x20 cm: Economy ETA 26 Oct, Standard 23 Oct, Express 21 Oct 2026
  - Standard: Freight $36.00, Fuel surcharge (8%) $2.88, Total $38.88
- **FR-QUO-02** (Must) Insurance costs 1.5% of the declared value and is added to every total after the surcharge.
  - Declared value 1500: insurance $22.50
  - Totals Economy $48.42, Standard $61.38, Express $88.38
- **FR-QUO-03** (Must) The declared value must be between $1 and $50,000; outside that range no insured quote is produced.
  - 60000 and 0: "Declared value must be between $1 and $50,000"
  - 50000 accepted; insurance row $750.00

## Shipping label (LBL)

Printable label for a shipment.

- **FR-LBL-01** (Could) The label shows tracking, routing, service, parcel count, weight in both units, ETA and a barcode number.
  - TMK-480411: "KEI > BRH", Standard, 3 parcels, 22.9 kg (50.5 lb), ETA 21 Oct 2026
  - Barcode number 9248041103

## Non-functional requirements

- **NFR-01** (Should) Data is held per browser tab; "Reset demo data" (confirmed with "Yes, reset data") restores the 30 seeded shipments.
  - After cancelling TMK-480305 and resetting: All 30 and TMK-480305 In transit

## Glossary and rules

- **Chargeable weight** — Per parcel, the greater of actual weight and dimensional weight; summed for the shipment.
- **Dimensional weight** — Length x width x height in cm divided by 5000, in kg.
- **Exception** — An open problem on an undelivered shipment, such as a customs hold.

## Out of scope

- Real carrier integrations
- Payments
- Printing hardware
