detached fdfc21c

Merge 8aa547e07ea278c9bb3e409a597c0899e2750235 into 70c00ad2d5a23676a0759d7ae2dcab5e5dcd4425

commit
fdfc21ceda337dd89e202ea7b75372997fa6a029
author
ermite · · 2026-10-19 19:08 UTC
merge of
70c00ad + 8aa547e · diff against the first parent
signature
unsigned
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 generated file: collapsed
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