detached 8aa547e

chore(hexcheck): bump to v0.4.0 and drop unused ignore directives

Remove the 89 ignore directives v0.4.0 reports as unused, annotate its 16 new findings, and state plainly in the remaining reasons which functions hold business rules pending a move to domain or usecase.
commit
8aa547e07ea278c9bb3e409a597c0899e2750235
author
brice · · 2026-10-19 19:11 UTC
parent
70c00ad
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
checks
4/4
57 files · +51 -183
M go.mod +1 -1
@@ -64,7 +64,7 @@ require (
6464 github.com/bep/godartsass/v2 v2.5.0 // indirect
6565 github.com/bep/golibsass v1.2.0 // indirect
6666 github.com/bits-and-blooms/bitset v1.24.5 // indirect
67- github.com/bnema/hexcheck v0.3.1 // indirect
67+ github.com/bnema/hexcheck v0.4.0 // indirect
6868 github.com/brunoga/deep v1.3.1 // indirect
6969 github.com/bufbuild/buf v1.73.0 // indirect
7070 github.com/bufbuild/protocompile v0.14.2-0.20260910151042-7436f7c76201 // indirect
@@ -64,7 +64,7 @@ require (
64 github.com/bep/godartsass/v2 v2.5.0 // indirect64 github.com/bep/godartsass/v2 v2.5.0 // indirect
65 github.com/bep/golibsass v1.2.0 // indirect65 github.com/bep/golibsass v1.2.0 // indirect
66 github.com/bits-and-blooms/bitset v1.24.5 // indirect66 github.com/bits-and-blooms/bitset v1.24.5 // indirect
67- github.com/bnema/hexcheck v0.3.1 // indirect67+ github.com/bnema/hexcheck v0.4.0 // indirect
68 github.com/brunoga/deep v1.3.1 // indirect68 github.com/brunoga/deep v1.3.1 // indirect
69 github.com/bufbuild/buf v1.73.0 // indirect69 github.com/bufbuild/buf v1.73.0 // indirect
70 github.com/bufbuild/protocompile v0.14.2-0.20260910151042-7436f7c76201 // indirect70 github.com/bufbuild/protocompile v0.14.2-0.20260910151042-7436f7c76201 // indirect
M go.sum +2 -2
@@ -108,8 +108,8 @@ github.com/bits-and-blooms/bitset v1.24.5 h1:654xBVHc23gJMAgOTkPNoCVfiRxuIOAUnAZ
108108 github.com/bits-and-blooms/bitset v1.24.5/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
109109 github.com/bmatcuk/doublestar/v4 v4.10.0 h1:zU9WiOla1YA122oLM6i4EXvGW62DvKZVxIe6TYWexEs=
110110 github.com/bmatcuk/doublestar/v4 v4.10.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
111-github.com/bnema/hexcheck v0.3.1 h1:Apv7w0KmsfbOBOq/r1jPlENX3Z7ukAEPlAxvWMTTd3I=
112-github.com/bnema/hexcheck v0.3.1/go.mod h1:8KuFStFhn1qNKDBrUvxOB5VzSP/uuePrURqPhq2KVAk=
111+github.com/bnema/hexcheck v0.4.0 h1:VwzikMw5uCRvyf+FcI+O67TXovw7iwqvn7dSOUCJs7c=
112+github.com/bnema/hexcheck v0.4.0/go.mod h1:8KuFStFhn1qNKDBrUvxOB5VzSP/uuePrURqPhq2KVAk=
113113 github.com/bnema/kvconf v0.1.2 h1:1hDKL9jkQSBdR9dSKbwTONhUUBfJgAdh5vu+yFHOb70=
114114 github.com/bnema/kvconf v0.1.2/go.mod h1:+P2X9I/sLx+Lfir45s9a7WA0GnC22WgKbZWE9LK6lcU=
115115 github.com/bnema/zerowrap v1.4.1 h1:v70w8LDU2+FU+EX/etY9DjVwOAWN0fUKShwZyZHnyLU=
@@ -108,8 +108,8 @@ github.com/bits-and-blooms/bitset v1.24.5 h1:654xBVHc23gJMAgOTkPNoCVfiRxuIOAUnAZ
108 github.com/bits-and-blooms/bitset v1.24.5/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=108 github.com/bits-and-blooms/bitset v1.24.5/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
109 github.com/bmatcuk/doublestar/v4 v4.10.0 h1:zU9WiOla1YA122oLM6i4EXvGW62DvKZVxIe6TYWexEs=109 github.com/bmatcuk/doublestar/v4 v4.10.0 h1:zU9WiOla1YA122oLM6i4EXvGW62DvKZVxIe6TYWexEs=
110 github.com/bmatcuk/doublestar/v4 v4.10.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=110 github.com/bmatcuk/doublestar/v4 v4.10.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
111-github.com/bnema/hexcheck v0.3.1 h1:Apv7w0KmsfbOBOq/r1jPlENX3Z7ukAEPlAxvWMTTd3I=111+github.com/bnema/hexcheck v0.4.0 h1:VwzikMw5uCRvyf+FcI+O67TXovw7iwqvn7dSOUCJs7c=
112-github.com/bnema/hexcheck v0.3.1/go.mod h1:8KuFStFhn1qNKDBrUvxOB5VzSP/uuePrURqPhq2KVAk=112+github.com/bnema/hexcheck v0.4.0/go.mod h1:8KuFStFhn1qNKDBrUvxOB5VzSP/uuePrURqPhq2KVAk=
113 github.com/bnema/kvconf v0.1.2 h1:1hDKL9jkQSBdR9dSKbwTONhUUBfJgAdh5vu+yFHOb70=113 github.com/bnema/kvconf v0.1.2 h1:1hDKL9jkQSBdR9dSKbwTONhUUBfJgAdh5vu+yFHOb70=
114 github.com/bnema/kvconf v0.1.2/go.mod h1:+P2X9I/sLx+Lfir45s9a7WA0GnC22WgKbZWE9LK6lcU=114 github.com/bnema/kvconf v0.1.2/go.mod h1:+P2X9I/sLx+Lfir45s9a7WA0GnC22WgKbZWE9LK6lcU=
115 github.com/bnema/zerowrap v1.4.1 h1:v70w8LDU2+FU+EX/etY9DjVwOAWN0fUKShwZyZHnyLU=115 github.com/bnema/zerowrap v1.4.1 h1:v70w8LDU2+FU+EX/etY9DjVwOAWN0fUKShwZyZHnyLU=
M internal/adapters/cilogs/cilogs.go +2 -0
@@ -244,6 +244,8 @@ func (s *Store) Count(_ context.Context, ref ports.CILogRef) (int64, error) {
244244 }
245245
246246 // Read returns lines from line number from.
247+//
248+//hexcheck:ignore suspicious-business-logic-in-adapter reads a bounded snapshot of stored log lines using sparse offsets and maps missing or out-of-range reads to port errors
247249 func (s *Store) Read(_ context.Context, ref ports.CILogRef, from int64, maxLines, maxBytes int) ([]domain.CILogLine, error) {
248250 if !validRef(ref) || from < 0 {
249251 return nil, domain.ErrNotFound
@@ -244,6 +244,8 @@ func (s *Store) Count(_ context.Context, ref ports.CILogRef) (int64, error) {
244 }244 }
245 245
246 // Read returns lines from line number from.246 // Read returns lines from line number from.
247+//
248+//hexcheck:ignore suspicious-business-logic-in-adapter reads a bounded snapshot of stored log lines using sparse offsets and maps missing or out-of-range reads to port errors
247 func (s *Store) Read(_ context.Context, ref ports.CILogRef, from int64, maxLines, maxBytes int) ([]domain.CILogLine, error) {249 func (s *Store) Read(_ context.Context, ref ports.CILogRef, from int64, maxLines, maxBytes int) ([]domain.CILogLine, error) {
248 if !validRef(ref) || from < 0 {250 if !validRef(ref) || from < 0 {
249 return nil, domain.ErrNotFound251 return nil, domain.ErrNotFound
M internal/adapters/cisummaries/cisummaries.go +2 -0
@@ -56,6 +56,8 @@ func (s *Store) path(ref ports.CILogRef, step int32) string {
5656 }
5757
5858 // Put stores the summary of a step, or removes it when markdown is empty.
59+//
60+//hexcheck:ignore suspicious-business-logic-in-adapter validates storage coordinates and atomically writes a step summary, deleting its file when empty
5961 func (s *Store) Put(_ context.Context, ref ports.CILogRef, step int32, markdown string) error {
6062 if !validRef(ref) || step < 1 || step > domain.CIMaxSteps {
6163 return domain.ErrNotFound
@@ -56,6 +56,8 @@ func (s *Store) path(ref ports.CILogRef, step int32) string {
56 }56 }
57 57
58 // Put stores the summary of a step, or removes it when markdown is empty.58 // Put stores the summary of a step, or removes it when markdown is empty.
59+//
60+//hexcheck:ignore suspicious-business-logic-in-adapter validates storage coordinates and atomically writes a step summary, deleting its file when empty
59 func (s *Store) Put(_ context.Context, ref ports.CILogRef, step int32, markdown string) error {61 func (s *Store) Put(_ context.Context, ref ports.CILogRef, step int32, markdown string) error {
60 if !validRef(ref) || step < 1 || step > domain.CIMaxSteps {62 if !validRef(ref) || step < 1 || step > domain.CIMaxSteps {
61 return domain.ErrNotFound63 return domain.ErrNotFound
M internal/adapters/ermitegit/commitobjects.go +1 -1
@@ -22,7 +22,7 @@ var _ ports.CommitObjectReader = (*Adapter)(nil)
2222 // always serves it, and the wrapped reader only the repositories the library
2323 // cannot read.
2424 //
25-//hexcheck:ignore suspicious-business-logic-in-adapter applies the limits of the port and of the domain
25+//hexcheck:ignore suspicious-business-logic-in-adapter business rule for commit eligibility and byte budgets; pending move to domain/usecase
2626 func (a *Adapter) ReadCommitObjects(ctx context.Context, repo domain.RepoName, ids []domain.ObjectID) (map[domain.ObjectID][]byte, error) {
2727 if len(ids) > ports.MaxCommitLimit {
2828 return nil, fmt.Errorf("%w: %d commit objects asked, at most %d", domain.ErrInvalid, len(ids), ports.MaxCommitLimit)
@@ -22,7 +22,7 @@ var _ ports.CommitObjectReader = (*Adapter)(nil)
22 // always serves it, and the wrapped reader only the repositories the library22 // always serves it, and the wrapped reader only the repositories the library
23 // cannot read.23 // cannot read.
24 //24 //
25-//hexcheck:ignore suspicious-business-logic-in-adapter applies the limits of the port and of the domain25+//hexcheck:ignore suspicious-business-logic-in-adapter business rule for commit eligibility and byte budgets; pending move to domain/usecase
26 func (a *Adapter) ReadCommitObjects(ctx context.Context, repo domain.RepoName, ids []domain.ObjectID) (map[domain.ObjectID][]byte, error) {26 func (a *Adapter) ReadCommitObjects(ctx context.Context, repo domain.RepoName, ids []domain.ObjectID) (map[domain.ObjectID][]byte, error) {
27 if len(ids) > ports.MaxCommitLimit {27 if len(ids) > ports.MaxCommitLimit {
28 return nil, fmt.Errorf("%w: %d commit objects asked, at most %d", domain.ErrInvalid, len(ids), ports.MaxCommitLimit)28 return nil, fmt.Errorf("%w: %d commit objects asked, at most %d", domain.ErrInvalid, len(ids), ports.MaxCommitLimit)
M internal/adapters/ermitegit/convert.go +1 -5
@@ -27,8 +27,6 @@ func domainID(id git.ObjectID) (domain.ObjectID, error) { return domain.ParseObj
2727 // listRefs lists HEAD, then the branches, then the tags, like gitcli: a tag
2828 // follows to its commit when it leads to one; HEAD takes the ids of its
2929 // branch or tag, and only the name of an unborn branch.
30-//
31-//hexcheck:ignore suspicious-business-logic-in-adapter converts ermite-git values into domain values; the limits and the orders come from domain
3230 func listRefs(r *git.Repo) ([]domain.Ref, error) {
3331 var refs []domain.Ref
3432 byName := make(map[string]domain.Ref)
@@ -127,7 +125,7 @@ func peelID(r *git.Repo, id git.ObjectID) (_ git.ObjectID, ok bool, _ error) {
127125 // abbreviated id as written. It does not use Repo.Resolve, whose order is
128126 // git's own (tags before branches, no ref for a missing full id).
129127 //
130-//hexcheck:ignore suspicious-business-logic-in-adapter tries the candidates of the port in its documented order, like gitcli; the rule is the port contract
128+//hexcheck:ignore suspicious-business-logic-in-adapter business rule for revision resolution order; pending move to domain.Revision in a follow-up
131129 func resolveRevision(r *git.Repo, rev domain.Revision) (resolved, error) {
132130 s := rev.String()
133131 if rev.IsHead() || s == "HEAD" {
@@ -477,8 +475,6 @@ func fillLastCommits(ctx context.Context, r *git.Repo, commit domain.ObjectID, d
477475 // The ids, the names, the emails and the message share one backing string, cut
478476 // into substrings: one allocation for the text of a commit instead of one per
479477 // field.
480-//
481-//hexcheck:ignore suspicious-business-logic-in-adapter converts ermite-git values into domain values; the limits and the orders come from domain
482478 func convertCommit(c *git.Commit) (domain.Commit, error) {
483479 if len(c.Encoding) > 0 && !isUTF8Label(c.Encoding) {
484480 return domain.Commit{}, errFallback
@@ -27,8 +27,6 @@ func domainID(id git.ObjectID) (domain.ObjectID, error) { return domain.ParseObj
27 // listRefs lists HEAD, then the branches, then the tags, like gitcli: a tag27 // listRefs lists HEAD, then the branches, then the tags, like gitcli: a tag
28 // follows to its commit when it leads to one; HEAD takes the ids of its28 // follows to its commit when it leads to one; HEAD takes the ids of its
29 // branch or tag, and only the name of an unborn branch.29 // branch or tag, and only the name of an unborn branch.
30-//
31-//hexcheck:ignore suspicious-business-logic-in-adapter converts ermite-git values into domain values; the limits and the orders come from domain
32 func listRefs(r *git.Repo) ([]domain.Ref, error) {30 func listRefs(r *git.Repo) ([]domain.Ref, error) {
33 var refs []domain.Ref31 var refs []domain.Ref
34 byName := make(map[string]domain.Ref)32 byName := make(map[string]domain.Ref)
@@ -127,7 +125,7 @@ func peelID(r *git.Repo, id git.ObjectID) (_ git.ObjectID, ok bool, _ error) {
127 // abbreviated id as written. It does not use Repo.Resolve, whose order is125 // abbreviated id as written. It does not use Repo.Resolve, whose order is
128 // git's own (tags before branches, no ref for a missing full id).126 // git's own (tags before branches, no ref for a missing full id).
129 //127 //
130-//hexcheck:ignore suspicious-business-logic-in-adapter tries the candidates of the port in its documented order, like gitcli; the rule is the port contract128+//hexcheck:ignore suspicious-business-logic-in-adapter business rule for revision resolution order; pending move to domain.Revision in a follow-up
131 func resolveRevision(r *git.Repo, rev domain.Revision) (resolved, error) {129 func resolveRevision(r *git.Repo, rev domain.Revision) (resolved, error) {
132 s := rev.String()130 s := rev.String()
133 if rev.IsHead() || s == "HEAD" {131 if rev.IsHead() || s == "HEAD" {
@@ -477,8 +475,6 @@ func fillLastCommits(ctx context.Context, r *git.Repo, commit domain.ObjectID, d
477 // The ids, the names, the emails and the message share one backing string, cut475 // The ids, the names, the emails and the message share one backing string, cut
478 // into substrings: one allocation for the text of a commit instead of one per476 // into substrings: one allocation for the text of a commit instead of one per
479 // field.477 // field.
480-//
481-//hexcheck:ignore suspicious-business-logic-in-adapter converts ermite-git values into domain values; the limits and the orders come from domain
482 func convertCommit(c *git.Commit) (domain.Commit, error) {478 func convertCommit(c *git.Commit) (domain.Commit, error) {
483 if len(c.Encoding) > 0 && !isUTF8Label(c.Encoding) {479 if len(c.Encoding) > 0 && !isUTF8Label(c.Encoding) {
484 return domain.Commit{}, errFallback480 return domain.Commit{}, errFallback
M internal/adapters/gitcli/archive.go +0 -2
@@ -28,8 +28,6 @@ var _ ports.GitArchive = (*Git)(nil)
2828 // not by a gzip binary. A client that goes away ends ctx, which kills git.
2929 // Nothing is written to w when the commit does not exist
3030 // (domain.ErrNotFound).
31-//
32-//hexcheck:ignore suspicious-business-logic-in-adapter runs git archive and compresses its output: a process concern, access and naming are the use case's
3331 func (g *Git) Archive(ctx context.Context, repo domain.RepoName, commit domain.ObjectID, prefix string, w io.Writer) error {
3432 dir, err := g.repoDir(repo)
3533 if err != nil {
@@ -28,8 +28,6 @@ var _ ports.GitArchive = (*Git)(nil)
28 // not by a gzip binary. A client that goes away ends ctx, which kills git.28 // not by a gzip binary. A client that goes away ends ctx, which kills git.
29 // Nothing is written to w when the commit does not exist29 // Nothing is written to w when the commit does not exist
30 // (domain.ErrNotFound).30 // (domain.ErrNotFound).
31-//
32-//hexcheck:ignore suspicious-business-logic-in-adapter runs git archive and compresses its output: a process concern, access and naming are the use case's
33 func (g *Git) Archive(ctx context.Context, repo domain.RepoName, commit domain.ObjectID, prefix string, w io.Writer) error {31 func (g *Git) Archive(ctx context.Context, repo domain.RepoName, commit domain.ObjectID, prefix string, w io.Writer) error {
34 dir, err := g.repoDir(repo)32 dir, err := g.repoDir(repo)
35 if err != nil {33 if err != nil {
M internal/adapters/gitcli/changed.go +0 -4
@@ -21,8 +21,6 @@ const emptyTree = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
2121 // renames not detected (a rename lists both paths, as GitHub's push filters
2222 // see it), and stops reading after max paths: truncated tells there were more.
2323 // A zero base diffs against the empty tree.
24-//
25-//hexcheck:ignore suspicious-business-logic-in-adapter reads the path list git prints; the bound comes from the port
2624 func (g *Git) ChangedPaths(ctx context.Context, repo domain.RepoName, base, head domain.ObjectID, limit int) ([]string, bool, error) {
2725 if limit < 1 || head.IsZero() {
2826 return nil, false, fmt.Errorf("changed paths: %w: limit %d", domain.ErrInvalid, limit)
@@ -63,8 +61,6 @@ func (g *Git) ChangedPaths(ctx context.Context, repo domain.RepoName, base, head
6361 // (refs/heads/*), newest first, at most limit. It runs
6462 // `git log --not --branches --not <head>`: tags do not count, so the commit of
6563 // another tag that no branch has is listed.
66-//
67-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values; the limit comes from the port
6864 func (g *Git) CommitsOffBranches(ctx context.Context, repo domain.RepoName, head domain.ObjectID, limit int) ([]domain.Commit, bool, error) {
6965 if head.IsZero() {
7066 return nil, false, fmt.Errorf("commits off branches: %w: no head", domain.ErrInvalid)
@@ -21,8 +21,6 @@ const emptyTree = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
21 // renames not detected (a rename lists both paths, as GitHub's push filters21 // renames not detected (a rename lists both paths, as GitHub's push filters
22 // see it), and stops reading after max paths: truncated tells there were more.22 // see it), and stops reading after max paths: truncated tells there were more.
23 // A zero base diffs against the empty tree.23 // A zero base diffs against the empty tree.
24-//
25-//hexcheck:ignore suspicious-business-logic-in-adapter reads the path list git prints; the bound comes from the port
26 func (g *Git) ChangedPaths(ctx context.Context, repo domain.RepoName, base, head domain.ObjectID, limit int) ([]string, bool, error) {24 func (g *Git) ChangedPaths(ctx context.Context, repo domain.RepoName, base, head domain.ObjectID, limit int) ([]string, bool, error) {
27 if limit < 1 || head.IsZero() {25 if limit < 1 || head.IsZero() {
28 return nil, false, fmt.Errorf("changed paths: %w: limit %d", domain.ErrInvalid, limit)26 return nil, false, fmt.Errorf("changed paths: %w: limit %d", domain.ErrInvalid, limit)
@@ -63,8 +61,6 @@ func (g *Git) ChangedPaths(ctx context.Context, repo domain.RepoName, base, head
63 // (refs/heads/*), newest first, at most limit. It runs61 // (refs/heads/*), newest first, at most limit. It runs
64 // `git log --not --branches --not <head>`: tags do not count, so the commit of62 // `git log --not --branches --not <head>`: tags do not count, so the commit of
65 // another tag that no branch has is listed.63 // another tag that no branch has is listed.
66-//
67-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values; the limit comes from the port
68 func (g *Git) CommitsOffBranches(ctx context.Context, repo domain.RepoName, head domain.ObjectID, limit int) ([]domain.Commit, bool, error) {64 func (g *Git) CommitsOffBranches(ctx context.Context, repo domain.RepoName, head domain.ObjectID, limit int) ([]domain.Commit, bool, error) {
69 if head.IsZero() {65 if head.IsZero() {
70 return nil, false, fmt.Errorf("commits off branches: %w: no head", domain.ErrInvalid)66 return nil, false, fmt.Errorf("commits off branches: %w: no head", domain.ErrInvalid)
M internal/adapters/gitcli/commitobjects.go +1 -1
@@ -19,7 +19,7 @@ var _ ports.CommitObjectReader = (*Git)(nil)
1919 // that would take the total over domain.MaxCommitObjectsBytes (known from
2020 // `info`, before any content is read, so the stream stays consistent).
2121 //
22-//hexcheck:ignore suspicious-business-logic-in-adapter applies the limits of the port and of the domain
22+//hexcheck:ignore suspicious-business-logic-in-adapter business rule for commit eligibility and byte budgets; pending move to domain/usecase
2323 func (g *Git) ReadCommitObjects(ctx context.Context, repo domain.RepoName, ids []domain.ObjectID) (map[domain.ObjectID][]byte, error) {
2424 if len(ids) > ports.MaxCommitLimit {
2525 return nil, fmt.Errorf("%w: %d commit objects asked, at most %d", domain.ErrInvalid, len(ids), ports.MaxCommitLimit)
@@ -19,7 +19,7 @@ var _ ports.CommitObjectReader = (*Git)(nil)
19 // that would take the total over domain.MaxCommitObjectsBytes (known from19 // that would take the total over domain.MaxCommitObjectsBytes (known from
20 // `info`, before any content is read, so the stream stays consistent).20 // `info`, before any content is read, so the stream stays consistent).
21 //21 //
22-//hexcheck:ignore suspicious-business-logic-in-adapter applies the limits of the port and of the domain22+//hexcheck:ignore suspicious-business-logic-in-adapter business rule for commit eligibility and byte budgets; pending move to domain/usecase
23 func (g *Git) ReadCommitObjects(ctx context.Context, repo domain.RepoName, ids []domain.ObjectID) (map[domain.ObjectID][]byte, error) {23 func (g *Git) ReadCommitObjects(ctx context.Context, repo domain.RepoName, ids []domain.ObjectID) (map[domain.ObjectID][]byte, error) {
24 if len(ids) > ports.MaxCommitLimit {24 if len(ids) > ports.MaxCommitLimit {
25 return nil, fmt.Errorf("%w: %d commit objects asked, at most %d", domain.ErrInvalid, len(ids), ports.MaxCommitLimit)25 return nil, fmt.Errorf("%w: %d commit objects asked, at most %d", domain.ErrInvalid, len(ids), ports.MaxCommitLimit)
M internal/adapters/gitcli/diff.go +1 -13
@@ -32,8 +32,6 @@ const maxDiffLine = 64 << 10
3232 // Statistics come from the line counts, binary files from their "-" counts.
3333 // The patch is parsed as it streams: nothing beyond the limits is kept, and
3434 // git is stopped once nothing more is needed.
35-//
36-//hexcheck:ignore suspicious-business-logic-in-adapter parses git diff-tree output into the domain diff, applying the limits the port passes in
3735 func (g *Git) GetCommit(ctx context.Context, repo domain.RepoName, rev domain.Revision, limits domain.DiffLimits) (domain.CommitDetail, error) {
3836 dir, err := g.repoDir(repo)
3937 if err != nil {
@@ -91,7 +89,7 @@ type rawEntry struct {
9189
9290 // readDiff parses the output of diff-tree --raw --numstat -p.
9391 //
94-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values, applying the limits the port passes in
92+//hexcheck:ignore suspicious-business-logic-in-adapter business rule for diff windowing and truncation budgets; pending move to domain/usecase
9593 func readDiff(r *bufio.Reader, limits domain.DiffLimits) (domain.Diff, domain.DiffStats, error) {
9694 entries, err := readRaw(r)
9795 if err != nil {
@@ -189,8 +187,6 @@ func wantsHunks(e *rawEntry, limits domain.DiffLimits, linesLeft, bytesLeft int)
189187 }
190188
191189 // readRaw reads the `--raw -z` records, which start with ':'.
192-//
193-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values
194190 func readRaw(r *bufio.Reader) ([]rawEntry, error) {
195191 var entries []rawEntry
196192 for {
@@ -241,8 +237,6 @@ func unexpectedEOF(err error) error {
241237
242238 // parseRawMeta parses ":<old mode> <new mode> <old id> <new id> <status>" and
243239 // returns the number of paths that follow.
244-//
245-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values
246240 func parseRawMeta(meta string) (rawEntry, int, error) {
247241 f := strings.Fields(strings.TrimPrefix(meta, ":"))
248242 if len(f) != 5 || f[4] == "" {
@@ -296,8 +290,6 @@ func parseRawMeta(meta string) (rawEntry, int, error) {
296290
297291 // readNumstat reads one `--numstat -z` record per entry. A binary file has
298292 // "-" counts.
299-//
300-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values
301293 func readNumstat(r *bufio.Reader, entries []rawEntry) error {
302294 for i := range entries {
303295 tok, err := readToken(r)
@@ -434,8 +426,6 @@ func (p *patchReader) file(sections, max int) (hunks []domain.Hunk, lines int, t
434426
435427 // section reads the hunks of the current section up to the next marker, which
436428 // stays pending. It gives up (truncated) after more than max lines.
437-//
438-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values, applying the limits the port passes in
439429 func (p *patchReader) section(max int) (hunks []domain.Hunk, lines int, truncated bool, err error) {
440430 var cur *domain.Hunk
441431 var oldN, newN int
@@ -499,8 +489,6 @@ func (p *patchReader) section(max int) (hunks []domain.Hunk, lines int, truncate
499489 }
500490
501491 // parseHunkHeader parses "@@ -a[,b] +c[,d] @@[ header]".
502-//
503-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values
504492 func parseHunkHeader(s string) (domain.Hunk, error) {
505493 bad := func() (domain.Hunk, error) {
506494 return domain.Hunk{}, fmt.Errorf("git diff-tree: unexpected hunk header %q", truncateText(s))
@@ -32,8 +32,6 @@ const maxDiffLine = 64 << 10
32 // Statistics come from the line counts, binary files from their "-" counts.32 // Statistics come from the line counts, binary files from their "-" counts.
33 // The patch is parsed as it streams: nothing beyond the limits is kept, and33 // The patch is parsed as it streams: nothing beyond the limits is kept, and
34 // git is stopped once nothing more is needed.34 // git is stopped once nothing more is needed.
35-//
36-//hexcheck:ignore suspicious-business-logic-in-adapter parses git diff-tree output into the domain diff, applying the limits the port passes in
37 func (g *Git) GetCommit(ctx context.Context, repo domain.RepoName, rev domain.Revision, limits domain.DiffLimits) (domain.CommitDetail, error) {35 func (g *Git) GetCommit(ctx context.Context, repo domain.RepoName, rev domain.Revision, limits domain.DiffLimits) (domain.CommitDetail, error) {
38 dir, err := g.repoDir(repo)36 dir, err := g.repoDir(repo)
39 if err != nil {37 if err != nil {
@@ -91,7 +89,7 @@ type rawEntry struct {
91 89
92 // readDiff parses the output of diff-tree --raw --numstat -p.90 // readDiff parses the output of diff-tree --raw --numstat -p.
93 //91 //
94-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values, applying the limits the port passes in92+//hexcheck:ignore suspicious-business-logic-in-adapter business rule for diff windowing and truncation budgets; pending move to domain/usecase
95 func readDiff(r *bufio.Reader, limits domain.DiffLimits) (domain.Diff, domain.DiffStats, error) {93 func readDiff(r *bufio.Reader, limits domain.DiffLimits) (domain.Diff, domain.DiffStats, error) {
96 entries, err := readRaw(r)94 entries, err := readRaw(r)
97 if err != nil {95 if err != nil {
@@ -189,8 +187,6 @@ func wantsHunks(e *rawEntry, limits domain.DiffLimits, linesLeft, bytesLeft int)
189 }187 }
190 188
191 // readRaw reads the `--raw -z` records, which start with ':'.189 // readRaw reads the `--raw -z` records, which start with ':'.
192-//
193-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values
194 func readRaw(r *bufio.Reader) ([]rawEntry, error) {190 func readRaw(r *bufio.Reader) ([]rawEntry, error) {
195 var entries []rawEntry191 var entries []rawEntry
196 for {192 for {
@@ -241,8 +237,6 @@ func unexpectedEOF(err error) error {
241 237
242 // parseRawMeta parses ":<old mode> <new mode> <old id> <new id> <status>" and238 // parseRawMeta parses ":<old mode> <new mode> <old id> <new id> <status>" and
243 // returns the number of paths that follow.239 // returns the number of paths that follow.
244-//
245-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values
246 func parseRawMeta(meta string) (rawEntry, int, error) {240 func parseRawMeta(meta string) (rawEntry, int, error) {
247 f := strings.Fields(strings.TrimPrefix(meta, ":"))241 f := strings.Fields(strings.TrimPrefix(meta, ":"))
248 if len(f) != 5 || f[4] == "" {242 if len(f) != 5 || f[4] == "" {
@@ -296,8 +290,6 @@ func parseRawMeta(meta string) (rawEntry, int, error) {
296 290
297 // readNumstat reads one `--numstat -z` record per entry. A binary file has291 // readNumstat reads one `--numstat -z` record per entry. A binary file has
298 // "-" counts.292 // "-" counts.
299-//
300-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values
301 func readNumstat(r *bufio.Reader, entries []rawEntry) error {293 func readNumstat(r *bufio.Reader, entries []rawEntry) error {
302 for i := range entries {294 for i := range entries {
303 tok, err := readToken(r)295 tok, err := readToken(r)
@@ -434,8 +426,6 @@ func (p *patchReader) file(sections, max int) (hunks []domain.Hunk, lines int, t
434 426
435 // section reads the hunks of the current section up to the next marker, which427 // section reads the hunks of the current section up to the next marker, which
436 // stays pending. It gives up (truncated) after more than max lines.428 // stays pending. It gives up (truncated) after more than max lines.
437-//
438-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values, applying the limits the port passes in
439 func (p *patchReader) section(max int) (hunks []domain.Hunk, lines int, truncated bool, err error) {429 func (p *patchReader) section(max int) (hunks []domain.Hunk, lines int, truncated bool, err error) {
440 var cur *domain.Hunk430 var cur *domain.Hunk
441 var oldN, newN int431 var oldN, newN int
@@ -499,8 +489,6 @@ func (p *patchReader) section(max int) (hunks []domain.Hunk, lines int, truncate
499 }489 }
500 490
501 // parseHunkHeader parses "@@ -a[,b] +c[,d] @@[ header]".491 // parseHunkHeader parses "@@ -a[,b] +c[,d] @@[ header]".
502-//
503-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values
504 func parseHunkHeader(s string) (domain.Hunk, error) {492 func parseHunkHeader(s string) (domain.Hunk, error) {
505 bad := func() (domain.Hunk, error) {493 bad := func() (domain.Hunk, error) {
506 return domain.Hunk{}, fmt.Errorf("git diff-tree: unexpected hunk header %q", truncateText(s))494 return domain.Hunk{}, fmt.Errorf("git diff-tree: unexpected hunk header %q", truncateText(s))
M internal/adapters/gitcli/merge.go +0 -16
@@ -39,8 +39,6 @@ func parseID(out string) (domain.ObjectID, error) {
3939 }
4040
4141 // BranchHead resolves refs/heads/<branch>^{commit} with `cat-file`.
42-//
43-//hexcheck:ignore suspicious-business-logic-in-adapter maps a branch name to a git object name
4442 func (g *Git) BranchHead(ctx context.Context, repo domain.RepoName, branch string) (domain.ObjectID, error) {
4543 dir, err := g.repoDir(repo)
4644 if err != nil {
@@ -95,8 +93,6 @@ func (g *Git) HasCommit(ctx context.Context, repo domain.RepoName, id domain.Obj
9593 }
9694
9795 // MergeBase runs `git merge-base`, which exits 1 when there is none.
98-//
99-//hexcheck:ignore suspicious-business-logic-in-adapter maps git exit codes to the domain not found error
10096 func (g *Git) MergeBase(ctx context.Context, repo domain.RepoName, a, b domain.ObjectID) (domain.ObjectID, error) {
10197 dir, err := g.repoDir(repo)
10298 if err != nil {
@@ -129,8 +125,6 @@ func (g *Git) IsAncestor(ctx context.Context, repo domain.RepoName, ancestor, de
129125 }
130126
131127 // ListRange runs `git log <head> ^<exclude>`.
132-//
133-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values; the limit comes from the port
134128 func (g *Git) ListRange(ctx context.Context, repo domain.RepoName, exclude, head domain.ObjectID, limit int) ([]domain.Commit, bool, error) {
135129 var excluded []string
136130 if !exclude.IsZero() {
@@ -142,8 +136,6 @@ func (g *Git) ListRange(ctx context.Context, repo domain.RepoName, exclude, head
142136 // logCommits runs `git log` for the commits reachable from head: revArgs go
143137 // before the head (options such as --not), excluded after it. Newest first,
144138 // at most limit; more says there were others.
145-//
146-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values; the limit comes from the port
147139 func (g *Git) logCommits(ctx context.Context, repo domain.RepoName, head domain.ObjectID, limit int, revArgs, excluded []string) ([]domain.Commit, bool, error) {
148140 if limit < 1 || limit > ports.MaxCommitLimit {
149141 return nil, false, fmt.Errorf("list range: %w: limit %d", domain.ErrInvalidPageSize, limit)
@@ -183,8 +175,6 @@ func (g *Git) logCommits(ctx context.Context, repo domain.RepoName, head domain.
183175 }
184176
185177 // DiffCommits reads the diff between two commits like GetCommit does.
186-//
187-//hexcheck:ignore suspicious-business-logic-in-adapter reads a git diff into the domain diff with the limits the port passes in
188178 func (g *Git) DiffCommits(ctx context.Context, repo domain.RepoName, base, head domain.ObjectID, limits domain.DiffLimits) (domain.DiffStats, domain.Diff, error) {
189179 dir, err := g.repoDir(repo)
190180 if err != nil {
@@ -198,8 +188,6 @@ func (g *Git) DiffCommits(ctx context.Context, repo domain.RepoName, base, head
198188 }
199189
200190 // CommitTree runs `git rev-parse <commit>^{tree}`.
201-//
202-//hexcheck:ignore suspicious-business-logic-in-adapter parses the id git printed
203191 func (g *Git) CommitTree(ctx context.Context, repo domain.RepoName, id domain.ObjectID) (domain.ObjectID, error) {
204192 dir, err := g.repoDir(repo)
205193 if err != nil {
@@ -229,8 +217,6 @@ func (g *Git) WriteCommit(ctx context.Context, repo domain.RepoName, object []by
229217 // UpdateBranch runs `git update-ref refs/heads/<branch> <new> <old>`, which
230218 // takes the ref lock and refuses when the ref is not at old. A failure is
231219 // told from a moved branch by reading the branch again.
232-//
233-//hexcheck:ignore suspicious-business-logic-in-adapter maps a refused update-ref to the conflict error of the port
234220 func (g *Git) UpdateBranch(ctx context.Context, repo domain.RepoName, branch string, old, newID domain.ObjectID) error {
235221 dir, err := g.repoDir(repo)
236222 if err != nil {
@@ -252,8 +238,6 @@ func (g *Git) UpdateBranch(ctx context.Context, repo domain.RepoName, branch str
252238 // DeleteBranch runs `git update-ref -d refs/heads/<branch> <old>`, which takes
253239 // the ref lock and refuses when the ref is not at old. A failure is told from
254240 // a moved or deleted branch by reading the branch again.
255-//
256-//hexcheck:ignore suspicious-business-logic-in-adapter maps a refused update-ref to the conflict error of the port
257241 func (g *Git) DeleteBranch(ctx context.Context, repo domain.RepoName, branch string, old domain.ObjectID) error {
258242 dir, err := g.repoDir(repo)
259243 if err != nil {
@@ -39,8 +39,6 @@ func parseID(out string) (domain.ObjectID, error) {
39 }39 }
40 40
41 // BranchHead resolves refs/heads/<branch>^{commit} with `cat-file`.41 // BranchHead resolves refs/heads/<branch>^{commit} with `cat-file`.
42-//
43-//hexcheck:ignore suspicious-business-logic-in-adapter maps a branch name to a git object name
44 func (g *Git) BranchHead(ctx context.Context, repo domain.RepoName, branch string) (domain.ObjectID, error) {42 func (g *Git) BranchHead(ctx context.Context, repo domain.RepoName, branch string) (domain.ObjectID, error) {
45 dir, err := g.repoDir(repo)43 dir, err := g.repoDir(repo)
46 if err != nil {44 if err != nil {
@@ -95,8 +93,6 @@ func (g *Git) HasCommit(ctx context.Context, repo domain.RepoName, id domain.Obj
95 }93 }
96 94
97 // MergeBase runs `git merge-base`, which exits 1 when there is none.95 // MergeBase runs `git merge-base`, which exits 1 when there is none.
98-//
99-//hexcheck:ignore suspicious-business-logic-in-adapter maps git exit codes to the domain not found error
100 func (g *Git) MergeBase(ctx context.Context, repo domain.RepoName, a, b domain.ObjectID) (domain.ObjectID, error) {96 func (g *Git) MergeBase(ctx context.Context, repo domain.RepoName, a, b domain.ObjectID) (domain.ObjectID, error) {
101 dir, err := g.repoDir(repo)97 dir, err := g.repoDir(repo)
102 if err != nil {98 if err != nil {
@@ -129,8 +125,6 @@ func (g *Git) IsAncestor(ctx context.Context, repo domain.RepoName, ancestor, de
129 }125 }
130 126
131 // ListRange runs `git log <head> ^<exclude>`.127 // ListRange runs `git log <head> ^<exclude>`.
132-//
133-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values; the limit comes from the port
134 func (g *Git) ListRange(ctx context.Context, repo domain.RepoName, exclude, head domain.ObjectID, limit int) ([]domain.Commit, bool, error) {128 func (g *Git) ListRange(ctx context.Context, repo domain.RepoName, exclude, head domain.ObjectID, limit int) ([]domain.Commit, bool, error) {
135 var excluded []string129 var excluded []string
136 if !exclude.IsZero() {130 if !exclude.IsZero() {
@@ -142,8 +136,6 @@ func (g *Git) ListRange(ctx context.Context, repo domain.RepoName, exclude, head
142 // logCommits runs `git log` for the commits reachable from head: revArgs go136 // logCommits runs `git log` for the commits reachable from head: revArgs go
143 // before the head (options such as --not), excluded after it. Newest first,137 // before the head (options such as --not), excluded after it. Newest first,
144 // at most limit; more says there were others.138 // at most limit; more says there were others.
145-//
146-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values; the limit comes from the port
147 func (g *Git) logCommits(ctx context.Context, repo domain.RepoName, head domain.ObjectID, limit int, revArgs, excluded []string) ([]domain.Commit, bool, error) {139 func (g *Git) logCommits(ctx context.Context, repo domain.RepoName, head domain.ObjectID, limit int, revArgs, excluded []string) ([]domain.Commit, bool, error) {
148 if limit < 1 || limit > ports.MaxCommitLimit {140 if limit < 1 || limit > ports.MaxCommitLimit {
149 return nil, false, fmt.Errorf("list range: %w: limit %d", domain.ErrInvalidPageSize, limit)141 return nil, false, fmt.Errorf("list range: %w: limit %d", domain.ErrInvalidPageSize, limit)
@@ -183,8 +175,6 @@ func (g *Git) logCommits(ctx context.Context, repo domain.RepoName, head domain.
183 }175 }
184 176
185 // DiffCommits reads the diff between two commits like GetCommit does.177 // DiffCommits reads the diff between two commits like GetCommit does.
186-//
187-//hexcheck:ignore suspicious-business-logic-in-adapter reads a git diff into the domain diff with the limits the port passes in
188 func (g *Git) DiffCommits(ctx context.Context, repo domain.RepoName, base, head domain.ObjectID, limits domain.DiffLimits) (domain.DiffStats, domain.Diff, error) {178 func (g *Git) DiffCommits(ctx context.Context, repo domain.RepoName, base, head domain.ObjectID, limits domain.DiffLimits) (domain.DiffStats, domain.Diff, error) {
189 dir, err := g.repoDir(repo)179 dir, err := g.repoDir(repo)
190 if err != nil {180 if err != nil {
@@ -198,8 +188,6 @@ func (g *Git) DiffCommits(ctx context.Context, repo domain.RepoName, base, head
198 }188 }
199 189
200 // CommitTree runs `git rev-parse <commit>^{tree}`.190 // CommitTree runs `git rev-parse <commit>^{tree}`.
201-//
202-//hexcheck:ignore suspicious-business-logic-in-adapter parses the id git printed
203 func (g *Git) CommitTree(ctx context.Context, repo domain.RepoName, id domain.ObjectID) (domain.ObjectID, error) {191 func (g *Git) CommitTree(ctx context.Context, repo domain.RepoName, id domain.ObjectID) (domain.ObjectID, error) {
204 dir, err := g.repoDir(repo)192 dir, err := g.repoDir(repo)
205 if err != nil {193 if err != nil {
@@ -229,8 +217,6 @@ func (g *Git) WriteCommit(ctx context.Context, repo domain.RepoName, object []by
229 // UpdateBranch runs `git update-ref refs/heads/<branch> <new> <old>`, which217 // UpdateBranch runs `git update-ref refs/heads/<branch> <new> <old>`, which
230 // takes the ref lock and refuses when the ref is not at old. A failure is218 // takes the ref lock and refuses when the ref is not at old. A failure is
231 // told from a moved branch by reading the branch again.219 // told from a moved branch by reading the branch again.
232-//
233-//hexcheck:ignore suspicious-business-logic-in-adapter maps a refused update-ref to the conflict error of the port
234 func (g *Git) UpdateBranch(ctx context.Context, repo domain.RepoName, branch string, old, newID domain.ObjectID) error {220 func (g *Git) UpdateBranch(ctx context.Context, repo domain.RepoName, branch string, old, newID domain.ObjectID) error {
235 dir, err := g.repoDir(repo)221 dir, err := g.repoDir(repo)
236 if err != nil {222 if err != nil {
@@ -252,8 +238,6 @@ func (g *Git) UpdateBranch(ctx context.Context, repo domain.RepoName, branch str
252 // DeleteBranch runs `git update-ref -d refs/heads/<branch> <old>`, which takes238 // DeleteBranch runs `git update-ref -d refs/heads/<branch> <old>`, which takes
253 // the ref lock and refuses when the ref is not at old. A failure is told from239 // the ref lock and refuses when the ref is not at old. A failure is told from
254 // a moved or deleted branch by reading the branch again.240 // a moved or deleted branch by reading the branch again.
255-//
256-//hexcheck:ignore suspicious-business-logic-in-adapter maps a refused update-ref to the conflict error of the port
257 func (g *Git) DeleteBranch(ctx context.Context, repo domain.RepoName, branch string, old domain.ObjectID) error {241 func (g *Git) DeleteBranch(ctx context.Context, repo domain.RepoName, branch string, old domain.ObjectID) error {
258 dir, err := g.repoDir(repo)242 dir, err := g.repoDir(repo)
259 if err != nil {243 if err != nil {
M internal/adapters/gitcli/pull.go +0 -2
@@ -18,8 +18,6 @@ var _ ports.PullGit = (*Git)(nil)
1818 // database and touches no ref or index: it prints the tree of the result and
1919 // exits 0, or exits 1 when the merge conflicts. Commits with no common history
2020 // do not merge (GitHub makes no test merge for them either).
21-//
22-//hexcheck:ignore suspicious-business-logic-in-adapter maps git exit codes to the clean/conflict answer of the port
2321 func (g *Git) TestMerge(ctx context.Context, repo domain.RepoName, base, head domain.ObjectID) (domain.ObjectID, bool, error) {
2422 dir, err := g.repoDir(repo)
2523 if err != nil {
@@ -18,8 +18,6 @@ var _ ports.PullGit = (*Git)(nil)
18 // database and touches no ref or index: it prints the tree of the result and18 // database and touches no ref or index: it prints the tree of the result and
19 // exits 0, or exits 1 when the merge conflicts. Commits with no common history19 // exits 0, or exits 1 when the merge conflicts. Commits with no common history
20 // do not merge (GitHub makes no test merge for them either).20 // do not merge (GitHub makes no test merge for them either).
21-//
22-//hexcheck:ignore suspicious-business-logic-in-adapter maps git exit codes to the clean/conflict answer of the port
23 func (g *Git) TestMerge(ctx context.Context, repo domain.RepoName, base, head domain.ObjectID) (domain.ObjectID, bool, error) {21 func (g *Git) TestMerge(ctx context.Context, repo domain.RepoName, base, head domain.ObjectID) (domain.ObjectID, bool, error) {
24 dir, err := g.repoDir(repo)22 dir, err := g.repoDir(repo)
25 if err != nil {23 if err != nil {
M internal/adapters/gitcli/read.go +5 -13
@@ -35,8 +35,6 @@ func notFound(err error) bool { return errors.Is(err, errObjectMissing) }
3535 // ListRefs lists HEAD, the branches and the tags with `git for-each-ref`.
3636 // An annotated tag is followed to its commit; a tag of a tag is followed with
3737 // one `cat-file` request each.
38-//
39-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain refs
4038 func (g *Git) ListRefs(ctx context.Context, repo domain.RepoName) ([]domain.Ref, error) {
4139 dir, err := g.repoDir(repo)
4240 if err != nil {
@@ -167,6 +165,8 @@ type revCandidate struct {
167165 // object exists. Otherwise it is the branch, then the tag, then (for "HEAD",
168166 // full ref names and abbreviations) as written. Other forms Git understands,
169167 // such as "main~2" or "FETCH_HEAD", are not revisions of ermite.
168+//
169+//hexcheck:ignore suspicious-business-logic-in-adapter business rule for revision resolution order; pending move to domain.Revision in a follow-up
170170 func candidates(rev domain.Revision) []revCandidate {
171171 s := rev.String()
172172 switch {
@@ -190,7 +190,7 @@ func candidates(rev domain.Revision) []revCandidate {
190190
191191 // resolve resolves rev on an open cat-file connection.
192192 //
193-//hexcheck:ignore suspicious-business-logic-in-adapter maps a revision to git object names, a git detail of the reader
193+//hexcheck:ignore suspicious-business-logic-in-adapter business rule for revision resolution order; pending move to domain.Revision in a follow-up
194194 func resolve(c *catConn, rev domain.Revision) (domain.ResolvedRevision, error) {
195195 for _, cand := range candidates(rev) {
196196 h, err := c.info(cand.spec)
@@ -213,8 +213,6 @@ func resolve(c *catConn, rev domain.Revision) (domain.ResolvedRevision, error) {
213213 }
214214
215215 // ResolveRevision resolves a revision with `cat-file`.
216-//
217-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values; limits and rules come from the port
218216 func (g *Git) ResolveRevision(ctx context.Context, repo domain.RepoName, rev domain.Revision) (domain.ResolvedRevision, error) {
219217 dir, err := g.repoDir(repo)
220218 if err != nil {
@@ -235,8 +233,6 @@ func (g *Git) ResolveRevision(ctx context.Context, repo domain.RepoName, rev dom
235233 // tag, full ref name, HEAD; a single segment may also be a commit id), longest
236234 // first, with up to one `cat-file` request per candidate on the repository's
237235 // process. At most domain.MaxRefPathTries segments are tried.
238-//
239-//hexcheck:ignore suspicious-business-logic-in-adapter the split is domain.SplitRefPath; this only runs it on a cat-file connection
240236 func (g *Git) ResolveRefPath(ctx context.Context, repo domain.RepoName, path string) (domain.RefPath, error) {
241237 dir, err := g.repoDir(repo)
242238 if err != nil {
@@ -264,6 +260,8 @@ type object struct {
264260 // lookup resolves rev and reads the header of the object at path, in one
265261 // request series on the repository's process. A missing path is
266262 // domain.ErrNotFound.
263+//
264+//hexcheck:ignore suspicious-business-logic-in-adapter uses the business rule for revision resolution order, pending move to domain.Revision in a follow-up, before looking up a path
267265 func (g *Git) lookup(ctx context.Context, dir string, rev domain.Revision, path domain.TreePath) (object, error) {
268266 var obj object
269267 err := g.cat.do(ctx, dir, func(c *catConn) error {
@@ -392,8 +390,6 @@ func (g *Git) GetTree(ctx context.Context, repo domain.RepoName, rev domain.Revi
392390 }
393391
394392 // parseTreeEntry parses "<mode> <type> <id> <size>\t<name>" of ls-tree -l.
395-//
396-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values; limits and rules come from the port
397393 func parseTreeEntry(rec string, parent domain.TreePath) (domain.TreeEntry, error) {
398394 meta, name, ok := strings.Cut(rec, "\t")
399395 f := strings.Fields(meta)
@@ -487,8 +483,6 @@ feed:
487483
488484 // lastCommit returns the newest commit reachable from head that changed path;
489485 // an empty path means head itself.
490-//
491-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values; limits and rules come from the port
492486 func (g *Git) lastCommit(ctx context.Context, dir string, head domain.ObjectID, path string) (domain.Commit, error) {
493487 var c domain.Commit
494488 found := false
@@ -520,8 +514,6 @@ const commitFormat = "%H%x00%P%x00%an%x00%ae%x00%at%x00%cn%x00%ce%x00%ct%x00%B"
520514
521515 // readCommit reads one commit in commitFormat. It returns io.EOF at the end
522516 // of the output.
523-//
524-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values; limits and rules come from the port
525517 func readCommit(r *bufio.Reader) (domain.Commit, error) {
526518 var f [9]string
527519 for i := range f {
@@ -35,8 +35,6 @@ func notFound(err error) bool { return errors.Is(err, errObjectMissing) }
35 // ListRefs lists HEAD, the branches and the tags with `git for-each-ref`.35 // ListRefs lists HEAD, the branches and the tags with `git for-each-ref`.
36 // An annotated tag is followed to its commit; a tag of a tag is followed with36 // An annotated tag is followed to its commit; a tag of a tag is followed with
37 // one `cat-file` request each.37 // one `cat-file` request each.
38-//
39-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain refs
40 func (g *Git) ListRefs(ctx context.Context, repo domain.RepoName) ([]domain.Ref, error) {38 func (g *Git) ListRefs(ctx context.Context, repo domain.RepoName) ([]domain.Ref, error) {
41 dir, err := g.repoDir(repo)39 dir, err := g.repoDir(repo)
42 if err != nil {40 if err != nil {
@@ -167,6 +165,8 @@ type revCandidate struct {
167 // object exists. Otherwise it is the branch, then the tag, then (for "HEAD",165 // object exists. Otherwise it is the branch, then the tag, then (for "HEAD",
168 // full ref names and abbreviations) as written. Other forms Git understands,166 // full ref names and abbreviations) as written. Other forms Git understands,
169 // such as "main~2" or "FETCH_HEAD", are not revisions of ermite.167 // such as "main~2" or "FETCH_HEAD", are not revisions of ermite.
168+//
169+//hexcheck:ignore suspicious-business-logic-in-adapter business rule for revision resolution order; pending move to domain.Revision in a follow-up
170 func candidates(rev domain.Revision) []revCandidate {170 func candidates(rev domain.Revision) []revCandidate {
171 s := rev.String()171 s := rev.String()
172 switch {172 switch {
@@ -190,7 +190,7 @@ func candidates(rev domain.Revision) []revCandidate {
190 190
191 // resolve resolves rev on an open cat-file connection.191 // resolve resolves rev on an open cat-file connection.
192 //192 //
193-//hexcheck:ignore suspicious-business-logic-in-adapter maps a revision to git object names, a git detail of the reader193+//hexcheck:ignore suspicious-business-logic-in-adapter business rule for revision resolution order; pending move to domain.Revision in a follow-up
194 func resolve(c *catConn, rev domain.Revision) (domain.ResolvedRevision, error) {194 func resolve(c *catConn, rev domain.Revision) (domain.ResolvedRevision, error) {
195 for _, cand := range candidates(rev) {195 for _, cand := range candidates(rev) {
196 h, err := c.info(cand.spec)196 h, err := c.info(cand.spec)
@@ -213,8 +213,6 @@ func resolve(c *catConn, rev domain.Revision) (domain.ResolvedRevision, error) {
213 }213 }
214 214
215 // ResolveRevision resolves a revision with `cat-file`.215 // ResolveRevision resolves a revision with `cat-file`.
216-//
217-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values; limits and rules come from the port
218 func (g *Git) ResolveRevision(ctx context.Context, repo domain.RepoName, rev domain.Revision) (domain.ResolvedRevision, error) {216 func (g *Git) ResolveRevision(ctx context.Context, repo domain.RepoName, rev domain.Revision) (domain.ResolvedRevision, error) {
219 dir, err := g.repoDir(repo)217 dir, err := g.repoDir(repo)
220 if err != nil {218 if err != nil {
@@ -235,8 +233,6 @@ func (g *Git) ResolveRevision(ctx context.Context, repo domain.RepoName, rev dom
235 // tag, full ref name, HEAD; a single segment may also be a commit id), longest233 // tag, full ref name, HEAD; a single segment may also be a commit id), longest
236 // first, with up to one `cat-file` request per candidate on the repository's234 // first, with up to one `cat-file` request per candidate on the repository's
237 // process. At most domain.MaxRefPathTries segments are tried.235 // process. At most domain.MaxRefPathTries segments are tried.
238-//
239-//hexcheck:ignore suspicious-business-logic-in-adapter the split is domain.SplitRefPath; this only runs it on a cat-file connection
240 func (g *Git) ResolveRefPath(ctx context.Context, repo domain.RepoName, path string) (domain.RefPath, error) {236 func (g *Git) ResolveRefPath(ctx context.Context, repo domain.RepoName, path string) (domain.RefPath, error) {
241 dir, err := g.repoDir(repo)237 dir, err := g.repoDir(repo)
242 if err != nil {238 if err != nil {
@@ -264,6 +260,8 @@ type object struct {
264 // lookup resolves rev and reads the header of the object at path, in one260 // lookup resolves rev and reads the header of the object at path, in one
265 // request series on the repository's process. A missing path is261 // request series on the repository's process. A missing path is
266 // domain.ErrNotFound.262 // domain.ErrNotFound.
263+//
264+//hexcheck:ignore suspicious-business-logic-in-adapter uses the business rule for revision resolution order, pending move to domain.Revision in a follow-up, before looking up a path
267 func (g *Git) lookup(ctx context.Context, dir string, rev domain.Revision, path domain.TreePath) (object, error) {265 func (g *Git) lookup(ctx context.Context, dir string, rev domain.Revision, path domain.TreePath) (object, error) {
268 var obj object266 var obj object
269 err := g.cat.do(ctx, dir, func(c *catConn) error {267 err := g.cat.do(ctx, dir, func(c *catConn) error {
@@ -392,8 +390,6 @@ func (g *Git) GetTree(ctx context.Context, repo domain.RepoName, rev domain.Revi
392 }390 }
393 391
394 // parseTreeEntry parses "<mode> <type> <id> <size>\t<name>" of ls-tree -l.392 // parseTreeEntry parses "<mode> <type> <id> <size>\t<name>" of ls-tree -l.
395-//
396-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values; limits and rules come from the port
397 func parseTreeEntry(rec string, parent domain.TreePath) (domain.TreeEntry, error) {393 func parseTreeEntry(rec string, parent domain.TreePath) (domain.TreeEntry, error) {
398 meta, name, ok := strings.Cut(rec, "\t")394 meta, name, ok := strings.Cut(rec, "\t")
399 f := strings.Fields(meta)395 f := strings.Fields(meta)
@@ -487,8 +483,6 @@ feed:
487 483
488 // lastCommit returns the newest commit reachable from head that changed path;484 // lastCommit returns the newest commit reachable from head that changed path;
489 // an empty path means head itself.485 // an empty path means head itself.
490-//
491-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values; limits and rules come from the port
492 func (g *Git) lastCommit(ctx context.Context, dir string, head domain.ObjectID, path string) (domain.Commit, error) {486 func (g *Git) lastCommit(ctx context.Context, dir string, head domain.ObjectID, path string) (domain.Commit, error) {
493 var c domain.Commit487 var c domain.Commit
494 found := false488 found := false
@@ -520,8 +514,6 @@ const commitFormat = "%H%x00%P%x00%an%x00%ae%x00%at%x00%cn%x00%ce%x00%ct%x00%B"
520 514
521 // readCommit reads one commit in commitFormat. It returns io.EOF at the end515 // readCommit reads one commit in commitFormat. It returns io.EOF at the end
522 // of the output.516 // of the output.
523-//
524-//hexcheck:ignore suspicious-business-logic-in-adapter parses git output into domain values; limits and rules come from the port
525 func readCommit(r *bufio.Reader) (domain.Commit, error) {517 func readCommit(r *bufio.Reader) (domain.Commit, error) {
526 var f [9]string518 var f [9]string
527 for i := range f {519 for i := range f {
M internal/adapters/gitcli/repos.go +1 -3
@@ -102,7 +102,7 @@ func (g *Git) Discard(_ context.Context, id ports.StagedID) error {
102102
103103 // PurgeStaging removes everything under repos/.staging/.
104104 //
105-//hexcheck:ignore suspicious-business-logic-in-adapter port method name only
105+//hexcheck:ignore suspicious-business-logic-in-adapter removes staging leftovers from disk, tolerates a missing directory, and logs each removal
106106 func (g *Git) PurgeStaging(ctx context.Context) error {
107107 entries, err := os.ReadDir(g.stagingDir())
108108 if err != nil {
@@ -280,8 +280,6 @@ func (g *Git) DefaultBranch(ctx context.Context, name domain.RepoName) (string,
280280 // HasBranch checks refs/heads/<branch> with `git for-each-ref` after
281281 // `git check-ref-format`, which rejects the glob characters for-each-ref
282282 // would otherwise interpret.
283-//
284-//hexcheck:ignore suspicious-business-logic-in-adapter port method name only
285283 func (g *Git) HasBranch(ctx context.Context, name domain.RepoName, branch string) (bool, error) {
286284 dir, err := g.repoDir(name)
287285 if err != nil {
@@ -102,7 +102,7 @@ func (g *Git) Discard(_ context.Context, id ports.StagedID) error {
102 102
103 // PurgeStaging removes everything under repos/.staging/.103 // PurgeStaging removes everything under repos/.staging/.
104 //104 //
105-//hexcheck:ignore suspicious-business-logic-in-adapter port method name only105+//hexcheck:ignore suspicious-business-logic-in-adapter removes staging leftovers from disk, tolerates a missing directory, and logs each removal
106 func (g *Git) PurgeStaging(ctx context.Context) error {106 func (g *Git) PurgeStaging(ctx context.Context) error {
107 entries, err := os.ReadDir(g.stagingDir())107 entries, err := os.ReadDir(g.stagingDir())
108 if err != nil {108 if err != nil {
@@ -280,8 +280,6 @@ func (g *Git) DefaultBranch(ctx context.Context, name domain.RepoName) (string,
280 // HasBranch checks refs/heads/<branch> with `git for-each-ref` after280 // HasBranch checks refs/heads/<branch> with `git for-each-ref` after
281 // `git check-ref-format`, which rejects the glob characters for-each-ref281 // `git check-ref-format`, which rejects the glob characters for-each-ref
282 // would otherwise interpret.282 // would otherwise interpret.
283-//
284-//hexcheck:ignore suspicious-business-logic-in-adapter port method name only
285 func (g *Git) HasBranch(ctx context.Context, name domain.RepoName, branch string) (bool, error) {283 func (g *Git) HasBranch(ctx context.Context, name domain.RepoName, branch string) (bool, error) {
286 dir, err := g.repoDir(name)284 dir, err := g.repoDir(name)
287 if err != nil {285 if err != nil {
M internal/adapters/gitcli/stats.go +0 -6
@@ -18,8 +18,6 @@ import (
1818
1919 // CountCommits runs `git rev-list --count`, from the commit graph when the
2020 // repository has one.
21-//
22-//hexcheck:ignore suspicious-business-logic-in-adapter reads the count git prints
2321 func (g *Git) CountCommits(ctx context.Context, repo domain.RepoName, head domain.ObjectID) (int, error) {
2422 if head.IsZero() {
2523 return 0, fmt.Errorf("count commits: %w: no head", domain.ErrInvalid)
@@ -45,8 +43,6 @@ func (g *Git) CountCommits(ctx context.Context, repo domain.RepoName, head domai
4543 // CommitTimes runs `git rev-list --since-as-filter --format=%ct`. The filter
4644 // looks at every reachable commit: --since stops the walk at the first older
4745 // one, and misses newer commits behind it when dates are out of order.
48-//
49-//hexcheck:ignore suspicious-business-logic-in-adapter reads the dates git prints; the bound comes from the port
5046 func (g *Git) CommitTimes(ctx context.Context, repo domain.RepoName, head domain.ObjectID, since time.Time) ([]time.Time, bool, error) {
5147 if head.IsZero() {
5248 return nil, false, fmt.Errorf("commit times: %w: no head", domain.ErrInvalid)
@@ -91,8 +87,6 @@ func (g *Git) CommitTimes(ctx context.Context, repo domain.RepoName, head domain
9187 }
9288
9389 // LatestTag runs `git for-each-ref --sort=-creatordate --count=1` on the tags.
94-//
95-//hexcheck:ignore suspicious-business-logic-in-adapter reads the line git prints
9690 func (g *Git) LatestTag(ctx context.Context, repo domain.RepoName) (domain.TagInfo, bool, error) {
9791 dir, err := g.repoDir(repo)
9892 if err != nil {
@@ -18,8 +18,6 @@ import (
18 18
19 // CountCommits runs `git rev-list --count`, from the commit graph when the19 // CountCommits runs `git rev-list --count`, from the commit graph when the
20 // repository has one.20 // repository has one.
21-//
22-//hexcheck:ignore suspicious-business-logic-in-adapter reads the count git prints
23 func (g *Git) CountCommits(ctx context.Context, repo domain.RepoName, head domain.ObjectID) (int, error) {21 func (g *Git) CountCommits(ctx context.Context, repo domain.RepoName, head domain.ObjectID) (int, error) {
24 if head.IsZero() {22 if head.IsZero() {
25 return 0, fmt.Errorf("count commits: %w: no head", domain.ErrInvalid)23 return 0, fmt.Errorf("count commits: %w: no head", domain.ErrInvalid)
@@ -45,8 +43,6 @@ func (g *Git) CountCommits(ctx context.Context, repo domain.RepoName, head domai
45 // CommitTimes runs `git rev-list --since-as-filter --format=%ct`. The filter43 // CommitTimes runs `git rev-list --since-as-filter --format=%ct`. The filter
46 // looks at every reachable commit: --since stops the walk at the first older44 // looks at every reachable commit: --since stops the walk at the first older
47 // one, and misses newer commits behind it when dates are out of order.45 // one, and misses newer commits behind it when dates are out of order.
48-//
49-//hexcheck:ignore suspicious-business-logic-in-adapter reads the dates git prints; the bound comes from the port
50 func (g *Git) CommitTimes(ctx context.Context, repo domain.RepoName, head domain.ObjectID, since time.Time) ([]time.Time, bool, error) {46 func (g *Git) CommitTimes(ctx context.Context, repo domain.RepoName, head domain.ObjectID, since time.Time) ([]time.Time, bool, error) {
51 if head.IsZero() {47 if head.IsZero() {
52 return nil, false, fmt.Errorf("commit times: %w: no head", domain.ErrInvalid)48 return nil, false, fmt.Errorf("commit times: %w: no head", domain.ErrInvalid)
@@ -91,8 +87,6 @@ func (g *Git) CommitTimes(ctx context.Context, repo domain.RepoName, head domain
91 }87 }
92 88
93 // LatestTag runs `git for-each-ref --sort=-creatordate --count=1` on the tags.89 // LatestTag runs `git for-each-ref --sort=-creatordate --count=1` on the tags.
94-//
95-//hexcheck:ignore suspicious-business-logic-in-adapter reads the line git prints
96 func (g *Git) LatestTag(ctx context.Context, repo domain.RepoName) (domain.TagInfo, bool, error) {90 func (g *Git) LatestTag(ctx context.Context, repo domain.RepoName) (domain.TagInfo, bool, error) {
97 dir, err := g.repoDir(repo)91 dir, err := g.repoDir(repo)
98 if err != nil {92 if err != nil {
M internal/adapters/gitcli/workflow_guard.go +1 -1
@@ -81,7 +81,7 @@ const (
8181 // objects of a push still in quarantine through the environment of the hook
8282 // (ports.PushObjects), accepted only inside the repository's objects directory.
8383 //
84-//hexcheck:ignore suspicious-business-logic-in-adapter reads the object ids and the path git prints for the compared trees; the rule that refuses is the use case's
84+//hexcheck:ignore suspicious-business-logic-in-adapter business rule for which pushed commits and ref changes alter workflows; pending move to domain/usecase
8585 func (g *Git) ChangedWorkflow(ctx context.Context, repo domain.RepoName, updates []domain.RefUpdate, objects ports.PushObjects) (string, error) {
8686 dir, err := g.repoDir(repo)
8787 if err != nil {
@@ -81,7 +81,7 @@ const (
81 // objects of a push still in quarantine through the environment of the hook81 // objects of a push still in quarantine through the environment of the hook
82 // (ports.PushObjects), accepted only inside the repository's objects directory.82 // (ports.PushObjects), accepted only inside the repository's objects directory.
83 //83 //
84-//hexcheck:ignore suspicious-business-logic-in-adapter reads the object ids and the path git prints for the compared trees; the rule that refuses is the use case's84+//hexcheck:ignore suspicious-business-logic-in-adapter business rule for which pushed commits and ref changes alter workflows; pending move to domain/usecase
85 func (g *Git) ChangedWorkflow(ctx context.Context, repo domain.RepoName, updates []domain.RefUpdate, objects ports.PushObjects) (string, error) {85 func (g *Git) ChangedWorkflow(ctx context.Context, repo domain.RepoName, updates []domain.RefUpdate, objects ports.PushObjects) (string, error) {
86 dir, err := g.repoDir(repo)86 dir, err := g.repoDir(repo)
87 if err != nil {87 if err != nil {
M internal/adapters/githttp/handler.go +4 -4
@@ -174,6 +174,8 @@ var gitSuffixes = []string{"/info/refs", "/" + serviceUpload, "/" + serviceRecei
174174 // and /<repo>/git-receive-pack, and the same under /<owner>/ for the owner of
175175 // the forge. info/refs without a service is the dumb protocol, which ermite
176176 // does not serve.
177+//
178+//hexcheck:ignore suspicious-business-logic-in-adapter decodes smart-HTTP repository routes and owner aliases, validating methods and service query parameters
177179 func (h *Handler) parseRoute(r *http.Request) (route, int) {
178180 p := strings.TrimPrefix(r.URL.Path, "/")
179181 var head, rest string
@@ -224,8 +226,6 @@ func (h *Handler) parseRoute(r *http.Request) (route, int) {
224226 }
225227
226228 // ServeHTTP implements http.Handler.
227-//
228-//hexcheck:ignore suspicious-business-logic-in-adapter transport orchestration: the authorization decisions are the use cases'
229229 func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
230230 var rt route
231231 var name domain.RepoName
@@ -328,6 +328,8 @@ func credentials(r *http.Request) (secret string, present bool) {
328328 // denied answers an authorization failure. A caller without valid
329329 // credentials is asked for them wherever the repository does not show itself,
330330 // which keeps a private repository and a missing one indistinguishable.
331+//
332+//hexcheck:ignore suspicious-business-logic-in-adapter maps authorization errors to HTTP responses, challenging anonymous callers on hidden or missing repositories
331333 func (h *Handler) denied(ctx context.Context, w http.ResponseWriter, p domain.Principal, err error) {
332334 switch {
333335 case errors.Is(err, domain.ErrUnauthenticated):
@@ -418,8 +420,6 @@ func (h *Handler) acquire(ctx context.Context, w http.ResponseWriter, rt route,
418420 }
419421
420422 // serveBackend runs git http-backend for an authorized request.
421-//
422-//hexcheck:ignore suspicious-business-logic-in-adapter process and CGI plumbing: no business rule is decided here
423423 func (h *Handler) serveBackend(w http.ResponseWriter, r *http.Request, rt route, name domain.RepoName, p domain.Principal, client string) {
424424 ctx := r.Context()
425425 logger := zerowrap.FromCtx(ctx)
@@ -174,6 +174,8 @@ var gitSuffixes = []string{"/info/refs", "/" + serviceUpload, "/" + serviceRecei
174 // and /<repo>/git-receive-pack, and the same under /<owner>/ for the owner of174 // and /<repo>/git-receive-pack, and the same under /<owner>/ for the owner of
175 // the forge. info/refs without a service is the dumb protocol, which ermite175 // the forge. info/refs without a service is the dumb protocol, which ermite
176 // does not serve.176 // does not serve.
177+//
178+//hexcheck:ignore suspicious-business-logic-in-adapter decodes smart-HTTP repository routes and owner aliases, validating methods and service query parameters
177 func (h *Handler) parseRoute(r *http.Request) (route, int) {179 func (h *Handler) parseRoute(r *http.Request) (route, int) {
178 p := strings.TrimPrefix(r.URL.Path, "/")180 p := strings.TrimPrefix(r.URL.Path, "/")
179 var head, rest string181 var head, rest string
@@ -224,8 +226,6 @@ func (h *Handler) parseRoute(r *http.Request) (route, int) {
224 }226 }
225 227
226 // ServeHTTP implements http.Handler.228 // ServeHTTP implements http.Handler.
227-//
228-//hexcheck:ignore suspicious-business-logic-in-adapter transport orchestration: the authorization decisions are the use cases'
229 func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {229 func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
230 var rt route230 var rt route
231 var name domain.RepoName231 var name domain.RepoName
@@ -328,6 +328,8 @@ func credentials(r *http.Request) (secret string, present bool) {
328 // denied answers an authorization failure. A caller without valid328 // denied answers an authorization failure. A caller without valid
329 // credentials is asked for them wherever the repository does not show itself,329 // credentials is asked for them wherever the repository does not show itself,
330 // which keeps a private repository and a missing one indistinguishable.330 // which keeps a private repository and a missing one indistinguishable.
331+//
332+//hexcheck:ignore suspicious-business-logic-in-adapter maps authorization errors to HTTP responses, challenging anonymous callers on hidden or missing repositories
331 func (h *Handler) denied(ctx context.Context, w http.ResponseWriter, p domain.Principal, err error) {333 func (h *Handler) denied(ctx context.Context, w http.ResponseWriter, p domain.Principal, err error) {
332 switch {334 switch {
333 case errors.Is(err, domain.ErrUnauthenticated):335 case errors.Is(err, domain.ErrUnauthenticated):
@@ -418,8 +420,6 @@ func (h *Handler) acquire(ctx context.Context, w http.ResponseWriter, rt route,
418 }420 }
419 421
420 // serveBackend runs git http-backend for an authorized request.422 // serveBackend runs git http-backend for an authorized request.
421-//
422-//hexcheck:ignore suspicious-business-logic-in-adapter process and CGI plumbing: no business rule is decided here
423 func (h *Handler) serveBackend(w http.ResponseWriter, r *http.Request, rt route, name domain.RepoName, p domain.Principal, client string) {423 func (h *Handler) serveBackend(w http.ResponseWriter, r *http.Request, rt route, name domain.RepoName, p domain.Principal, client string) {
424 ctx := r.Context()424 ctx := r.Context()
425 logger := zerowrap.FromCtx(ctx)425 logger := zerowrap.FromCtx(ctx)
M internal/adapters/githttp/hooks.go +0 -2
@@ -175,8 +175,6 @@ func (s *HookServer) Close(ctx context.Context) {
175175 }
176176
177177 // handle serves one connection: one request line, one reply line.
178-//
179-//hexcheck:ignore suspicious-business-logic-in-adapter hook protocol dispatch: the decisions are the use cases'
180178 func (s *HookServer) handle(ctx context.Context, conn net.Conn) {
181179 log := zerowrap.FromCtx(ctx)
182180 _ = conn.SetReadDeadline(time.Now().Add(readTimeout))
@@ -175,8 +175,6 @@ func (s *HookServer) Close(ctx context.Context) {
175 }175 }
176 176
177 // handle serves one connection: one request line, one reply line.177 // handle serves one connection: one request line, one reply line.
178-//
179-//hexcheck:ignore suspicious-business-logic-in-adapter hook protocol dispatch: the decisions are the use cases'
180 func (s *HookServer) handle(ctx context.Context, conn net.Conn) {178 func (s *HookServer) handle(ctx context.Context, conn net.Conn) {
181 log := zerowrap.FromCtx(ctx)179 log := zerowrap.FromCtx(ctx)
182 _ = conn.SetReadDeadline(time.Now().Add(readTimeout))180 _ = conn.SetReadDeadline(time.Now().Add(readTimeout))
M internal/adapters/kvstore/ci.go +4 -11
@@ -310,6 +310,9 @@ func decodeRun(item kv.Item) (domain.CIRun, error) {
310310 }, nil
311311 }
312312
313+// encodeJob serializes a job for storage.
314+//
315+//hexcheck:ignore suspicious-business-logic-in-adapter encodes a job as protobuf, rejecting an empty repository and omitting an absent token hash
313316 func encodeJob(j domain.CIJob) ([]byte, error) {
314317 if j.Repo.IsZero() {
315318 return nil, fmt.Errorf("%w: empty name", domain.ErrInvalidName)
@@ -346,7 +349,6 @@ func encodeJob(j domain.CIJob) ([]byte, error) {
346349 return mustMarshal(pb), nil
347350 }
348351
349-//hexcheck:ignore suspicious-business-logic-in-adapter maps the stored record to the domain job field by field: no rule is decided here
350352 func decodeJob(item kv.Item) (domain.CIJob, error) {
351353 var pb storagepb.CIJob
352354 if err := proto.Unmarshal(item.Value, &pb); err != nil {
@@ -530,8 +532,6 @@ func (c *CI) stageRecords(ctx context.Context, b *kv.Batch, w ports.CIWrite) (gu
530532 }
531533
532534 // Apply writes the records in one batch.
533-//
534-//hexcheck:ignore suspicious-business-logic-in-adapter stages records and their derived indexes under version preconditions: a storage concern, no policy
535535 func (c *CI) Apply(ctx context.Context, w ports.CIWrite) (uint64, error) {
536536 var b kv.Batch
537537 guarded, err := c.stageRecords(ctx, &b, w)
@@ -578,7 +578,7 @@ const createRunTries = 20
578578
579579 // CreateRun takes the next run id and number and stores the draft.
580580 //
581-//hexcheck:ignore suspicious-business-logic-in-adapter takes the next numbers under version preconditions: a storage concern, no policy
581+//hexcheck:ignore suspicious-business-logic-in-adapter business rule rejecting runs of disabled workflows, atomically with creation; pending move to domain/usecase
582582 func (c *CI) CreateRun(ctx context.Context, repo domain.RepoName, workflowPath string, build func(id, number int64) ports.CIRunDraft) (ports.CIRunDraft, error) {
583583 offKey := workflowOffKey(repo, workflowPath)
584584 for range createRunTries {
@@ -669,8 +669,6 @@ func (c *CI) GetRunSource(ctx context.Context, runID int64) (domain.CIRunSource,
669669 }
670670
671671 // ListRuns returns the runs of the repository, newest first.
672-//
673-//hexcheck:ignore suspicious-business-logic-in-adapter port method name only: reads a key range and reverses it
674672 func (c *CI) ListRuns(ctx context.Context, repo domain.RepoName, before int64, limit int) ([]domain.CIRun, error) {
675673 start := []byte(runsPrefix(repo))
676674 end := []byte(runPrefix + repo.String() + "0") // '/' + 1
@@ -906,8 +904,6 @@ func ciKeys(ctx context.Context, snap *kv.Snapshot, repo domain.RepoName) [][]by
906904 const sweepChunk = 500
907905
908906 // Sweep removes the runs completed before the time.
909-//
910-//hexcheck:ignore suspicious-business-logic-in-adapter chunked delete of expired records: a storage concern, the retention is decided by the caller
911907 func (c *CI) Sweep(ctx context.Context, before time.Time) ([]int64, error) {
912908 snap := c.db.Snapshot(ctx)
913909 var ids []int64
@@ -955,8 +951,6 @@ func runnerNameKey(n string) []byte { return []byte(runnerName + stri
955951 func runnerTokenKey(h domain.TokenHash) []byte { return []byte(runnerTokPref + h.String()) }
956952
957953 // CreateRunner stores the runner, its name index and its token index.
958-//
959-//hexcheck:ignore suspicious-business-logic-in-adapter replaces a runner of the same name in one batch: a storage concern, the rule is decided by the caller
960954 func (c *CI) CreateRunner(ctx context.Context, r domain.CIRunner, replace bool) ([]domain.CIRunner, error) {
961955 for range createRunTries {
962956 var b kv.Batch
@@ -1115,7 +1109,6 @@ func encodeCall(c *domain.CICall) *storagepb.CICall {
11151109 }
11161110 }
11171111
1118-//hexcheck:ignore suspicious-business-logic-in-adapter maps the stored call to the domain call field by field: no rule is decided here
11191112 func decodeCall(pb *storagepb.CICall) *domain.CICall {
11201113 if pb == nil {
11211114 return nil
@@ -310,6 +310,9 @@ func decodeRun(item kv.Item) (domain.CIRun, error) {
310 }, nil310 }, nil
311 }311 }
312 312
313+// encodeJob serializes a job for storage.
314+//
315+//hexcheck:ignore suspicious-business-logic-in-adapter encodes a job as protobuf, rejecting an empty repository and omitting an absent token hash
313 func encodeJob(j domain.CIJob) ([]byte, error) {316 func encodeJob(j domain.CIJob) ([]byte, error) {
314 if j.Repo.IsZero() {317 if j.Repo.IsZero() {
315 return nil, fmt.Errorf("%w: empty name", domain.ErrInvalidName)318 return nil, fmt.Errorf("%w: empty name", domain.ErrInvalidName)
@@ -346,7 +349,6 @@ func encodeJob(j domain.CIJob) ([]byte, error) {
346 return mustMarshal(pb), nil349 return mustMarshal(pb), nil
347 }350 }
348 351
349-//hexcheck:ignore suspicious-business-logic-in-adapter maps the stored record to the domain job field by field: no rule is decided here
350 func decodeJob(item kv.Item) (domain.CIJob, error) {352 func decodeJob(item kv.Item) (domain.CIJob, error) {
351 var pb storagepb.CIJob353 var pb storagepb.CIJob
352 if err := proto.Unmarshal(item.Value, &pb); err != nil {354 if err := proto.Unmarshal(item.Value, &pb); err != nil {
@@ -530,8 +532,6 @@ func (c *CI) stageRecords(ctx context.Context, b *kv.Batch, w ports.CIWrite) (gu
530 }532 }
531 533
532 // Apply writes the records in one batch.534 // Apply writes the records in one batch.
533-//
534-//hexcheck:ignore suspicious-business-logic-in-adapter stages records and their derived indexes under version preconditions: a storage concern, no policy
535 func (c *CI) Apply(ctx context.Context, w ports.CIWrite) (uint64, error) {535 func (c *CI) Apply(ctx context.Context, w ports.CIWrite) (uint64, error) {
536 var b kv.Batch536 var b kv.Batch
537 guarded, err := c.stageRecords(ctx, &b, w)537 guarded, err := c.stageRecords(ctx, &b, w)
@@ -578,7 +578,7 @@ const createRunTries = 20
578 578
579 // CreateRun takes the next run id and number and stores the draft.579 // CreateRun takes the next run id and number and stores the draft.
580 //580 //
581-//hexcheck:ignore suspicious-business-logic-in-adapter takes the next numbers under version preconditions: a storage concern, no policy581+//hexcheck:ignore suspicious-business-logic-in-adapter business rule rejecting runs of disabled workflows, atomically with creation; pending move to domain/usecase
582 func (c *CI) CreateRun(ctx context.Context, repo domain.RepoName, workflowPath string, build func(id, number int64) ports.CIRunDraft) (ports.CIRunDraft, error) {582 func (c *CI) CreateRun(ctx context.Context, repo domain.RepoName, workflowPath string, build func(id, number int64) ports.CIRunDraft) (ports.CIRunDraft, error) {
583 offKey := workflowOffKey(repo, workflowPath)583 offKey := workflowOffKey(repo, workflowPath)
584 for range createRunTries {584 for range createRunTries {
@@ -669,8 +669,6 @@ func (c *CI) GetRunSource(ctx context.Context, runID int64) (domain.CIRunSource,
669 }669 }
670 670
671 // ListRuns returns the runs of the repository, newest first.671 // ListRuns returns the runs of the repository, newest first.
672-//
673-//hexcheck:ignore suspicious-business-logic-in-adapter port method name only: reads a key range and reverses it
674 func (c *CI) ListRuns(ctx context.Context, repo domain.RepoName, before int64, limit int) ([]domain.CIRun, error) {672 func (c *CI) ListRuns(ctx context.Context, repo domain.RepoName, before int64, limit int) ([]domain.CIRun, error) {
675 start := []byte(runsPrefix(repo))673 start := []byte(runsPrefix(repo))
676 end := []byte(runPrefix + repo.String() + "0") // '/' + 1674 end := []byte(runPrefix + repo.String() + "0") // '/' + 1
@@ -906,8 +904,6 @@ func ciKeys(ctx context.Context, snap *kv.Snapshot, repo domain.RepoName) [][]by
906 const sweepChunk = 500904 const sweepChunk = 500
907 905
908 // Sweep removes the runs completed before the time.906 // Sweep removes the runs completed before the time.
909-//
910-//hexcheck:ignore suspicious-business-logic-in-adapter chunked delete of expired records: a storage concern, the retention is decided by the caller
911 func (c *CI) Sweep(ctx context.Context, before time.Time) ([]int64, error) {907 func (c *CI) Sweep(ctx context.Context, before time.Time) ([]int64, error) {
912 snap := c.db.Snapshot(ctx)908 snap := c.db.Snapshot(ctx)
913 var ids []int64909 var ids []int64
@@ -955,8 +951,6 @@ func runnerNameKey(n string) []byte { return []byte(runnerName + stri
955 func runnerTokenKey(h domain.TokenHash) []byte { return []byte(runnerTokPref + h.String()) }951 func runnerTokenKey(h domain.TokenHash) []byte { return []byte(runnerTokPref + h.String()) }
956 952
957 // CreateRunner stores the runner, its name index and its token index.953 // CreateRunner stores the runner, its name index and its token index.
958-//
959-//hexcheck:ignore suspicious-business-logic-in-adapter replaces a runner of the same name in one batch: a storage concern, the rule is decided by the caller
960 func (c *CI) CreateRunner(ctx context.Context, r domain.CIRunner, replace bool) ([]domain.CIRunner, error) {954 func (c *CI) CreateRunner(ctx context.Context, r domain.CIRunner, replace bool) ([]domain.CIRunner, error) {
961 for range createRunTries {955 for range createRunTries {
962 var b kv.Batch956 var b kv.Batch
@@ -1115,7 +1109,6 @@ func encodeCall(c *domain.CICall) *storagepb.CICall {
1115 }1109 }
1116 }1110 }
1117 1111
1118-//hexcheck:ignore suspicious-business-logic-in-adapter maps the stored call to the domain call field by field: no rule is decided here
1119 func decodeCall(pb *storagepb.CICall) *domain.CICall {1112 func decodeCall(pb *storagepb.CICall) *domain.CICall {
1120 if pb == nil {1113 if pb == nil {
1121 return nil1114 return nil
M internal/adapters/kvstore/ci_artifact.go +3 -5
@@ -79,6 +79,9 @@ var artifactStates = []struct {
7979 {domain.CIArtifactFinal, storagepb.CIArtifactState_CI_ARTIFACT_STATE_FINAL},
8080 }
8181
82+// encodeArtifact serializes an artifact for storage.
83+//
84+//hexcheck:ignore suspicious-business-logic-in-adapter validates artifact storage identifiers, UTF-8 and enum encoding before protobuf serialization
8285 func encodeArtifact(a domain.CIArtifact) ([]byte, error) {
8386 if a.Repo.IsZero() || a.ID < 1 || a.RunID < 1 {
8487 return nil, fmt.Errorf("%w: artifact without id, run or repository", domain.ErrInvalid)
@@ -106,7 +109,6 @@ func encodeArtifact(a domain.CIArtifact) ([]byte, error) {
106109 return mustMarshal(pb), nil
107110 }
108111
109-//hexcheck:ignore suspicious-business-logic-in-adapter decodes a record into the domain type: a storage concern, no policy
110112 func decodeArtifact(item kv.Item) (domain.CIArtifact, error) {
111113 var pb storagepb.CIArtifact
112114 if err := proto.Unmarshal(item.Value, &pb); err != nil {
@@ -141,8 +143,6 @@ func decodeArtifact(item kv.Item) (domain.CIArtifact, error) {
141143 const artifactIDTries = 1000
142144
143145 // NextArtifactID takes the next id in its own batch.
144-//
145-//hexcheck:ignore suspicious-business-logic-in-adapter takes the next number under a version precondition: a storage concern, no policy
146146 func (c *CIArtifacts) NextArtifactID(ctx context.Context) (int64, error) {
147147 ci := &CI{db: c.db}
148148 for range artifactIDTries {
@@ -274,8 +274,6 @@ func (c *CIArtifacts) BlockArtifactIDs(ctx context.Context) ([]int64, error) {
274274 // --- writes ---
275275
276276 // ApplyArtifacts writes w in one batch.
277-//
278-//hexcheck:ignore suspicious-business-logic-in-adapter stages records and their derived keys under version preconditions: a storage concern, no policy
279277 func (c *CIArtifacts) ApplyArtifacts(ctx context.Context, w ports.CIArtifactWrite) error {
280278 var b kv.Batch
281279 guard := false
@@ -79,6 +79,9 @@ var artifactStates = []struct {
79 {domain.CIArtifactFinal, storagepb.CIArtifactState_CI_ARTIFACT_STATE_FINAL},79 {domain.CIArtifactFinal, storagepb.CIArtifactState_CI_ARTIFACT_STATE_FINAL},
80 }80 }
81 81
82+// encodeArtifact serializes an artifact for storage.
83+//
84+//hexcheck:ignore suspicious-business-logic-in-adapter validates artifact storage identifiers, UTF-8 and enum encoding before protobuf serialization
82 func encodeArtifact(a domain.CIArtifact) ([]byte, error) {85 func encodeArtifact(a domain.CIArtifact) ([]byte, error) {
83 if a.Repo.IsZero() || a.ID < 1 || a.RunID < 1 {86 if a.Repo.IsZero() || a.ID < 1 || a.RunID < 1 {
84 return nil, fmt.Errorf("%w: artifact without id, run or repository", domain.ErrInvalid)87 return nil, fmt.Errorf("%w: artifact without id, run or repository", domain.ErrInvalid)
@@ -106,7 +109,6 @@ func encodeArtifact(a domain.CIArtifact) ([]byte, error) {
106 return mustMarshal(pb), nil109 return mustMarshal(pb), nil
107 }110 }
108 111
109-//hexcheck:ignore suspicious-business-logic-in-adapter decodes a record into the domain type: a storage concern, no policy
110 func decodeArtifact(item kv.Item) (domain.CIArtifact, error) {112 func decodeArtifact(item kv.Item) (domain.CIArtifact, error) {
111 var pb storagepb.CIArtifact113 var pb storagepb.CIArtifact
112 if err := proto.Unmarshal(item.Value, &pb); err != nil {114 if err := proto.Unmarshal(item.Value, &pb); err != nil {
@@ -141,8 +143,6 @@ func decodeArtifact(item kv.Item) (domain.CIArtifact, error) {
141 const artifactIDTries = 1000143 const artifactIDTries = 1000
142 144
143 // NextArtifactID takes the next id in its own batch.145 // NextArtifactID takes the next id in its own batch.
144-//
145-//hexcheck:ignore suspicious-business-logic-in-adapter takes the next number under a version precondition: a storage concern, no policy
146 func (c *CIArtifacts) NextArtifactID(ctx context.Context) (int64, error) {146 func (c *CIArtifacts) NextArtifactID(ctx context.Context) (int64, error) {
147 ci := &CI{db: c.db}147 ci := &CI{db: c.db}
148 for range artifactIDTries {148 for range artifactIDTries {
@@ -274,8 +274,6 @@ func (c *CIArtifacts) BlockArtifactIDs(ctx context.Context) ([]int64, error) {
274 // --- writes ---274 // --- writes ---
275 275
276 // ApplyArtifacts writes w in one batch.276 // ApplyArtifacts writes w in one batch.
277-//
278-//hexcheck:ignore suspicious-business-logic-in-adapter stages records and their derived keys under version preconditions: a storage concern, no policy
279 func (c *CIArtifacts) ApplyArtifacts(ctx context.Context, w ports.CIArtifactWrite) error {277 func (c *CIArtifacts) ApplyArtifacts(ctx context.Context, w ports.CIArtifactWrite) error {
280 var b kv.Batch278 var b kv.Batch
281 guard := false279 guard := false
M internal/adapters/kvstore/ci_concurrency.go +0 -4
@@ -103,7 +103,6 @@ func encodeConcurrencyRecord(r domain.CIConcurrencyRecord) []byte {
103103 return mustMarshal(pb)
104104 }
105105
106-//hexcheck:ignore suspicious-business-logic-in-adapter maps the stored record to the domain record field by field: no rule is decided here
107106 func decodeConcurrencyRecord(val []byte) (domain.CIConcurrencyRecord, error) {
108107 var pb storagepb.CIConcurrencyRecord
109108 if err := proto.Unmarshal(val, &pb); err != nil {
@@ -146,7 +145,6 @@ func encodeConcurrencyMark(m domain.CIConcurrencyMark) []byte {
146145 return mustMarshal(pb)
147146 }
148147
149-//hexcheck:ignore suspicious-business-logic-in-adapter maps the stored mark to the domain mark field by field: no rule is decided here
150148 func decodeConcurrencyMark(val []byte) (domain.CIConcurrencyMark, error) {
151149 var pb storagepb.CIConcurrencyMark
152150 if err := proto.Unmarshal(val, &pb); err != nil {
@@ -257,8 +255,6 @@ func (c *CI) UpdateConcurrency(ctx context.Context, repo domain.RepoName, group
257255 }
258256
259257 // ListConcurrency returns every stored group with its marks.
260-//
261-//hexcheck:ignore suspicious-business-logic-in-adapter lists and decodes records and marks: no rule is decided here
262258 func (c *CI) ListConcurrency(ctx context.Context) ([]ports.CIConcurrencyGroup, error) {
263259 type id struct{ repo, group string }
264260 snap := c.db.Snapshot(ctx)
@@ -103,7 +103,6 @@ func encodeConcurrencyRecord(r domain.CIConcurrencyRecord) []byte {
103 return mustMarshal(pb)103 return mustMarshal(pb)
104 }104 }
105 105
106-//hexcheck:ignore suspicious-business-logic-in-adapter maps the stored record to the domain record field by field: no rule is decided here
107 func decodeConcurrencyRecord(val []byte) (domain.CIConcurrencyRecord, error) {106 func decodeConcurrencyRecord(val []byte) (domain.CIConcurrencyRecord, error) {
108 var pb storagepb.CIConcurrencyRecord107 var pb storagepb.CIConcurrencyRecord
109 if err := proto.Unmarshal(val, &pb); err != nil {108 if err := proto.Unmarshal(val, &pb); err != nil {
@@ -146,7 +145,6 @@ func encodeConcurrencyMark(m domain.CIConcurrencyMark) []byte {
146 return mustMarshal(pb)145 return mustMarshal(pb)
147 }146 }
148 147
149-//hexcheck:ignore suspicious-business-logic-in-adapter maps the stored mark to the domain mark field by field: no rule is decided here
150 func decodeConcurrencyMark(val []byte) (domain.CIConcurrencyMark, error) {148 func decodeConcurrencyMark(val []byte) (domain.CIConcurrencyMark, error) {
151 var pb storagepb.CIConcurrencyMark149 var pb storagepb.CIConcurrencyMark
152 if err := proto.Unmarshal(val, &pb); err != nil {150 if err := proto.Unmarshal(val, &pb); err != nil {
@@ -257,8 +255,6 @@ func (c *CI) UpdateConcurrency(ctx context.Context, repo domain.RepoName, group
257 }255 }
258 256
259 // ListConcurrency returns every stored group with its marks.257 // ListConcurrency returns every stored group with its marks.
260-//
261-//hexcheck:ignore suspicious-business-logic-in-adapter lists and decodes records and marks: no rule is decided here
262 func (c *CI) ListConcurrency(ctx context.Context) ([]ports.CIConcurrencyGroup, error) {258 func (c *CI) ListConcurrency(ctx context.Context) ([]ports.CIConcurrencyGroup, error) {
263 type id struct{ repo, group string }259 type id struct{ repo, group string }
264 snap := c.db.Snapshot(ctx)260 snap := c.db.Snapshot(ctx)
M internal/adapters/kvstore/ci_settings.go +6 -4
@@ -85,6 +85,8 @@ func settingsKeys(ctx context.Context, snap *kv.Snapshot, repo domain.RepoName)
8585
8686 // BindSecretsKey stores the key check when there is none and compares it
8787 // otherwise.
88+//
89+//hexcheck:ignore suspicious-business-logic-in-adapter initializes or compares the persisted encryption-key check with compare-and-swap retries
8890 func (s *Settings) BindSecretsKey(ctx context.Context, check []byte) error {
8991 key := []byte(secretsKeyCheck)
9092 for range updateAttempts {
@@ -111,6 +113,8 @@ func (s *Settings) BindSecretsKey(ctx context.Context, check []byte) error {
111113
112114 // stage makes the batch depend on the scope: the repository key is guarded
113115 // and, for an environment, its record is required at the version read.
116+//
117+//hexcheck:ignore suspicious-business-logic-in-adapter validates a settings scope and adds repository and environment existence/version preconditions to a storage batch
114118 func (s *Settings) stage(ctx context.Context, b *kv.Batch, scope domain.SettingsScope) error {
115119 if !scope.Valid() {
116120 return fmt.Errorf("%w: scope", domain.ErrInvalid)
@@ -203,6 +207,8 @@ func (s *Settings) GetSealedSecret(ctx context.Context, scope domain.SettingsSco
203207 }
204208
205209 // existsIn is exists on a snapshot, so a listing and its check agree.
210+//
211+//hexcheck:ignore suspicious-business-logic-in-adapter validates a settings scope and checks repository and environment keys in the same snapshot as a listing
206212 func (s *Settings) existsIn(ctx context.Context, snap *kv.Snapshot, scope domain.SettingsScope) error {
207213 if !scope.Valid() {
208214 return fmt.Errorf("%w: scope", domain.ErrInvalid)
@@ -309,8 +315,6 @@ func decodeEnvironment(val []byte) (domain.Environment, error) {
309315 }
310316
311317 // CreateEnvironment implements ports.CISettingsStore.
312-//
313-//hexcheck:ignore suspicious-business-logic-in-adapter create-if-absent under a version precondition: a storage concern, no policy
314318 func (s *Settings) CreateEnvironment(ctx context.Context, repo domain.RepoName, name string, at time.Time) (domain.Environment, error) {
315319 key := envKey(repo, name)
316320 for range updateAttempts {
@@ -353,8 +357,6 @@ func (s *Settings) ListEnvironments(ctx context.Context, repo domain.RepoName) (
353357 }
354358
355359 // DeleteEnvironment implements ports.CISettingsStore.
356-//
357-//hexcheck:ignore suspicious-business-logic-in-adapter removes the keys of an environment in one batch: a storage concern, no policy
358360 func (s *Settings) DeleteEnvironment(ctx context.Context, repo domain.RepoName, name string) error {
359361 key := envKey(repo, name)
360362 scope := domain.EnvironmentScope(repo, name)
@@ -85,6 +85,8 @@ func settingsKeys(ctx context.Context, snap *kv.Snapshot, repo domain.RepoName)
85 85
86 // BindSecretsKey stores the key check when there is none and compares it86 // BindSecretsKey stores the key check when there is none and compares it
87 // otherwise.87 // otherwise.
88+//
89+//hexcheck:ignore suspicious-business-logic-in-adapter initializes or compares the persisted encryption-key check with compare-and-swap retries
88 func (s *Settings) BindSecretsKey(ctx context.Context, check []byte) error {90 func (s *Settings) BindSecretsKey(ctx context.Context, check []byte) error {
89 key := []byte(secretsKeyCheck)91 key := []byte(secretsKeyCheck)
90 for range updateAttempts {92 for range updateAttempts {
@@ -111,6 +113,8 @@ func (s *Settings) BindSecretsKey(ctx context.Context, check []byte) error {
111 113
112 // stage makes the batch depend on the scope: the repository key is guarded114 // stage makes the batch depend on the scope: the repository key is guarded
113 // and, for an environment, its record is required at the version read.115 // and, for an environment, its record is required at the version read.
116+//
117+//hexcheck:ignore suspicious-business-logic-in-adapter validates a settings scope and adds repository and environment existence/version preconditions to a storage batch
114 func (s *Settings) stage(ctx context.Context, b *kv.Batch, scope domain.SettingsScope) error {118 func (s *Settings) stage(ctx context.Context, b *kv.Batch, scope domain.SettingsScope) error {
115 if !scope.Valid() {119 if !scope.Valid() {
116 return fmt.Errorf("%w: scope", domain.ErrInvalid)120 return fmt.Errorf("%w: scope", domain.ErrInvalid)
@@ -203,6 +207,8 @@ func (s *Settings) GetSealedSecret(ctx context.Context, scope domain.SettingsSco
203 }207 }
204 208
205 // existsIn is exists on a snapshot, so a listing and its check agree.209 // existsIn is exists on a snapshot, so a listing and its check agree.
210+//
211+//hexcheck:ignore suspicious-business-logic-in-adapter validates a settings scope and checks repository and environment keys in the same snapshot as a listing
206 func (s *Settings) existsIn(ctx context.Context, snap *kv.Snapshot, scope domain.SettingsScope) error {212 func (s *Settings) existsIn(ctx context.Context, snap *kv.Snapshot, scope domain.SettingsScope) error {
207 if !scope.Valid() {213 if !scope.Valid() {
208 return fmt.Errorf("%w: scope", domain.ErrInvalid)214 return fmt.Errorf("%w: scope", domain.ErrInvalid)
@@ -309,8 +315,6 @@ func decodeEnvironment(val []byte) (domain.Environment, error) {
309 }315 }
310 316
311 // CreateEnvironment implements ports.CISettingsStore.317 // CreateEnvironment implements ports.CISettingsStore.
312-//
313-//hexcheck:ignore suspicious-business-logic-in-adapter create-if-absent under a version precondition: a storage concern, no policy
314 func (s *Settings) CreateEnvironment(ctx context.Context, repo domain.RepoName, name string, at time.Time) (domain.Environment, error) {318 func (s *Settings) CreateEnvironment(ctx context.Context, repo domain.RepoName, name string, at time.Time) (domain.Environment, error) {
315 key := envKey(repo, name)319 key := envKey(repo, name)
316 for range updateAttempts {320 for range updateAttempts {
@@ -353,8 +357,6 @@ func (s *Settings) ListEnvironments(ctx context.Context, repo domain.RepoName) (
353 }357 }
354 358
355 // DeleteEnvironment implements ports.CISettingsStore.359 // DeleteEnvironment implements ports.CISettingsStore.
356-//
357-//hexcheck:ignore suspicious-business-logic-in-adapter removes the keys of an environment in one batch: a storage concern, no policy
358 func (s *Settings) DeleteEnvironment(ctx context.Context, repo domain.RepoName, name string) error {360 func (s *Settings) DeleteEnvironment(ctx context.Context, repo domain.RepoName, name string) error {
359 key := envKey(repo, name)361 key := envKey(repo, name)
360 scope := domain.EnvironmentScope(repo, name)362 scope := domain.EnvironmentScope(repo, name)
M internal/adapters/kvstore/issues.go +0 -8
@@ -84,8 +84,6 @@ func issueKeys(ctx context.Context, snap *kv.Snapshot, repo domain.RepoName) [][
8484 // Create takes the next number of the repository from mrseq/<repo>, the
8585 // sequence of the merge requests, and stores the issue under it; see
8686 // createNumbered. A missing repository gives domain.ErrNotFound.
87-//
88-//hexcheck:ignore suspicious-business-logic-in-adapter takes the next number under a version precondition: a storage concern, no policy
8987 func (i *Issues) Create(ctx context.Context, issue domain.Issue) (domain.Issue, error) {
9088 err := createNumbered(ctx, i.db, i.locks, issue.Repo, func(b *kv.Batch, n int64) error {
9189 issue.Number = n
@@ -118,8 +116,6 @@ func (i *Issues) Get(ctx context.Context, repo domain.RepoName, number int64) (d
118116
119117 // List returns a page of the issues of the repository, highest number first. The
120118 // page token is the last number of the previous page.
121-//
122-//hexcheck:ignore suspicious-business-logic-in-adapter pages through the keys of a prefix: a storage concern, no policy
123119 func (i *Issues) List(ctx context.Context, repo domain.RepoName, params ports.ListIssuesParams) (ports.IssuePage, error) {
124120 before := int64(0) // 0: from the highest
125121 if params.PageToken != "" {
@@ -225,8 +221,6 @@ func (i *Issues) ListOpenAll(ctx context.Context) ([]domain.Issue, error) {
225221 // Update replaces the issue with a version precondition and moves its index key
226222 // in the same batch. The repository must exist (see guardRepoKey), so that a
227223 // concurrent delete of the repository leaves no index key behind.
228-//
229-//hexcheck:ignore suspicious-business-logic-in-adapter port method name only
230224 func (i *Issues) Update(ctx context.Context, issue domain.Issue) error {
231225 val, err := encodeIssue(issue)
232226 if err != nil {
@@ -330,7 +324,6 @@ func encodeIssue(issue domain.Issue) ([]byte, error) {
330324 }), nil
331325 }
332326
333-//hexcheck:ignore suspicious-business-logic-in-adapter schema decoding, not a policy
334327 func decodeIssue(repo domain.RepoName, item kv.Item) (domain.Issue, error) {
335328 var pb storagepb.Issue
336329 if err := proto.Unmarshal(item.Value, &pb); err != nil {
@@ -373,7 +366,6 @@ func encodeIssueComment(c domain.IssueComment) ([]byte, error) {
373366 }), nil
374367 }
375368
376-//hexcheck:ignore suspicious-business-logic-in-adapter schema decoding, not a policy
377369 func decodeIssueComment(item kv.Item) (domain.IssueComment, error) {
378370 var pb storagepb.IssueComment
379371 if err := proto.Unmarshal(item.Value, &pb); err != nil {
@@ -84,8 +84,6 @@ func issueKeys(ctx context.Context, snap *kv.Snapshot, repo domain.RepoName) [][
84 // Create takes the next number of the repository from mrseq/<repo>, the84 // Create takes the next number of the repository from mrseq/<repo>, the
85 // sequence of the merge requests, and stores the issue under it; see85 // sequence of the merge requests, and stores the issue under it; see
86 // createNumbered. A missing repository gives domain.ErrNotFound.86 // createNumbered. A missing repository gives domain.ErrNotFound.
87-//
88-//hexcheck:ignore suspicious-business-logic-in-adapter takes the next number under a version precondition: a storage concern, no policy
89 func (i *Issues) Create(ctx context.Context, issue domain.Issue) (domain.Issue, error) {87 func (i *Issues) Create(ctx context.Context, issue domain.Issue) (domain.Issue, error) {
90 err := createNumbered(ctx, i.db, i.locks, issue.Repo, func(b *kv.Batch, n int64) error {88 err := createNumbered(ctx, i.db, i.locks, issue.Repo, func(b *kv.Batch, n int64) error {
91 issue.Number = n89 issue.Number = n
@@ -118,8 +116,6 @@ func (i *Issues) Get(ctx context.Context, repo domain.RepoName, number int64) (d
118 116
119 // List returns a page of the issues of the repository, highest number first. The117 // List returns a page of the issues of the repository, highest number first. The
120 // page token is the last number of the previous page.118 // page token is the last number of the previous page.
121-//
122-//hexcheck:ignore suspicious-business-logic-in-adapter pages through the keys of a prefix: a storage concern, no policy
123 func (i *Issues) List(ctx context.Context, repo domain.RepoName, params ports.ListIssuesParams) (ports.IssuePage, error) {119 func (i *Issues) List(ctx context.Context, repo domain.RepoName, params ports.ListIssuesParams) (ports.IssuePage, error) {
124 before := int64(0) // 0: from the highest120 before := int64(0) // 0: from the highest
125 if params.PageToken != "" {121 if params.PageToken != "" {
@@ -225,8 +221,6 @@ func (i *Issues) ListOpenAll(ctx context.Context) ([]domain.Issue, error) {
225 // Update replaces the issue with a version precondition and moves its index key221 // Update replaces the issue with a version precondition and moves its index key
226 // in the same batch. The repository must exist (see guardRepoKey), so that a222 // in the same batch. The repository must exist (see guardRepoKey), so that a
227 // concurrent delete of the repository leaves no index key behind.223 // concurrent delete of the repository leaves no index key behind.
228-//
229-//hexcheck:ignore suspicious-business-logic-in-adapter port method name only
230 func (i *Issues) Update(ctx context.Context, issue domain.Issue) error {224 func (i *Issues) Update(ctx context.Context, issue domain.Issue) error {
231 val, err := encodeIssue(issue)225 val, err := encodeIssue(issue)
232 if err != nil {226 if err != nil {
@@ -330,7 +324,6 @@ func encodeIssue(issue domain.Issue) ([]byte, error) {
330 }), nil324 }), nil
331 }325 }
332 326
333-//hexcheck:ignore suspicious-business-logic-in-adapter schema decoding, not a policy
334 func decodeIssue(repo domain.RepoName, item kv.Item) (domain.Issue, error) {327 func decodeIssue(repo domain.RepoName, item kv.Item) (domain.Issue, error) {
335 var pb storagepb.Issue328 var pb storagepb.Issue
336 if err := proto.Unmarshal(item.Value, &pb); err != nil {329 if err := proto.Unmarshal(item.Value, &pb); err != nil {
@@ -373,7 +366,6 @@ func encodeIssueComment(c domain.IssueComment) ([]byte, error) {
373 }), nil366 }), nil
374 }367 }
375 368
376-//hexcheck:ignore suspicious-business-logic-in-adapter schema decoding, not a policy
377 func decodeIssueComment(item kv.Item) (domain.IssueComment, error) {369 func decodeIssueComment(item kv.Item) (domain.IssueComment, error) {
378 var pb storagepb.IssueComment370 var pb storagepb.IssueComment
379 if err := proto.Unmarshal(item.Value, &pb); err != nil {371 if err := proto.Unmarshal(item.Value, &pb); err != nil {
M internal/adapters/kvstore/issues_pending.go +0 -5
@@ -94,8 +94,6 @@ func (s *PendingIssues) Get(ctx context.Context, repo domain.RepoName, id domain
9494 // creation time then repository then id. There are at most
9595 // domain.MaxPendingIssues of them (a little more under a race), so they are
9696 // read and sorted. The page token is the position of the last item returned.
97-//
98-//hexcheck:ignore suspicious-business-logic-in-adapter pages through the keys of a prefix: a storage concern, no policy
9997 func (s *PendingIssues) List(ctx context.Context, repo domain.RepoName, page ports.ListPendingParams) (ports.PendingIssuePage, error) {
10098 prefix := pendingPrefix
10199 if !repo.IsZero() {
@@ -216,8 +214,6 @@ func (s *PendingIssues) Count(ctx context.Context) (int, error) {
216214 // Approve numbers the pending issue from mrseq/<repo> (see createNumbered),
217215 // writes the open issue and its index key and deletes the pending record, in
218216 // one batch that requires the pending record to be unchanged.
219-//
220-//hexcheck:ignore suspicious-business-logic-in-adapter only sets the number under a version precondition; the issue itself is built by domain.ApprovedIssue
221217 func (s *PendingIssues) Approve(ctx context.Context, repo domain.RepoName, id domain.PendingIssueID, now time.Time) (domain.Issue, error) {
222218 var number int64
223219 err := createNumbered(ctx, s.db, s.locks, repo, func(b *kv.Batch, n int64) error {
@@ -291,7 +287,6 @@ func encodePending(p domain.PendingIssue) ([]byte, error) {
291287 }), nil
292288 }
293289
294-//hexcheck:ignore suspicious-business-logic-in-adapter schema decoding, not a policy
295290 func decodePending(repo domain.RepoName, id domain.PendingIssueID, item kv.Item) (domain.PendingIssue, error) {
296291 var pb storagepb.PendingIssue
297292 if err := proto.Unmarshal(item.Value, &pb); err != nil {
@@ -94,8 +94,6 @@ func (s *PendingIssues) Get(ctx context.Context, repo domain.RepoName, id domain
94 // creation time then repository then id. There are at most94 // creation time then repository then id. There are at most
95 // domain.MaxPendingIssues of them (a little more under a race), so they are95 // domain.MaxPendingIssues of them (a little more under a race), so they are
96 // read and sorted. The page token is the position of the last item returned.96 // read and sorted. The page token is the position of the last item returned.
97-//
98-//hexcheck:ignore suspicious-business-logic-in-adapter pages through the keys of a prefix: a storage concern, no policy
99 func (s *PendingIssues) List(ctx context.Context, repo domain.RepoName, page ports.ListPendingParams) (ports.PendingIssuePage, error) {97 func (s *PendingIssues) List(ctx context.Context, repo domain.RepoName, page ports.ListPendingParams) (ports.PendingIssuePage, error) {
100 prefix := pendingPrefix98 prefix := pendingPrefix
101 if !repo.IsZero() {99 if !repo.IsZero() {
@@ -216,8 +214,6 @@ func (s *PendingIssues) Count(ctx context.Context) (int, error) {
216 // Approve numbers the pending issue from mrseq/<repo> (see createNumbered),214 // Approve numbers the pending issue from mrseq/<repo> (see createNumbered),
217 // writes the open issue and its index key and deletes the pending record, in215 // writes the open issue and its index key and deletes the pending record, in
218 // one batch that requires the pending record to be unchanged.216 // one batch that requires the pending record to be unchanged.
219-//
220-//hexcheck:ignore suspicious-business-logic-in-adapter only sets the number under a version precondition; the issue itself is built by domain.ApprovedIssue
221 func (s *PendingIssues) Approve(ctx context.Context, repo domain.RepoName, id domain.PendingIssueID, now time.Time) (domain.Issue, error) {217 func (s *PendingIssues) Approve(ctx context.Context, repo domain.RepoName, id domain.PendingIssueID, now time.Time) (domain.Issue, error) {
222 var number int64218 var number int64
223 err := createNumbered(ctx, s.db, s.locks, repo, func(b *kv.Batch, n int64) error {219 err := createNumbered(ctx, s.db, s.locks, repo, func(b *kv.Batch, n int64) error {
@@ -291,7 +287,6 @@ func encodePending(p domain.PendingIssue) ([]byte, error) {
291 }), nil287 }), nil
292 }288 }
293 289
294-//hexcheck:ignore suspicious-business-logic-in-adapter schema decoding, not a policy
295 func decodePending(repo domain.RepoName, id domain.PendingIssueID, item kv.Item) (domain.PendingIssue, error) {290 func decodePending(repo domain.RepoName, id domain.PendingIssueID, item kv.Item) (domain.PendingIssue, error) {
296 var pb storagepb.PendingIssue291 var pb storagepb.PendingIssue
297 if err := proto.Unmarshal(item.Value, &pb); err != nil {292 if err := proto.Unmarshal(item.Value, &pb); err != nil {
M internal/adapters/kvstore/mergerequests.go +3 -9
@@ -96,6 +96,8 @@ func indexKey(prefix string, repo domain.RepoName, branch string, n int64) []byt
9696 // when old is not known, as for a new request or a comment: the keys of mr are
9797 // then put or deleted, whatever they were). Deleting a key that is not there is
9898 // not an error.
99+//
100+//hexcheck:ignore suspicious-business-logic-in-adapter maintains source and target indexes to match the stored merge request open state and branch names
99101 func indexOpen(b *kv.Batch, old *domain.MergeRequest, mr domain.MergeRequest) {
100102 if old != nil && old.IsOpen() {
101103 if !mr.IsOpen() || old.Source != mr.Source {
@@ -204,8 +206,6 @@ func (m *MergeRequests) guardRepo(ctx context.Context, b *kv.Batch, repo domain.
204206 // rewrites it (see guardRepo), so that a repository deleted meanwhile is not
205207 // left with a stray merge request (a push recording pushed_at makes it retry). A missing repository gives
206208 // domain.ErrNotFound.
207-//
208-//hexcheck:ignore suspicious-business-logic-in-adapter takes the next number under a version precondition: a storage concern, no policy
209209 func (m *MergeRequests) Create(ctx context.Context, mr domain.MergeRequest) (domain.MergeRequest, error) {
210210 err := createNumbered(ctx, m.db, m.locks, mr.Repo, func(b *kv.Batch, n int64) error {
211211 mr.Number = n
@@ -451,7 +451,7 @@ func (m *MergeRequests) CountOpen(ctx context.Context, repo domain.RepoName) (in
451451
452452 // Update replaces the merge request with a version precondition.
453453 //
454-//hexcheck:ignore suspicious-business-logic-in-adapter port method name only
454+//hexcheck:ignore suspicious-business-logic-in-adapter replaces a versioned record and maintains open-request indexes and the derived mergeability record
455455 func (m *MergeRequests) Update(ctx context.Context, mr domain.MergeRequest) error {
456456 val, err := encodeMergeRequest(mr)
457457 if err != nil {
@@ -564,8 +564,6 @@ func (m *MergeRequests) GetRead(ctx context.Context, repo domain.RepoName, numbe
564564
565565 // SetRead writes mrread/<repo>/<number>. The repository must exist (see
566566 // guardRepo): domain.ErrNotFound otherwise.
567-//
568-//hexcheck:ignore suspicious-business-logic-in-adapter retries a write that lost a race with the repository key: a storage concern, no policy
569567 func (m *MergeRequests) SetRead(ctx context.Context, repo domain.RepoName, number int64, head domain.ObjectID) error {
570568 if head.IsZero() {
571569 return fmt.Errorf("%w: empty read position", domain.ErrInvalidObjectID)
@@ -748,7 +746,6 @@ func encodeMergeRequest(mr domain.MergeRequest) ([]byte, error) {
748746 }), nil
749747 }
750748
751-//hexcheck:ignore suspicious-business-logic-in-adapter schema decoding, not a policy
752749 func decodeMergeRequest(repo domain.RepoName, item kv.Item) (domain.MergeRequest, error) {
753750 var pb storagepb.MergeRequest
754751 if err := proto.Unmarshal(item.Value, &pb); err != nil {
@@ -815,7 +812,6 @@ func encodeComment(c domain.Comment) ([]byte, error) {
815812 }), nil
816813 }
817814
818-//hexcheck:ignore suspicious-business-logic-in-adapter schema decoding, not a policy
819815 func decodeComment(item kv.Item) (domain.Comment, error) {
820816 var pb storagepb.Comment
821817 if err := proto.Unmarshal(item.Value, &pb); err != nil {
@@ -931,8 +927,6 @@ func encodeSettings(s domain.RepoSettings) (*storagepb.RepoSettings, error) {
931927
932928 // decodeSettings returns the defaults for a repository stored before merge
933929 // requests existed, and for settings left with no mode that this build knows.
934-//
935-//hexcheck:ignore suspicious-business-logic-in-adapter schema decoding with the documented defaults
936930 func decodeSettings(pb *storagepb.RepoSettings) domain.RepoSettings {
937931 if pb == nil {
938932 return domain.DefaultRepoSettings()
@@ -96,6 +96,8 @@ func indexKey(prefix string, repo domain.RepoName, branch string, n int64) []byt
96 // when old is not known, as for a new request or a comment: the keys of mr are96 // when old is not known, as for a new request or a comment: the keys of mr are
97 // then put or deleted, whatever they were). Deleting a key that is not there is97 // then put or deleted, whatever they were). Deleting a key that is not there is
98 // not an error.98 // not an error.
99+//
100+//hexcheck:ignore suspicious-business-logic-in-adapter maintains source and target indexes to match the stored merge request open state and branch names
99 func indexOpen(b *kv.Batch, old *domain.MergeRequest, mr domain.MergeRequest) {101 func indexOpen(b *kv.Batch, old *domain.MergeRequest, mr domain.MergeRequest) {
100 if old != nil && old.IsOpen() {102 if old != nil && old.IsOpen() {
101 if !mr.IsOpen() || old.Source != mr.Source {103 if !mr.IsOpen() || old.Source != mr.Source {
@@ -204,8 +206,6 @@ func (m *MergeRequests) guardRepo(ctx context.Context, b *kv.Batch, repo domain.
204 // rewrites it (see guardRepo), so that a repository deleted meanwhile is not206 // rewrites it (see guardRepo), so that a repository deleted meanwhile is not
205 // left with a stray merge request (a push recording pushed_at makes it retry). A missing repository gives207 // left with a stray merge request (a push recording pushed_at makes it retry). A missing repository gives
206 // domain.ErrNotFound.208 // domain.ErrNotFound.
207-//
208-//hexcheck:ignore suspicious-business-logic-in-adapter takes the next number under a version precondition: a storage concern, no policy
209 func (m *MergeRequests) Create(ctx context.Context, mr domain.MergeRequest) (domain.MergeRequest, error) {209 func (m *MergeRequests) Create(ctx context.Context, mr domain.MergeRequest) (domain.MergeRequest, error) {
210 err := createNumbered(ctx, m.db, m.locks, mr.Repo, func(b *kv.Batch, n int64) error {210 err := createNumbered(ctx, m.db, m.locks, mr.Repo, func(b *kv.Batch, n int64) error {
211 mr.Number = n211 mr.Number = n
@@ -451,7 +451,7 @@ func (m *MergeRequests) CountOpen(ctx context.Context, repo domain.RepoName) (in
451 451
452 // Update replaces the merge request with a version precondition.452 // Update replaces the merge request with a version precondition.
453 //453 //
454-//hexcheck:ignore suspicious-business-logic-in-adapter port method name only454+//hexcheck:ignore suspicious-business-logic-in-adapter replaces a versioned record and maintains open-request indexes and the derived mergeability record
455 func (m *MergeRequests) Update(ctx context.Context, mr domain.MergeRequest) error {455 func (m *MergeRequests) Update(ctx context.Context, mr domain.MergeRequest) error {
456 val, err := encodeMergeRequest(mr)456 val, err := encodeMergeRequest(mr)
457 if err != nil {457 if err != nil {
@@ -564,8 +564,6 @@ func (m *MergeRequests) GetRead(ctx context.Context, repo domain.RepoName, numbe
564 564
565 // SetRead writes mrread/<repo>/<number>. The repository must exist (see565 // SetRead writes mrread/<repo>/<number>. The repository must exist (see
566 // guardRepo): domain.ErrNotFound otherwise.566 // guardRepo): domain.ErrNotFound otherwise.
567-//
568-//hexcheck:ignore suspicious-business-logic-in-adapter retries a write that lost a race with the repository key: a storage concern, no policy
569 func (m *MergeRequests) SetRead(ctx context.Context, repo domain.RepoName, number int64, head domain.ObjectID) error {567 func (m *MergeRequests) SetRead(ctx context.Context, repo domain.RepoName, number int64, head domain.ObjectID) error {
570 if head.IsZero() {568 if head.IsZero() {
571 return fmt.Errorf("%w: empty read position", domain.ErrInvalidObjectID)569 return fmt.Errorf("%w: empty read position", domain.ErrInvalidObjectID)
@@ -748,7 +746,6 @@ func encodeMergeRequest(mr domain.MergeRequest) ([]byte, error) {
748 }), nil746 }), nil
749 }747 }
750 748
751-//hexcheck:ignore suspicious-business-logic-in-adapter schema decoding, not a policy
752 func decodeMergeRequest(repo domain.RepoName, item kv.Item) (domain.MergeRequest, error) {749 func decodeMergeRequest(repo domain.RepoName, item kv.Item) (domain.MergeRequest, error) {
753 var pb storagepb.MergeRequest750 var pb storagepb.MergeRequest
754 if err := proto.Unmarshal(item.Value, &pb); err != nil {751 if err := proto.Unmarshal(item.Value, &pb); err != nil {
@@ -815,7 +812,6 @@ func encodeComment(c domain.Comment) ([]byte, error) {
815 }), nil812 }), nil
816 }813 }
817 814
818-//hexcheck:ignore suspicious-business-logic-in-adapter schema decoding, not a policy
819 func decodeComment(item kv.Item) (domain.Comment, error) {815 func decodeComment(item kv.Item) (domain.Comment, error) {
820 var pb storagepb.Comment816 var pb storagepb.Comment
821 if err := proto.Unmarshal(item.Value, &pb); err != nil {817 if err := proto.Unmarshal(item.Value, &pb); err != nil {
@@ -931,8 +927,6 @@ func encodeSettings(s domain.RepoSettings) (*storagepb.RepoSettings, error) {
931 927
932 // decodeSettings returns the defaults for a repository stored before merge928 // decodeSettings returns the defaults for a repository stored before merge
933 // requests existed, and for settings left with no mode that this build knows.929 // requests existed, and for settings left with no mode that this build knows.
934-//
935-//hexcheck:ignore suspicious-business-logic-in-adapter schema decoding with the documented defaults
936 func decodeSettings(pb *storagepb.RepoSettings) domain.RepoSettings {930 func decodeSettings(pb *storagepb.RepoSettings) domain.RepoSettings {
937 if pb == nil {931 if pb == nil {
938 return domain.DefaultRepoSettings()932 return domain.DefaultRepoSettings()
M internal/adapters/kvstore/passkeys.go +0 -2
@@ -134,8 +134,6 @@ func (s *Passkeys) Create(ctx context.Context, p domain.Passkey) error {
134134 }
135135
136136 // Update replaces a stored passkey, or returns domain.ErrNotFound.
137-//
138-//hexcheck:ignore suspicious-business-logic-in-adapter version-checked replace, not a policy
139137 func (s *Passkeys) Update(ctx context.Context, p domain.Passkey) error {
140138 val, err := encodePasskey(p)
141139 if err != nil {
@@ -134,8 +134,6 @@ func (s *Passkeys) Create(ctx context.Context, p domain.Passkey) error {
134 }134 }
135 135
136 // Update replaces a stored passkey, or returns domain.ErrNotFound.136 // Update replaces a stored passkey, or returns domain.ErrNotFound.
137-//
138-//hexcheck:ignore suspicious-business-logic-in-adapter version-checked replace, not a policy
139 func (s *Passkeys) Update(ctx context.Context, p domain.Passkey) error {137 func (s *Passkeys) Update(ctx context.Context, p domain.Passkey) error {
140 val, err := encodePasskey(p)138 val, err := encodePasskey(p)
141 if err != nil {139 if err != nil {
M internal/adapters/kvstore/repos.go +0 -4
@@ -67,8 +67,6 @@ func (s *Store) List(ctx context.Context) ([]domain.Repo, error) {
6767 const repoMutationTries = 8
6868
6969 // Mutate applies a retry-safe mutation under the version it read.
70-//
71-//hexcheck:ignore suspicious-business-logic-in-adapter optimistic concurrency is a storage concern
7270 func (s *Store) Mutate(ctx context.Context, name domain.RepoName, fn func(*domain.Repo) (bool, error)) (domain.Repo, error) {
7371 key := repoKey(name)
7472 for range repoMutationTries {
@@ -158,8 +156,6 @@ const deleteTries = 32
158156 // got in after the listing makes the batch fail and the keys are listed again,
159157 // and a write after the batch finds no repository: no key outlives the
160158 // repository to attach itself to a repository created again.
161-//
162-//hexcheck:ignore suspicious-business-logic-in-adapter chunked delete under a version precondition: a storage concern, no policy
163159 func (s *Store) Delete(ctx context.Context, name domain.RepoName) error {
164160 for range deleteTries {
165161 snap := s.db.Snapshot(ctx)
@@ -67,8 +67,6 @@ func (s *Store) List(ctx context.Context) ([]domain.Repo, error) {
67 const repoMutationTries = 867 const repoMutationTries = 8
68 68
69 // Mutate applies a retry-safe mutation under the version it read.69 // Mutate applies a retry-safe mutation under the version it read.
70-//
71-//hexcheck:ignore suspicious-business-logic-in-adapter optimistic concurrency is a storage concern
72 func (s *Store) Mutate(ctx context.Context, name domain.RepoName, fn func(*domain.Repo) (bool, error)) (domain.Repo, error) {70 func (s *Store) Mutate(ctx context.Context, name domain.RepoName, fn func(*domain.Repo) (bool, error)) (domain.Repo, error) {
73 key := repoKey(name)71 key := repoKey(name)
74 for range repoMutationTries {72 for range repoMutationTries {
@@ -158,8 +156,6 @@ const deleteTries = 32
158 // got in after the listing makes the batch fail and the keys are listed again,156 // got in after the listing makes the batch fail and the keys are listed again,
159 // and a write after the batch finds no repository: no key outlives the157 // and a write after the batch finds no repository: no key outlives the
160 // repository to attach itself to a repository created again.158 // repository to attach itself to a repository created again.
161-//
162-//hexcheck:ignore suspicious-business-logic-in-adapter chunked delete under a version precondition: a storage concern, no policy
163 func (s *Store) Delete(ctx context.Context, name domain.RepoName) error {159 func (s *Store) Delete(ctx context.Context, name domain.RepoName) error {
164 for range deleteTries {160 for range deleteTries {
165 snap := s.db.Snapshot(ctx)161 snap := s.db.Snapshot(ctx)
M internal/adapters/kvstore/store.go +0 -2
@@ -186,8 +186,6 @@ var preIssueScopes = []domain.Scope{
186186 // for, so it gets each of them if missing (this is no escalation). Every other
187187 // token is left as it is. The batch requires each token to be at the version it
188188 // was read at.
189-//
190-//hexcheck:ignore suspicious-business-logic-in-adapter one-time storage upgrade of the stored tokens: a storage concern, no policy
191189 func (s *Store) upgradeTokens(ctx context.Context, b *kv.Batch) error {
192190 for key, item := range s.db.Snapshot(ctx).Prefix(ctx, []byte(tokenPrefix)) {
193191 pb := &storagepb.Token{}
@@ -186,8 +186,6 @@ var preIssueScopes = []domain.Scope{
186 // for, so it gets each of them if missing (this is no escalation). Every other186 // for, so it gets each of them if missing (this is no escalation). Every other
187 // token is left as it is. The batch requires each token to be at the version it187 // token is left as it is. The batch requires each token to be at the version it
188 // was read at.188 // was read at.
189-//
190-//hexcheck:ignore suspicious-business-logic-in-adapter one-time storage upgrade of the stored tokens: a storage concern, no policy
191 func (s *Store) upgradeTokens(ctx context.Context, b *kv.Batch) error {189 func (s *Store) upgradeTokens(ctx context.Context, b *kv.Batch) error {
192 for key, item := range s.db.Snapshot(ctx).Prefix(ctx, []byte(tokenPrefix)) {190 for key, item := range s.db.Snapshot(ctx).Prefix(ctx, []byte(tokenPrefix)) {
193 pb := &storagepb.Token{}191 pb := &storagepb.Token{}
M internal/adapters/kvstore/tokens.go +0 -6
@@ -153,8 +153,6 @@ func (s *Tokens) Revoke(ctx context.Context, id string) error {
153153
154154 // Touch sets last_used_at when the given time is later than the stored one,
155155 // so that racing writers never move it back.
156-//
157-//hexcheck:ignore suspicious-business-logic-in-adapter monotonic write guard, not a policy
158156 func (s *Tokens) Touch(ctx context.Context, id string, at time.Time) error {
159157 if !validTokenID(id) {
160158 return domain.ErrNotFound
@@ -194,8 +192,6 @@ func (s *Tokens) Touch(ctx context.Context, id string, at time.Time) error {
194192 // encodeToken refuses what the use case already refused (scopes, branch
195193 // prefixes): a malformed prefix must never reach the store, where it would
196194 // limit a token wrongly or not at all.
197-//
198-//hexcheck:ignore suspicious-business-logic-in-adapter schema encoding: it re-checks the syntax the use case enforced, it decides no policy
199195 func encodeToken(t domain.Token) ([]byte, error) {
200196 if !validTokenID(t.ID) {
201197 return nil, fmt.Errorf("%w: invalid id %q", domain.ErrInvalidToken, t.ID)
@@ -237,8 +233,6 @@ func encodeToken(t domain.Token) ([]byte, error) {
237233
238234 // decodeToken drops scopes it does not know (written by a newer ermite): a
239235 // token never gains rights by being read by an older build.
240-//
241-//hexcheck:ignore suspicious-business-logic-in-adapter schema decoding, not a policy
242236 func decodeToken(val []byte) (domain.Token, error) {
243237 var pb storagepb.Token
244238 if err := proto.Unmarshal(val, &pb); err != nil {
@@ -153,8 +153,6 @@ func (s *Tokens) Revoke(ctx context.Context, id string) error {
153 153
154 // Touch sets last_used_at when the given time is later than the stored one,154 // Touch sets last_used_at when the given time is later than the stored one,
155 // so that racing writers never move it back.155 // so that racing writers never move it back.
156-//
157-//hexcheck:ignore suspicious-business-logic-in-adapter monotonic write guard, not a policy
158 func (s *Tokens) Touch(ctx context.Context, id string, at time.Time) error {156 func (s *Tokens) Touch(ctx context.Context, id string, at time.Time) error {
159 if !validTokenID(id) {157 if !validTokenID(id) {
160 return domain.ErrNotFound158 return domain.ErrNotFound
@@ -194,8 +192,6 @@ func (s *Tokens) Touch(ctx context.Context, id string, at time.Time) error {
194 // encodeToken refuses what the use case already refused (scopes, branch192 // encodeToken refuses what the use case already refused (scopes, branch
195 // prefixes): a malformed prefix must never reach the store, where it would193 // prefixes): a malformed prefix must never reach the store, where it would
196 // limit a token wrongly or not at all.194 // limit a token wrongly or not at all.
197-//
198-//hexcheck:ignore suspicious-business-logic-in-adapter schema encoding: it re-checks the syntax the use case enforced, it decides no policy
199 func encodeToken(t domain.Token) ([]byte, error) {195 func encodeToken(t domain.Token) ([]byte, error) {
200 if !validTokenID(t.ID) {196 if !validTokenID(t.ID) {
201 return nil, fmt.Errorf("%w: invalid id %q", domain.ErrInvalidToken, t.ID)197 return nil, fmt.Errorf("%w: invalid id %q", domain.ErrInvalidToken, t.ID)
@@ -237,8 +233,6 @@ func encodeToken(t domain.Token) ([]byte, error) {
237 233
238 // decodeToken drops scopes it does not know (written by a newer ermite): a234 // decodeToken drops scopes it does not know (written by a newer ermite): a
239 // token never gains rights by being read by an older build.235 // token never gains rights by being read by an older build.
240-//
241-//hexcheck:ignore suspicious-business-logic-in-adapter schema decoding, not a policy
242 func decodeToken(val []byte) (domain.Token, error) {236 func decodeToken(val []byte) (domain.Token, error) {
243 var pb storagepb.Token237 var pb storagepb.Token
244 if err := proto.Unmarshal(val, &pb); err != nil {238 if err := proto.Unmarshal(val, &pb); err != nil {
M internal/adapters/rpc/git.go +0 -1
@@ -187,7 +187,6 @@ func (s *gitService) GetCommit(ctx context.Context, req *connect.Request[pb.GetC
187187 return connect.NewResponse(commitDetailToPB(detail)), nil
188188 }
189189
190-//hexcheck:ignore suspicious-business-logic-in-adapter port method name only
191190 func (s *gitService) ResolveRevision(ctx context.Context, req *connect.Request[pb.ResolveRevisionRequest]) (*connect.Response[pb.ResolveRevisionResponse], error) {
192191 name, rev, err := target(req.Msg.GetRepo(), req.Msg.GetRevision())
193192 if err != nil {
@@ -187,7 +187,6 @@ func (s *gitService) GetCommit(ctx context.Context, req *connect.Request[pb.GetC
187 return connect.NewResponse(commitDetailToPB(detail)), nil187 return connect.NewResponse(commitDetailToPB(detail)), nil
188 }188 }
189 189
190-//hexcheck:ignore suspicious-business-logic-in-adapter port method name only
191 func (s *gitService) ResolveRevision(ctx context.Context, req *connect.Request[pb.ResolveRevisionRequest]) (*connect.Response[pb.ResolveRevisionResponse], error) {190 func (s *gitService) ResolveRevision(ctx context.Context, req *connect.Request[pb.ResolveRevisionRequest]) (*connect.Response[pb.ResolveRevisionResponse], error) {
192 name, rev, err := target(req.Msg.GetRepo(), req.Msg.GetRevision())191 name, rev, err := target(req.Msg.GetRepo(), req.Msg.GetRevision())
193 if err != nil {192 if err != nil {
M internal/adapters/rpc/mergerequest.go +0 -2
@@ -212,8 +212,6 @@ func commentID(s string) int64 {
212212 }
213213
214214 // headID parses a commit id of a request; the empty string is the zero id.
215-//
216-//hexcheck:ignore suspicious-business-logic-in-adapter parses a request field into the domain id and names the field in the error; no rule is decided here
217215 func headID(s string) (domain.ObjectID, error) {
218216 if s == "" {
219217 return domain.ObjectID{}, nil
@@ -212,8 +212,6 @@ func commentID(s string) int64 {
212 }212 }
213 213
214 // headID parses a commit id of a request; the empty string is the zero id.214 // headID parses a commit id of a request; the empty string is the zero id.
215-//
216-//hexcheck:ignore suspicious-business-logic-in-adapter parses a request field into the domain id and names the field in the error; no rule is decided here
217 func headID(s string) (domain.ObjectID, error) {215 func headID(s string) (domain.ObjectID, error) {
218 if s == "" {216 if s == "" {
219 return domain.ObjectID{}, nil217 return domain.ObjectID{}, nil
M internal/adapters/rpc/repo.go +0 -2
@@ -83,8 +83,6 @@ func (s *repoService) UpdateRepo(ctx context.Context, req *connect.Request[pb.Up
8383 // "settings.allowed_merge_modes" and "settings.failing_checks_block", and
8484 // nothing else; the optional issues field stands outside the mask, and alone
8585 // it is a valid update.
86-//
87-//hexcheck:ignore suspicious-business-logic-in-adapter maps the field mask of the contract to the optional fields of the use case; no rule is decided here
8886 func updateParams(msg *pb.UpdateRepoRequest) (ports.UpdateRepoParams, error) {
8987 var params ports.UpdateRepoParams
9088 paths := msg.GetUpdateMask().GetPaths()
@@ -83,8 +83,6 @@ func (s *repoService) UpdateRepo(ctx context.Context, req *connect.Request[pb.Up
83 // "settings.allowed_merge_modes" and "settings.failing_checks_block", and83 // "settings.allowed_merge_modes" and "settings.failing_checks_block", and
84 // nothing else; the optional issues field stands outside the mask, and alone84 // nothing else; the optional issues field stands outside the mask, and alone
85 // it is a valid update.85 // it is a valid update.
86-//
87-//hexcheck:ignore suspicious-business-logic-in-adapter maps the field mask of the contract to the optional fields of the use case; no rule is decided here
88 func updateParams(msg *pb.UpdateRepoRequest) (ports.UpdateRepoParams, error) {86 func updateParams(msg *pb.UpdateRepoRequest) (ports.UpdateRepoParams, error) {
89 var params ports.UpdateRepoParams87 var params ports.UpdateRepoParams
90 paths := msg.GetUpdateMask().GetPaths()88 paths := msg.GetUpdateMask().GetPaths()
M internal/adapters/rpc/server.go +2 -0
@@ -42,6 +42,8 @@ func (s *serverService) GetSigningKey(context.Context, *connect.Request[pb.GetSi
4242
4343 // RotateOIDCKey replaces the key that signs the ID tokens of CI jobs. Only the
4444 // owner may; failed_precondition when the server issues no ID tokens.
45+//
46+//hexcheck:ignore suspicious-business-logic-in-adapter business policy restricting disabled-OIDC rotation errors to owners; pending move to domain/usecase
4547 func (s *serverService) RotateOIDCKey(ctx context.Context, _ *connect.Request[pb.RotateOIDCKeyRequest]) (*connect.Response[pb.RotateOIDCKeyResponse], error) {
4648 p := caller(ctx)
4749 if s.oidc == nil {
@@ -42,6 +42,8 @@ func (s *serverService) GetSigningKey(context.Context, *connect.Request[pb.GetSi
42 42
43 // RotateOIDCKey replaces the key that signs the ID tokens of CI jobs. Only the43 // RotateOIDCKey replaces the key that signs the ID tokens of CI jobs. Only the
44 // owner may; failed_precondition when the server issues no ID tokens.44 // owner may; failed_precondition when the server issues no ID tokens.
45+//
46+//hexcheck:ignore suspicious-business-logic-in-adapter business policy restricting disabled-OIDC rotation errors to owners; pending move to domain/usecase
45 func (s *serverService) RotateOIDCKey(ctx context.Context, _ *connect.Request[pb.RotateOIDCKeyRequest]) (*connect.Response[pb.RotateOIDCKeyResponse], error) {47 func (s *serverService) RotateOIDCKey(ctx context.Context, _ *connect.Request[pb.RotateOIDCKeyRequest]) (*connect.Response[pb.RotateOIDCKeyResponse], error) {
46 p := caller(ctx)48 p := caller(ctx)
47 if s.oidc == nil {49 if s.oidc == nil {
M internal/adapters/sigverify/gpg.go +0 -2
@@ -41,8 +41,6 @@ var _ ports.SignatureVerifier = GPG{}
4141
4242 // Verify implements ports.SignatureVerifier. signedAt is ignored: see the time
4343 // policy of GPG.
44-//
45-//hexcheck:ignore suspicious-business-logic-in-adapter this is the OpenPGP protocol check the port delegates to the adapter; the trust and email rules stay in domain
4644 func (GPG) Verify(payload, signature []byte, committerEmail string, _ int64, keys []domain.TrustedKey) (v domain.CommitVerification) {
4745 v = domain.CommitVerification{Format: domain.FormatGPG, Status: domain.StatusBadSignature}
4846 defer func() { // a parser bug must not take the server down
@@ -41,8 +41,6 @@ var _ ports.SignatureVerifier = GPG{}
41 41
42 // Verify implements ports.SignatureVerifier. signedAt is ignored: see the time42 // Verify implements ports.SignatureVerifier. signedAt is ignored: see the time
43 // policy of GPG.43 // policy of GPG.
44-//
45-//hexcheck:ignore suspicious-business-logic-in-adapter this is the OpenPGP protocol check the port delegates to the adapter; the trust and email rules stay in domain
46 func (GPG) Verify(payload, signature []byte, committerEmail string, _ int64, keys []domain.TrustedKey) (v domain.CommitVerification) {44 func (GPG) Verify(payload, signature []byte, committerEmail string, _ int64, keys []domain.TrustedKey) (v domain.CommitVerification) {
47 v = domain.CommitVerification{Format: domain.FormatGPG, Status: domain.StatusBadSignature}45 v = domain.CommitVerification{Format: domain.FormatGPG, Status: domain.StatusBadSignature}
48 defer func() { // a parser bug must not take the server down46 defer func() { // a parser bug must not take the server down
M internal/adapters/sigverify/ssh.go +0 -2
@@ -49,8 +49,6 @@ type sshSigBlob struct {
4949 }
5050
5151 // Verify implements ports.SignatureVerifier.
52-//
53-//hexcheck:ignore suspicious-business-logic-in-adapter this is the SSHSIG protocol check the port delegates to the adapter; the trust and email rules stay in domain
5452 func (SSH) Verify(payload, signature []byte, committerEmail string, signedAt int64, keys []domain.TrustedKey) (v domain.CommitVerification) {
5553 v = domain.CommitVerification{Format: domain.FormatSSH, Status: domain.StatusBadSignature}
5654 defer func() { // a parser bug must not take the server down
@@ -49,8 +49,6 @@ type sshSigBlob struct {
49 }49 }
50 50
51 // Verify implements ports.SignatureVerifier.51 // Verify implements ports.SignatureVerifier.
52-//
53-//hexcheck:ignore suspicious-business-logic-in-adapter this is the SSHSIG protocol check the port delegates to the adapter; the trust and email rules stay in domain
54 func (SSH) Verify(payload, signature []byte, committerEmail string, signedAt int64, keys []domain.TrustedKey) (v domain.CommitVerification) {52 func (SSH) Verify(payload, signature []byte, committerEmail string, signedAt int64, keys []domain.TrustedKey) (v domain.CommitVerification) {
55 v = domain.CommitVerification{Format: domain.FormatSSH, Status: domain.StatusBadSignature}53 v = domain.CommitVerification{Format: domain.FormatSSH, Status: domain.StatusBadSignature}
56 defer func() { // a parser bug must not take the server down54 defer func() { // a parser bug must not take the server down
M internal/adapters/sigverify/verifier.go +0 -2
@@ -42,8 +42,6 @@ func (Verifier) Verify(payload, signature []byte, committerEmail string, signedA
4242 // trusted completes the verification of a signature whose cryptography is
4343 // valid and whose key is trusted: verified when the key may sign for the
4444 // committer email, email_mismatch otherwise.
45-//
46-//hexcheck:ignore suspicious-business-logic-in-adapter the email rule is domain.TrustedKey.TrustsEmail; this only maps it to the port's status
4745 func trusted(v domain.CommitVerification, key domain.TrustedKey, committerEmail string) domain.CommitVerification {
4846 v.KeyID, v.KeyTitle = key.ID, key.Title
4947 if key.TrustsEmail(committerEmail) {
@@ -42,8 +42,6 @@ func (Verifier) Verify(payload, signature []byte, committerEmail string, signedA
42 // trusted completes the verification of a signature whose cryptography is42 // trusted completes the verification of a signature whose cryptography is
43 // valid and whose key is trusted: verified when the key may sign for the43 // valid and whose key is trusted: verified when the key may sign for the
44 // committer email, email_mismatch otherwise.44 // committer email, email_mismatch otherwise.
45-//
46-//hexcheck:ignore suspicious-business-logic-in-adapter the email rule is domain.TrustedKey.TrustsEmail; this only maps it to the port's status
47 func trusted(v domain.CommitVerification, key domain.TrustedKey, committerEmail string) domain.CommitVerification {45 func trusted(v domain.CommitVerification, key domain.TrustedKey, committerEmail string) domain.CommitVerification {
48 v.KeyID, v.KeyTitle = key.ID, key.Title46 v.KeyID, v.KeyTitle = key.ID, key.Title
49 if key.TrustsEmail(committerEmail) {47 if key.TrustsEmail(committerEmail) {
M internal/adapters/web/actions_artifacts.go +0 -4
@@ -53,8 +53,6 @@ type ArtifactsView struct {
5353 // runArtifacts is the artifacts section of a run, nil when there is nothing to
5454 // show: no artifacts on this server, a visitor who cannot list them, no
5555 // artifact, or a failed read, which is logged; the run page never fails for it.
56-//
57-//hexcheck:ignore suspicious-business-logic-in-adapter builds the artifacts section from the use case results; which errors hide it is presentation, no rule is decided here
5856 func (s *Server) runArtifacts(ctx context.Context, repo domain.RepoName, p RunPage) *ArtifactsView {
5957 if s.cfg.Artifacts == nil || !SignedIn(ctx) {
6058 return nil
@@ -112,8 +110,6 @@ func parseArtifactPath(r *http.Request) (int64, error) {
112110 // is never served: a zip is application/zip, anything else
113111 // application/octet-stream, and the answer is sandboxed and not sniffed, so
114112 // that nothing uploaded by a job can run in the origin of the forge.
115-//
116-//hexcheck:ignore suspicious-business-logic-in-adapter streams what the use case sends; the headers are about the response, no rule is decided here
117113 func (s *Server) artifactDownload(w http.ResponseWriter, r *http.Request) {
118114 ctx, cancel := context.WithTimeout(r.Context(), artifactTimeout)
119115 defer cancel()
@@ -53,8 +53,6 @@ type ArtifactsView struct {
53 // runArtifacts is the artifacts section of a run, nil when there is nothing to53 // runArtifacts is the artifacts section of a run, nil when there is nothing to
54 // show: no artifacts on this server, a visitor who cannot list them, no54 // show: no artifacts on this server, a visitor who cannot list them, no
55 // artifact, or a failed read, which is logged; the run page never fails for it.55 // artifact, or a failed read, which is logged; the run page never fails for it.
56-//
57-//hexcheck:ignore suspicious-business-logic-in-adapter builds the artifacts section from the use case results; which errors hide it is presentation, no rule is decided here
58 func (s *Server) runArtifacts(ctx context.Context, repo domain.RepoName, p RunPage) *ArtifactsView {56 func (s *Server) runArtifacts(ctx context.Context, repo domain.RepoName, p RunPage) *ArtifactsView {
59 if s.cfg.Artifacts == nil || !SignedIn(ctx) {57 if s.cfg.Artifacts == nil || !SignedIn(ctx) {
60 return nil58 return nil
@@ -112,8 +110,6 @@ func parseArtifactPath(r *http.Request) (int64, error) {
112 // is never served: a zip is application/zip, anything else110 // is never served: a zip is application/zip, anything else
113 // application/octet-stream, and the answer is sandboxed and not sniffed, so111 // application/octet-stream, and the answer is sandboxed and not sniffed, so
114 // that nothing uploaded by a job can run in the origin of the forge.112 // that nothing uploaded by a job can run in the origin of the forge.
115-//
116-//hexcheck:ignore suspicious-business-logic-in-adapter streams what the use case sends; the headers are about the response, no rule is decided here
117 func (s *Server) artifactDownload(w http.ResponseWriter, r *http.Request) {113 func (s *Server) artifactDownload(w http.ResponseWriter, r *http.Request) {
118 ctx, cancel := context.WithTimeout(r.Context(), artifactTimeout)114 ctx, cancel := context.WithTimeout(r.Context(), artifactTimeout)
119 defer cancel()115 defer cancel()
M internal/adapters/web/browse.go +0 -2
@@ -71,8 +71,6 @@ func (s *Server) openBlobAt(ctx context.Context, repo domain.RepoName, rev, path
7171 }
7272
7373 // resolveRevision resolves rev to the commit it designates.
74-//
75-//hexcheck:ignore suspicious-business-logic-in-adapter parses the URL text and calls the use case; no rule is decided here
7674 func (s *Server) resolveRevision(ctx context.Context, repo domain.RepoName, rev string) (domain.ResolvedRevision, error) {
7775 r, err := domain.ParseRevision(rev)
7876 if err != nil {
@@ -71,8 +71,6 @@ func (s *Server) openBlobAt(ctx context.Context, repo domain.RepoName, rev, path
71 }71 }
72 72
73 // resolveRevision resolves rev to the commit it designates.73 // resolveRevision resolves rev to the commit it designates.
74-//
75-//hexcheck:ignore suspicious-business-logic-in-adapter parses the URL text and calls the use case; no rule is decided here
76 func (s *Server) resolveRevision(ctx context.Context, repo domain.RepoName, rev string) (domain.ResolvedRevision, error) {74 func (s *Server) resolveRevision(ctx context.Context, repo domain.RepoName, rev string) (domain.ResolvedRevision, error) {
77 r, err := domain.ParseRevision(rev)75 r, err := domain.ParseRevision(rev)
78 if err != nil {76 if err != nil {
M internal/adapters/web/checks.go +2 -0
@@ -53,6 +53,8 @@ func (s *Server) checksFor(ctx context.Context, repo domain.RepoName, sha string
5353 }
5454
5555 // checksSummary reduces checks to the mark a list shows next to a commit.
56+//
57+//hexcheck:ignore suspicious-business-logic-in-adapter renders domain check outcomes as a commit-list mark, passed count, label and actions link
5658 func checksSummary(repo domain.RepoName, sha string, checks []ports.CheckView) ChecksSummary {
5759 if len(checks) == 0 {
5860 return ChecksSummary{}
@@ -53,6 +53,8 @@ func (s *Server) checksFor(ctx context.Context, repo domain.RepoName, sha string
53 }53 }
54 54
55 // checksSummary reduces checks to the mark a list shows next to a commit.55 // checksSummary reduces checks to the mark a list shows next to a commit.
56+//
57+//hexcheck:ignore suspicious-business-logic-in-adapter renders domain check outcomes as a commit-list mark, passed count, label and actions link
56 func checksSummary(repo domain.RepoName, sha string, checks []ports.CheckView) ChecksSummary {58 func checksSummary(repo domain.RepoName, sha string, checks []ports.CheckView) ChecksSummary {
57 if len(checks) == 0 {59 if len(checks) == 0 {
58 return ChecksSummary{}60 return ChecksSummary{}
M internal/adapters/web/commit.go +0 -2
@@ -96,8 +96,6 @@ func diffLines(files []DiffFile) (lines int, invisible bool) {
9696
9797 // commit shows a commit: its message, its totals, the changed files and the
9898 // diff against the first parent. ?view=split selects the split layout.
99-//
100-//hexcheck:ignore suspicious-business-logic-in-adapter builds the commit page from the use case results; no rule is decided here
10199 func (s *Server) commit(ctx context.Context, r *http.Request) (templ.Component, int, error) {
102100 sha := r.PathValue("sha")
103101 if !isCommitID(sha) {
@@ -96,8 +96,6 @@ func diffLines(files []DiffFile) (lines int, invisible bool) {
96 96
97 // commit shows a commit: its message, its totals, the changed files and the97 // commit shows a commit: its message, its totals, the changed files and the
98 // diff against the first parent. ?view=split selects the split layout.98 // diff against the first parent. ?view=split selects the split layout.
99-//
100-//hexcheck:ignore suspicious-business-logic-in-adapter builds the commit page from the use case results; no rule is decided here
101 func (s *Server) commit(ctx context.Context, r *http.Request) (templ.Component, int, error) {99 func (s *Server) commit(ctx context.Context, r *http.Request) (templ.Component, int, error) {
102 sha := r.PathValue("sha")100 sha := r.PathValue("sha")
103 if !isCommitID(sha) {101 if !isCommitID(sha) {
M internal/adapters/web/compare.go +1 -3
@@ -27,8 +27,6 @@ const compareDepth = maxComparePages * pageSize
2727 // own diff is then the whole change). Otherwise it lists the commits, which
2828 // link to their own diffs, and says the whole diff comes with the merge
2929 // request.
30-//
31-//hexcheck:ignore suspicious-business-logic-in-adapter builds the compare page from the use case results; the merge rules are the use case's
3230 func (s *Server) compare(ctx context.Context, r *http.Request) (templ.Component, int, error) {
3331 d, err := s.loadRepo(ctx, r.PathValue("repo"))
3432 if err != nil {
@@ -144,7 +142,7 @@ func (s *Server) compare(ctx context.Context, r *http.Request) (templ.Component,
144142 // meets the target. behind is true when the target has commits the source
145143 // lacks (the tip of the target is not an ancestor of the source).
146144 //
147-//hexcheck:ignore suspicious-business-logic-in-adapter walks the history pages the use case returns to find where the branch left its target; the page needs it, the forge decides nothing
145+//hexcheck:ignore suspicious-business-logic-in-adapter business rule inferring ahead/behind from bounded history walks; pending move to domain/usecase
148146 func (s *Server) commitsAhead(ctx context.Context, repo domain.RepoName, srcTip, tgtTip string) (ahead []domain.Commit, exact, behind bool, err error) {
149147 if srcTip == tgtTip {
150148 return nil, true, false, nil
@@ -27,8 +27,6 @@ const compareDepth = maxComparePages * pageSize
27 // own diff is then the whole change). Otherwise it lists the commits, which27 // own diff is then the whole change). Otherwise it lists the commits, which
28 // link to their own diffs, and says the whole diff comes with the merge28 // link to their own diffs, and says the whole diff comes with the merge
29 // request.29 // request.
30-//
31-//hexcheck:ignore suspicious-business-logic-in-adapter builds the compare page from the use case results; the merge rules are the use case's
32 func (s *Server) compare(ctx context.Context, r *http.Request) (templ.Component, int, error) {30 func (s *Server) compare(ctx context.Context, r *http.Request) (templ.Component, int, error) {
33 d, err := s.loadRepo(ctx, r.PathValue("repo"))31 d, err := s.loadRepo(ctx, r.PathValue("repo"))
34 if err != nil {32 if err != nil {
@@ -144,7 +142,7 @@ func (s *Server) compare(ctx context.Context, r *http.Request) (templ.Component,
144 // meets the target. behind is true when the target has commits the source142 // meets the target. behind is true when the target has commits the source
145 // lacks (the tip of the target is not an ancestor of the source).143 // lacks (the tip of the target is not an ancestor of the source).
146 //144 //
147-//hexcheck:ignore suspicious-business-logic-in-adapter walks the history pages the use case returns to find where the branch left its target; the page needs it, the forge decides nothing145+//hexcheck:ignore suspicious-business-logic-in-adapter business rule inferring ahead/behind from bounded history walks; pending move to domain/usecase
148 func (s *Server) commitsAhead(ctx context.Context, repo domain.RepoName, srcTip, tgtTip string) (ahead []domain.Commit, exact, behind bool, err error) {146 func (s *Server) commitsAhead(ctx context.Context, repo domain.RepoName, srcTip, tgtTip string) (ahead []domain.Commit, exact, behind bool, err error) {
149 if srcTip == tgtTip {147 if srcTip == tgtTip {
150 return nil, true, false, nil148 return nil, true, false, nil
M internal/adapters/web/context.go +1 -1
@@ -30,7 +30,7 @@ type ContextRows struct {
3030 // the numbers of the first hidden line on each side, which move together (the
3131 // lines are unchanged); n the number of lines, 0 for the rest of the file.
3232 //
33-//hexcheck:ignore suspicious-business-logic-in-adapter cuts a file the use case opened into rows of the diff; no rule is decided here
33+//hexcheck:ignore suspicious-business-logic-in-adapter validates diff-context HTTP parameters, rejects binary or oversized files, and caps rendered context rows
3434 func (s *Server) diffContext(ctx context.Context, r *http.Request) (templ.Component, int, error) {
3535 sha := r.PathValue("sha")
3636 if !isFullID(sha) {
@@ -30,7 +30,7 @@ type ContextRows struct {
30 // the numbers of the first hidden line on each side, which move together (the30 // the numbers of the first hidden line on each side, which move together (the
31 // lines are unchanged); n the number of lines, 0 for the rest of the file.31 // lines are unchanged); n the number of lines, 0 for the rest of the file.
32 //32 //
33-//hexcheck:ignore suspicious-business-logic-in-adapter cuts a file the use case opened into rows of the diff; no rule is decided here33+//hexcheck:ignore suspicious-business-logic-in-adapter validates diff-context HTTP parameters, rejects binary or oversized files, and caps rendered context rows
34 func (s *Server) diffContext(ctx context.Context, r *http.Request) (templ.Component, int, error) {34 func (s *Server) diffContext(ctx context.Context, r *http.Request) (templ.Component, int, error) {
35 sha := r.PathValue("sha")35 sha := r.PathValue("sha")
36 if !isFullID(sha) {36 if !isFullID(sha) {
M internal/adapters/web/diff_highlight.go +0 -2
@@ -370,8 +370,6 @@ func computeFile(ctx context.Context, lx chroma.Lexer, hunks []domain.Hunk) (d *
370370
371371 // applyFile puts the colours on the lines of a file; false when the data is
372372 // not the one of this file (another number of lines), nothing is changed.
373-//
374-//hexcheck:ignore suspicious-business-logic-in-adapter puts coloured runs on the lines of a diff for the page; no rule is decided here
375373 func applyFile(d *hlData, f *DiffFile, hunks []domain.Hunk) bool {
376374 n := 0
377375 for _, h := range hunks {
@@ -370,8 +370,6 @@ func computeFile(ctx context.Context, lx chroma.Lexer, hunks []domain.Hunk) (d *
370 370
371 // applyFile puts the colours on the lines of a file; false when the data is371 // applyFile puts the colours on the lines of a file; false when the data is
372 // not the one of this file (another number of lines), nothing is changed.372 // not the one of this file (another number of lines), nothing is changed.
373-//
374-//hexcheck:ignore suspicious-business-logic-in-adapter puts coloured runs on the lines of a diff for the page; no rule is decided here
375 func applyFile(d *hlData, f *DiffFile, hunks []domain.Hunk) bool {373 func applyFile(d *hlData, f *DiffFile, hunks []domain.Hunk) bool {
376 n := 0374 n := 0
377 for _, h := range hunks {375 for _, h := range hunks {
M internal/adapters/web/events.go +2 -0
@@ -342,6 +342,8 @@ func (s *Server) canSee(ctx context.Context, rawName string) error {
342342
343343 // issuesOn is domain.ErrNotFound unless the repository has issues on and
344344 // s.cfg.Issues is set: the same answer as for a repository the visitor cannot see.
345+//
346+//hexcheck:ignore suspicious-business-logic-in-adapter business policy hiding issue streams when issues are disabled; pending move to domain/usecase
345347 func (s *Server) issuesOn(ctx context.Context, rawName string) error {
346348 if s.cfg.Issues == nil {
347349 return domain.ErrNotFound
@@ -342,6 +342,8 @@ func (s *Server) canSee(ctx context.Context, rawName string) error {
342 342
343 // issuesOn is domain.ErrNotFound unless the repository has issues on and343 // issuesOn is domain.ErrNotFound unless the repository has issues on and
344 // s.cfg.Issues is set: the same answer as for a repository the visitor cannot see.344 // s.cfg.Issues is set: the same answer as for a repository the visitor cannot see.
345+//
346+//hexcheck:ignore suspicious-business-logic-in-adapter business policy hiding issue streams when issues are disabled; pending move to domain/usecase
345 func (s *Server) issuesOn(ctx context.Context, rawName string) error {347 func (s *Server) issuesOn(ctx context.Context, rawName string) error {
346 if s.cfg.Issues == nil {348 if s.cfg.Issues == nil {
347 return domain.ErrNotFound349 return domain.ErrNotFound
M internal/adapters/web/fragments.go +1 -1
@@ -356,7 +356,7 @@ func (f *fanout) lead(key fanKey, e *fanEntry, build func() ([]fragment, error))
356356 // banner tells the commits page how many commits its branch got since the
357357 // head it lists.
358358 //
359-//hexcheck:ignore suspicious-business-logic-in-adapter counts the commits of a page for the banner text; display only
359+//hexcheck:ignore suspicious-business-logic-in-adapter business rule inferring new commit counts and branch rewrites from one history page; pending move to domain/usecase
360360 func (l *liveStream) banner(ctx context.Context, p domain.PushEvent) ([]fragment, error) {
361361 if l.ref == "" || !isFullID(l.head) {
362362 return nil, nil
@@ -356,7 +356,7 @@ func (f *fanout) lead(key fanKey, e *fanEntry, build func() ([]fragment, error))
356 // banner tells the commits page how many commits its branch got since the356 // banner tells the commits page how many commits its branch got since the
357 // head it lists.357 // head it lists.
358 //358 //
359-//hexcheck:ignore suspicious-business-logic-in-adapter counts the commits of a page for the banner text; display only359+//hexcheck:ignore suspicious-business-logic-in-adapter business rule inferring new commit counts and branch rewrites from one history page; pending move to domain/usecase
360 func (l *liveStream) banner(ctx context.Context, p domain.PushEvent) ([]fragment, error) {360 func (l *liveStream) banner(ctx context.Context, p domain.PushEvent) ([]fragment, error) {
361 if l.ref == "" || !isFullID(l.head) {361 if l.ref == "" || !isFullID(l.head) {
362 return nil, nil362 return nil, nil
M internal/adapters/web/issues.go +0 -2
@@ -216,8 +216,6 @@ func (s *Server) issueNew(ctx context.Context, r *http.Request) (templ.Component
216216 }
217217
218218 // issueShow shows an issue with its comments.
219-//
220-//hexcheck:ignore suspicious-business-logic-in-adapter builds the issue page from the use case results; no rule is decided here
221219 func (s *Server) issueShow(ctx context.Context, r *http.Request) (templ.Component, int, error) {
222220 n, err := mrNumber(r)
223221 if err != nil {
@@ -216,8 +216,6 @@ func (s *Server) issueNew(ctx context.Context, r *http.Request) (templ.Component
216 }216 }
217 217
218 // issueShow shows an issue with its comments.218 // issueShow shows an issue with its comments.
219-//
220-//hexcheck:ignore suspicious-business-logic-in-adapter builds the issue page from the use case results; no rule is decided here
221 func (s *Server) issueShow(ctx context.Context, r *http.Request) (templ.Component, int, error) {219 func (s *Server) issueShow(ctx context.Context, r *http.Request) (templ.Component, int, error) {
222 n, err := mrNumber(r)220 n, err := mrNumber(r)
223 if err != nil {221 if err != nil {
M internal/adapters/web/issues_form.go +2 -0
@@ -245,6 +245,8 @@ func (s *Server) formAgain(ctx context.Context, w http.ResponseWriter, r *http.R
245245 }
246246
247247 // issueSubmittedPage is GET /<repo>/issues/submitted.
248+//
249+//hexcheck:ignore suspicious-business-logic-in-adapter business policy exposing the submission receipt only for public issues; pending move to domain/usecase
248250 func (s *Server) issueSubmittedPage(w http.ResponseWriter, r *http.Request) {
249251 ctx, cancel := context.WithTimeout(r.Context(), requestTimeout)
250252 defer cancel()
@@ -245,6 +245,8 @@ func (s *Server) formAgain(ctx context.Context, w http.ResponseWriter, r *http.R
245 }245 }
246 246
247 // issueSubmittedPage is GET /<repo>/issues/submitted.247 // issueSubmittedPage is GET /<repo>/issues/submitted.
248+//
249+//hexcheck:ignore suspicious-business-logic-in-adapter business policy exposing the submission receipt only for public issues; pending move to domain/usecase
248 func (s *Server) issueSubmittedPage(w http.ResponseWriter, r *http.Request) {250 func (s *Server) issueSubmittedPage(w http.ResponseWriter, r *http.Request) {
249 ctx, cancel := context.WithTimeout(r.Context(), requestTimeout)251 ctx, cancel := context.WithTimeout(r.Context(), requestTimeout)
250 defer cancel()252 defer cancel()
M internal/adapters/web/issues_post.go +0 -1
@@ -67,7 +67,6 @@ func (s *Server) issueReopen(ctx context.Context, r *http.Request) (string, stri
6767 return s.issueTransition(ctx, r, s.cfg.Issues.Reopen)
6868 }
6969
70-//hexcheck:ignore suspicious-business-logic-in-adapter closes or reopens through the use case that owns the transition; the form only picks which
7170 func (s *Server) issueTransition(ctx context.Context, r *http.Request, do func(context.Context, domain.Principal, domain.RepoName, int64) (domain.Issue, error)) (string, string, error) {
7271 repo := r.PathValue("repo")
7372 n, err := number(r)
@@ -67,7 +67,6 @@ func (s *Server) issueReopen(ctx context.Context, r *http.Request) (string, stri
67 return s.issueTransition(ctx, r, s.cfg.Issues.Reopen)67 return s.issueTransition(ctx, r, s.cfg.Issues.Reopen)
68 }68 }
69 69
70-//hexcheck:ignore suspicious-business-logic-in-adapter closes or reopens through the use case that owns the transition; the form only picks which
71 func (s *Server) issueTransition(ctx context.Context, r *http.Request, do func(context.Context, domain.Principal, domain.RepoName, int64) (domain.Issue, error)) (string, string, error) {70 func (s *Server) issueTransition(ctx context.Context, r *http.Request, do func(context.Context, domain.Principal, domain.RepoName, int64) (domain.Issue, error)) (string, string, error) {
72 repo := r.PathValue("repo")71 repo := r.PathValue("repo")
73 n, err := number(r)72 n, err := number(r)
M internal/adapters/web/mr.go +1 -1
@@ -546,7 +546,7 @@ func (s *Server) mrSince(ctx context.Context, r *http.Request) (templ.Component,
546546 return s.mrPage(ctx, r, true)
547547 }
548548
549-//hexcheck:ignore suspicious-business-logic-in-adapter builds the merge request page from the use case results; no rule is decided here
549+//hexcheck:ignore suspicious-business-logic-in-adapter business rules for owner-only read positions and identifying unread commits; pending move to domain/usecase
550550 func (s *Server) mrPage(ctx context.Context, r *http.Request, since bool) (templ.Component, int, error) {
551551 n, err := mrNumber(r)
552552 if err != nil {
@@ -546,7 +546,7 @@ func (s *Server) mrSince(ctx context.Context, r *http.Request) (templ.Component,
546 return s.mrPage(ctx, r, true)546 return s.mrPage(ctx, r, true)
547 }547 }
548 548
549-//hexcheck:ignore suspicious-business-logic-in-adapter builds the merge request page from the use case results; no rule is decided here549+//hexcheck:ignore suspicious-business-logic-in-adapter business rules for owner-only read positions and identifying unread commits; pending move to domain/usecase
550 func (s *Server) mrPage(ctx context.Context, r *http.Request, since bool) (templ.Component, int, error) {550 func (s *Server) mrPage(ctx context.Context, r *http.Request, since bool) (templ.Component, int, error) {
551 n, err := mrNumber(r)551 n, err := mrNumber(r)
552 if err != nil {552 if err != nil {
M internal/adapters/web/mr_files.go +0 -2
@@ -157,8 +157,6 @@ func splitPath(p string) (name, dir string) {
157157 // the files of a window with their hunks and their comments, for a
158158 // placeholder of the page. A base or a head that is not the one of the diff
159159 // any more answers 409: the page says to reload.
160-//
161-//hexcheck:ignore suspicious-business-logic-in-adapter builds a window of the merge request page from the use case results; no rule is decided here
162160 func (s *Server) mrFiles(ctx context.Context, r *http.Request) (templ.Component, int, error) {
163161 n, err := mrNumber(r)
164162 if err != nil {
@@ -157,8 +157,6 @@ func splitPath(p string) (name, dir string) {
157 // the files of a window with their hunks and their comments, for a157 // the files of a window with their hunks and their comments, for a
158 // placeholder of the page. A base or a head that is not the one of the diff158 // placeholder of the page. A base or a head that is not the one of the diff
159 // any more answers 409: the page says to reload.159 // any more answers 409: the page says to reload.
160-//
161-//hexcheck:ignore suspicious-business-logic-in-adapter builds a window of the merge request page from the use case results; no rule is decided here
162 func (s *Server) mrFiles(ctx context.Context, r *http.Request) (templ.Component, int, error) {160 func (s *Server) mrFiles(ctx context.Context, r *http.Request) (templ.Component, int, error) {
163 n, err := mrNumber(r)161 n, err := mrNumber(r)
164 if err != nil {162 if err != nil {
M internal/adapters/web/mr_post.go +0 -2
@@ -295,8 +295,6 @@ func commentID(s string) int64 {
295295 }
296296
297297 // headID parses a commit id of a form; the empty string is the zero id.
298-//
299-//hexcheck:ignore suspicious-business-logic-in-adapter parses a form field into the domain id and names the field in the error; no rule is decided here
300298 func headID(s string) (domain.ObjectID, error) {
301299 if s == "" {
302300 return domain.ObjectID{}, nil
@@ -295,8 +295,6 @@ func commentID(s string) int64 {
295 }295 }
296 296
297 // headID parses a commit id of a form; the empty string is the zero id.297 // headID parses a commit id of a form; the empty string is the zero id.
298-//
299-//hexcheck:ignore suspicious-business-logic-in-adapter parses a form field into the domain id and names the field in the error; no rule is decided here
300 func headID(s string) (domain.ObjectID, error) {298 func headID(s string) (domain.ObjectID, error) {
301 if s == "" {299 if s == "" {
302 return domain.ObjectID{}, nil300 return domain.ObjectID{}, nil
M internal/adapters/web/paths.go +0 -2
@@ -33,8 +33,6 @@ type pathList struct {
3333 // an ETag that makes it a 304 (answered before the list is loaded, so it never
3434 // waits for a build); the owner's copy is private and never stored. The ETag
3535 // differs for the gzip and the plain variant.
36-//
37-//hexcheck:ignore suspicious-business-logic-in-adapter serves a cached list after the use case authorized it; the headers are about the response, no rule is decided here
3836 func (s *Server) paths(w http.ResponseWriter, r *http.Request) {
3937 ctx, cancel := context.WithTimeout(r.Context(), requestTimeout)
4038 defer cancel()
@@ -33,8 +33,6 @@ type pathList struct {
33 // an ETag that makes it a 304 (answered before the list is loaded, so it never33 // an ETag that makes it a 304 (answered before the list is loaded, so it never
34 // waits for a build); the owner's copy is private and never stored. The ETag34 // waits for a build); the owner's copy is private and never stored. The ETag
35 // differs for the gzip and the plain variant.35 // differs for the gzip and the plain variant.
36-//
37-//hexcheck:ignore suspicious-business-logic-in-adapter serves a cached list after the use case authorized it; the headers are about the response, no rule is decided here
38 func (s *Server) paths(w http.ResponseWriter, r *http.Request) {36 func (s *Server) paths(w http.ResponseWriter, r *http.Request) {
39 ctx, cancel := context.WithTimeout(r.Context(), requestTimeout)37 ctx, cancel := context.WithTimeout(r.Context(), requestTimeout)
40 defer cancel()38 defer cancel()
M internal/adapters/web/raw.go +0 -2
@@ -31,8 +31,6 @@ const rawCSP = "default-src 'none'; sandbox"
3131 // image types (by their bytes, never SVG) as images, and anything else as an
3232 // attachment of unknown type. A file is never served as HTML or SVG, so what
3333 // a repository holds cannot run in the origin of the forge.
34-//
35-//hexcheck:ignore suspicious-business-logic-in-adapter streams a file the use case opened; the headers are about the response, no rule is decided here
3634 func (s *Server) raw(w http.ResponseWriter, r *http.Request) {
3735 ctx, cancel := context.WithTimeout(r.Context(), rawTimeout)
3836 defer cancel()
@@ -31,8 +31,6 @@ const rawCSP = "default-src 'none'; sandbox"
31 // image types (by their bytes, never SVG) as images, and anything else as an31 // image types (by their bytes, never SVG) as images, and anything else as an
32 // attachment of unknown type. A file is never served as HTML or SVG, so what32 // attachment of unknown type. A file is never served as HTML or SVG, so what
33 // a repository holds cannot run in the origin of the forge.33 // a repository holds cannot run in the origin of the forge.
34-//
35-//hexcheck:ignore suspicious-business-logic-in-adapter streams a file the use case opened; the headers are about the response, no rule is decided here
36 func (s *Server) raw(w http.ResponseWriter, r *http.Request) {34 func (s *Server) raw(w http.ResponseWriter, r *http.Request) {
37 ctx, cancel := context.WithTimeout(r.Context(), rawTimeout)35 ctx, cancel := context.WithTimeout(r.Context(), rawTimeout)
38 defer cancel()36 defer cancel()
M internal/adapters/web/refs.go +0 -4
@@ -15,8 +15,6 @@ import (
1515 // that is the short name of a branch or tag wins. A branch wins over a tag of
1616 // the same name. rest has no leading slash and is "" when the path is the ref
1717 // alone. ok is false when no ref matches; the caller may then try a commit id.
18-//
19-//hexcheck:ignore suspicious-business-logic-in-adapter finds the ref a URL path starts with; URL routing, no rule is decided here
2018 func resolveRef(refs []domain.Ref, p string) (ref domain.Ref, rest string, ok bool) {
2119 names := refsByName(refs)
2220 p = strings.Trim(p, "/")
@@ -97,8 +95,6 @@ func (t target) commitID() string {
9795 // resolveCommit sets the full id of a target named by an abbreviated commit id,
9896 // with one ResolveRevision. The page renders without it (it only lacks the file
9997 // finder), so a failure is not one.
100-//
101-//hexcheck:ignore suspicious-business-logic-in-adapter learns the full id of the commit a URL names for the finder links; no rule is decided here
10298 func (s *Server) resolveCommit(ctx context.Context, repo domain.RepoName, t *target) {
10399 if !t.detached || isFullID(t.rev) {
104100 return
@@ -15,8 +15,6 @@ import (
15 // that is the short name of a branch or tag wins. A branch wins over a tag of15 // that is the short name of a branch or tag wins. A branch wins over a tag of
16 // the same name. rest has no leading slash and is "" when the path is the ref16 // the same name. rest has no leading slash and is "" when the path is the ref
17 // alone. ok is false when no ref matches; the caller may then try a commit id.17 // alone. ok is false when no ref matches; the caller may then try a commit id.
18-//
19-//hexcheck:ignore suspicious-business-logic-in-adapter finds the ref a URL path starts with; URL routing, no rule is decided here
20 func resolveRef(refs []domain.Ref, p string) (ref domain.Ref, rest string, ok bool) {18 func resolveRef(refs []domain.Ref, p string) (ref domain.Ref, rest string, ok bool) {
21 names := refsByName(refs)19 names := refsByName(refs)
22 p = strings.Trim(p, "/")20 p = strings.Trim(p, "/")
@@ -97,8 +95,6 @@ func (t target) commitID() string {
97 // resolveCommit sets the full id of a target named by an abbreviated commit id,95 // resolveCommit sets the full id of a target named by an abbreviated commit id,
98 // with one ResolveRevision. The page renders without it (it only lacks the file96 // with one ResolveRevision. The page renders without it (it only lacks the file
99 // finder), so a failure is not one.97 // finder), so a failure is not one.
100-//
101-//hexcheck:ignore suspicious-business-logic-in-adapter learns the full id of the commit a URL names for the finder links; no rule is decided here
102 func (s *Server) resolveCommit(ctx context.Context, repo domain.RepoName, t *target) {98 func (s *Server) resolveCommit(ctx context.Context, repo domain.RepoName, t *target) {
103 if !t.detached || isFullID(t.rev) {99 if !t.detached || isFullID(t.rev) {
104 return100 return
M internal/adapters/web/repo.go +1 -1
@@ -45,7 +45,7 @@ func (s *Server) repoView(ctx context.Context, name domain.RepoName) (ports.Repo
4545 // repoRecord reads the repository record only, without Git: its name,
4646 // visibility and settings (the defaults when it has none).
4747 //
48-//hexcheck:ignore suspicious-business-logic-in-adapter reads the repository from the use case; filling in the default settings for display decides no rule
48+//hexcheck:ignore suspicious-business-logic-in-adapter business rule replacing zero repository settings with defaults; pending move to domain/usecase
4949 func (s *Server) repoRecord(ctx context.Context, name domain.RepoName) (domain.Repo, error) {
5050 repo, err := s.cfg.Repos.Get(ctx, principal(ctx), name)
5151 if err != nil {
@@ -45,7 +45,7 @@ func (s *Server) repoView(ctx context.Context, name domain.RepoName) (ports.Repo
45 // repoRecord reads the repository record only, without Git: its name,45 // repoRecord reads the repository record only, without Git: its name,
46 // visibility and settings (the defaults when it has none).46 // visibility and settings (the defaults when it has none).
47 //47 //
48-//hexcheck:ignore suspicious-business-logic-in-adapter reads the repository from the use case; filling in the default settings for display decides no rule48+//hexcheck:ignore suspicious-business-logic-in-adapter business rule replacing zero repository settings with defaults; pending move to domain/usecase
49 func (s *Server) repoRecord(ctx context.Context, name domain.RepoName) (domain.Repo, error) {49 func (s *Server) repoRecord(ctx context.Context, name domain.RepoName) (domain.Repo, error) {
50 repo, err := s.cfg.Repos.Get(ctx, principal(ctx), name)50 repo, err := s.cfg.Repos.Get(ctx, principal(ctx), name)
51 if err != nil {51 if err != nil {
M internal/adapters/web/tree.go +0 -2
@@ -72,8 +72,6 @@ func (p TreePage) Unit() string {
7272
7373 // tree lists a directory of a ref, with the last commit of each entry. With
7474 // ?rows it answers the entries alone, for a directory opened in place.
75-//
76-//hexcheck:ignore suspicious-business-logic-in-adapter builds the directory page from the use case results; no rule is decided here
7775 func (s *Server) tree(ctx context.Context, r *http.Request) (templ.Component, int, error) {
7876 d, err := s.loadRepo(ctx, r.PathValue("repo"))
7977 if err != nil {
@@ -72,8 +72,6 @@ func (p TreePage) Unit() string {
72 72
73 // tree lists a directory of a ref, with the last commit of each entry. With73 // tree lists a directory of a ref, with the last commit of each entry. With
74 // ?rows it answers the entries alone, for a directory opened in place.74 // ?rows it answers the entries alone, for a directory opened in place.
75-//
76-//hexcheck:ignore suspicious-business-logic-in-adapter builds the directory page from the use case results; no rule is decided here
77 func (s *Server) tree(ctx context.Context, r *http.Request) (templ.Component, int, error) {75 func (s *Server) tree(ctx context.Context, r *http.Request) (templ.Component, int, error) {
78 d, err := s.loadRepo(ctx, r.PathValue("repo"))76 d, err := s.loadRepo(ctx, r.PathValue("repo"))
79 if err != nil {77 if err != nil {
M internal/adapters/webauthn/webauthn.go +0 -2
@@ -137,8 +137,6 @@ func (v *Verifier) BeginLogin() ([]byte, []byte, error) {
137137
138138 // FinishLogin implements ports.PasskeyVerifier. The library compares the user
139139 // handle of the response with userHandle.
140-//
141-//hexcheck:ignore suspicious-business-logic-in-adapter copies the counter and backup state the library verified into the stored passkey; it decides nothing: the use case refuses a counter that does not advance
142140 func (v *Verifier) FinishLogin(userHandle []byte, ceremony, response []byte, lookup func(id []byte) (domain.Passkey, error)) (domain.Passkey, error) {
143141 var session gowebauthn.SessionData
144142 if err := json.Unmarshal(ceremony, &session); err != nil {
@@ -137,8 +137,6 @@ func (v *Verifier) BeginLogin() ([]byte, []byte, error) {
137 137
138 // FinishLogin implements ports.PasskeyVerifier. The library compares the user138 // FinishLogin implements ports.PasskeyVerifier. The library compares the user
139 // handle of the response with userHandle.139 // handle of the response with userHandle.
140-//
141-//hexcheck:ignore suspicious-business-logic-in-adapter copies the counter and backup state the library verified into the stored passkey; it decides nothing: the use case refuses a counter that does not advance
142 func (v *Verifier) FinishLogin(userHandle []byte, ceremony, response []byte, lookup func(id []byte) (domain.Passkey, error)) (domain.Passkey, error) {140 func (v *Verifier) FinishLogin(userHandle []byte, ceremony, response []byte, lookup func(id []byte) (domain.Passkey, error)) (domain.Passkey, error) {
143 var session gowebauthn.SessionData141 var session gowebauthn.SessionData
144 if err := json.Unmarshal(ceremony, &session); err != nil {142 if err := json.Unmarshal(ceremony, &session); err != nil {

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 4

Tags 45

↑↓ moveenter openesc close