Skip to content

feat: Messages screen — journal shape, raw source, behaviors UI, protocol-aware journal#196

Merged
omercelikdev merged 7 commits into
mainfrom
feat/messages-screen-polish
Jul 26, 2026
Merged

feat: Messages screen — journal shape, raw source, behaviors UI, protocol-aware journal#196
omercelikdev merged 7 commits into
mainfrom
feat/messages-screen-polish

Conversation

@omercelikdev

Copy link
Copy Markdown
Owner

Follow-up to #191, completing the Messages experience before the release tag.

Closes #192, closes #193, closes #194.

Validation: differential 190/190 (WireMock oracle incl.), unit 272/272, all verified in-browser.

🤖 Generated with Claude Code

omercelikdev and others added 7 commits July 26, 2026 16:34
…l behaviors

Messages-screen polish (post-#191), on the approved plan:

- positioning: the inbox holds OUTBOUND traffic (what the app under
  test sent); Mockifyr answers like the real SMTP server / SMS provider
  and delivers nothing. A subtitle states it; the empty state is a
  quick-start with copyable one-liners (--smtp-port 1025 /
  --sms-profile twilio + how to point an app) and the one-call OTP
  verify hint
- inbox stays master-detail (journal family, not stubs tabs — the
  agreed model) and gains date-group headers in the list
- NEW — Channel behaviors sheet, the UI for G18e's
  /__admin/messages/behaviors: SMTP fault (none/reject/drop) + DATA
  delay, simulated SMS provider error code, capture webhook URL, with
  reset-to-defaults; server-side validation surfaces (negative delay /
  bad code → error toast)

Verified in-browser: subtitle + date groups render; the behaviors
sheet round-trips through the admin API (PUT 200, GET reflects, invalid
422, DELETE resets); the quick-start shows when the inbox is empty.
All six locales translated.

Refs #183

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…or traffic

Design decision, confirmed in review: EDITED things (Stubs) use the
workspace/tabs layout; TRAFFIC (Journal, Messages) uses the page +
card + sortable table + detail-sheet layout. Messages now mirrors the
Journal exactly:

- channel switcher as the Journal's pill (All/Email/SMS with counts)
- page header with the outbound-capture positioning line
- one card: toolbar (filter, Channel behaviors, Refresh, Density,
  Clear inbox) + sortable columns (Channel/To/Content/From/Received
  with full timestamp + relative time) + Showing-x-of-y footer with
  pagination
- row click opens a detail sheet: mail = attachments + sandboxed
  Preview/Text/Details tabs; SMS = the recipient's conversation thread
  with click-to-copy OTP badges; OTP also badges inline in the Content
  column
- quick-start renders inside the card when the inbox is empty;
  master-detail split panes are gone

Verified in-browser: table renders both channels with sort/pagination,
mail sheet shows tabs, SMS sheet shows the thread + OTP 775533 badge.

Refs #183

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…d as what they are

Review feedback: the stub list learned its protocol (ADR 0010) but the
journal still showed every entry as bare HTTP — Twilio-profile sends
read as mystery unmatched POSTs, gRPC calls as plain routes.

- GET /__admin/requests stamps a computed protocol per entry: sms by
  the provider path, grpc via the descriptor probe, graphql via the
  matched stub's custom matcher (an unmatched GraphQL-shaped post
  honestly stays http — there is no stub to inspect). Same decision
  table as the stub list, computed at query time, never stored
- journal UI: protocol chips in the URL column (HTTP stays unmarked,
  the stub-tree rule) + a Protocol facet beside Method/Status

Proven end to end (G18JournalProtocolTests): real traffic driven over
all four channels — a gRPC call with a real client, a GraphQL post, a
Twilio-profile send, plain HTTP — each classified correctly in the
journal; verified in-browser with chips + facet rendering.

Refs #183, #184

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…JSON field; env spacing

Review feedback, in one pass:

- raw source capture (#194): MessageEnvelope carries the wire payload
  as received — SMTP keeps the full MIME text (headers, boundaries,
  every part, byte-for-byte), the Twilio profile keeps the provider
  form body. GET /__admin/messages/{id} returns it; the mail detail
  sheet gains a Source tab and each SMS bubble a source toggle, both
  fetched on demand so the list stays lean. Proven end to end: a
  multipart mail's raw shows the multipart header, both parts and the
  HTML intact; the SMS raw is the urlencoded body verbatim
- the sidebar Messages item now badges the captured count like
  Stubs/Journal (#194)
- the WebSocket channel form's reply uses the framed JSON editor
  (lint relaxed — a reply may be plain text) instead of a bare
  textarea (#193)
- Environments header/example copy breathes (leading-relaxed) (#192)

Verified in-browser: badge renders, Source tab shows the real MIME,
SMS source toggle works; G18 suite (35) + Application (180) green.

Closes #192, closes #193, closes #194. Refs #183

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…te proof

Review feedback: the detail sheet's panes should all offer the standard
niceties.

- Preview: Copy HTML button (the visual pane's escape hatch); the
  iframe now fills the pane height
- Text: copy the body
- Source: copy the raw wire payload — deliberately NOT beautified, the
  pane's promise is byte-for-byte truth
- Details: the id and every meta value copy on click (they travel into
  tests constantly)
- copyHtml translated in all six locales

Proven with a real-world styled template: a gradient-header,
inline-CSS order-confirmation mail (table layout, dashed OTP box, CTA
button) sent over real SMTP renders pixel-faithful in the sandboxed
preview; all four tabs verified in-browser with their copy actions.

Refs #194, #183

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Review feedback:

- the subject line and the from→to address line in the detail sheet
  header now copy on click, with the copy icon appearing on hover —
  both travel into tests and bug reports constantly
- the Details pane no longer hugs the tab bar: it opens with the same
  rhythm as the other panes and its rows gained real spacing
  (gap-y-3 / gap-x-6)

Verified in-browser: header renders as two copy controls, Details rows
aligned and readable.

Refs #194, #183

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Found in the pre-merge edge sweep: a 25-recipient mail rendered its
whole address list in the To column, blowing the row up to 550px. The
column now shows the first address (truncated) + a "+N" count chip;
the full list stays in the detail sheet header.

Edge sweep also verified: an XSS-bearing HTML mail cannot escape the
sandboxed preview (no navigation, no script), a subjectless/empty mail
opens as "(no subject)", a 300KB body with a unicode attachment name
renders, a 12-digit number does NOT false-badge as OTP while a real
6-digit code does. Full suites green: differential 190/190 (oracle
included), unit 272/272.

Refs #183

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@omercelikdev
omercelikdev merged commit 588b127 into main Jul 26, 2026
3 checks passed
@omercelikdev
omercelikdev deleted the feat/messages-screen-polish branch July 26, 2026 15:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant