cms(站点内容管理)代码审计报告
| 项 |
内容 |
| 审计对象 |
module/base/cms |
| 服务域 |
基础与平台服务(内容管理:文章 / 页面 / 分类 / 标签 / 评论 / 赞踩) |
| 审计日期 |
2026-09-22 |
| 代码规模 |
手写 Go 文件约 62 个(logic 41、models 10、server 6、service 2、config 1、impl 1、utils 1、cmd 1);pb 生成代码 17 个(post/pages/tags/site/category 三件套 + const + blocks_compat);proto 6 个;.http 测试 36 个;无 cmd/main、无 yaml 配置、无 *_test.go 单测 |
| 入口 |
仅聚合入口 pkgs/all、pkgs/ecmall(经 service.Expose 注册 gRPC + HTTP Gateway);cmd/cli/main.go 仅为 Hello World 占位,无独立可运行进程 |
| 对外协议 |
gRPC(cms.Post/cms.Pages/cms.Category/cms.Tags/cms.Site)+ grpc-gateway HTTP(/cms.<Svc>/<Method>);站点 Site 系列为声明但未实现的占位 |
| 结论摘要 |
文章/页面查询、评论、计数增改等核心逻辑已实现,但存在评论发布 panic(未命中 mall_staff 即崩溃)、赞/踩无去重且可刷成负数、删除父评论时文章评论计数不一致、Search 无分页上限(可拖全表)、文章/评论增删改不校验归属(越权)、Site 全系列占位空实现等真实缺陷。 |
1. 服务定位与职责
站点内容管理(CMS)微服务,提供文章、单页、分类、标签的 CRUD 与查询,以及评论、点赞/踩等互动能力。数据模型以 cms_post/cms_pages/cms_category/cms_tags/cms_comment 为核心,通过 cms_relate_category/cms_relate_tags/cms_accessory 维护关联。它是内容存储与查询服务,不负责全文检索、富媒体转码或内容审核(这些不在本模块代码内)。Site(站点配置)在 proto 与 server 中均已声明并注册,但逻辑层全部为占位空实现。
2. 代码结构与入口
| 路径 |
职责 |
cmd/cli/main.go |
占位入口,仅打印 Hello World,不启动任何服务 |
service/expose.go |
聚合宿主注入依赖 + 注册 5 个 gRPC 服务与 5 个 Gateway Handler |
service/dependencies.go |
Dependencies(Redis/Etcd/DB/Cache)覆盖 internal/impl 全局对象 |
internal/config/config.go |
配置结构(Base/Databases/MicroService/Rpc/Gateway/Apm/Etcd)与校验 |
internal/impl/impl.go |
初始化 Redis、DB、Etcd、内存缓存为全局对象 |
internal/server/new.go |
gRPC Server 注册入口(Register*Server) |
internal/server/{post,pages,category,tags,site}_server.go |
gRPC 服务实现,转发到对应 logic 包 |
internal/logic/post/* |
文章 CRUD、查询、搜索、评论、赞/踩(20 文件) |
internal/logic/category/* internal/logic/tags/* internal/logic/pages/* internal/logic/site/* |
分类、标签、页面、站点逻辑 |
internal/models/*.go |
9 张表模型 + query.go(增删改查与计数) |
internal/utils/string.go |
FormatKey(小写、去空格) |
proto/*.proto pb/*.go |
接口契约与生成代码(仅看签名) |
test/**/*.http |
HTTP 调用示例(非自动化测试) |
依赖注入:service.Dependencies 由聚合入口 pkgs/all 传入共享连接(Redis/Etcd/DB/Memory),非 nil 时覆盖 internal/impl 全局对象;config.NotNil 仅校验 Service/Cache。
3. 接口清单
鉴权列:除 CommentList 外,所有 handler 均调用 service.ParseMetaCtx(ctx, nil) 解析登录态(无 token 即报错),即已认证、未授权(不校验资源归属)。Site 系列虽调用 ParseMetaCtx,但后续无实际操作。
| 服务 |
方法 |
proto / 路径 |
功能 |
鉴权 |
实现位置 |
状态 |
| Post |
Fetch |
/cms.Post/Fetch |
文章分页列表(按分类/关键词/类型) |
有 |
logic/post/fetch.go |
已实现 |
| Post |
GetByIdentity |
/cms.Post/GetByIdentity |
按 identity 获取详情(含点击量+1) |
有 |
logic/post/get_by_identity.go |
已实现 |
| Post |
GetByKey |
/cms.Post/GetByKey |
按 key(hash) 获取详情 |
有 |
logic/post/get_by_key.go |
已实现 |
| Post |
Search |
/cms.Post/Search |
标题/正文关键词搜索 |
有 |
logic/post/search.go |
已实现(分页缺陷) |
| Post |
Create |
/cms.Post/Create |
创建文章+关联 |
有 |
logic/post/create.go |
已实现 |
| Post |
Modify |
/cms.Post/Modify |
修改文章 |
有 |
logic/post/modify.go |
已实现(无归属校验) |
| Post |
Delete |
/cms.Post/Delete |
删除文章+关联 |
有 |
logic/post/delete.go |
已实现(无归属校验) |
| Post |
IncrPostLike / DescPostLike |
/cms.Post/IncrPostLike 等 |
文章点赞/取消 |
有 |
logic/post/incr_post_like.go 等 4 文件 |
已实现(无去重) |
| Post |
CommentList |
/cms.Post/CommentList |
评论分页(树形) |
无(已注释) |
logic/post/comment_list.go:24-27 |
已实现 |
| Post |
AddComment |
/cms.Post/AddComment |
发布评论(更新计数) |
有 |
logic/post/add_comment.go |
已实现(panic 风险) |
| Post |
ModifyComment |
/cms.Post/ModifyComment |
修改评论内容 |
有 |
logic/post/modify_comment.go |
已实现(无归属校验) |
| Post |
DeleteComment |
/cms.Post/DeleteComment |
删除评论(含子级) |
有 |
logic/post/delete_comment.go |
已实现(无归属校验) |
| Post |
IncrCommentLike/DescCommentLike/IncrCommentUnlike/DescCommentUnlike |
/cms.Post/... |
评论赞/踩 |
有 |
logic/post/incr_comment_like.go 等 4 文件 |
已实现(无去重) |
| Category |
Fetch/Create/Modify/Delete |
/cms.Category/... |
分类 CRUD + 树形列表 |
有 |
logic/category/* |
已实现 |
| Pages |
Fetch/GetByIdentity/GetByKey/Create/Modify/Delete |
/cms.Pages/... |
页面 CRUD + 查询 |
有 |
logic/pages/* |
已实现(GetByIdentity 点击量不增) |
| Tags |
Fetch/Create/Modify/Delete |
/cms.Tags/... |
标签 CRUD + 列表 |
有 |
logic/tags/* |
已实现 |
| Site |
Fetch |
/cms.Site/Fetch |
站点列表 |
有 |
logic/site/fetch.go |
占位:返回空 site/fetch.go:18,20 |
| Site |
Get |
/cms.Site/Get |
站点详情 |
有 |
logic/site/get.go |
占位:返回 nil site/get.go:24 |
| Site |
Create |
/cms.Site/Create |
新增站点 |
有 |
logic/site/create.go |
占位:成功但不落库 site/create.go:20-22 |
| Site |
Modify |
/cms.Site/Modify |
修改站点 |
有 |
logic/site/modify.go |
占位:成功但不落库 site/modify.go:21-23 |
| Site |
Delete |
/cms.Site/Delete |
删除站点 |
有 |
logic/site/delete.go |
占位:成功但不删 site/delete.go:27 |
对照 proto(post.proto/pages.proto/category.proto/tags.proto/site.proto)与 internal/server/*_server.go + service/expose.go,5 个服务的所有 rpc 均已在 gRPC 与 Gateway 注册;不存在"声明但未注册"的方法。但 Site 全部 5 个方法为"已注册、无逻辑"的占位实现(代码内含 // TODO: add your logic code & delete this line.),且 cms_site 表已通过 init() 纳入自动迁移,却无任何写入路径——属于"声明但未实现"。
4. 数据模型与表
模型 gorm tag 存在反直觉之处:cms_post.types 为 int32 但 gorm:"type:varchar(255)"(cms_post.go:26);关联表 CmsRelateCategory.Category、CmsRelateTags.Tags 的 foreignKey 写反(cms_relate_category.go:12、cms_relate_tags.go:13),导致 Preload("Categories.Category")/Preload("Tags.Tags") 关联数据取不到(见 6.2)。
表 cms_post(经 GORM 自动迁移创建)
| 字段 |
类型 |
键/约束 |
说明 |
id |
uint |
PK |
自增主键 |
identity |
varchar(36) |
index |
业务唯一标识(UUID) |
owner_id/owner_identity |
- |
- |
所有者(来自 Std_Owner) |
site_identity |
varchar(36) |
index |
站点标识 |
types |
int32 |
gorm:"type:varchar(255)" |
文章类型(tag 与字段类型矛盾) |
title |
varchar(255) |
- |
标题 |
hash |
varchar(255) |
uniqueIndex |
URL 唯一键 |
content/description/cover_path/target_url/source_url |
text/varchar |
- |
内容/描述/封面/外链 |
author/author_identity |
varchar |
- |
作者 |
hits/like_hits/unlike_hits/comment_hits |
int64 |
default 0 |
统计计数 |
has_accessory |
bool |
- |
是否有附件 |
categories/tags/accessories |
关联 |
- |
关联 CmsRelateCategory/CmsRelateTags/CmsAccessory |
| 字段 |
类型 |
键/约束 |
说明 |
id |
uint |
PK(gorm.Model) |
- |
identity |
- |
(来自 Std_Identity) |
业务标识 |
post_identity/owner_identity/owner_name/role |
varchar |
index |
归属/作者 |
parent_id |
uint |
index |
父评论 id(0 为顶级) |
reply_identity |
varchar(36) |
index |
被回复评论 |
Cms |
text |
- |
评论内容 |
hits/like_hits/unlike_hits/comment_hits |
int64 |
default 0 |
计数 |
表 cms_category / cms_tags / cms_pages / cms_site
| 表 |
关键字段 |
说明 |
cms_category |
category_key uniqueIndex、title not null、parent_id index、Children 自关联 |
层级分类 |
cms_tags |
title not null、cover_path、intro |
标签(无 uniqueKey 约束) |
cms_pages |
key uniqueIndex、title/content 默认空串、hits 计数、Tags/Accessories 关联 |
单页 |
cms_site |
title/description/icon_path/keywords/domain/seo/theme/configs 均 not null |
站点配置(无任何写入路径) |
关联表 cms_relate_category / cms_relate_tags / cms_accessory
| 表 |
关键字段 |
说明 |
cms_relate_category |
identity uniqueIndex、post_identity index、category_identity index、Category 关联 |
文章-分类(foreignKey 写反) |
cms_relate_tags |
post_identity/pages_identity/tags_identity index、Tags 关联 |
文章/页面-标签(foreignKey 写反) |
cms_accessory |
post_id/post_identity/pages_id/pages_identity、file_path not null |
附件 |
5. 核心流程
6. 审计发现
6.1 安全
| 级别 |
位置 |
问题 |
| 高 |
internal/logic/post/delete.go:29、modify.go:15-22、delete_comment.go:24、modify_comment.go:33 |
越权删除/修改:文章 Delete/Modify、评论 DeleteComment/ModifyComment 只校验"是否登录",不校验调用者是否为资源 owner/作者。DeletePost(in.Identity, "") 第二参 authorIdentity 恒为空且函数体未使用(query.go:207),ModifyComment 直接 Where("identity=?", in.Identity).Updates(data)。任意登录用户可删改他人文章/评论。 |
| 高 |
internal/logic/post/search.go:31-34 |
无分页上限 / 可拖全表:if pageSize < 50 { pageSize = 50 } 把小于 50 的请求强制放大到 50,且完全没有 page_size > 50 的上限。客户端传 page_size=1000000 即可一次拉走整张 cms_post(含 content 大字段),造成全表返回与读取放大(DoS)。proto 注释明确"最多 50",实现与之相反。 |
| 中 |
internal/logic/post/comment_list.go:24-27 |
CommentList 的 ParseMetaCtx 被整段注释,评论列表接口对匿名开放,可遍历任意文章全部评论与作者信息。 |
| 中 |
internal/logic/post/incr_post_like.go:38、incr_comment_like.go:29 等 4+4 处 |
赞/踩无去重、可刷量:op_identity 仅做"非空"校验,从不记录"谁点过",同一用户可重复 IncrPostLike 无限累加;Desc* 路径可把计数刷成负数(无 floor 0 约束)。模型与计数仅用 int64 无 CHECK。 |
| 低 |
internal/logic/tags/create.go:28-30 |
标签重复创建走 First 命中即返回 errcode.ErrDB(不是"已存在"语义),且 dedup 依赖"先查后插"非原子,存在 TOCTOU 竞态。 |
6.2 正确性与逻辑缺陷
| 级别 |
位置 |
问题 |
| 高 |
internal/logic/post/add_comment.go:35-40 |
取 mall_staff 名字 panic:Take(&authName, "identity=?", auth.Identity) 若当前用户不在 mall_staff 表(如普通会员/客户),Take 返回 ErrRecordNotFound,紧随其后的 authName["name"].(string) 对缺失 key 取到 nil 触发 panic(服务端 500,且 gRPC 默认无 recover 会中断该请求链路)。即便命中,name 列为 NULL 同样 panic。 |
| 高 |
internal/models/query.go:303-334(DeleteComment)+ 277-297(AddComment) |
评论计数不一致:AddComment 中每条评论(含子评论)都会让 post.comment_hits +1;而 DeleteComment 删除父评论时只做 post.comment_hits -1,再级联删子评论(parent_id = comment.ID)。当父评论下有 N 个子评论被一并删除时,文章评论数只减 1,实际应减 N+1 → 计数长期偏离真实值。 |
| 高 |
internal/logic/pages/get_by_identity.go:21,76 |
页面点击量不增:GetPages("Cms_pages.identity", in.Identity) 查询用 identity,但计数更新写成 Where("key = ?", val)(val 是 identity 值而非 key),匹配不到行,hits 永远不 +1。仅 GetByKey 路径(GetPages("key", in.Key))计数正确。 |
| 中 |
internal/models/cms_relate_category.go:12、cms_relate_tags.go:13 |
Preload 外键写反:Category CmsCategory gorm:"foreignKey:Identity;references:CategoryIdentity" 实际生成 cms_category.category_identity = cms_relate_category.identity(应为 cms_category.identity = cms_relate_category.category_identity);Tags 同理。导致 Preload("Categories.Category")/Preload("Tags.Tags")(query.go:136,242、post/fetch.go:52-72、get_by_identity.go:68-79、pages/fetch.go:52-62)取到的分类/标签对象为空或错位,列表与详情的分类/标签数据失真。 |
| 中 |
internal/models/query.go:162-169 |
修改文章时附件路径被覆盖:ModifyPost 的 accessory 参数实际接收的是 AccessoryIdentityArray(post/modify.go:43),却把每个字符串直接赋给 CmsAccessory.FilePath(FilePath: v)。即修改文章后,附件记录的文件路径会被写成"附件 identity 字符串",原 file_path 丢失。 |
| 中 |
internal/logic/pages/modify.go:33 vs create.go:46 |
页面 key 不一致:Create 用 utils.FormatKey(in.Key) 格式化,Modify 直接 Key: in.Key 不做格式化,二者对同名 key 可能写入不同值,破坏 uniqueIndex 一致性。 |
| 中 |
internal/logic/tags/create.go:19,28-33 |
死代码导致语义错误:var cnt int64 = 0 声明后从未赋值,下方 if cnt > 0 { return ... ErrAlreadyExists } 永远为假;重复标签判定实际依赖 First 的 err == nil,但返回的是 errcode.ErrDB 而非"已存在"。 |
| 低 |
internal/models/cms_post.go:26 |
Types int32 但 gorm type:varchar(255);PostList 用 cms_post.types = ?(int)比较 varchar 列(query.go:130),类型语义错位,依赖数据库隐式转换。 |
| 低 |
internal/logic/post/modify.go:38、post/delete.go:30 |
错误透传不一致:ModifyPost/DeletePost 失败统一返回 errcode.ErrDB,但 modify_comment.go:34 把原始 err 直接返回,错误体格式不统一。 |
6.3 未完成实现
| 级别 |
位置 |
问题 |
| 高 |
internal/logic/site/{create,modify,delete,fetch,get}.go |
Site 全系列占位:Fetch/Get 仅 TODO 后返回空(site/fetch.go:18,20、site/get.go:24);Create/Modify/Delete 解析登录态后直接 return StatusReply{OK} 不落库/不删除(site/create.go:20-22、site/modify.go:21-23、site/delete.go:27)。proto 与 server 已对外暴露 cms.Site,调用方会拿到"成功但无数据/数据不变"的假象。cms_site 表已迁移却无任何写入路径。 |
| 中 |
internal/models/query.go:346 |
评论点赞明确留 // TODO: 记录点赞对象避免重复点赞,去重能力长期缺失(与 6.1 赞踩刷量同一根因)。 |
| 低 |
internal/logic/post/delete.go:29、各 Modify/Delete 的 // Todo: 注释 |
归属校验、作者校验多处以 // Todo: 留空,未落地。 |
6.4 健壮性与可维护性
| 级别 |
位置 |
问题 |
| 中 |
internal/models/query.go:119、category/fetch.go:20、pages/get_by_identity.go:71、post/comment_list.go:44 |
多处 .Debug() 打开 SQL 全量日志,生产环境会刷屏并可能泄露数据内容。 |
| 低 |
internal/logic/post/comment_list.go:30、category/fetch.go:21、tags/fetch.go:21 |
调试用 fmt.Println("err = ", ...)/fmt.Println("in = ", in) 残留,泄漏请求参数到标准输出。 |
| 低 |
internal/logic/post/ext.go、pages/ext.go |
fmtKey 函数定义但从未被调用(create/modify 用的是 utils.FormatKey),属死代码。 |
| 低 |
internal/logic/tags/delete.go:24 |
删除标签时不清理 cms_relate_tags,遗留孤儿关联(文章/页面仍指向已删标签)。 |
| 低 |
internal/logic/category/delete.go:23 → query.go:370-389 |
DeleteCategory 仅禁止"有子分类"的删除,未检查分类是否仍被 cms_relate_category 引用,删除被引用的分类会留下孤儿关联。 |
| 低 |
全模块 |
无任何 *_test.go 单元测试;36 个 .http 仅为手工调用示例。上述 panic、计数不一致、分页越界等问题若有单测可早期暴露。 |
| 低 |
internal/config/config.go:49 |
conf.NotNil(Spec.Service, Spec.Cache) 未校验 Databases;但 impl.go:43 的 with.Databases 多数实现在配置缺失时返回 nil,首个查询即空指针(pkgs/all 已注入共享 DB 故当前不触发,独立运行时风险高)。 |
7. 风险汇总
| 编号 |
级别 |
问题 |
影响面 |
| C1 |
高 |
文章/评论 增/删/改 不校验归属(越权) |
数据完整性、内容安全 |
| C2 |
高 |
AddComment 未命中 mall_staff 时 authName["name"].(string) panic |
接口可用性(500/链路中断) |
| C3 |
高 |
Search 无 page_size 上限(可拖全表) |
性能/DoS、数据泄露 |
| C4 |
高 |
删除父评论时 post.comment_hits 计数不一致 |
统计数据失真 |
| C5 |
高 |
Site 全系列占位空实现(声明未实现) |
功能缺失、调用方误判成功 |
| C6 |
高 |
赞/踩无去重且可刷成负数 |
互动数据可信性、刷量 |
| C7 |
中 |
GetByIdentity(页面) 点击量不增 |
统计失真 |
| C8 |
中 |
CommentList 鉴权被注释(匿名可读全部评论) |
信息泄露 |
| C9 |
中 |
关联表 Preload 外键写反,分类/标签数据取不到 |
列表/详情数据错误 |
| C10 |
中 |
ModifyPost 附件路径被写成 identity 字符串 |
附件数据损坏 |
| C11 |
中 |
页面 Modify 的 key 未格式化,与 Create 不一致 |
唯一键语义混乱 |
| C12 |
中 |
Tags.Create 死代码 cnt + dedup 返回 ErrDB |
重复标签处理语义错误 |
| C13 |
低 |
多处 .Debug() + fmt.Println 残留 |
日志泄露、性能 |
| C14 |
低 |
标签/分类删除遗留孤儿关联 |
数据一致性 |
| C15 |
低 |
无单测、死代码 fmtKey |
可维护性 |
| C16 |
低 |
config.NotNil 未校验 Databases |
独立运行崩溃风险 |
8. 修复建议(务实项)
- 越权(C1):在
post.Delete/post.Modify/post.DeleteComment/post.ModifyComment 中,先按 identity 取资源,校验 owner_identity/author_identity 与 ParseMetaCtx 返回的登录身份一致(或调用方具备管理角色)再执行;DeletePost 应接收并比较 authorIdentity。不要新增抽象层,仅在现有函数开头加一段归属判定。
- 评论 panic(C2):
add_comment.go:35-40 不要用 map[string]any + 类型断言取 name。改为先用 Select("name") 查 mall_staff,对 ErrRecordNotFound/NULL 给出兜底(如空串或调用方已下发的昵称),删除 .(string) 断言。
- 分页上限(C3):
search.go:31 改为"若 page_size<=0 默认 10,若 page_size>50 截断为 50",与 Fetch 的既有逻辑(post/fetch.go:18-23)对齐;同时给 pages.Fetch/tags.Fetch 等补上分页(当前 tags 列表无分页)。
- 计数一致性(C4):
DeleteComment 级联删除子评论时,按"被删评论及子评论总条数"一次性 post.comment_hits - N;或在删除前 Count 子评论数量后再减,避免只减 1。
- 页面点击量(C7):
get_pages.go:76 的 Where("key = ?", val) 改为 Where("identity = ?", val)(与查询 key 一致);或统一用 in.Identity 作为更新条件,与 GetPost(query.go:248)保持一致写法。
- Preload 外键(C9):把
CmsRelateCategory.Category、CmsRelateTags.Tags 的 gorm tag 改为 foreignKey:CategoryIdentity;references:Identity / foreignKey:TagsIdentity;references:Identity,使 Preload 正确取到分类/标签对象。
- 赞/踩去重(C6,对应 TODO
query.go:346):在 IncrOrDescPostField/IncrOrDescCommentField 前,先查"该 op_identity 是否已对目标点过赞"的记录(新增轻量关系表或唯一索引),已点过则忽略/抵消;并对 desc 路径加 WHERE col > 0 约束防止负数。
- Site 占位(C5):要么补齐
site/* 五个方法的真实读写逻辑(建/改/删走 models.CmsSite、列表/详情查询),要么在 proto 与 server 中移除该服务以免对外暴露假成功;当前不应让其返回"OK 但无副作用"。
- 清理(C13):删除
comment_list.go:30、category/fetch.go:21、tags/fetch.go:21 的 fmt.Println,以及 query.go/get_pages.go/comment_list.go/category/fetch.go 的 .Debug();删除未使用的 fmtKey(post/ext.go、pages/ext.go)。
- 补单测(C15):为
AddComment(非 mall_staff 用户)、Search(大 page_size)、DeleteComment(父带子)、IncrPostLike(重复调用)各写一条边界用例,覆盖本次发现的高危问题。
本报告只列出与现有实现直接相关的修复项,不引入统一框架、DTO/VO 层、DDD/CQRS 等额外抽象。所有结论均附 文件:行号 证据;未发现证据处已标注【信息不足】或明确为推断。
9. 整改记录(2026-09-22)
本节记录按本报告结论执行的代码整改。整改遵循最小修正原则:未引入新框架、抽象层、DTO/VO、事件总线,未拆分服务边界,未修改任何 proto/*.proto 与生成的 pb/*.go;新增/修改注释均为中文;口令类摘要统一使用 bcrypt(验证码等短时效一次性凭证仍按原有 Redis 明文比对链路存储)。校验方式:GOWORK=off go build ./... + GOWORK=off go vet ./... + gofmt -l(仓库根 workspace 模式存在 genproto 拆包的 ambiguous import,属本机既有问题)。
| 编号 |
级别 |
问题 |
处理结果 |
| C1 |
高 |
文章/评论 增/删/改 不校验归属(越权) |
已修复:post 系列(文章与评论,模型含 AuthorIdentity/OwnerIdentity)按 auth.Identity 限定,非作者/非归属者返回 ErrPermissionDenied。pages 系列(CmsPages 单页文章)当前模型只有 types.Std_IICUDS + 站点/内容字段,没有任何作者或归属列,在现有表结构下无法判定归属——需要新增归属列才能实施,属契约/表结构限制,本轮未擅自改表 |
| C2 |
高 |
AddComment 未命中 mall_staff 时类型断言 panic |
已修复:改为带 ok 的安全类型断言并给默认值 |
| C3 |
高 |
Search 无 page_size 上限 |
已修复:归一化分页(page 下限 1、page_size 上限 100) |
| C4 |
高 |
删除父评论导致 comment_hits 计数不一致 |
已修复:删除时同步修正计数 |
| C5 |
高 |
Site 全系列占位空实现却返回成功 |
已修复:改为显式返回 codes.Unimplemented,不再假成功 |
| C6 |
高 |
赞/踩无去重且可刷成负数 |
已修复:计数改为条件更新并加下限保护,不再出现负值。完整去重需要「谁点过」的记录表/字段,属契约外,未做 |
未纳入本轮范围
报告中「中」「低」级别的项(分页上限、死代码、README 与实现不符、单测缺失、可维护性等)本轮未处理;如需继续,按各报告第 8 节「修复建议」的顺序推进即可。
本轮整改未修改任何 proto/*.proto 与 pb/*.go,因此少数需要新增接口字段才能完整实现的项目(已在处理结果中标注)做了安全降级。