30 Commits
Author SHA1 Message Date
BaaRai 8c9c1fc0ab feat(findings): optional counterevidence and confidence_rationale
Add two optional free-text fields to findings so a reporter can record
what was tested and did not work (counterevidence) and why the
conclusion holds (confidence_rationale).

- db: idempotent ADD COLUMN IF NOT EXISTS, TEXT NOT NULL DEFAULT '',
  no CHECK; RecordFindingInput, the INSERT, the shared select list and
  all three scan sites carry them.
- agent: report_finding accepts both as optional strings; the worker
  and pentest prompts say to fill them when confidence is not high.
- server: FindingDTO (list and detail) carries both, omitted when empty;
  existing databases get the two schema properties added to the stored
  report_finding row once, without overwriting user edits.
- web: the finding detail page shows each section only when non-empty.

Both fields stay optional: a missing field never refuses a finding.
2026-11-11 23:43:12 +01:00
BaaRai 1f4cb65ca6 feat(intercept): target-gate schema, opt-in flag and approval requests (S3b 1.2-1.4)
Storage, flag and request path of the approval gate for asset targets. The
gate itself is not wired into the tool hook yet (steps 1.5 to 1.7): with this
change nothing is extracted, resolved or blocked, whatever the flag says.

Schema and store (1.2)
- tasks.target_gate, conversations.target_gate (default false).
- intercept_pending.target_key and a partial unique index: one open request
  per scope (task or conversation) and host:port.
- target_pins (no foreign keys: a pin outlives its task, its conversation and
  its request row) and target_gate_exemption_log. All DDL is idempotent; no
  CHECK constraints; the cascade on intercept_pending.conversation_id stays.
- db/target_pins.go: pin lookup with port precedence, list, revoke,
  find-or-create of a request, and ResolveTargetRequest, which settles the
  row, supersedes the old pin and writes the new version in one transaction.
- Deleting a task or an archive stub revokes its pins and settles its open
  target requests in the delete transaction. DeleteConversation and
  DeleteConversations revoke the pins of the removed conversations in the
  same transaction as the delete.

Opt-in flag (1.3)
- Per task through the create and metadata-patch paths, per conversation
  through create and patch; exposed in the task DTO. A retest conversation
  takes the flag of the finding's task, never its pins. A spawned task starts
  with the gate off.
- The task flag is atomic and read on every call through TargetScope.Enabled.
  TargetScope now carries the Interceptor that owns the gate.

Request, wait, decide (1.4)
- pendingManager keeps a list of waiters per request; resolve wakes all.
- RequestTargets: find-or-create per target, one card per request, wait on
  channel, poll, context and wait bound. A plain request is never settled by
  a call that leaves. A request merged with an ask is bound to its creating
  call and a timeout never allows it.
- Decide records the approver (subject of the session token) and the remote
  address for every human decision, classic asks included. On a target
  request "allowed" pins the displayed addresses; that is the only writer of
  pins.
- A request raised while the global egress proxy is set says the approval is
  name-only and its pin is stored with name_only_effective.
- Routes: GET/POST .../target-pins and .../target-pins/{pid}/revoke under
  /api/tasks/{id} and /api/conversations/{id}; decision_source=target filter.
- ValidateExemptionHost: an exemption written as an IP literal may be private
  unicast, never loopback, link-local or metadata, unspecified or multicast.
2026-11-10 23:05:47 +01:00
BaaRai f938ba00d9 feat: verified findings backend (S1)
Add a machine-checked verification state to findings, separate from the
human disposition (status). A finding is verified only when a proof or
verification traffic body is bound, the agent declares POE L3 or higher,
and every evidence quote appears verbatim, after whitespace
normalization, in one of those response bodies.

- schema: poe_level, verification_status, verification_note on findings
  (idempotent ADD COLUMN IF NOT EXISTS, no CHECK, no backfill).
- db: SetFindingVerification validates status and POE 0-4; the three
  fields are scanned with the finding rows and exposed in the DTO.
