# Changelog of UCC Lien Filing Scraper — CT + CO State Portals (`devilscrapes/ucc-lien-filing-scraper`) Actor

- **URL**: https://apify.com/devilscrapes/ucc-lien-filing-scraper/changelog.md
- **Full Actor documentation**: https://apify.com/devilscrapes/ucc-lien-filing-scraper.md

## Changelog — ucc-lien-filing-scraper

### 0.2 — post-publish customer-run fixes (2026-09-24)

Three defects found in real customer runs after this Actor went public
and priced 2026-09-23 (30-day success rate flagged by the daily
report). All three verified live against `data.ct.gov`/
`data.colorado.gov` before and after the fix.

- **Fix: Colorado individual debtors billed with an empty
  `debtor_name`.** CO's debtor and secured-party datasets store people
  in `firstname`/`middlename`/`lastname`/`suffix` when there is no
  `organizationname` — `map_co_row` read only `organizationname`, so
  every individual CO debtor shipped a row with `debtor_name == ""`
  (still a billed `result-emitted` event). New
  `co_person_or_org_name()` composes "Last, First Middle Suffix" the
  same way CT's `business_or_individual_name` already did; applied to
  both `debtor_name` and `secured_party_name`, and to the
  `debtor_name_contains` filter so individual debtors are searchable
  too.
- **Fix: no sort order — a capped run returned the oldest filings in
  the window, not the newest.** Neither state's Socrata query passed
  `$order`, so a `maxResults` cap smaller than the date window
  returned whatever Socrata's undefined default order produced —
  verified live to be oldest-first. `client.soda_page` now accepts an
  `order` param; both adapters request `<date column> DESC`
  (`dt_accept DESC` for CT, `filingdate DESC` for CO), so a capped run
  surfaces the newest filings — the use case this Actor is sold on.
- **Fix: dates shipped as full timestamps, not the `YYYY-MM-DD` the
  README documents.** Both states' date columns are Socrata "floating
  timestamp" types and come back as `2026-09-08T00:00:00.000` over the
  wire. New `adapters._to_iso_date()` normalizes `filing_date` and
  `lapse_date` on every row for both states, matching the documented
  output schema.

### 0.1 — pre-publish QA fixes (2026-09-22)

Two defects found by a pre-publish deep QA run (`NYA3N3Qv8pab9rYgw`,
`states=[CT,CO]`, `daysBack=120`, `maxResults=200`) before this Actor
was ever made public. Not shipped to any customer.

- **Fix: CO adapter dropped extra debtors on multi-debtor filings.**
  `build_co_joined_filings` kept only the first joined debtor row per
  `fileid`, silently discarding the rest. It now emits one row per
  (filing, debtor) pair — matching CT, whose source dataset already
  ships one raw record per debtor per filing. Decided this is the
  correct contract (not "aggregate to one row per filing"): it's CT's
  native shape, it's the more useful shape for the lead-gen use case,
  and it's what the deep run actually exercised. README, spec.md, and
  Store copy corrected to say "one row per filing-debtor pair"
  throughout, including a billing callout next to the price — PPE's
  `result-emitted` event bills per row, so a multi-debtor filing costs
  more than one row.
- **Fix: a 2-state request could starve the second state of the
  entire `max_results` budget.** `main._run` handed the whole
  remaining cap to whichever state was fetched first; with
  `states=[CT,CO]` and `maxResults=200`, CT alone consumed all 200
  before CO was ever queried, even though CO had matching filings in
  the same window (verified directly against `data.colorado.gov`).
  `max_results` is now split evenly across `cfg.states` up front, with
  a state's unused share rolling over to the next state so the global
  cap is never wasted.

### 0.0 — scaffold (2026-09-22)

- Actor skeleton created (`actor-scaffolder`). Boots, reads input, pushes one
  `{"placeholder": true, ...}` dataset row. No real scraping logic yet.
- See `docs/specs/ucc-lien-filing-scraper/tasks.md` for the implementation
  plan (T02-T10).
