# ADR-123 Dispatch Reporting Access & PII Model — Internal MIS vs Client Report

## Status

Proposed, 2026-07-27.

## Status History

```yaml
status_history:
  - date: 2026-07-27
    status: Proposed
    changed_by: hkl
    reason: Initial proposal — records the deliberate reporting access + PII exposure decision for DispatchWithAutomation.
    changed_via: adr-kit (360lm) — authored from DL CLI via SSH
```

## Context

The module produces two report surfaces: an internal **MIS report** and a **client-facing report**.
The TIMEX web dashboard deliberately **excluded** consignee phone/address from its public JSON
because it was a single unauthenticated GET. For DispatchWithAutomation the owner has decided the
**client report should include address + phone** (the consignees are the client's own dealers) and
that the client report is reached via an **unlisted URL with no password** (§19.2 decision). This
*reverses* the earlier PII-trim, so per the ADR coding-rules (security-significant) it must be
recorded as a conscious decision with its trade-off, not left implicit.

## Decision

Two distinct report surfaces under the `dispatch` module:
- **MIS report — internal, login-gated (hub SSO, ADR-012/011), FULL detail** (phone, address, cost,
  every field). Roles: Admin + Viewer read it (ADR: roles per MDD §15). Screenshot-deterrence per
  ADR-035.
- **Client report — external, reached via an UNLISTED URL (no password), INCLUDING address + phone**
  on the Delivery Status page, plus the drill-down overview. Delivered as a PostgREST-native view
  (ADR-074) of the same data; Excel export retained as a legacy channel.

**Explicitly accepted trade-off:** an unlisted URL is *not* authenticated — anyone with the link can
see full consignee PII. The owner accepts this for client convenience; the URL is an unguessable
token, not shared publicly. Shiprocket credentials never appear in either report. This decision is
revisitable: if exposure becomes a concern, upgrade to a per-client magic-link (ADR-048) or an
expiring link without changing the data model.

**Decision Maker:** hkl

## Implementation Notes

- **MIS:** hub-auth-gated PWA screens + PostgREST reads with full columns; Admin/Viewer roles.
- **Client report:** unguessable token in the URL → a PostgREST view exposing overview + delivery-status-with-PII for that campaign only; no login. Generalizes/absorbs the standalone `timex-dashboard` (kept during transition, then retired — §19.4).
- **PII boundary:** the client-report token scopes strictly to one campaign; no cross-campaign enumeration; token is long/random.
- **Find sites:** `grep -rn "client_report_token\|mis_report" /var/www/360lm/dispatch`

## Alternatives Considered

- **Per-client password / magic-link before PII (ADR-048).** Recommended by the assistant; **not chosen** by the owner for v1 (convenience). Recorded as the primary upgrade path if exposure concerns arise.
- **PII-trim the client report (no phone/address), full PII only in MIS.** Rejected by owner: the client legitimately needs dealer contact details in the shared view.
- **Expiring per-campaign link.** Not chosen for v1; noted as an alternative upgrade.

## Consequences

**Positive:**
- Client sees exactly what they need (dealer contacts + status) with zero login friction; internal MIS keeps the complete picture behind auth; single data source, two views.

**Negative / Trade-offs:**
- **Full consignee PII sits behind an unauthenticated (if unlisted) URL** — the accepted risk. A leaked/forwarded link exposes that campaign's dealer contacts.

**Risks and mitigations:**
- *Link leakage → PII exposure* → long unguessable token, per-campaign scope, no enumeration; documented upgrade path to ADR-048 magic-link / expiry if needed.
- *Scope creep to cross-campaign data* → token strictly binds to one campaign's view.

## Related Decisions

- ADR-048 (external client magic-link — the upgrade path), ADR-035 (screenshot deterrence), ADR-012/011 (hub/PIN auth for MIS), ADR-074 (accept-profile), ADR-120 (data these reports read). Reverses the TIMEX-dashboard PII-trim posture (documented in MDD §16).

## References

- `/var/www/360lm/docs/MDD_dispatch_automation.md` §13, §16, §19.2.
- `…/shiprocket-timex/HANDOFF.md` (original PII-trim rationale being consciously reversed).
