style(project): silence remaining lint findings (stutter, max shadow, gosec)

This commit is contained in:
2026-05-01 10:33:16 +08:00
parent 76a1461f4b
commit 1567f21a82
4 changed files with 23 additions and 20 deletions
+7 -1
View File
@@ -17,6 +17,7 @@ import (
// 字符串常量保持与 DB CHECK 约束一致。 // 字符串常量保持与 DB CHECK 约束一致。
type Phase string type Phase string
// 五阶段枚举值,与 migrations/0002 的 CHECK 约束完全一致。
const ( const (
PhasePlanning Phase = "planning" PhasePlanning Phase = "planning"
PhaseAuditing Phase = "auditing" PhaseAuditing Phase = "auditing"
@@ -41,6 +42,7 @@ func (p Phase) IsValid() bool {
// Status 是 Requirement / Issue 通用的开/关状态。 // Status 是 Requirement / Issue 通用的开/关状态。
type Status string type Status string
// 开/关状态枚举值,与 DB CHECK 约束一致。
const ( const (
StatusOpen Status = "open" StatusOpen Status = "open"
StatusClosed Status = "closed" StatusClosed Status = "closed"
@@ -50,6 +52,7 @@ const (
// internal 所有登录用户可读;写权限两者都仅限 owner+admin。 // internal 所有登录用户可读;写权限两者都仅限 owner+admin。
type Visibility string type Visibility string
// 可见性枚举值,与 DB CHECK 约束一致。
const ( const (
VisibilityPrivate Visibility = "private" VisibilityPrivate Visibility = "private"
VisibilityInternal Visibility = "internal" VisibilityInternal Visibility = "internal"
@@ -111,7 +114,10 @@ type Caller struct {
IsAdmin bool IsAdmin bool
} }
// ProjectService 暴露 Project 聚合根的应用服务方法。 // ProjectService 暴露 Project 聚合根的应用服务方法。包内有三个并列服务
// (Project/Requirement/Issue),这里保留聚合名前缀以避免歧义。
//
//nolint:revive // 名字带聚合根前缀比 "Service" 更准确:包里有 3 个并列服务接口
type ProjectService interface { type ProjectService interface {
Create(ctx context.Context, c Caller, in CreateProjectInput) (*Project, error) Create(ctx context.Context, c Caller, in CreateProjectInput) (*Project, error)
Get(ctx context.Context, c Caller, slug string) (*Project, error) Get(ctx context.Context, c Caller, slug string) (*Project, error)
+3 -3
View File
@@ -45,7 +45,7 @@ func assertReadable(p *Project, c Caller) error {
// assertWritable 是 write 类操作的鉴权门面:仅 owner+admin。已归档项目额外 // assertWritable 是 write 类操作的鉴权门面:仅 owner+admin。已归档项目额外
// 拒绝;调用方应在执行写入前调用此函数。 // 拒绝;调用方应在执行写入前调用此函数。
func assertWritable(p *Project, c Caller) error { func assertWritable(p *Project, c Caller) error {
if !(c.IsAdmin || p.OwnerID == c.UserID) { if !c.IsAdmin && p.OwnerID != c.UserID {
// stranger 对 private 看不见;对 internal 也不能写。统一 not_found 防探测。 // stranger 对 private 看不见;对 internal 也不能写。统一 not_found 防探测。
if p.Visibility == VisibilityPrivate { if p.Visibility == VisibilityPrivate {
return errs.New(errs.CodeNotFound, "project 不存在") return errs.New(errs.CodeNotFound, "project 不存在")
@@ -148,7 +148,7 @@ func (s *projectService) Archive(ctx context.Context, c Caller, slug string) err
return err return err
} }
// 归档/取消归档仍要 owner+admin 校验,但已归档不再额外阻塞 archive。 // 归档/取消归档仍要 owner+admin 校验,但已归档不再额外阻塞 archive。
if !(c.IsAdmin || p.OwnerID == c.UserID) { if !c.IsAdmin && p.OwnerID != c.UserID {
if p.Visibility == VisibilityPrivate { if p.Visibility == VisibilityPrivate {
return errs.New(errs.CodeNotFound, "project 不存在") return errs.New(errs.CodeNotFound, "project 不存在")
} }
@@ -169,7 +169,7 @@ func (s *projectService) Unarchive(ctx context.Context, c Caller, slug string) e
if err != nil { if err != nil {
return err return err
} }
if !(c.IsAdmin || p.OwnerID == c.UserID) { if !c.IsAdmin && p.OwnerID != c.UserID {
if p.Visibility == VisibilityPrivate { if p.Visibility == VisibilityPrivate {
return errs.New(errs.CodeNotFound, "project 不存在") return errs.New(errs.CodeNotFound, "project 不存在")
} }
+10 -13
View File
@@ -120,13 +120,13 @@ func (r *fakeRepo) UnarchiveProject(_ context.Context, id uuid.UUID) error {
// ===== Requirement ===== // ===== Requirement =====
func (r *fakeRepo) nextRequirementNumber(projectID uuid.UUID) int { func (r *fakeRepo) nextRequirementNumber(projectID uuid.UUID) int {
max := 0 maxNum := 0
for _, x := range r.requirements { for _, x := range r.requirements {
if x.ProjectID == projectID && x.Number > max { if x.ProjectID == projectID && x.Number > maxNum {
max = x.Number maxNum = x.Number
} }
} }
return max + 1 return maxNum + 1
} }
func (r *fakeRepo) CreateRequirement(_ context.Context, in *Requirement) (*Requirement, error) { func (r *fakeRepo) CreateRequirement(_ context.Context, in *Requirement) (*Requirement, error) {
@@ -235,13 +235,13 @@ func (r *fakeRepo) ReopenRequirement(_ context.Context, id uuid.UUID) error {
// ===== Issue ===== // ===== Issue =====
func (r *fakeRepo) nextIssueNumber(projectID uuid.UUID) int { func (r *fakeRepo) nextIssueNumber(projectID uuid.UUID) int {
max := 0 maxNum := 0
for _, x := range r.issues { for _, x := range r.issues {
if x.ProjectID == projectID && x.Number > max { if x.ProjectID == projectID && x.Number > maxNum {
max = x.Number maxNum = x.Number
} }
} }
return max + 1 return maxNum + 1
} }
func (r *fakeRepo) CreateIssue(_ context.Context, in *Issue) (*Issue, error) { func (r *fakeRepo) CreateIssue(_ context.Context, in *Issue) (*Issue, error) {
@@ -280,17 +280,14 @@ func (r *fakeRepo) ListIssues(_ context.Context, projectID uuid.UUID, filter Iss
continue continue
} }
if filter.Requirement != nil { if filter.Requirement != nil {
switch { if *filter.Requirement == 0 {
case *filter.Requirement == 0:
if x.RequirementID != nil { if x.RequirementID != nil {
continue continue
} }
default: } else if x.RequirementID == nil || *x.RequirementID != *requirementID {
if x.RequirementID == nil || *x.RequirementID != *requirementID {
continue continue
} }
} }
}
if filter.AssigneeID != nil { if filter.AssigneeID != nil {
if x.AssigneeID == nil || *x.AssigneeID != *filter.AssigneeID { if x.AssigneeID == nil || *x.AssigneeID != *filter.AssigneeID {
continue continue
+2 -2
View File
@@ -232,7 +232,7 @@ func (r *pgRepo) CreateRequirement(ctx context.Context, in *Requirement) (*Requi
func (r *pgRepo) GetRequirementByNumber(ctx context.Context, projectID uuid.UUID, number int) (*Requirement, error) { func (r *pgRepo) GetRequirementByNumber(ctx context.Context, projectID uuid.UUID, number int) (*Requirement, error) {
row, err := r.q.GetRequirementByNumber(ctx, projectsqlc.GetRequirementByNumberParams{ row, err := r.q.GetRequirementByNumber(ctx, projectsqlc.GetRequirementByNumberParams{
ProjectID: toPgUUID(projectID), ProjectID: toPgUUID(projectID),
Number: int32(number), Number: int32(number), //nolint:gosec // number 来自 service 层 number int 字段,原值即来自 DB int32,溢出不可达
}) })
if err != nil { if err != nil {
if errors.Is(err, pgx.ErrNoRows) { if errors.Is(err, pgx.ErrNoRows) {
@@ -364,7 +364,7 @@ func (r *pgRepo) CreateIssue(ctx context.Context, in *Issue) (*Issue, error) {
func (r *pgRepo) GetIssueByNumber(ctx context.Context, projectID uuid.UUID, number int) (*Issue, error) { func (r *pgRepo) GetIssueByNumber(ctx context.Context, projectID uuid.UUID, number int) (*Issue, error) {
row, err := r.q.GetIssueByNumber(ctx, projectsqlc.GetIssueByNumberParams{ row, err := r.q.GetIssueByNumber(ctx, projectsqlc.GetIssueByNumberParams{
ProjectID: toPgUUID(projectID), ProjectID: toPgUUID(projectID),
Number: int32(number), Number: int32(number), //nolint:gosec // 同上:number 原始来自 DB int32
}) })
if err != nil { if err != nil {
if errors.Is(err, pgx.ErrNoRows) { if errors.Is(err, pgx.ErrNoRows) {