Multi-select supported (§3.5 step 1). Teacher either opens the camera in-app or picks from the device's camera roll.
Take a photo Select from camera rollSelected:
Roster MUST be filtered to children enrolled in the teacher's assigned classroom(s). A child from another classroom MUST NOT appear here (§3.5 step 2).
allsolo_onlysolo_onlynoneA tagged child from outside the teacher's assigned classroom is unreachable via the UI; if reached, treated as blocking error per §3.10 error case.
[child C] has "solo only" consent, and this photo has 2 tagged children. You need to choose:
[exact wording — not specified in spec; spec §3.10 step 2 names the three options but not the microcopy]
Teacher MUST take explicit action to proceed. Solo_only single-tag = permitted, no warning (§3.10 step 3).
Separate flow: a tagged none child blocks the entire send.
[child D] has "no photos" consent. You need to re-tag or remove [child D] to send.
I-Consent-Block (§5.1): a PhotoTag with consent_evaluation = blocked MUST NOT generate any PhotoDelivery. Zero-tolerance.
[exact copy on which child is named vs. anonymized — spec §3.10 step 1 says "without disclosing other children's consent details unnecessarily" — the mock names the blocking child because the teacher needs to act on them; calibration signal]
On confirmation, each photo is written to an offline-tolerant local queue and the send UI returns control to the teacher immediately (§3.5 step 4). Teacher does not wait for upload.
[message entry mechanism — Q6 open parameter, §5.4]. Options listed in the spec: teacher_typed, library_picked, ai_generated, ai_assisted, none. Calibration signal: Nelson + Allan decide Q6 before this surface is designed.
Send
Underlying entity status values: queued, uploading, delivered, failed_retrying, failed_permanent (§3.5 step 5).
AC7 (new, tot-8ba spike): the teacher send view MUST display a per-photo upload-status indicator at all times, with distinct visible states for all five entity statuses. Silent background progress is prohibited.
| Photo | Status badge | State |
|---|---|---|
photo 1 | queued | queued — awaiting network |
photo 2 | uploading… | uploading — in-flight |
photo 3 | sent ✓ | delivered — teacher UI MAY label "sent" |
photo 4 | retrying… | failed_retrying — backoff in progress |
photo 5 | failed — retry? | failed_permanent — manual retry offered |
[teacher-facing labels — spec notes teacher UI "MAY label delivered as 'sent'" (§3.5 step 5); other labels are inferred from enum values]
AC8 (new, tot-8ba spike): on iOS Safari specifically, the send view MUST display a teacher-facing note whenever at least one photo is in queued, uploading, or failed_retrying. Motivation: iOS Safari cannot resume uploads in the background (no Background Sync / Periodic Sync / Background Fetch).
"Keep this tab open until your photos finish uploading." — exact copy is a product parameter per spec AC8; final wording TBD.
inference: the mock cannot actually user-agent-sniff (static HTML, no JS). The banner is rendered visible with the explicit conditional label above. A real implementation would:
any(photo.status ∈ {queued, uploading, failed_retrying});delivered or failed_permanent.On server-side persistence, the system creates per-recipient PhotoDelivery records for each guardian linked to each tagged child, subject to the consent evaluation performed at send time (§3.5 step 6, I-Consent-AtSend). Guardians are notified per their preferences (real-time or daily digest). See B6.
AC2 (revised 2026-04-24 per Q2 Amendment): a photo queued offline MUST reach a guardian within 10 minutes of the teacher next actively opening the Littlereach app after connectivity returns — bounded-by-web-platform form, since iOS Safari lacks Background Sync / Periodic Sync / Background Fetch (see spike tot-8ba RESULTS.md, open-questions.md §Q2 Amendment 2026-04-24).
AC3: a photo with a none-consent child tagged MUST NOT reach any guardian under any circumstances.
AC6: a failed_permanent photo is never deleted from the device until the teacher confirms.
Photo sits in queue with status queued. Teacher sees a clear queued indicator — no silent failure (§3.5 error cases, AC7).
Upload resumes automatically when connectivity returns. On iOS Safari specifically, the upload cannot resume while the tab is backgrounded or closed; it resumes on the next active app open (AC2 revised, AC8 banner applies).
Parameter: 10 retries over 24h (spec). Status moves to failed_permanent. Teacher sees this clearly and is offered a manual retry. Local copy MUST NOT be deleted until a successful delivery is confirmed.
Every PhotoTag gets exactly one immutable consent_evaluation value: permitted | warned_override | blocked, stamped at send time. Queryable for audit throughout the photo's lifetime.
| Photo | Tagged child | Consent eval | Stamped at |
|---|---|---|---|
| photo 1 | [child A] | permitted | [timestamp] |
| photo 1 | [child C] | warned_override | [timestamp] |
| photo 1 | [child D] | blocked | [timestamp] |