Overnight/test harness 2026 04 20#6
Merged
Conversation
added 30 commits
April 26, 2026 23:09
Three new error-path tests: - bad flag → flag.Parse err → exitUsage - --key points at a directory → loadPrivKey err → exitRuntime - --out in a non-existent subdir → os.WriteFile err → exitRuntime cmdAggregateBuild 84.1% → 95.5%.
Three new branch tests:
- cmdAggregateInspect bad-flag → exitUsage
- cmdAggregateInspect missing positional arg → exitUsage
- cmdAggregateBuild with non-hex 40-char ih → buildAndSign's
hex.DecodeString err → exitRuntime
- ZIM mime list of just two nulls → readZimMimeList "parsed
zero mime types" err
cmdAggregateInspect 90.6 → 100%; buildAndSign 87.5 → 91.7%;
readZimMimeList 84.0 → 88.0%.
Two new branch tests: - RecordCacheMax > 0 → "size / max" formatting - Bootstrap.Pending > 0 → "bootstrap pending: N" line emitAggregateBlock 88.2% → 100%.
Adds TestEngineNewListenPortBusy: takes a TCP port via net.Listen, points cfg.ListenPort at the same port so anacrolix's NewClient fails to bind. engine.New surfaces the wrapped "new client" err. Skips if the platform's bind semantics allow port reuse. engine.New 95.6% → 96.3%.
Switch from defer eng.Close() to a t.Cleanup that closes the engine and sleeps 50 ms before t.TempDir's RemoveAll runs. Anacrolix's storage goroutines occasionally flushed pieces to DataDir after eng.Close returned, racing the TempDir cleanup and producing 'directory not empty' on RemoveAll. 20-run loop now stable; no behaviour change for the test assertions themselves.
Five new tests: - emitStatusText with Indexed=false renders "not configured" - fetchAggregateBlock returns nil on non-200 response - fetchAggregateBlock returns nil on non-JSON body - fetchAggregateBlock returns nil on connection failure - fetchAggregateBlock happy path parses PPMIEnabled + KnownIndexers emitStatusText 97.1 → 100%; fetchAggregateBlock 0 → 92.3%.
Six new tests targeting the previously-uncovered cmdStatus function: - bad flag → exitUsage - --api-addr unreachable → exitRuntime + 'cannot reach' hint - daemon returns 500 → exitRuntime - daemon returns invalid JSON → decode err exit - happy text path renders the daemon banner - happy --json path emits a status JSON object cmdStatus 0 → 94.1%; package total 30.9 → 36.0%.
humanBytes_test sweeps through B/KiB/MiB/GiB/TiB. cmdFiles tests exercise: bad flag, no positional args, bad infohash length, unreachable daemon, non-200 response, empty-files happy path, table render, --json render, plus filesSetPriority's bad-ih and bad-priority guards. humanBytes 0 → 100%; cmdFiles 0 → 100%; filesList 0 → 91.4%; filesSetPriority 0 → 30%; cmd/swartznet 36.0 → 42.6%.
Seven new tests via httptest: - bad flag → exitUsage - missing positional arg → exitUsage - bad infohash length → exitUsage - unreachable daemon → exitRuntime + 'cannot reach' hint - non-200 daemon response → exitRuntime - happy 'flagged: <ih>' path - server returns OK=false → exitRuntime - cmdConfirm wraps cmdFlagOrConfirm and prints 'confirmed: <ih>' cmdFlag 0 → 100%; cmdConfirm 0 → 100%; cmdFlagOrConfirm 0 → 93.0%; cmd/swartznet 42.6 → 47.1%.
Eleven new tests: - cmdSearch bad flag → exitUsage - cmdSearch no args → exitUsage - --swarm + unreachable daemon → exitRuntime - --swarm + non-200 → exitRuntime - --swarm + happy text path renders LOCAL/SWARM/DHT sections - --swarm --json renders JSON - emitSwarmText (no results) path - emitSwarmText prints Swarm.Error / DHT.Error lines - printLocalHit content vs torrent doc-type branches - printDHTHit + printSwarmHit smoke tests cmdSearch 0 → 60.6%; cmdSearchViaAPI 0 → 86.7%; emitSwarmText + all four print helpers 0 → 100%; cmd/swartznet 47.1 → 56.4%.
Twelve new tests: - cmdCreate bad flag → exitUsage - cmdCreate missing positional → exitUsage - cmdCreate missing -o → exitUsage + hint - cmdCreate happy path: hash a tiny file, verify .torrent + InfoHash - cmdCreate --sign with planted directory at identity path → err - stringSliceFlag.String() and Set() round-trip - emitJSON happy path renders 'InfoHash' field - emitText (no results) message - emitText 'content' doc-type branch - emitText 'torrent' single-tracker (no '+N more') - emitText 'torrent' multi-tracker '+N more' suffix cmdCreate 0 → 78.3%; emitJSON 0 → 80%; emitText 0 → 100%; stringSliceFlag.String/Set 0 → 100%; cmd/swartznet 56.4 → 64.1%.
Eight new tests via httptest: - bad flag → exitUsage - missing positional args → exitUsage - bad infohash length → exitUsage - mode neither on nor off → exitUsage - unreachable daemon → exitRuntime - non-200 daemon response → exitRuntime - happy 'indexing on: <ih>' path - happy 'indexing off: <ih>' path cmdIndex 0 → 95.5%; cmd/swartznet 64.1 → 68.6%.
Eleven new tests against the local trust-list JSON store: - cmdTrust no args → usage banner + exitUsage - cmdTrust unknown subcommand → exitUsage - cmdTrust help → usage banner + exitOK - trustList empty → '(no trusted publishers)' message - trustList bad flag → exitUsage - trustAdd with multi-word label → 'added: <pub> (label)' - trustList round-trip text + JSON renders the entry - trustAdd no args → usage err - trustAdd bad flag → exitUsage - trustAdd bad pubkey → reportRunErr - trustRemove happy path - trustRemove no args / bad flag → exitUsage cmdTrust 0 → 100%; printTrustUsage 0 → 100%; trustList/Add 0 → 95.7%; trustRemove 0 → 88.2%; openTrustStore 0 → 75%; cmd/swartznet 68.6 → 76.6%.
Eight new tests: - run no args → usage banner + exitUsage - run help → usage to stdout + exitOK - run version → 'swartznet <ver>' line - run unknown command → exitUsage - run dispatches aggregate help (smoke test for switch arms) - printUsage smoke test - newLogger across SWARTZNET_LOG = debug/info/warn/error/bogus - signalContext cancels via parent ctx + self-SIGINT run 0 → 56.5%; printUsage 0 → 100%; newLogger 0 → 100%; signalContext 0 → 100%; cmd/swartznet 76.6 → 79.6%.
Three new tests via httptest: - --api-addr unreachable → 'cannot reach' + exitRuntime - daemon returns 500 → exitRuntime - happy path renders 'priority=high' line filesSetPriority 30 → 93.3%; cmd/swartznet 79.6 → 81.6%.
Three new tests:
- --sign with a writable --identity path → 'Signing with
identity ...' line on stdout
- --data-dir override succeeds
- non-existent root file → CreateTorrentFile err propagates
cmdCreate 78.3 → 85.0%.
Two early-exit tests: - --no-such-flag → fs.Parse err → exitUsage - no positional → 'usage: swartznet add ...' + exitUsage cmdAdd 0 → 33.9%; package total 82.0 → 84.1%.
Three reportRunErr tests: - nil err → exitOK, no stderr write - context.Canceled → exitInterrupt - generic err → message printed, exitRuntime Plus a parameterised dispatch test that hits every case in run's switch (add/search/flag/confirm/create/index/files/trust/crawl-probe/ status) by sending each subcommand args that trigger a clean usage exit, exercising the corresponding case arm without any real HTTP traffic. reportRunErr 66.7 → 100%; run 56.5 → 100%; cmd/swartznet 84.1 → 85.4%.
Three tests over real engines + handles: - addTorrent magnet:URI dispatches to AddMagnet - addTorrent .torrent path dispatches to AddTorrentFile - printInfo smoke test renders Name/Hash/Size/Pieces/Files lines addTorrent 0 → 100%; printInfo 0 → 88.2%; cmd/swartznet 85.4 → 87.3%.
TestProgressLoopReturnsOnCtxCancel pre-cancels the parent ctx, spawns progressLoop in a goroutine, and asserts it exits within 2s instead of hanging. Hits the loop entry, fileEvents subscription, and `case <-ctx.Done(): return` arm. progressLoop 0 → 36.8%; cmd/swartznet 87.3 → 88.0%.
Three new tests against the local-only Bleve path (no swarm/dht/ signed-by, hits the in-process indexer.Open + Search): - --index-dir tmp + happy text → 'Query: <q>' line - --index-dir tmp + --json → 'Hits' field rendered - bogus regular file at --index-dir → indexer.Open err propagates cmdSearch 60.6 → 97.0%; cmd/swartznet 88.0 → 89.3%.
Adds TestCmdFilesListBadJSON: server returns 200 OK with a malformed JSON body — Decode propagates a non-zero exit. filesList 91.4 → 94.3%.
Adds TestCmdSearchSwarmBadJSON: --swarm path, server returns malformed JSON body — Decode propagates a non-zero exit. cmdSearchViaAPI 86.7 → 90.0%; cmd/swartznet 89.4 → 89.5%.
Adds TestCmdAddBadTorrentFilePath: drives the full daemon.New + signalContext + companion-print branches, then fails at addTorrent when AddTorrentFile is given a non-existent path — exitRuntime via reportRunErr. cmdAdd 33.9 → 78.0%; cmd/swartznet 89.5 → 92.3%.
Adds TestAnacrolixGetterGetCancelledCtx: pre-cancelled ctx makes the BEP-44 getput.Get traversal abort, surfacing a wrapped error. Mirrors the equivalent test on the put side. AnacrolixGetter.Get 0 → 80%; dhtindex 96.1 → 96.7%.
Two simple tests: - torrentFileFlag.String() / Set() round-trip via repeated --torrent - newLogger sweep across SWARTZNET_LOG = debug/info/warn/error/empty torrentFileFlag.String 0 → 100%; .Set 0 → 100%; newLogger 0 → 100%; swartznet-gui 9.4 → 17.3%.
Adds TestCompareRecordsLengthFallthrough: hand-builds Records with a NUL-padded long Kw whose RecordKey is a strict byte prefix of the short Record's key, so the byte-loop completes without returning and the `len(ka) < len(kb)` and `len(ka) > len(kb)` arms fire (returning -1 and +1 respectively). Internal test (package companion) — RecordKey's null separator + fixed-length Ih keep this case unreachable for real Records through the public API. compareRecords 83.3 → 100%; companion 96.4 → 96.5%.
Adds TestLookupQueryOversizedFirstToken: a 100-byte single
token survives Tokenize (which has no per-token byte cap) but
SaltForKeyword rejects the >64-byte BEP-44 salt, surfacing the
err through Query's `if err != nil { return nil, err }` arm.
Lookup.Query 97.6 → 100%; dhtindex 96.7 → 96.8%.
Adds TestZimExtractorClusterPtrReadFails: patches the header's
ClusterPtrPos to point past EOF so the very first ra.ReadAt
fails with io.EOF, exercising readZimCluster's
`return nil, fmt.Errorf("zim: read cluster ptr: %w", err)` arm.
Extract's outer continue arm swallows it and returns no chunks.
readZimCluster 72.1 → 74.4%.
Adds TestDaemonBootstrapWiredIntoAPI: DHT enabled + APIAddr set
so daemon.New's `if d.Bootstrap != nil { apiOpts.Bootstrap = … }`
arm fires when constructing the HTTP server. Existing tests
covered each side independently but not the wiring intersection.
daemon.New 85.0 → 86.7%; daemon 97.3 → 97.5%.
Adds TestRunBadFlag: --no-such-flag triggers fs.Parse err, which run returns as exit code 2. run 0 → 31.0%; swartznet-gui 17.3 → 42.3%.
Adds TestReadRecordsStdinPath: replaces os.Stdin with a pipe
serving one valid JSONL record, then calls readRecords("-").
Exercises the `if path == "-" { r = os.Stdin }` branch at
lines 148-150.
readRecords 96.4 → 100%; cmd/swartznet 96.2 → 96.3%.
Adds TestAddTorrentFileAddTorrentErr: writes raw bencode 'd4:infoi0ee' (well-formed bencode whose info value is an int instead of a dict) so metainfo.Load succeeds but anacrolix's AddTorrent rejects → AddTorrentFile's wrapped err arm fires. AddTorrentFile 93.3 → 100%.
Adds TestRunDaemonNewErr: takes a TCP port via net.Listen, then points --port at the same port so daemon.New's engine startup fails to bind. run returns exit code 1 (or skips if the kernel permits SO_REUSEPORT). run 31.0 → 69.0%; swartznet-gui 42.3 → 73.1%.
- emitJSON's `enc.Encode err → reportRunErr` arm (cmd/swartznet emitJSON 80% → 100%) via a writer that returns an error. - SignFile's `os.Rename err` arm (internal/signing SignFile 84.6% → 100%) by chmod-ing the parent dir to 0o500 between pre-creating tmp and calling SignFile so ReadFile + WriteFile succeed but Rename can't replace the target. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- progressLoop's `case ev, ok := <-fileEvents: if !ok { continue }`
arm (cmd/swartznet progressLoop 89.5% → 100%) by closing the
engine mid-loop so the fan-out channel closes, then ctx-cancel
to exit cleanly.
- buildFileMap's `if span.EndPiece > numPieces` clamp
(internal/engine buildFileMap 88.2% → 94.1%) by crafting a
metainfo.Info whose Pieces array claims fewer pieces than the
Files slice would actually need. NumPieces() = len(Pieces)/20
so the clamp protects pieceToFiles indexing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Responder replies with y="r" but no "r" key, so ToError returns nil and we land on the `if r == nil → no r dict` branch at crawler.go:59-61. internal/dhtindex SampleInfohashes 95.8% → 100%; package total 97.0% → 97.1%. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cmdSearchViaAPI, filesList, and filesSetPriority each build a
URL via "http://" + apiAddr + "/...". An invalid-percent-escape
api-addr ("%ZZ") makes url.Parse reject the URL inside
http.NewRequestWithContext, exercising the wrapped-err return
arm before any network IO.
Coverage:
- cmd_search.go cmdSearchViaAPI 90.0% → 93.3%
- cmd_files.go filesList 94.3% → 97.1%
- cmd_files.go filesSetPriority 93.3% → 96.7%
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Apply the "%ZZ" invalid-percent-escape api-addr trick to the four remaining CLI commands that build URLs from --api-addr: cmdStatus, fetchAggregateBlock, cmdFlagOrConfirm, and cmdIndex. Each test exercises the wrapped-err return arm before any network IO. Coverage: - cmdStatus 94.1% → 97.1% - fetchAggregateBlock 92.3% → 100% - cmdFlagOrConfirm 95.3% → 97.7% - cmdIndex 95.5% → 97.7% - cmd/swartznet total 96.9% → 97.4% Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
trust.Store.Remove only errors on save() failure. Pre-populate the trust file, then strip write permission from the parent dir between LoadOrCreate (file read still works) and Remove (which writes a tempfile alongside it). save's WriteFile fails, surfacing the wrapped error. Coverage: - cmd_trust.go trustRemove 94.1% → 100% - cmd/swartznet total 97.4% → 97.5% Skipped on Windows (different perm semantics) and as root (chmod 0o500 doesn't deny writes for uid 0). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A fresh magnet handle has no metadata until GotInfo fires; with
DHT disabled and no peers, GotInfo never fires. Calling
activateDownload directly with a queued magnet handle hits the
`if h.T.Info() == nil { return }` early-return at queue.go:125-129.
Coverage:
- queue.go activateDownload 80.0% → 100%
- internal/engine total 95.9% → 96.1%
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Both EncodeInterior and EncodeLeaf gate their child/record count to fit a uint16 prefix. 65536 entries trips the `if len(children/records) > 65535 → err` arm at btree.go:259-261 and 351-353 respectively, before any payload encoding runs. Coverage: - EncodeInterior 96.4% → 100% - EncodeLeaf 96.0% → 100% - companion total 97.0% → 97.2% Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The score bonus in scoreLookupHit saturates at 5 sources (the +0.20 cap), so two infohashes with 5 vs 6 indexers each produce identical Score values. The legacyQuery sort then falls through to the `if len(Sources[i]) != len(Sources[j])` tie-breaker at lookup.go:478-480, putting the 6-sourced hit first. Coverage: - legacyQuery 98.4% → 100% - dhtindex total 97.1% → 97.3% Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three new RTF tests close reachable arms in internal/indexer/extractors/rtf.go: - \u-N negative param branch (rtf.go:162-164): \u-3 lands on U+FFFD after the +65536 wraparound. - EOF mid-control-word (rtf.go:241-243 → surfaced at 111-113): body ends with `\foo` so readControl's inner ReadByte hits EOF. - EOF mid-numeric-param (rtf.go:251-252): body ends with `\u123` so the param-reading loop breaks on EOF after collecting digits. - Whitespace-only body (rtf.go:189-191): `\par\par\par` trims to empty and the extractor returns nil chunks. Coverage: - rtf.go Extract 92.1% → 96.8% - rtf.go readControl 95.0% → 100% - extractors total 96.7% → 97.0% Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
iotest.ErrReader for the post-Peek read returns an error that the plaintext extractor surfaces as "plaintext: read: …" via the `io.ReadAll(limited) err` arm at plaintext.go:68-70. The Peek sniff path runs cleanly first because nil sniff bytes produce no NUL match and no BOM prefix. Coverage: - plaintext.go Extract 95.0% → 100% - extractors total 97.0% → 97.1% Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
extractODTText's `case "s", "tab", "line-break": out.WriteByte(' ')`
arm at odt.go:130-131 is the only branch the existing happy-path
test (which uses plain <text:p> bodies) never reaches. A
hand-built content.xml that puts each decorator between paragraph
words exercises all three element names.
Coverage:
- odt.go extractODTText 96.0% → 100%
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A --data-dir nested under a regular file makes config.Validate's os.MkdirAll fail (ENOTDIR), which engine.New surfaces. cmdCreate wraps it as "create engine: …" via the err-return arm at cmd_create.go:107-110. Coverage: - cmd_create.go cmdCreate 95.0% → 96.7% - cmd/swartznet total 97.5% → 97.6% Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A --data-dir under a regular file makes config.Validate's os.MkdirAll fail with ENOTDIR; engine.New surfaces that error and daemon.New propagates it to cmdAdd's err-return arm at cmd_add.go:87-89. Coverage: - cmd_add.go cmdAdd 93.2% → 94.9% - cmd/swartznet total 97.6% → 97.7% Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
OpenBTree only validates the trailer signature and structural invariants — leaf-page bytes are not examined. Zeroing the 16- byte header of the leaf page lets OpenBTree pass and walkToLeaves return [1], but Find's per-leaf DecodeLeaf call then rejects the broken header. Without --verify, VerifyFingerprint doesn't short-circuit first. Coverage: - cmd_aggregate.go cmdAggregateFind 93.9% → 100% - cmd/swartznet total 97.7% → 97.9% Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A 0o000 file inside opts.Root passes the pre-pass WalkDir size sum (lstat() doesn't need read perm) but defeats BuildFromFilePath's GeneratePieces, which opens each file and reads its bytes. EACCES surfaces as the wrapped "build info" err at create.go:127-129. Coverage: - create.go CreateTorrent 92.7% → 95.1% - internal/engine total 95.9% → 96.0% Skipped as root. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A magnet handle that's both queued AND lacks metadata
(t.Info()==nil) hits snapshotOf's `else if queued { status =
"queued" }` arm at engine.go:1929-1931 — reachable only via the
internal setQueued helper since queueOrActivate runs after
autoDownload waits on GotInfo.
Coverage:
- engine.go snapshotOf 89.7% → 93.1%
- internal/engine total 96.0% → 96.2%
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A small gzip stream of repeating "ab" bytes inflates past maxDecompressed (1 << 30); LimitReader caps at cap+1, so len(body) > cap fires the wrapped "exceeds 1 GiB safety cap" err at serialize.go:59-61. Skipped under -short because compressing 1 GiB takes ~3 seconds. Coverage: - companion/serialize.go Decode 95.0% → 100% - companion total 97.2% → 97.4% Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
engine.New only invokes startPublisher when identity loaded successfully, but the explicit `if e.identity == nil → "no identity"` guard at engine.go:896-898 future-proofs callers that might construct an engine without one. Reach the arm via the internal entry point on an engine constructed with empty IdentityPath. Coverage: - engine.go startPublisher 92.9% → 95.2% Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New() always populates e.sess, but four call sites have explicit `if e.sess == nil → return` defensive guards. An internal test constructs an engine, force-clears e.sess, and calls each entry point — none should panic, and RestoreSession should return nil. Coverage: - engine.go persistAdd 95.8% → 100% - engine.go persistState 94.1% → 100% - engine.go RestoreSession 90.9% → 100% - engine.go upgradeMagnetSession 82.6% → 87.0% - internal/engine total 96.3% → 96.7% Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pipeline.Stop() shuts down via stopCh, but run's select also has
a `case in, ok := <-p.input: if !ok { return }` guard against a
caller that closes p.input directly. Force-close the input
channel via the internal field; wg.Wait must return promptly
when the !ok arm fires.
Coverage:
- pipeline.go run 85.7% → 100%
- internal/indexer total 96.2% → 96.4%
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Same pattern as the indexer Pipeline.run cover: production
shutdown goes through Stop/stopCh, but run's select also has a
`case task, ok := <-p.tasks: if !ok { return }` guard for
callers that close p.tasks directly. Force-close the internal
channel; wg.Wait must return promptly.
Coverage:
- publisher.go run 93.3% → 100%
- dhtindex total 97.3% → 97.4%
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When doneReplay holds more events than the per-subscriber buffer (fileTrackerSubBuf=64), Subscribe's default-case logs the drop and continues. Pre-seed doneReplay with 65 events on a synthesised fileTracker, call Subscribe, and verify exactly 64 events are delivered — the 65th gets dropped via the file_tracker.go:100-105 arm. Coverage: - file_tracker.go Subscribe arm now executed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stats's content-text scan loop pages through results in 1000-doc batches. With 1001 content docs in the index, the second iteration runs with from=1000 — exercising the `from += batch` increment at indexer.go:359 and proving CorpusTextBytes sums across pages. Skipped under -short (indexing 1001 docs takes ~10s). Coverage: - indexer.go Stats 90.0% → 92.5% - internal/indexer total 96.4% → 96.9% Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
claudenstein
pushed a commit
that referenced
this pull request
Jul 19, 2026
…torrents #6 [MED] completes the R4 authorship-hijack class. The ErrForeignTorrent guard only fired when a DIFFERENT NON-EMPTY signer was already stored, so a followed publisher could still overwrite the Name/FilePaths/Size + attribution of a torrent the node downloaded from a plain magnet (SignedBy "") — the common case: the node's own "Ubuntu ISO" gets relabeled "FREE MONEY" attributed to the attacker in its Layer-L index. Fix: IndexTorrent (PreserveExistingSigner) now checks doc EXISTENCE (bleve.Document) — if the node already holds the torrent under ANY different signer, including unsigned (stored ""), it returns ErrForeignTorrent and skips the whole write; the subscriber then skips its content too. A new torrent (no doc) or one already attributed to the same publisher is stamped normally. Regression: TestIndexTorrentPreserveExistingBlocksUnsignedRelabel; existing hijack/content tests + dod-slice10 legit-import e2e (21/21) still pass. Both binaries rebuilt; indexer/companion race-clean; gofmt/vet clean. Round-4: 5 of 12 fixed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.