- update_finding_report: optional poe_level and evidence_quotes. The
  report is always saved; verification only decides the status. Read
  failures give not_assessed, never unverified.
- report agent guidance: declare POE and exact quotes from the bound body.

Not in this change: UI badges and filters, the blocked and false_positive
transitions, and the stored default report prompt for existing databases
(the guidance is appended at run time).
2026-11-09 20:21:27 +01:00
BaaRai 13dde2da15 feat(llm): optional custom User-Agent for LLM requests
Add an optional per-profile User-Agent that overrides the header on every
outbound LLM request. When empty (the default), the existing behaviour is
unchanged and the default User-Agent is left untouched.

The value is trimmed and validated: control characters / newlines (header
injection) and values longer than 256 bytes are rejected. Wired through the
profile config struct, the Postgres llm_profiles schema, the profile API/DTO,
the connection-test path, and the LLM profile form, following the existing
session-header field. Addresses part of #154; the fixed-full-URL mode is not
included.
2026-11-08 17:11:43 +01:00
BaaRai 89348b5512 feat(engine): per-intent LLM chain-head rotation (opt-in llm_rotate)
Implements the per-intent rotation shape from #85: a task created with
llm_rotate=true distributes worker intents round-robin over its LLM chain
heads, so lane A can hunt on one model while lane B hunts on another
(different lenses per intent, no extra tokens). Default stays the classic
ordered failover from the active head; planner/goals/mainagent keep the
active head always.

Mechanics: the engine pins the next chain head into the run context when a
worker claims an intent; the pin travels through the provider resolver
(hooks.current now takes ctx). A pin is only a dispatch preference - it must
belong to the task chain and never bypasses failover state (an exhausted
chain stays exhausted). Schema: tasks.llm_rotate boolean, default false,
idempotent ALTER; exposed on the create payload and the task DTO.

Closes #85 (the ensemble/P4 shape stays parked as before)
2026-10-21 15:00:16 +02:00
BaaRai 9f03b8c16a feat: per-task planner quiet-mode switch, editable mid-run
Quiet-mode was compile-time only; wanting it off mid-task (empty frontier, one long intent, idle lanes) was impossible. tasks.plan_quiet_mode (default on) gates the edge-round skip in runRound, PATCH /api/tasks/{id} flips it live (the next round reads it), creation accepts plan_quiet_mode, and the DTO exposes it.
2026-10-12 21:13:28 +02:00
BaaRai e233c02314 Translate all Chinese text to English
Comments, doc comments, UI labels, log and error messages, LLM prompt
strings, markdown docs, test data and assertions. Identifiers, enum
keys, routes, placeholders and code structure are unchanged.

Notes:
- docs/漏洞流量证据.md renamed to docs/vulnerability-traffic-evidence.md
- tests that exercised CJK specific handling (GBK zip names, Chinese
  full text search) now use ASCII equivalents; go build passes and the
  test suite matches the pre translation baseline (remaining failures
  need a PostgreSQL DSN and fail identically on the original)
- frontend mention syntax now uses English kinds (finding, asset, ...)
  matching the backend, chat mentions tests pass
2026-10-08 23:14:34 +02:00
Autumn-27 1a10c153b0 feat(tasks): 漏洞列改为按严重度分档显示 严/高/中/低
- TaskListMetricsAll 用 COUNT(*) FILTER 按 severity 分四档统计(同一条查询)
- TaskListMetrics.Findings 及 TaskDTO.findings 由数字改为 {critical,high,medium,low}
- 列表页「漏洞」列渲染 x/x/x/x,配色沿用 severity 语义、为 0 的档位弱化
- severity 为空/白名单外的记录不计入任一档;mock 同步为对象结构
2026-09-24 13:32:45 -04:00
Autumn-27 ee33f91bc1 feat(tasks): 任务列表新增漏洞数量列,描述/目标列收窄
- 任务列表接口 TaskListMetricsAll 批量统计每任务的漏洞数(findings 表,
  按 task_id),经 TaskDTO.findings 下发;列表页新增「漏洞」列,>0 高亮
