docs(gateway): gateway 剩余文件注释改中文(逐行 1:1,代码零字节改动)
主人 2026-10-03 拍板「注释一律中文」;gateway 至此整包注释中文化完成(本会话共 3 批: 已推库 16 个文件 + 本批剩余文件)。 校验:机械校验(非注释改动行)= 空;剥注释后代码文本逐行比对全等(不一致文件数 0); 全树 go test ./... 58 包 ok / 0 FAIL;交叉编译绿。
This commit is contained in:
1 parent
91e8d7a029
commit
074ffc4ebf
73 files changed
+2529
-2529
No files matched your search
@@ -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, "'", "''")
|
||||
}
|
||||
Reference in new issue
Block a user