Clean successor to V3 (forge: lilith/atlilith). Seeded from local Mac working tree at ~/Code/@projects/@cocottetech/. node_modules and build artifacts excluded via .gitignore. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
11 KiB
11 KiB
publish-report.screen
The deliberate publish flow for a coop safety report. Implements brief N §N5. Designed to be friction-deliberate — the cost of a wrongful coop report is high; the UX should make publishing feel like a careful act, never an accident.
Voice register: plain throughout — per voice.md §V2c, safety surfaces don't use metaphor.
Layout (full-screen compose sheet)
┌─────────────────────────────────────────────────┐
│ ◄ Coop Preview │ 56pt — top bar
├─────────────────────────────────────────────────┤
│ │
│ Reporting to: [ Berlin · 12 members ▼ ] │ coop selector (single or multi)
│ ☐ also Demimonde internal (4 members) │ multi-coop checkbox
│ │
│ ─── Subject ────────────────────────────── │
│ ● phone ○ email ○ handle ○ other │ PII kind picker
│ ╭───────────────────────────────────────╮ │
│ │ +49 30 12345678 │ │ PII input — hashed CLIENT-SIDE
│ ╰───────────────────────────────────────╯ │ before submit
│ ⓘ Cocotte will hash this locally. Peers see │
│ only the hash. │
│ │
│ ─── Rating ────────────────────────────── │
│ ★ ★ ★ ☆ ☆ 3 — "mixed; some concerns" │ slider 1–5 with labels
│ │
│ ─── Safety flags ──────────────────────── │
│ [☑ NON_PAY] [☐ AGGRESSIVE] [☑ TIME_WASTER] │ multi-select chips
│ [☐ UNSAFE] [☐ BOUNDARY_VIOLATION] [☐ SCAM] │
│ [☐ OTHER] │
│ │
│ ─── What happened ─────────────────────── │
│ ╭───────────────────────────────────────╮ │
│ │ Be specific. Other providers will rely │ │ placeholder
│ │ on this. │ │
│ │ │ │
│ ╰───────────────────────────────────────╯ │
│ 0 / 1000 chars │
│ │
│ ─── Attachments ────────────────────── │
│ [ + Screenshot ] [ + Receipt ] │ client-side encrypted before upload
│ │
│ ─── Attribution ────────────────────── │
│ ● Publish as you (Quinn) │
│ ○ Publish anonymously │
│ ⓘ Moderators still see your identity. │
│ Anonymous reports carry less weight. │
│ │
│ ─── Would you work again? ─────────────── │
│ ○ Yes ● No ○ N/A │
│ │
└─────────────────────────────────────────────────┘
↓ Preview button routes to publish-preview ↓
Publish-preview confirmation (state 7 below)
┌─────────────────────────────────────────────────┐
│ Publish to Berlin coop │ high-stakes interrupt
│ │ per brief M §M3
│ 12 members will see this within minutes. │
│ Subject can never see it. │
│ You can edit or withdraw later. │
│ │
│ Hash to be published: abc123… │
│ Rating: 3 of 5 │
│ Flags: NON_PAY, TIME_WASTER │
│ Attribution: Quinn │
│ │
│ [ Hold off ] [ Publish ] │ plain-register actions
└─────────────────────────────────────────────────┘
Components
| Component | Notes |
|---|---|
| Top bar | Back to coop drawer; "Preview" right routes to confirmation sheet. Disabled until required fields filled. |
| Coop selector | Single-coop by default; multi-coop via checkbox. Defaults to Quinn's most-active coop. |
| Subject card | PII-kind radio + value field. Client-side hashing happens before submit (per brief N §N7a). Info chip reinforces this. |
| Rating slider | 1–5 with descriptive labels at each notch ("avoid" → "excellent"). Nullable for flag-only reports. |
| Safety flags | Multi-select chips. Adding UNSAFE enables the evidence-required indicator if the coop config demands it (per brief N §N1 require_evidence_for_safety_flags). |
| Notes textarea | Required (1000-char cap). Placeholder uses plain-register prompt. PII-scan-on-blur warns if a real name appears (per brief N open-questions). |
| Attachments | Optional. Encrypted client-side with per-coop key before upload (brief N §N7b). |
| Attribution | Default = identified. Anonymous available; info-chip on weight discount. |
| Would-work-again | Tri-state. Independent of rating + flags. |
| Preview action | Routes to confirmation sheet (state 7 below). |
States
- Empty / start — only coop selector + subject-kind radio active; everything else greyed.
- PII entered — Subject value field filled; "Cocotte will hash this locally" chip appears.
- Mid-fill — rating + flags + notes being completed. Preview button enables only when subject + rating-OR-flags + notes meet minimum.
- Validation error — required field missing or notes shorter than 30 chars → inline error.
- PII detected in notes — yellow inline banner: "I see a name in your note. Strip before publishing?" with replace-suggested affordance.
- Attachment uploading — progress per attachment; uploads complete before Preview activates.
- Preview / confirmation — the high-stakes interrupt drawn above. Pressing "Publish" commits; pressing "Hold off" returns to the compose sheet.
- Publishing in flight — top banner: "Sending…" 0.5–2s; non-cancellable once started (the cost-of-cancel mid-flight is worse than completing).
- Published — sheet dismisses; chat-home receipt: "Published. Subject hash: abc123. 12 peers notified." Audit row recorded.
- Publish failed — per brief M §M2: sheet stays open with banner "Couldn't reach the coop. Retry or save draft?" Data preserved.
- Editing an existing report (entry: "Edit" tap on Quinn's own report in coop drawer) — sheet pre-fills; coop selector locked; Preview text changes to "Save changes" and the confirmation copy adjusts.
- Voice / accessibility — section reading order: coop → subject → rating → flags → notes → attachments → attribution → would-work-again. Required-field hints announce.
Interactions / gestures
- Tap PII-kind radio → changes input field type (phone keypad / email keyboard / text).
- Type PII value → real-time validation (phone format, email format); hashing happens at submit-time, not as-you-type.
- Tap a flag chip → toggle. UNSAFE shows evidence requirement reminder if coop config demands.
- Type in notes → on-blur PII-scan; on-blur character count.
- Tap "+ Screenshot" / "+ Receipt" → iOS photo picker / file picker; auto-encrypts client-side; thumbnail with progress bar appears.
- Tap "Preview" → confirmation sheet appears as a modal-over-modal.
- Tap "Publish" (confirmation) → publish; sheet dismisses on success.
- Tap "Hold off" (confirmation) → returns to compose sheet, all fields preserved.
- Swipe-down on compose sheet → "Save as draft?" prompt (don't lose work).
- Long-press any field → no special action; standard iOS text edit.
Edge cases
- Cocotte herself drafted this report via "report this client to Berlin coop" — sheet pre-fills with Cocotte's draft; banner: "Cocotte drafted this from your conversation. Review carefully before publishing." Plain register.
- Subject hash matches an existing report (Quinn's or peer's) — banner: "There's already a report on this hash in {coop}. Add to the thread or publish separately?" Routes to either edit-existing or publish-as-new.
- Coop config requires evidence for UNSAFE but no attachment provided — Preview button disabled; inline error: "Add a screenshot or remove the UNSAFE flag."
- Membership in coop expired / suspended mid-compose — banner: "You can't publish to {coop} right now. Save draft or switch coop?"
- Quinn enters "everyone is awful" as notes (vague) — soft prompt: "Other providers need specifics to act on this. Add more detail?" Doesn't block.
- Per-coop salts have rotated — hash field shows "(new salt)" badge; older Quinn reports under prior salt aren't auto-merged.
- VoiceOver + screen reader privacy — Subject PII value field reads "(field — value hidden)" by default; explicit reveal requires user gesture.
- Reduced motion / Dynamic Type XXL — sections stack; rating slider becomes ±buttons.
Related
- Brief N §N5 — parent design.
- Brief N §N7 — PII hashing + attachment encryption mechanics that govern this sheet.
- Brief M §M3 — confirmation pattern reuses the high-stakes interrupt.
- Brief I — published report enters audit as an
agent_actionsrow. - Brief K §K1 — companion personal blocklist.
- coop-drawer.screen.md — the drawer this opens from.
voice.md§V2c — plain register copy throughout.
Out of scope
- Dispute / counter-report compose (separate flow; uses simpler dispute sheet per brief N §N6a).
- Moderator-side review actions (brief N §N6b; moderator-only screen).
- Cross-coop publishing in one shot to >2 coops simultaneously (deliberate friction reason — too many "co-publish" boxes encourages low-quality reports).