- 描述/目标列宽 max-w-xs → max-w-40,目标列补 title 悬浮全文
- mock data/handler 同步补 findings 字段
2026-09-24 13:26:22 -04:00
Autumn-27 6f295f48f8 feat(intent): 意图删除支持假删除/真删除两种模式
删除入口区分两种模式(待领/运行中/已暂停的意图均可删除):

- 假删除(默认):意图置 state='deleted'、删除原因记入新字段 delete_reason,
  保留节点与全部产出/血缘,不再在图上另挂 fact。
- 真删除:物理删除意图及「仅由它支撑」的独占子孙(沿 yields/derived_from
  级联到叶子),避免孤立数据;共享节点、目标、任务根事实保留。被删意图先做
  token rollup 并清理 activity/副会话,被删 finding 先删 findings 行。

两种模式都照常用 cancelled 触发通知 planner(带删除前捕获的意图摘要 + 原因),
planner 文案不再声称原因挂为事实。

- DB: 新增 SoftDeleteIntent、重写 CancelIntent 为深度独占级联;schema 加
  delete_reason 列与 intent 的 deleted 状态(含旧库迁移)。
- 前端: 删除对话框加模式切换与动态说明,状态徽章/图标新增「已删除」,
  播报板展开展示删除原因。
2026-09-17 12:52:57 -04:00
Autumn-27 2954781cb7 feat(agent): 任务内主 Agent 支持多会话,可切换且上下文可重置
主 Agent 会话原为一个任务恒定单例,对话历史随 transcript 只增不减、
上下文越滚越大。现引入会话分段(seq):新建会话切一个干净的 transcript
段,任务的图谱/资产/目标共享保留,旧段以只读历史随时切回查看。

- db: 新增 main_sessions 表与 activity.main_seg 列(ALTER ADD COLUMN
  IF NOT EXISTS 兼容旧库);ActivitySessionFilter 按段过滤(段 0 兼容
  旧 NULL 行);新增 CurrentMainSeg/ListMainSessions/NewMainSession;
  per-session token 统计按 main:<seg> 分段
- agent: MainAgent.Chat 增加 mainSeg,transcript SessionID 分段
  (段 0 保留旧名 exp<id>-main 兼容既有对话)
- server: parseActivitySession 支持 main:<seq>;chat handler 每轮
  stamp 当前段;新增 GET main-sessions / POST main-session/new
