docs(gateway): gateway 剩余文件注释改中文(逐行 1:1,代码零字节改动)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

主人 2026-10-03 拍板「注释一律中文」;gateway 至此整包注释中文化完成(本会话共 3 批:
已推库 16 个文件 + 本批剩余文件)。
校验:机械校验(非注释改动行)= 空;剥注释后代码文本逐行比对全等(不一致文件数 0);
全树 go test ./... 58 包 ok / 0 FAIL;交叉编译绿。
This commit is contained in:
AskaEth committed 2026-10-03 22:28:25 +08:00
1 parent 91e8d7a029
commit 074ffc4ebf
73 files changed
+2529 -2529

No files matched your search

+45 -45
View File
@@ -17,13 +17,13 @@ import (
apperr "git.yeij.top/AskaEth/Cyrene_v2/internal/errors"
)
// System management admin writes (owner-only, audited; design/11 §4 敏感操作代审 +
// design/10 §3 module 14 系统设置). Every handler audits a system.* action and never
// echoes a JWT secret or a database path back to the client.
// 系统管理写操作(仅 owner,带审计;design/11 §4 敏感操作代审 +
// design/10 §3 module 14 系统设置)。每个 handler 都会审计一个 system.* 动作,
// 绝不把 JWT 秘密或数据库路径回显给客户端。
// adminRevokeAllKeys revokes every currently registered API key. It is the
// `system.revoke_keys` admin write; the table is emptied so no prior key can
// authenticate afterward.
// adminRevokeAllKeys 吊销当前已注册的每一个 API key。它是
// `system.revoke_keys` 管理写;该表被清空,因此此前任何 key
// 之后都无法认证。
func (s *Server) adminRevokeAllKeys(w http.ResponseWriter, r *http.Request) {
keys, ok := s.users.(*auth.APIKey)
if !ok {
@@ -36,15 +36,15 @@ func (s *Server) adminRevokeAllKeys(w http.ResponseWriter, r *http.Request) {
writeJSON(w, http.StatusOK, map[string]any{"revoked": n})
}
// rotateJWTRequest is the POST /api/v1/admin/system/rotate-jwt body. The new
// secret is accepted from the request so the owner can supply a fresh value; it
// is never echoed back or logged.
// rotateJWTRequest 是 POST /api/v1/admin/system/rotate-jwt 的请求体。新
// 秘密从请求中接受,使主人能提供新值;它绝不
// 被回显或被记日志。
type rotateJWTRequest struct {
NewSecret string `json:"newSecret"`
}
// adminRotateJWT replaces the JWT signing secret, invalidating every token issued
// under the old secret. It is the `system.rotate_jwt` admin write.
// adminRotateJWT 替换 JWT 签名秘密,使在旧秘密下签发的所有
// token 失效。它是 `system.rotate_jwt` 管理写。
func (s *Server) adminRotateJWT(w http.ResponseWriter, r *http.Request) {
var req rotateJWTRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
@@ -71,10 +71,10 @@ func (s *Server) adminRotateJWT(w http.ResponseWriter, r *http.Request) {
writeError(w, apperr.Wrap(apperr.ErrInternal, "rotate_failed", "failed to rotate jwt secret"))
return
}
// Credential rotation must invalidate every long-lived grant too, not only the
// access tokens signed under the old secret. Refresh tokens are opaque and
// secret-independent, so they are deleted wholesale — the minimal, exact
// global invalidation in this architecture (no token_version column needed).
// 凭据轮换也必须让每一个长期授权失效,而不只是旧秘密下
// 签发的访问令牌。refresh token 是不透明的、与秘密无关,
// 因此被整体删除 —— 这是本架构中最小且精确的
// 全局失效手段(无需 token_version 列)。
var refreshRevoked int64
if s.refresh != nil {
n, rerr := s.refresh.RevokeAll(r.Context())
@@ -95,9 +95,9 @@ func (s *Server) adminRotateJWT(w http.ResponseWriter, r *http.Request) {
})
}
// adminBackup snapshots the SQLite database into the data directory using
// `VACUUM INTO` (which includes committed WAL content), returning the backup path
// and size. It is the `system.backup` admin write.
// adminBackup 用 `VACUUM INTO` 把 SQLite 数据库快照进数据目录
// (该语句包含已提交的 WAL 内容),返回备份路径
// 与大小。它是 `system.backup` 管理写。
func (s *Server) adminBackup(w http.ResponseWriter, r *http.Request) {
if strings.TrimSpace(s.dbPath) == "" {
s.auditClaims(r, "system.backup", "error")
@@ -115,17 +115,17 @@ func (s *Server) adminBackup(w http.ResponseWriter, r *http.Request) {
writeJSON(w, http.StatusOK, map[string]any{"path": path, "size": size})
}
// restoreRequest is the POST /api/v1/admin/system/restore body. Path is the
// backup file to restore, expected to live inside the data directory.
// restoreRequest 是 POST /api/v1/admin/system/restore 的请求体。Path 是
// 要恢复的备份文件,预期位于数据目录内。
type restoreRequest struct {
Path string `json:"path"`
}
// adminRestore validates a backup path (must be inside the data directory — a
// path-traversal guard), snapshots the current database first, then replaces the
// live DB file. Because the running process holds the SQLite file handle open, the
// replace takes effect on restart; it is reported as such. It is the
// `system.restore` admin write.
// adminRestore 校验备份路径(必须位于数据目录内 —— 这是
// 路径穿越防护),先为当前数据库做快照,然后替换
// 活的 DB 文件。由于运行中的进程仍持有 SQLite 文件句柄,
// 替换在重启后生效;响应中如实说明。它是
// `system.restore` 管理写。
func (s *Server) adminRestore(w http.ResponseWriter, r *http.Request) {
var req restoreRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
@@ -154,8 +154,8 @@ func (s *Server) adminRestore(w http.ResponseWriter, r *http.Request) {
writeError(w, apperr.Wrap(apperr.ErrNotFound, "not_found", "备份文件不存在"))
return
}
// Snapshot the current database before touching it, so an accidental restore
// of the wrong file is recoverable.
// 在动它之前先为当前数据库做快照,这样误恢复
// 错文件时仍可挽回。
curPath, _, err := s.backupDatabase(r.Context())
if err != nil {
s.auditClaims(r, "system.restore", "error")
@@ -177,10 +177,10 @@ func (s *Server) adminRestore(w http.ResponseWriter, r *http.Request) {
})
}
// restorePathWithinDataDir resolves src to an absolute path and reports whether it
// lives inside the data directory (the parent of s.dbPath). It is the path-
// traversal guard for the restore endpoint: only paths under the data dir are
// accepted.
// restorePathWithinDataDir 把 src 解析为绝对路径并报告它是否
// 位于数据目录(s.dbPath 的父目录)内。它是恢复端点的
// 路径穿越防护:只接受数据目录之下的
// 路径。
func (s *Server) restorePathWithinDataDir(src string) (string, bool) {
dataDir, err := filepath.Abs(filepath.Dir(s.dbPath))
if err != nil {
@@ -199,11 +199,11 @@ func (s *Server) restorePathWithinDataDir(src string) (string, bool) {
return absSrc, true
}
// backupDatabase snapshots the live SQLite database into
// <dataDir>/backup-<ts>.db via `VACUUM INTO`, which includes every committed WAL
// transaction, and returns the new file's path and size. Opening a second
// connection to the file-backed database is safe: SQLite serializes access, and
// busy_timeout handles a momentarily locked source.
// backupDatabase 经 `VACUUM INTO` 把活的 SQLite 数据库快照到
// <dataDir>/backup-<ts>.db,该语句包含每一个已提交的 WAL
// 事务,并返回新文件的路径与大小。对基于文件的数据库再开
// 一个连接是安全的:SQLite 会串行化访问,而
// busy_timeout 能应对源被短暂锁定。
func (s *Server) backupDatabase(ctx context.Context) (string, int64, error) {
dir := filepath.Dir(s.dbPath)
if err := os.MkdirAll(dir, 0o755); err != nil {
@@ -215,8 +215,8 @@ func (s *Server) backupDatabase(ctx context.Context) (string, int64, error) {
return "", 0, fmt.Errorf("open db for backup: %w", err)
}
defer conn.Close()
// VACUUM INTO takes a string literal, not a bound parameter; escape the
// generated filename (safe characters, but escape defensively).
// VACUUM INTO 接受字符串字面量,而不是绑定参数;对生成的
// 文件名做转义(字符本身安全,但防御性地转义)。
query := fmt.Sprintf("VACUUM INTO '%s'", escapeSQLString(dest))
if _, err := conn.ExecContext(ctx, query); err != nil {
return "", 0, fmt.Errorf("vacuum into: %w", err)
@@ -228,11 +228,11 @@ func (s *Server) backupDatabase(ctx context.Context) (string, int64, error) {
return dest, info.Size(), nil
}
// replaceDatabase atomically replaces the live DB file at dest with a copy of src,
// writing to a temp file first so a failure never leaves dest truncated. On Linux
// a running SQLite connection keeps its open handle to the old inode, so the new
// data becomes visible only after the process restarts — which the restore
// endpoint reports.
// replaceDatabase 用 src 的副本原子替换 dest 处的活 DB 文件,
// 先写临时文件,因此失败绝不留下被截断的 dest。在 Linux 上
// 运行中的 SQLite 连接仍持有旧 inode 的句柄,因此新数据
// 只有在进程重启后才可见 —— 恢复端点会如实
// 报告这一点。
func replaceDatabase(src, dest string) error {
in, err := os.Open(src)
if err != nil {
@@ -260,8 +260,8 @@ func replaceDatabase(src, dest string) error {
return nil
}
// escapeSQLString doubles any single quote so a filename can be safely embedded
// in a SQL string literal for VACUUM INTO.
// escapeSQLString 把每个单引号翻倍,使文件名能安全地嵌入
// 供 VACUUM INTO 使用的 SQL 字符串字面量。
func escapeSQLString(s string) string {
return strings.ReplaceAll(s, "'", "''")
}