srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/PLAN.md
diff options
context:
space:
mode:
Diffstat (limited to 'PLAN.md')
-rw-r--r--PLAN.md73
1 files changed, 73 insertions, 0 deletions
diff --git a/PLAN.md b/PLAN.md
index 2b94b81..e95622c 100644
--- a/PLAN.md
+++ b/PLAN.md
@@ -674,3 +674,76 @@ after use - never part of the build) confirmed the captured messages
in `ws_messages` via `ipc.Client.ListWSMessages`, matching what the
test client actually sent and received, correctly attributed to
direction and opcode.
+
+## Sorting and highlighting
+
+Filtering already existed (FTS5 search plus `status:`/`source:`/
+`flagged:` and column filters - see Search above); sorting and
+highlighting didn't, at all, until now.
+
+Sorting is client-side, applied on top of whatever order List/Search
+already returned (newest-first, or FTS5 relevance) - `o` cycles the
+sort column (the default "captured" - no override - then status,
+size, time taken, method, host, path), `O` reverses it.
+`refreshTable()` doesn't just re-render sorted rows, it reorders
+`m.entries` itself to match: every "act on the selected row" key
+handler (enter/r/i/f/c/x, and the mouse equivalents) reads
+`m.table.Cursor()` and indexes straight into `m.entries` at that
+position, with no indirection layer. If the table's rendered order and
+`m.entries`'s order ever diverged, the highlighted row and the entry
+an action actually targets would silently disagree. Keeping them
+identical sidesteps that whole bug class rather than updating every
+one of those call sites to go through a lookup.
+
+Highlighting has two parts, and they needed genuinely different
+solutions because they render through different paths:
+
+- **JSON syntax highlighting** (`cmd/mitmux/jsoncolor.go`): walks the
+ token stream via `json.Decoder.Token()` with an explicit stack
+ rather than recursive calls, so depth is bounded by available memory
+ rather than Go's call stack for deeply nested attacker-controlled
+ JSON. Every string value and object key gets re-escaped via
+ `json.Marshal` before being written - which is also the entire
+ safety argument for *not* running the colorized output through
+ `sanitizeControl` afterward the way every other raw-text view in
+ this codebase does: JSON's own encoding rules forbid a literal
+ control character (ESC included) in a string, so re-marshaling one
+ neutralizes it as a side effect of just producing valid JSON text.
+ Running the already-colored output through `sanitizeControl`
+ afterward would instead corrupt the ANSI codes this function adds -
+ it treats ESC like any other control byte, correctly, for content
+ that hasn't been through this treatment. `prettyResponse` sanitizes
+ the header/status block (still server-controlled, still raw text)
+ separately from the colorized body for exactly this reason. This
+ path renders into a `viewport`, a plain scrolling text pane with no
+ fixed-width cell model, so ANSI content survives untouched.
+- **Status-code color-coding** (2xx green through 5xx red, Burp/
+ Caido's own convention) does *not* live in the history or Intruder-
+ results tables, despite an initial attempt to put it there. Confirmed
+ live, not guessed: `bubbles/table` v1.0.0 - the newest version
+ available, there is no newer one to upgrade to - fits cell text to
+ its column width via `go-runewidth`'s `Truncate`, which has zero ANSI
+ awareness; it counts every visible character of a
+ `"\x1b[38;5;42m"` escape sequence as real display width. Coloring the
+ Status cell didn't misalign the table, it silently deleted the status
+ text from the row entirely - the width-fitting truncation cut into
+ the escape sequence itself. `styledStatus` exists but is deliberately
+ unused inside any `table.Row`; it's used once, in `detailView`'s
+ title, which is a plain string lipgloss-renders whole with no width
+ constraint - nesting one nested `Render()` call inside another works
+ correctly there (confirmed live via raw escape-code inspection), at
+ the cost of one trailing space losing the outer title's bold/color
+ after the inner reset code, placed at the very end of the string
+ specifically to keep that cost minimal.
+
+Verified live in tmux against a running daemon with six real captured
+entries spanning 200/302/404/500 responses: `o` sorted ascending by
+status (200, 200, 200, 302, 404, 500), `O` reversed it; the detail
+view's title rendered the status code in the correct color per class
+(confirmed red for the 500 entry via raw escape-code capture, not just
+visually); pretty-printing a real JSON response produced correctly
+colored, correctly indented output - keys blue, string values green,
+numbers orange, booleans/null magenta, punctuation gray, confirmed
+against the raw captured ANSI codes, not just eyeballed - and the
+request tab (never JSON, never pretty-printed) rendered as plain
+unstyled text, unaffected.