- web: 主 Agent 分组渲染多段会话,支持新建(轻确认)、切换、旧段只读
2026-09-10 12:56:59 -04:00
Autumn-27 028d9bd25c Merge PR #102: feat: 支持漏洞关联多条流量证据
冲突解决:
- db/schema.sql: 复测表(#103)与流量证据表(#102)均为追加,两者保留
- server/server.go: 启动序列同时保留 seedFindingRetester 与 evidence GC
- web/src/lib/types.ts: InterceptAudit/InterceptDetail(#101) 与流量证据类型(#102)并存
- findings/detail/page.tsx: 去掉 #103 带入的重复 import,仅保留 FindingRetestPanel
- chat/page.tsx: 保留 #103 的 Spinner import
2026-09-10 10:04:53 -04:00
ji ruo 1c77195e79 feat: 支持会话级漏洞复测与运行状态展示 2026-09-10 16:06:08 +08:00
ji ruo e6f8195500 feat: 支持漏洞关联多条流量证据 2026-09-10 13:03:20 +08:00
Autumn-27 76bdf4c3d2 feat(llm): 五层重试的次数与间隔可配
一次模型调用的失败由内到外经过五层重试:建连(SDK)、空响应(SDK)、同 provider
安全窗口、轮询熔断、意图重跑。此前五层的次数与间隔全是写死的常量,遇到脾气各异
的中转站只能改代码。现在都能在 LLM 页配置,不配就是原来的默认值。

配置语义五层统一(db.RetryRule):次数 0=内置默认 / -1=关掉这层 / >0=该值;
间隔 0=原本的指数退避 / >0=改用固定间隔。0 被"未配置"占用,故关闭用 -1。
写库前夹紧到 次数 [-1,20]、间隔 [0,1h],DB 另有 CHECK 兜底。

粒度按层的性质分:前三层跟着端点走,可在每个模型配置里逐字段覆盖全局默认(只钉
间隔的仍继承全局次数);熔断与意图重跑是进程级语义,只有全局一份。

生效路径:①②是 provider 构建参数,保存后重建缓存;③随每次 hooks.current()
解析,故障转移换配置时重试节奏跟着换;④在失败路径上每次都要读,由 applyRetryPolicy
推给 llmpool.Registry;⑤每条意图收尾读一次。全部热生效,无需重启。

连接测试刻意不带这些参数——它有 30s 硬超时,叠上用户配的重试只会把本来能用的
端点测成超时失败。

norma 升 v0.3.5(llm.Config 新增 RetryInterval / EmptyResponseRetries /
EmptyResponseInterval)。旧库升级后行为逐字节不变:新列默认 0,settings 键不
存在即全默认。设计见 docs/LLM重试设计.md。
2026-09-09 13:35:04 -04:00
Autumn-27 57fa1dba3a feat(tasks): 任务列表新增「运行中 Worker」列
TaskListMetricsAll 增加一个 LATERAL 子查询统计 kind='intent' 且
state='running' 的节点数,随 TaskDTO.in_flight 一并返回,口径与任务
详情页概览的「运行中 Worker」完全一致。列表页在「目标进度」后新增该
列,无运行中 Worker 时显示 0。
2026-09-08 14:25:49 -04:00
Autumn-27 12b63ab671 feat(llm): 每个 LLM 配置支持自定义会话头
新增 session_header_key:非空时每次 LLM 请求带上该 HTTP 头,头值为当前
运行的 session id(chat 会话=conv-<id>,worker=exp<x>-worker-i<intent>
等)。用于某些按 session-id 头做提示缓存/粘性路由的网关。

实现:在已有的 quotaAwareTransport 里从请求 context 读取 session id
(transcript.WithSessionID 挂上的)并注入,无需改 norma;同一共享 provider
也能按会话发出不同头值。DB 加 session_header_key 列(带旧库迁移),前端
LLM 配置弹窗新增输入框。
2026-09-07 11:21:50 -04:00
Autumn-27 a0c17701c2 feat(llm): 模型配置新增输出上限,支持 max_completion_tokens 字段名
llm_profiles 加两列:max_tokens(单次回复输出上限,0=不发送该字段,由服务端
默认值决定)与 max_tokens_field(上限发哪个键)。后者仅对 format=openai 生效:
空(默认)= max_tokens;'max_completion_tokens' = 新键。OpenAI 推理模型
(o 系列/GPT-5)拒收 max_tokens、只认新键,而多数兼容网关反过来只认旧键,
故做成显式开关而非自动推断。anthropic 与 openai-responses 自带字段名,
存下来只会误导,保存时一并清空。

顺带补上一处从未接通的链路:planner/worker/chat/mainagent/goals 五个
agentcore.Options 都没设过 MaxTokens,恒为 0——openai 系因 omitempty 压根
不发上限,anthropic 走 norma 的 8192 兜底。光加配置项而不接这条线,用户在
后台填了数字也不会生效,故本次一并接通,取值与 streaming 一样按 profile
每轮解析,故障转移切换后下一轮即生效。

task_llm.go 里 nonStreaming() 的来源优先级(agent 绑定 → 任务链激活 profile
→ 全局)抽成共用的 activeCfg(),避免 maxTokens() 再抄一份同样的三级回退。

norma 升到 v0.3.3(该版本提供 Config.MaxTokensField)。go.mod 只动 norma 这
一行:仓库此前未 tidy 过,跑 go mod tidy 会顺带升 x/crypto、x/net 等一批无关
依赖,不混进本次改动。

迁移:新列走 ADD COLUMN IF NOT EXISTS + 默认 0/'',旧库升级后行为完全不变;
CHECK 约束限定取值,每次启动先删后建保持幂等。
2026-08-31 12:20:31 -04:00
pphua 3675f7e530 chore: sync upstream v0.3.6 changes 2026-08-28 14:03:07 +08:00
pphua 809e94f6e4 归档 2026-08-28 12:56:29 +08:00
pphua 51d4857da1 1、将排序做到border-b transition-colors hover:bg-muted/50 has-aria-expanded:bg-muted/50 data-[state=selected]:bg-muted里,无需单独做个button 2、指定重命名使用ICO,无需使用菜单 2026-08-25 14:56:15 +08:00
pphua 0cb55d2b28 feat(api): integrate task workflows and mock contracts 2026-08-24 19:31:16 +08:00
pphua 259a0ae965 同步 2026-08-24 14:14:15 +08:00
Autumn-27 3e7aa493f9 feat: finding 增加详细报告字段 report(Markdown),详情页证据下方渲染
- findings 表加 report 列(TEXT 默认空,schema + ALTER 补旧库)
- 仅 GetFinding 查 report,列表/分页不带以免 payload 膨胀;FindingDTO.report omitempty
- 详情页「概览」证据卡下方新增「详细报告」卡,复用 <Markdown> 组件渲染,空时占位提示
- 前端 Finding.report? 类型;mock 单条 GET 返回 report、列表剥掉,并给 f-12 加示例报告
- 字段先留空,后续由写入方填充;db 测试补 report 往返断言

next build 通过。
2026-08-18 11:52:34 -04:00
Autumn-27 30b790154e feat: 漏洞新增 severity=critical(严重) 与 name(漏洞名称)字段
severity 严重级:
- report_finding 工具 severity 说明改为 critical|high|medium|low
- DB 排序 CASE、report 报告 sevRank、FindingStats 增加 critical
- 前端 Severity 类型、status.ts 新增 rose 色调(实心高强调,视觉高于高危)、
  发现页严重度筛选/统计卡、任务发现 Tab 排序、dashboard 汇总均加入严重

name 漏洞名称:
- findings 表加 name 列(schema + ALTER TABLE ADD COLUMN IF NOT EXISTS 补旧库)
- report_finding 工具新增 name 入参(非必填),写入 node payload 与独立 findings 行
- DBFinding/AddFinding/AddStandaloneFinding、FindingDTO、findingPayload、report 全链路透传
- 发现列表页与任务发现 Tab 展示 name,为空时回退 vulnclass;vulnclass 移到展开详情「类型」
- report 报告标题优先 name,回退 vulnclass

无 CHECK 约束,旧库仅需补 name 列;critical/name 均向后兼容。
db 测试补充 critical 排序/统计与 name 往返断言。
2026-08-18 11:21:08 -04:00
Autumn-27 21f5073eec feat: 发现列表改为服务端分页 + 全表聚合(去掉 500 上限)
- db.ListFindingsPage:WHERE(严重度/状态/类型)+ ORDER BY(严重度 CASE 或时间)+ LIMIT/OFFSET,返回当前页与匹配总数
- db.FindingStats:全表 COUNT FILTER 聚合(总数/待处理/高/中/低)+ DISTINCT 漏洞类型,供统计卡与类型下拉,不受分页影响
- GET /api/exploration/findings 带 page/limit → 分页对象{items,total,page,page_size};不带 → 保留裸数组(dashboard 汇总,与 intents 端点兼容策略一致)
- 新增 GET /api/exploration/findings/stats
- 筛选/排序全部下推到 SQL,前端不再一次拉全量再本地切片
- 资产按当前页所需批量解析;per-task 视图经 node_id 关联独立行,复用同一状态并补齐绑定资产
- 前端:发现页改为服务端驱动分页/筛选/排序,统计卡与类型下拉走 stats 接口
- db 层加 findings 分页/筛选/聚合测试(隔离标记 vulnclass,自清理)
2026-08-18 10:05:18 -04:00
Autumn-27 328e6f2438 feat: finding 增加处置状态(待处理/误报/忽略/已处理)+ 发现列表页改版
- findings 表新增 status 列(默认 pending),schema.sql 同步 ALTER TABLE 补旧库
- 新增 PATCH /api/exploration/findings/{id} 更新处置状态,server 侧白名单校验
- FindingDTO 增加 status/finding_id/assets(后端预渲染资产 label)
- 任务内发现节点通过 node_id 关联独立 findings 行,复用同一处置状态
- 发现列表页:漏洞名称(类型主 + 摘要小字)、新增资产列与状态列(可下拉修改)、状态筛选与待处理统计
- 任务详情发现 Tab 同步展示/编辑处置状态与绑定资产
2026-08-18 09:46:46 -04:00
Autumn-27 9ad38361e3 feat(agent): 支持为每个 agent 绑定 LLM 配置(agent 级默认模型)
按优先级 Agent 绑定 > 任务/会话指定 > 全局激活 解析每个 agent 运行的模型,
使 planner/worker/goals/mainagent/自定义 agent 可各自走不同 profile(如 plan 用
强模型、work 用弱模型)。未绑定时行为与原先完全一致。

- db: Agent 增 llm_profile_id + SetAgentLLMProfile;schema 幂等兜底 ALTER
- server: 新增 effectiveProfileForAgent/providerForProfile/providerForAgent;
  buildPlannerWorker 让 planner/worker 各自解析 provider;provider 按 profile id
  缓存以共享限速器;goals/会话链同步走绑定;绑定变更热重载
- api: agent 配置接口收 llm_profile_id(三态) + 返回可选 profile 列表
- web: agent 编辑器「配置与提示词」页新增「默认模型」下拉
2026-08-11 12:15:38 -04:00
Autumn-27andClaude Opus 4.8 92041b9444 feat(agent): 触发后处理可配置(运行模式/合并模式/并发上限) + 修复抽屉内下拉误关
每个自定义 agent 可配置触发后如何调度运行:
- 运行模式 serial|parallel:串行排队一次一个 / 每次触发各自并发一个会话
- 合并模式 by_task|all|none(仅 serial):同任务合并 / 全部合并成一条 / 不合并
- parallel 带每 agent 最大并发上限(0=不限),超限排队等空位

实现:
- DB: agents 加 trigger_run_mode/trigger_merge_mode/trigger_max_parallel 三列
  (schema + 幂等 ALTER 迁移,已发版补旧库);Agent 结构/scan/SetAgentTriggerBehavior
- 调度重构: triggerRun bool → triggerActive 计数 + triggerCfg 缓存;
  StartTriggeredRun 走 pumpLocked/runAndPump 统一泵模型,nextTriggerRun 按合并模式
  取(新增 mergeAllRuns);并发安全(session 按 conv-id 隔离,已确认)
- config 接口暴露/接收三字段;max_turns 改可选指针,避免触发 tab 部分 patch 清零
- 前端: 触发 tab 顶部加运行/合并模式下拉 + 最大并发输入,改动即存

修复: 抽屉(Sheet)内 Select 下拉 portal 到抽屉外,点选项/点别处被当成点击外部
误关抽屉。SelectContent 改 position=popper,并给 SheetContent 加 onInteractOutside
守卫(按 e.detail.originalEvent.target 判定弹层内点击则不关)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-08 04:23:09 -04:00
Autumn-27andClaude Opus 4.8 0ef8561411 chore: ARTEX 初始化
ARTEX — AI 自主渗透测试系统(Go 后端 + Next.js 前端,单二进制内嵌)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-26 04:27:45 -04:00