Documentation
¶
Overview ¶
Package store persists flow metadata in SQLite and bodies on disk.
Index ¶
- Constants
- func DecodeNotesImagePayload(mime, b64 string) (string, []byte, error)
- func FlowSortValue(fl *Flow, key string) string
- func NormalizeFlowSortKey(key string) string
- func NormalizeTags(tags []string) []string
- func SanitizeNotesImageMIME(mime string) string
- type APIKey
- type Activity
- type BodyWriter
- type Endpoint
- type EndpointFilter
- type Finding
- type FindingBlock
- type FindingFlow
- type Flow
- type FlowFilter
- type HostStat
- type Issue
- type Rule
- type SavedView
- type ScopeRule
- type Store
- func (s *Store) AddFlowTags(flowID int64, tags []string) ([]string, error)
- func (s *Store) AttachFlow(findingID, flowID int64, note string, pos int) error
- func (s *Store) AttachTags(flows []*Flow) error
- func (s *Store) BackupTo(destPath string) error
- func (s *Store) BodiesDir() string
- func (s *Store) ClearIssues() error
- func (s *Store) Close() error
- func (s *Store) CountFlowsWithFlag(flag int64) (int64, error)
- func (s *Store) CountSuccessfulHTTPS(hostSubstring string) (int64, error)
- func (s *Store) CreateAPIKey(label string) (token string, key APIKey, err error)
- func (s *Store) CreateFinding(f *Finding) (int64, error)
- func (s *Store) CreateRule(r *Rule) (int64, error)
- func (s *Store) CreateScopeRule(r *ScopeRule) (int64, error)
- func (s *Store) CreateView(v *SavedView) (int64, error)
- func (s *Store) DeleteAPIKey(id int64) error
- func (s *Store) DeleteActivity() error
- func (s *Store) DeleteFinding(id int64) error
- func (s *Store) DeleteFlows(ids []int64) (int64, error)
- func (s *Store) DeleteFlowsByHost(hosts []string, keepOnly bool) (int64, error)
- func (s *Store) DeleteRule(id int64) error
- func (s *Store) DeleteScopeRule(id int64) error
- func (s *Store) DeleteView(id int64) error
- func (s *Store) DetachFlow(findingID, flowID int64) error
- func (s *Store) DistinctTags() ([]TagCount, error)
- func (s *Store) Endpoints(f EndpointFilter) ([]Endpoint, string, error)
- func (s *Store) FlowCount() (int64, error)
- func (s *Store) FlowIDsBodySearch(f FlowFilter, maxScan int) ([]int64, string, error)
- func (s *Store) FlowTags(flowID int64) ([]string, error)
- func (s *Store) GCBodies() (removedFiles int64, freedBytes int64, err error)
- func (s *Store) GCNotesImages(notes string) error
- func (s *Store) GetFinding(id int64) (*Finding, error)
- func (s *Store) GetFlow(id int64) (*Flow, error)
- func (s *Store) GetNotesImage(id int64) (mime string, data []byte, err error)
- func (s *Store) GetSetting(key string) (string, bool, error)
- func (s *Store) HasAPIKeys() (bool, error)
- func (s *Store) HostStats() ([]HostStat, error)
- func (s *Store) InsertActivity(a *Activity) (int64, error)
- func (s *Store) InsertFlow(f *Flow) (int64, error)
- func (s *Store) InsertNotesImage(mime string, data []byte) (int64, error)
- func (s *Store) ListAPIKeys() ([]APIKey, error)
- func (s *Store) ListActivity(limit int) ([]Activity, error)
- func (s *Store) ListFindings(severity, status string) ([]Finding, error)
- func (s *Store) ListIssues() ([]Issue, error)
- func (s *Store) ListRules() ([]Rule, error)
- func (s *Store) ListScopeRules() ([]ScopeRule, error)
- func (s *Store) ListViews() ([]SavedView, error)
- func (s *Store) LoadNotes() (string, error)
- func (s *Store) NewBodyWriter() (*BodyWriter, error)
- func (s *Store) NormalizeNotesMarkdown(notes string) (string, error)
- func (s *Store) NotesImageExists(id int64) (bool, error)
- func (s *Store) OpenBody(sum string) (io.ReadCloser, error)
- func (s *Store) PersistNotes(notes string) (string, error)
- func (s *Store) QueryFlows(limit int) ([]*Flow, error)
- func (s *Store) QueryFlowsFilter(f FlowFilter) ([]*Flow, error)
- func (s *Store) QueryFlowsListFilter(f FlowFilter) ([]*Flow, error)
- func (s *Store) QueryWSFrames(flowID int64, limit int) ([]*WSFrame, error)
- func (s *Store) RemoveFlowTag(flowID int64, tag string) error
- func (s *Store) SaveIssues(issues []Issue) error
- func (s *Store) SaveWSFrame(f *WSFrame) error
- func (s *Store) SetFlowNote(id int64, note string) error
- func (s *Store) SetFlowTags(flowID int64, tags []string) ([]string, error)
- func (s *Store) SetSetting(key, value string) error
- func (s *Store) SetTagColor(tag, color string) error
- func (s *Store) TagsForFlows(ids []int64) (map[int64][]string, error)
- func (s *Store) UpdateFinding(id int64, ...) error
- func (s *Store) UpdateFlow(f *Flow) error
- func (s *Store) UpdateRule(r *Rule) error
- func (s *Store) UpdateScopeRule(r *ScopeRule) error
- func (s *Store) VerifyAPIKey(token string) (bool, error)
- type TagCount
- type WSFrame
Constants ¶
const ( EndpointSearchPath = "path" // host, path, method (default) EndpointSearchHeaders = "headers" // req/res headers JSON EndpointSearchBody = "body" // req/res body files (bounded scan) EndpointSearchAll = "all" // path + headers + body )
Endpoint search scopes for the attack-surface map.
const ( FlagIntercepted int64 = 1 << iota // request passed through the intercept hold queue FlagEdited // request was edited before forwarding FlagDropped // request was dropped by the user (not forwarded) FlagCaptureError // a body could not be captured; forwarding still succeeded FlagTLSFailed // TLS interception failed for this flow FlagWebSocket // a protocol-upgrade (WebSocket) handshake, tunneled transparently FlagRepeater // a request sent from the Repeater module FlagIntruder // a request sent from the Intruder module FlagImported // a flow imported from a HAR file (not proxied) FlagActiveScan // a probe sent by the active scanner FlagAI // request originated from the AI assistant (over MCP) FlagAuthz // a request replayed by the authorization (access-control) tester FlagDiscovery // an endpoint found by the content-discovery (forced-browse) engine FlagTLSBypassed // CONNECT tunneled raw (no MITM) — host on the TLS-bypass list )
Flow flag bits, OR'd into Flow.Flags.
Variables ¶
This section is empty.
Functions ¶
func DecodeNotesImagePayload ¶ added in v0.8.0
DecodeNotesImagePayload decodes a base64 image upload body.
func FlowSortValue ¶ added in v0.12.0
FlowSortValue returns the string form of a flow's sort key (for client cursors).
func NormalizeFlowSortKey ¶ added in v0.12.0
NormalizeFlowSortKey returns a whitelisted sort key (default id).
func NormalizeTags ¶ added in v0.11.0
NormalizeTags cleans, de-duplicates and sorts a tag list, dropping empties and capping the count. Exposed so callers (API/MCP) can normalize before display.
func SanitizeNotesImageMIME ¶ added in v0.10.0
SanitizeNotesImageMIME returns mime when it is an allowlisted raster image type, otherwise "application/octet-stream" (served inert — never as HTML, SVG or script). Applied both on insert and on serve, so already-stored rows with a dangerous MIME are also neutralized.
Types ¶
type APIKey ¶
type APIKey struct {
ID int64 `json:"id"`
Label string `json:"label"`
Prefix string `json:"prefix"`
Created int64 `json:"created"` // unix millis
}
APIKey is metadata for an issued control-API key. The secret token itself is never stored — only its SHA-256 hash and a short identifying prefix.
type Activity ¶ added in v0.6.0
type Activity struct {
ID int64 `json:"id"`
TS int64 `json:"ts"` // unix millis
Tool string `json:"tool"`
Summary string `json:"summary"`
OK bool `json:"ok"`
Result string `json:"result"`
Ms int64 `json:"ms"`
Intent string `json:"intent,omitempty"` // the AI's stated "why" for a consequential action
}
Activity is one recorded AI (MCP) tool call, persisted per-project so the glass-box feed survives restarts.
type BodyWriter ¶
type BodyWriter struct {
// contains filtered or unexported fields
}
BodyWriter streams bytes to a temp file while hashing them, then commits the file to a content-addressed path on Finalize. Safe for bounded memory: bytes are never buffered whole.
func (*BodyWriter) Abort ¶
func (w *BodyWriter) Abort()
Abort discards an in-progress body (e.g. on error).
type Endpoint ¶ added in v0.5.0
type Endpoint struct {
Host string `json:"host"`
Method string `json:"method"`
Path string `json:"path"`
Scheme string `json:"scheme"`
LastStatus int `json:"lastStatus"` // status of the most recent hit
Statuses []int `json:"statuses"` // every distinct status seen, sorted
Hits int `json:"hits"`
LastFlowID int64 `json:"lastFlowId"` // most recent flow, for click-through
ResBodyHash string `json:"resBodyHash"` // SHA-256 of latest response body (empty if none)
ResLen int64 `json:"resLen"` // length of latest response body
Soft404 bool `json:"soft404"` // 2xx/3xx body matches a "not found" content signature
}
Endpoint is a unique (host, method, path) surface aggregated from flows — the building block of the endpoint map. Repeated hits collapse into one row.
type EndpointFilter ¶ added in v0.5.0
type EndpointFilter struct {
Host string
Search string
SearchScope string // path, headers, body, all — see EndpointSearch* constants
ExcludeFlags int64
Tag string // only endpoints with at least one flow carrying this tag
HideNoiseOnly bool // drop endpoints that only ever returned 403/404 (forced-browse noise)
}
EndpointFilter narrows which flows are aggregated into endpoints.
type Finding ¶ added in v0.10.0
type Finding struct {
ID int64 `json:"id"`
TS int64 `json:"ts"` // created, unix millis
UpdatedTS int64 `json:"updatedTs"` // last modified, unix millis
Severity string `json:"severity"` // Critical | High | Medium | Low | Info
Status string `json:"status"` // open | verified | false_positive | wont_fix | fixed
Source string `json:"source"` // human | ai | scanner
Title string `json:"title"`
Target string `json:"target"`
Detail string `json:"detail"` // legacy / MCP compat: first text block synced here
Evidence string `json:"evidence"` // legacy only
Fix string `json:"fix"` // back-compat: kept but superseded by Impact
Impact string `json:"impact"` // security impact — what an attacker gains / business consequence
Cvss string `json:"cvss,omitempty"` // CVSS score or vector string, e.g. "7.5" or "CVSS:3.1/AV:N/..."
Body string `json:"body,omitempty"` // stored JSON blocks (use Blocks for rendering)
Flows []FindingFlow `json:"flows"` // attached flow metadata (for list sidebar count)
Blocks []FindingBlock `json:"blocks"` // ordered narrative body (source of truth for UI)
}
Finding is a curated vulnerability write-up for a project. Unlike a scanner Issue (auto-generated, ephemeral), a Finding is persistent and human/AI-curated: it carries a status the operator manages and has a narrative body — an ordered sequence of text blocks (markdown) and flow-reference blocks (clickable PoC request/response), freely interleaved.
type FindingBlock ¶ added in v0.12.0
type FindingBlock struct {
Type string `json:"type"` // "text" or "flow"
MD string `json:"md,omitempty"` // type=="text": markdown content
FlowID int64 `json:"flowId,omitempty"` // type=="flow": attached flow
Note string `json:"note,omitempty"` // type=="flow": annotation
// Enriched at read time from the flows JOIN — never stored in the body JSON.
Method string `json:"method,omitempty"`
Host string `json:"host,omitempty"`
Path string `json:"path,omitempty"`
Status int `json:"status,omitempty"`
// Missing is set (type=="flow" only) when the referenced flow no longer exists
// in the flows table — e.g. it was purged via prune_history / GC. The block and
// its human annotation are preserved; the UI/report surface that the PoC
// evidence is gone rather than silently rendering an empty flow.
Missing bool `json:"missing,omitempty"`
}
FindingBlock is one element in a finding's narrative body.
type FindingFlow ¶ added in v0.10.0
type FindingFlow struct {
FlowID int64 `json:"flowId"`
Ord int `json:"ord"`
Note string `json:"note,omitempty"`
Method string `json:"method,omitempty"`
Host string `json:"host,omitempty"`
Path string `json:"path,omitempty"`
Status int `json:"status,omitempty"`
// Missing is true when the referenced flow row no longer exists in the flows
// table (purged via prune_history / GC). The attachment row and note survive.
Missing bool `json:"missing,omitempty"`
}
FindingFlow is one PoC flow attached to a finding, enriched with a compact flow summary for display (the human selects request/responses to record here).
type Flow ¶
type Flow struct {
ID int64
TS time.Time
Method string
Scheme string
Host string
Port int
Path string
HTTPVersion string
Status int
ReqHeaders map[string][]string
ResHeaders map[string][]string
ReqBodyHash string
ResBodyHash string
ReqLen int64
ResLen int64
Mime string
DurationMs int64
ClientAddr string
Error string
Flags int64
Note string // free-text annotation an operator (or the AI) attaches to the flow
Tags []string // labels attached to the flow (manual or AI); loaded on demand, not a flows column
}
Flow is one captured request/response exchange. Bodies are referenced by content hash, never embedded.
type FlowFilter ¶
type FlowFilter struct {
Limit int // max rows (defaults to 200 when <= 0)
BeforeID int64 // legacy cursor: id < BeforeID when sorting id DESC
CursorID int64 // keyset cursor flow id (0 = first page)
CursorVal string // sort value at the cursor row (required for non-id sorts)
SortKey string // id|method|host|path|status|size|time|mime
SortDir int // +1 asc, -1 desc; 0 = default for the key
Method string // exact method match
Host string // case-insensitive substring of host
Search string // FTS on host/path/method/note, or exact id when SearchScope=id / #id / id:N
SearchScope string // path (default FTS), body (handled in control), id (exact flow id)
Scheme string // exact scheme match ("http"/"https")
StatusClass int // 1..5 → 1xx..5xx; 0 = any
RequireFlags int64 // only rows with any of these flag bits set
ExcludeFlags int64 // only rows with none of these flag bits set
IncludeFlags int64 // rows with any of these bits are kept even if ExcludeFlags also matches
WithoutFlags int64 // only rows with none of these flag bits set (independent of ExcludeFlags)
// Negative filters — each entry excludes matching rows; multiples are ANDed.
NotMethods []string // exclude these exact methods
NotHosts []string // exclude rows whose host contains any of these
NotPaths []string // exclude rows whose path contains any of these
NotStatuses []int // exclude these exact status codes
FlowIDs []int64 // when set, only these ids (used for body search results)
HasNote bool // only rows with a non-empty note
Tag string // only rows carrying this exact tag
}
FlowFilter selects and pages flows. Zero-valued fields are ignored.
type HostStat ¶ added in v0.7.0
HostStat aggregates flow counts and approximate byte totals for one host. Bytes is SUM(req_len + res_len) across all flows for that host — an approximation, because content-addressed bodies are deduplicated on disk, so flows sharing a body each contribute to the sum even though only one file exists. Use it for a rough UI size-breakdown, not an exact disk-usage figure.
type Issue ¶
type Issue struct {
ID int64 `json:"id"`
FlowID int64 `json:"flowId"`
Severity string `json:"severity"`
Title string `json:"title"`
Target string `json:"target"`
Detail string `json:"detail"`
Evidence string `json:"evidence"`
Fix string `json:"fix"`
}
Issue is one scanner finding. Severity is "High" | "Medium" | "Low" | "Info".
type Rule ¶
Rule is one ordered match-&-replace transform. Type is one of "req-header", "req-body" (response-side types are reserved for a later slice).
type SavedView ¶
SavedView is a named history filter (its Data is an opaque JSON blob the UI understands: scheme/method/status/search/host/inScope).
type ScopeRule ¶
type ScopeRule struct {
ID int64 `json:"id"`
Ord int `json:"ord"`
Enabled bool `json:"enabled"`
Action string `json:"action"`
Host string `json:"host"`
Path string `json:"path"`
Scheme string `json:"scheme"`
Port int `json:"port"`
}
ScopeRule is one target-scope rule. Action is "include" | "exclude". Empty host/path/scheme and port 0 mean "any" for that field.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store owns the SQLite database and the on-disk body directory.
func (*Store) AddFlowTags ¶ added in v0.11.0
AddFlowTags adds tags to a flow (union) and returns the flow's full tag set.
func (*Store) AttachFlow ¶ added in v0.10.0
AttachFlow records a flow as a PoC for a finding and inserts (or updates) a flow block in the finding's narrative body. pos is the 0-based block index at which to insert the flow block; pass -1 to append at the end. Idempotent on re-attach — updates the note in both tables and in the body block (position unchanged if the block already exists).
func (*Store) AttachTags ¶ added in v0.11.0
AttachTags populates each flow's Tags field from one batch query.
func (*Store) BackupTo ¶ added in v0.26.0
BackupTo writes a consistent, compacted snapshot of the database to destPath using SQLite's `VACUUM INTO`. It is safe to call on a live WAL-mode database: the snapshot is a single self-contained file with every committed row folded in (no separate -wal/-shm needed) and free pages reclaimed, so it is both consistent and typically smaller than a raw file copy.
destPath must not already exist — VACUUM INTO refuses to overwrite. The filename is a SQL string literal (not a bound parameter), so single quotes in the path are escaped to keep it a single literal.
func (*Store) BodiesDir ¶ added in v0.26.0
BodiesDir returns the absolute directory holding content-addressed body blobs for this store. Callers that archive a whole project (DB + bodies) need it.
func (*Store) CountFlowsWithFlag ¶ added in v0.21.0
CountFlowsWithFlag returns how many flows have any of the given flag bits set.
func (*Store) CountSuccessfulHTTPS ¶ added in v0.21.0
CountSuccessfulHTTPS returns flows where HTTPS MITM completed (non-zero status, not a recorded TLS handshake failure).
func (*Store) CreateAPIKey ¶
CreateAPIKey mints a new key, returning the full token (shown to the user once) and its stored metadata. The token is "ick_" + 48 hex chars.
func (*Store) CreateFinding ¶ added in v0.10.0
CreateFinding inserts a finding and sets f.ID/f.TS/f.UpdatedTS. Title is required. If Body is empty it is synthesized from Detail + Evidence so new findings are immediately in the interleaved-body format.
func (*Store) CreateRule ¶
CreateRule inserts a rule and returns its id.
func (*Store) CreateScopeRule ¶
CreateScopeRule inserts a scope rule and returns its id.
func (*Store) CreateView ¶
CreateView stores a named view and returns its id.
func (*Store) DeleteAPIKey ¶
DeleteAPIKey revokes a key by id.
func (*Store) DeleteActivity ¶ added in v0.6.0
DeleteActivity removes every recorded activity row (the user cleared the feed).
func (*Store) DeleteFinding ¶ added in v0.10.0
DeleteFinding removes a finding and its PoC attachments.
func (*Store) DeleteFlows ¶ added in v0.5.0
DeleteFlows removes the given flows and returns how many rows were deleted. An empty id list is a no-op. Content-addressed body files are left in place (they are shared/deduplicated across flows); the metadata rows are what go.
func (*Store) DeleteFlowsByHost ¶ added in v0.7.0
DeleteFlowsByHost removes flows by host pattern and returns how many rows were deleted.
- When keepOnly is false, every flow whose host matches ANY pattern in hosts is deleted. An empty hosts slice is a no-op (returns 0, nil).
- When keepOnly is true, every flow whose host matches NONE of the patterns is deleted (i.e. the listed hosts are kept, everything else is purged). An empty hosts slice with keepOnly=true is rejected with an error to prevent silently wiping all data.
Pattern matching is case-insensitive and supports leading-wildcard patterns (e.g. "*.example.com" matches "example.com" and all subdomains).
func (*Store) DeleteRule ¶
DeleteRule removes a rule by id.
func (*Store) DeleteScopeRule ¶
DeleteScopeRule removes a scope rule by id.
func (*Store) DeleteView ¶
DeleteView removes a view by id.
func (*Store) DetachFlow ¶ added in v0.10.0
DetachFlow removes a PoC flow from a finding's flow table and body.
func (*Store) DistinctTags ¶ added in v0.11.0
DistinctTags lists every tag in use with its flow count and color, most-used first.
func (*Store) Endpoints ¶ added in v0.5.0
func (s *Store) Endpoints(f EndpointFilter) ([]Endpoint, string, error)
Endpoints returns unique endpoints aggregated from flows. When SearchScope is headers, body, or all, Search filters by stored headers and/or body content (body search is bounded — see maxEndpointBodyScanFlows).
func (*Store) FlowIDsBodySearch ¶ added in v0.9.0
FlowIDsBodySearch returns flow ids whose request or response body contains term (case-insensitive). Other FlowFilter fields apply; Search is the body term.
func (*Store) GCBodies ¶ added in v0.7.0
GCBodies reclaims body files that are no longer referenced by any flow. It walks bodiesDir, collects every file whose name looks like a content hash (a 64-hex-char sha256 stored under a two-level prefix directory), queries the flows table for all referenced hashes, and removes any file whose hash is not among them.
GCBodies returns the number of files removed and the total bytes freed. It is safe to call while the store is in use: it never removes a file that is still referenced, and it never touches files outside bodiesDir or files whose names do not match the content-hash scheme (e.g. ".tmp-*" partials).
func (*Store) GCNotesImages ¶ added in v0.8.0
GCNotesImages deletes notebook images no longer referenced in the markdown.
func (*Store) GetFinding ¶ added in v0.10.0
GetFinding loads one finding with its narrative body blocks and PoC flow list.
func (*Store) GetNotesImage ¶ added in v0.8.0
GetNotesImage loads a stored notebook image by id.
func (*Store) GetSetting ¶
GetSetting returns the value and whether it was present.
func (*Store) HasAPIKeys ¶ added in v0.6.0
HasAPIKeys reports whether any control-API key exists. Auth is opt-in: while this is false the MCP endpoint stays open (loopback trust); once the operator creates a key, a valid bearer token is required.
func (*Store) HostStats ¶ added in v0.7.0
HostStats returns per-host flow counts and approximate byte totals, sorted descending by bytes. See HostStat for the approximation caveat.
func (*Store) InsertActivity ¶ added in v0.6.0
InsertActivity persists an AI tool-call record (a.TS set by the caller) and sets a.ID. Rows older than the most recent activityKeep are pruned so the log can't grow without bound.
func (*Store) InsertFlow ¶
InsertFlow stores a new flow and sets f.ID to the assigned row id.
func (*Store) InsertNotesImage ¶ added in v0.8.0
InsertNotesImage stores one embedded notebook image and returns its row id.
func (*Store) ListAPIKeys ¶
ListAPIKeys returns all key metadata (never the token or hash), newest first.
func (*Store) ListActivity ¶ added in v0.6.0
ListActivity returns recorded activity newest-first, capped at limit.
func (*Store) ListFindings ¶ added in v0.10.0
ListFindings returns findings ordered by severity (High→Info) then newest, each with its PoC flows and narrative blocks. Empty severity/status means "any".
func (*Store) ListIssues ¶
ListIssues returns all issues ordered by severity (High→Info) then id.
func (*Store) ListScopeRules ¶
ListScopeRules returns scope rules ordered by ord then id.
func (*Store) LoadNotes ¶ added in v0.8.0
LoadNotes returns project notes, migrating any legacy inline data-URL images.
func (*Store) NewBodyWriter ¶
func (s *Store) NewBodyWriter() (*BodyWriter, error)
NewBodyWriter starts a new body capture.
func (*Store) NormalizeNotesMarkdown ¶ added in v0.8.0
NormalizeNotesMarkdown replaces inline data-URL images with /api/notes/images/{id} references backed by SQLite blobs, so the markdown stays small.
func (*Store) NotesImageExists ¶ added in v0.8.0
NotesImageExists reports whether an image id is present (for tests).
func (*Store) OpenBody ¶
func (s *Store) OpenBody(sum string) (io.ReadCloser, error)
OpenBody returns a reader for the body with the given hash. An empty hash yields an empty reader (no body).
func (*Store) PersistNotes ¶ added in v0.8.0
PersistNotes saves normalized markdown and drops orphaned images.
func (*Store) QueryFlows ¶
QueryFlows returns up to limit flows, newest first.
func (*Store) QueryFlowsFilter ¶
func (s *Store) QueryFlowsFilter(f FlowFilter) ([]*Flow, error)
QueryFlowsFilter returns flows matching f, newest first. Filtering and paging are pushed down to SQL so large histories never materialize in memory.
func (*Store) QueryFlowsListFilter ¶ added in v0.8.0
func (s *Store) QueryFlowsListFilter(f FlowFilter) ([]*Flow, error)
QueryFlowsListFilter is like QueryFlowsFilter but skips req/res header columns.
func (*Store) QueryWSFrames ¶
QueryWSFrames returns up to limit frames for a flow, oldest first.
func (*Store) RemoveFlowTag ¶ added in v0.11.0
RemoveFlowTag detaches a single tag from a flow.
func (*Store) SaveIssues ¶
SaveIssues upserts issues, deduplicated by (title, target).
func (*Store) SaveWSFrame ¶
SaveWSFrame records a captured frame, trimming the flow to the most recent wsFramesPerFlow frames.
func (*Store) SetFlowNote ¶ added in v0.5.0
SetFlowNote sets (or clears, with "") the free-text note attached to a flow.
func (*Store) SetFlowTags ¶ added in v0.11.0
SetFlowTags replaces a flow's tag set with the normalized `tags` (empty clears).
func (*Store) SetSetting ¶
SetSetting upserts a key/value setting.
func (*Store) SetTagColor ¶ added in v0.11.0
SetTagColor sets (or clears, with "") a tag's display color. The value is stored verbatim; callers validate it's a safe CSS color before persisting.
func (*Store) TagsForFlows ¶ added in v0.11.0
TagsForFlows batch-loads tags for many flows in one query (no N+1), returning a map from flow id to its sorted tag list. Ids with no tags are absent from the map.
func (*Store) UpdateFinding ¶ added in v0.10.0
func (s *Store) UpdateFinding(id int64, severity, status, title, target, detail, evidence, fix, body, impact, cvss *string) error
UpdateFinding applies non-nil fields and bumps updated_ts. body, when set, is stored as the new narrative body (already-serialized JSON). When detail is set but body is nil, the first text block in an existing body is updated (MCP backward-compat: AI updates detail → UI sees the change). When body is set, detail is synced from its first text block so MCP list_findings still shows meaningful text.
func (*Store) UpdateFlow ¶ added in v0.3.0
UpdateFlow fills in the response-side (and post-send request) fields of a flow that was first inserted at request time, keyed by f.ID. The immutable request identity (ts, scheme, host, port, version, client) is left untouched.
func (*Store) UpdateRule ¶
UpdateRule overwrites the rule identified by r.ID.
func (*Store) UpdateScopeRule ¶
UpdateScopeRule overwrites the rule identified by r.ID.
type TagCount ¶ added in v0.11.0
type TagCount struct {
Tag string `json:"tag"`
Count int `json:"count"`
Color string `json:"color,omitempty"`
}
TagCount is a tag with how many flows carry it and its (optional) color.
type WSFrame ¶
type WSFrame struct {
ID int64 `json:"id"`
FlowID int64 `json:"flowId"`
TS time.Time `json:"-"`
Dir string `json:"dir"`
Opcode int `json:"opcode"`
Length int64 `json:"length"`
Preview string `json:"preview"`
}
WSFrame is one captured WebSocket frame. Dir is "send" (client→server) or "recv" (server→client). Preview holds a bounded prefix of the (unmasked) payload; Length is the full frame payload length.