• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

decentraland / catalyst-storage / 30272322309
95%

Build:
DEFAULT BRANCH: main
Ran 27 Jul 2026 01:53PM UTC
Jobs 1
Files 17
Run time 1min
Badge
Embed ▾
README BADGES
x

If you need to use a raster PNG badge, change the '.svg' to '.png' in the link

Markdown

Textile

RDoc

HTML

Rst

27 Jul 2026 01:52PM UTC coverage: 94.216% (-0.4%) from 94.59%
30272322309

push

github

web-flow
fix!: refuse partially-read sources, stop treating directories as content, bound the decompress cache (#120)

* fix!: refuse partially-read sources, stop treating directories as content, bound the decompress cache

Findings from a read-only audit of the whole package, each reproduced against the
compiled library before being fixed and pinned by a test.

Silent corruption

- assertStorableStream only rejected a FULLY consumed source. The four flags it
  checked describe a finished stream and all flip a tick after the read that made
  the source unusable, so a caller that hashed, sniffed or measured a body first
  walked through it and the store RESOLVED three different ways: an fs.ReadStream
  after read(4) stored the body minus its first four bytes, a push-based source
  after one iterator.next() stored zero bytes, and a Readable.from whose iterator
  was left suspended never settled at all. Now also rejects readableDidRead, which
  is false for a fresh source and for a live-but-empty one. Exported so a caller
  that must inspect a body can check before storing.

Phantom content paths

- statForRead and existsForInvariant treated "something is here" as "content is
  here". Nested ids are legal, so storeStream('a/b') creates the directory `a` and
  'a.gzip/b' creates a's compressed path: the never-stored id `a` reported exist
  true, a fileInfo sized from the directory, an asStream() that died EISDIR, and a
  delete that rejected FOREVER, poisoning every GC batch containing it. Both now
  require isFile(), which is what allFileIds already assumed.

Resource lifetime

- A store rejecting on id validation never destroyed the caller's stream, leaking
  one descriptor (or one undrained request socket) per rejected call until EMFILE:
  30 per 30 rejected calls, on every backend. runStoreWithSignal now releases it.
- The unencoded asStream()/asRawStream() returned an unlistened source, so the
  documented read/delete race emitted an 'error' nobody handled an... (continued)

751 of 843 branches covered (89.09%)

Branch coverage included in aggregate %.

285 of 296 new or added lines in 11 files covered. (96.28%)

2 existing lines in 1 file now uncovered.

1334 of 1370 relevant lines covered (97.37%)

1277.02 hits per line

Uncovered Changes

Lines Coverage ∆ File
6
96.01
-0.57% src/folder-based-storage-component.ts
3
93.31
-1.51% src/folder-based/intent-journal.ts
1
95.52
0.75% src/folder-based/decompress-cache.ts
1
89.36
0.77% src/s3-based-storage-component.ts

Coverage Regressions

Lines Coverage ∆ File
2
97.89
-1.11% src/content-item.ts
Jobs
ID Job ID Ran Files Coverage
1 30272322309.1 27 Jul 2026 01:53PM UTC 17
94.22
GitHub Action Run
Source Files on build 30272322309
  • Tree
  • List 17
  • Changed 15
  • Source Changed 15
  • Coverage Changed 12
Coverage ∆ File Lines Relevant Covered Missed Hits/Line Branch Hits Branch Misses
  • Back to Repo
  • Github Actions Build #30272322309
  • bd3c8e6f on github
  • Prev Build on main (#30227514701)
  • Next Build on main (#30286356801)
  • Delete
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc