Phase 7 起步: Admin OpenAPI + Scalar UI + Cluster CRUD HTML

用户问题: 有 list_clusters MCP tool 但没简易 admin HTML。
A + B 方案:
- A: OpenAPI 文档 + Scalar UI(让人看 + 试 admin API)
- B: Cluster CRUD HTML 页面(让人填表创建/改 cluster)

实现:
- internal/admin/openapi.yaml: 手写 6 admin 端点 + Cluster/AuditEntry/Error
  schema。auth_password 不在 spec(因 json:"-" tag)
- internal/admin/openapi.go: //go:embed openapi.yaml + Scalar HTML
  GET /admin/docs 返 Scalar UI (CDN), GET /admin/docs/spec 返 YAML
- internal/admin/web/cluster.html: 单文件 401 行暗色 monospace 风格
  cluster CRUD 页面, 14 字段表单, vanilla JS + localStorage token
  + 内嵌 CSS, 无前端框架, 无 bundler
- internal/admin/web.go: //go:embed web/cluster.html
- internal/admin/router.go: Mount 里追加 4 路由 (GET /admin, /admin/,
  /admin/docs, /admin/docs/spec), 全部在 AdminAuth 组内

Linus 视角决策: 整个 /admin 子树 (含 HTML) 统一用 AdminAuth —
用户进页面前输 token, JS 存 localStorage, 后续 fetch 自动加 header。
简单且一致, 不搞"白名单 + 不带 token 也能看页"这种特殊 case。

Constraint:
- 不引第三方 Go 库 (不用 gofiber/swagger/scalar-go)
- 不引前端框架 (no React/Vue)
- 不开 JS bundler (no webpack/vite)
- HTML/CSS/JS 全内嵌在 cluster.html 一个文件
- Scalar 走 CDN (@scalar/api-reference latest)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
tao.chen
2026-07-10 18:17:37 +08:00
co-authored by Claude
parent 77d8bae503
commit 9a48f9e68e
5 changed files with 606 additions and 0 deletions
+4
View File
@@ -19,12 +19,16 @@ import (
// bearer-token admin authentication.
func Mount(r *gin.Engine, repo *storage.ClusterRepo, auditRepo *audit.Repo, adminTokens []string) {
g := r.Group("/admin", middleware.AdminAuth(adminTokens))
g.GET("", webHandler)
g.GET("/", webHandler)
g.GET("/clusters", listClusters(repo))
g.POST("/clusters", createCluster(repo, auditRepo))
g.GET("/clusters/:id", getCluster(repo))
g.PUT("/clusters/:id", updateCluster(repo, auditRepo))
g.DELETE("/clusters/:id", deleteCluster(repo, auditRepo))
g.GET("/audit", listAudit(auditRepo))
g.GET("/docs", DocsHandler)
g.GET("/docs/spec", OpenAPISpecHandler)
}
func listClusters(repo *storage.ClusterRepo) gin.HandlerFunc {