Commit Graph
7 Commits
Author SHA1 Message Date
tao.chenandClaude 25f93dfb59 admin: submissions page, download endpoint, uploads search by app_id
Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-14 13:45:11 +08:00
tao.chenandClaude a2232cecc4 storage: add spark_submissions table and SubmissionRepo
Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-14 13:45:03 +08:00
tao.chenandClaude df9b01272f admin: uploads list view with search, sort, and delete
Add /admin/uploads HTML page and JSON API backed by the upload_files

DB index. The page lists file_id, name, size (KB), uploaded_at, and

sha256 with client-side search by name, column sort, and per-row delete.

DELETE /admin/uploads/:id removes the DB index row and the on-disk

data file plus .meta.json sidecar. Admin deletes are written to the

audit log.

Wire the new dependencies through admin.Mount and main.go, and run

the backfill step on startup so pre-existing sidecars are indexed.

Tests cover auth, HTML rendering, JSON search, delete removing all

artifacts, and audit entry creation.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-14 11:39:56 +08:00
tao.chenandClaude 1796b5b872 storage: add upload_files table and UploadRepo
Add the upload_files SQLite table and UploadRepo CRUD methods

(Create/Get/List/Delete). The table stores file_id, name, size,

sha256, and uploaded_at as a queryable index.

The .meta.json sidecar remains the source of truth for uploads;

the DB is only an index for admin visibility. On startup the next

commit will backfill any pre-existing sidecars into this table.

Tests cover Create/Get/List/Delete round-trip, name search

filtering, descending time ordering, and limit defaults/cap.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-14 11:21:38 +08:00
tao.chenandClaude 77d8bae503 Linus 修复: 空 list JSON 序列化成 [] + seed.sh curl 续行
Linus 视角问题: ClusterRepo.List / AuditRepo.List 在空 list 时
返 nil, encoding/json 默认序列化成 null, 不是 []。
LLM/前端期望一致空数组语义。

- internal/storage/cluster_repo.go: List 返回前 out = []*cluster.Cluster{}
- internal/audit/repo.go: List 返回前 out = []*Entry{}

scripts/seed.sh curl 续行 bug: 在 set -euo pipefail 下 \\ 续行
被解析成多行, curl 收到混乱 argv 报 "URL rejected: Bad hostname"。
改为单行 + backslash 续行在 bash 中更稳。

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-10 17:24:40 +08:00
tao.chenandClaude 2c39091706 Phase 3+4: 共享 HTTP 客户端 + admin API + audit log
Phase 3 (httpclient):
- shared Client (Timeout + MaxResponseBytes 截断)
- SSRF: 16 段私网 CIDR (含 169.254/::ffff:0:0/96 IPv4-mapped)
  + hostname allowlist (精确/后缀/*. 通配)
  + scheme 校验 (仅 http/https)
- auth 适配器: none / simple (YARN user.name) / basic (SetBasicAuth)
- DoWithRedirect: 跨主机跳转保留 Authorization, max 5 默认
- 19 个测试全绿 (httptest 模拟)

Phase 4 (admin + audit):
- internal/audit: Entry + Repo.Insert/List + MarshalDetails, snake_case JSON
- internal/middleware: AdminAuth/AgentAuth (constant-time 比对)
- internal/admin: 6 端点 (GET/POST/PUT/DELETE /admin/clusters, GET /admin/audit)
  + 写操作触发 audit_log (含 before/after diff)
  + AuthPassword 空=保留旧密码
  + 校验: 必填字段 + auth_type 枚举 + rate_limit>=0
- main.go: 挂载 storage.Open + admin.Mount
- L fix: audit.Entry 加 json tag (smoke test 发现大写 key 不规范)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-10 13:54:24 +08:00
tao.chenandClaude a4e2472716 Phase 0+1+2 续: 项目骨架 + 配置 + 日志 + 存储层
Phase 0 (项目骨架):
- main.go 改为最小骨架 (config + logging + gin + /healthz + 优雅退出)
- internal/{config,logging,storage,cluster,...}/ 目录占位

Phase 1 (配置 + 日志):
- internal/config: env 解析 + 必填校验 + token 隐藏的 String()
- internal/logging: slog multi-handler 双输出 (终端 text + 主文件 JSON)
  + StartToolCall per-tool 独立文件 (0600), tools 目录 0700

Phase 2 续 (存储层):
- internal/cluster: 16 字段 Cluster struct (AuthPassword json:"-")
- internal/storage: modernc.org/sqlite 接入, WAL 模式, schema 自动迁移
- ClusterRepo CRUD: Create/Get/List/Update/Delete + ErrNotFound
  + AuthPassword 空字符串 = 保留旧密码 (核心约定)
- 7 个单元测试全绿 (:memory: DB)
- created_at/updated_at 改纳秒精度, 消除 List 测试的 sleep 特殊 case

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-10 12:12:53 +08:00