feat: Messages screen — journal shape, raw source, behaviors UI, protocol-aware journal#196
Merged
Merged
Conversation
…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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #191, completing the Messages experience before the release tag.
/__admin/messages/behaviors): SMTP fault/delay, simulated SMS error, capture webhook, resetCloses #192, closes #193, closes #194.
Validation: differential 190/190 (WireMock oracle incl.), unit 272/272, all verified in-browser.
🤖 Generated with Claude Code