srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/internal/ipc/ipc.go
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2026-05-18 23:30:00 +0200
committersrdusr <[email protected]>2026-05-18 23:30:00 +0200
commit4fa511ac5f2aa422456c49610a2cf29dfee46dfd (patch)
treec033651e2fcd3a3f1131998f86a5118bcfc56034 /internal/ipc/ipc.go
parent1707cf827592bc3de7ea9c2805b7adea49b3cbc5 (diff)
downloadmitmux-4fa511ac5f2aa422456c49610a2cf29dfee46dfd.tar.gz
mitmux-4fa511ac5f2aa422456c49610a2cf29dfee46dfd.zip
History deletion: delete one entry (x) or clear everything (X)
Store had full CRUD for match-and-replace rules but no way to delete or prune history at all - it only ever grew, with no way to remove an accidental capture or start a new engagement clean short of manually deleting the DB file outside the tool entirely. internal/store: DeleteEntry(id) removes one history row and its history_fts search index row in a transaction. ClearHistory() empties both tables entirely; rules are untouched. internal/ipc: new "delete_entry" and "clear_history" request types, Client.DeleteEntry/ ClearHistory methods. TUI: 'x' deletes the selected history entry, 'X' clears the whole database. Both gated behind a y/n confirmation - a small reusable confirmPrompt/confirmYes model state, checked first in the history list's key handling, so any key other than y/Y safely cancels rather than falling through to whatever that key normally does elsewhere (this also means ctrl+c during a pending confirmation cancels the prompt rather than quitting - a deliberate fail-safe, not an oversight: quick to dismiss, and a second ctrl+c then quits normally). 'X' is explicitly NOT scoped to an active search filter - it always clears the true total (read from daemon status, not len(m.entries), which would understate the count under a filter and make the confirmation prompt itself misleading about what's about to happen). Verified live in tmux against a running daemon with real captured entries: 'x' shows "delete #N? y/n", 'n' cancels with the entry untouched, 'y' deletes it and the list/count both refresh correctly; 'X' shows "clear all N history entries (not just this view)? y/n" with the true count, 'y' empties the database (confirmed via direct SQLite query: both history and history_fts at 0 rows afterward) and the TUI correctly shows "history (0)" / "0 requests"; 'x'/'X' on an empty list correctly no-op without crashing. go build/vet/gofmt/test/mod tidy all clean.
Diffstat (limited to 'internal/ipc/ipc.go')
-rw-r--r--internal/ipc/ipc.go41
1 files changed, 38 insertions, 3 deletions
diff --git a/internal/ipc/ipc.go b/internal/ipc/ipc.go
index 5dac21f..c2be080 100644
--- a/internal/ipc/ipc.go
+++ b/internal/ipc/ipc.go
@@ -18,7 +18,7 @@ import (
// Request is sent by a client to the daemon.
type Request struct {
- Type string `json:"type"` // "list", "get", "subscribe", "repeat", "intrude", "rules_list", "rules_save", "rules_delete", or "rules_toggle"
+ Type string `json:"type"` // "list", "get", "subscribe", "repeat", "intrude", "rules_list", "rules_save", "rules_delete", "rules_toggle", "delete_entry", or "clear_history"
Limit int `json:"limit,omitempty"`
BeforeID int64 `json:"before_id,omitempty"`
ID int64 `json:"id,omitempty"`
@@ -55,13 +55,14 @@ type Request struct {
RuleID int64 `json:"rule_id,omitempty"`
RuleEnabled bool `json:"rule_enabled,omitempty"`
- // For "set_flagged": ID identifies the history entry.
+ // For "set_flagged" and "delete_entry": ID identifies the history
+ // entry. "clear_history" needs no fields at all.
Flagged bool `json:"flagged,omitempty"`
}
// Response is sent by the daemon to a client.
type Response struct {
- Type string `json:"type"` // "list", "get", "new", "repeat", "rules", "intrude_result", "intrude_done", "status", "flagged", or "error"
+ Type string `json:"type"` // "list", "get", "new", "repeat", "rules", "intrude_result", "intrude_done", "status", "flagged", "deleted", "cleared", or "error"
Entries []store.Summary `json:"entries,omitempty"` // for "list"
Detail *EntryDetail `json:"detail,omitempty"` // for "get" and "repeat"
New *store.Summary `json:"new,omitempty"` // for "new" (subscribe push)
@@ -158,6 +159,40 @@ func (c *Client) SetFlagged(id int64, flagged bool) error {
return nil
}
+// DeleteEntry removes a single history entry.
+func (c *Client) DeleteEntry(id int64) error {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ if err := c.enc.Encode(Request{Type: "delete_entry", ID: id}); err != nil {
+ return err
+ }
+ var resp Response
+ if err := c.dec.Decode(&resp); err != nil {
+ return err
+ }
+ if resp.Type == "error" {
+ return errors.New(resp.Error)
+ }
+ return nil
+}
+
+// ClearHistory removes every history entry. Rules are untouched.
+func (c *Client) ClearHistory() error {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ if err := c.enc.Encode(Request{Type: "clear_history"}); err != nil {
+ return err
+ }
+ var resp Response
+ if err := c.dec.Decode(&resp); err != nil {
+ return err
+ }
+ if resp.Type == "error" {
+ return errors.New(resp.Error)
+ }
+ return nil
+}
+
// Status returns basic daemon info for a status bar.
func (c *Client) Status() (*StatusMsg, error) {
c.mu.Lock()