Commit graph build-cran-binaries/local/backfill-abi-classification.R
Author SHA1 Message Date
5c4cca6cce fix: verify the metadata database certificate with sslmode=verify-full (#235)
Part of https://codefloe.com/rpkgs/bincraft/issues/225. Stacked on #234.

Every connection to the metadata database used `sslmode = 'require'`, which encrypts but does not authenticate the server, so anyone able to impersonate `r-binaries.devxy.io:15432` would receive `PGPASS`.

## Changes

- `.crow/build-all-versions.yaml`, `process-updates.yaml`, `prune-stale-flat-binaries.yaml`, `reindex.yaml`, `weekly-rebuild-reindex.yaml`: `metadata_db_sslmode = 'verify-full'` in every bincraft call.
- `local/*.R`: the same for bincraft calls; scripts that call `DBI::dbConnect()` directly also pass `sslrootcert = bincraft::postgres_sslrootcert("verify-full")`, because libpq looks for `~/.postgresql/root.crt` rather than the system trust store.
- `README.md`: note that the endpoint serves a Let's Encrypt certificate and how to verify it.
- air reformatted three `=` assignments to `<-` in `local/missing-cran-packages-db.R` and `local/packages-without-any-binary.R` while the hook ran on those files.

## Ordering: merge last

1. devxy/k8s-talos#417 must be live: today the server presents an in-cluster certificate from a private CA, which `verify-full` rejects.
2. https://codefloe.com/rpkgs/bincraft/pulls/226 must be released: `local/install-bincraft.R` installs the latest tag, and older releases neither pass a root certificate nor export `postgres_sslrootcert()`.
3. #234 must be merged.

Merging early fails every database connection in CI, and since #234 per-minor reindex failures fail the pipeline.

Reviewed-on: #235
2026-10-17 07:45:46 +00:00
853b924765 feat(abi): backfill classifier verdicts for pre-per-minor packages (#199)
All checks were successful
ci/crow/manual/rebuild-abi-gap/17 Pipeline was successful
ci/crow/manual/backfill-abi-classification Pipeline was successful
## Why

bincraft PR #124 makes the `abi_classification` cache authoritative for the risky-package set, breaking the circularity where a package counted as ABI-risky only once it had already been built per-minor.

On its own that changes nothing for the packages actually at risk. The cache only holds verdicts for packages that passed through the build pipeline after the per-minor scheme existed; everything older has no verdict, and no verdict means the flat binary is carried into every per-minor index. That is exactly how a `base64enc` built under R 4.4.3 reached an R 4.6.1 client:

```
base64enc.so: undefined symbol: SETLENGTH
```

This is the backfill that gives those packages a verdict.

## What it does

`local/backfill-abi-classification.R` enumerates a slot's flat index and runs each compiled package through `bincraft::classify_r_minor_sensitive()`, which looks the verdict up in the cache, and on a miss downloads the CRAN source, classifies it and stores the result.

The verdict is a property of the source, independent of OS, arch and R minor, so **one run populates the cache for every slot**. The arch/codename arguments only choose which flat index to enumerate.

Only `NeedsCompilation=yes` packages are classified: a package with no compiled code has no symbols to bind and cannot fail this way, so proving it by download would be wasted work. On amd64/resolute that is 4585 packages rather than 23218.

Re-running is cheap and resumable: cached verdicts return without touching the network, so a second run costs one query per package and downloads only the remainder.

## Verification

The enumeration was run against the live indexes and matches an independent symbol scan of the same slot exactly:

```
flat binaries: 23218 | due classification: 4585
base64enc included: TRUE
lobstr included:    TRUE
```

4585 is the same population I scanned with `nm -D --undefined-only` when establishing the blast radius, and both packages confirmed to break under 4.6 are in it.

`crow lint` passes.

## Sequencing

Merge after bincraft #124 and after a bincraft release the pipelines pick up, otherwise the verdicts are written but nothing reads them yet. Writing them early is harmless.

Then re-index the slots so the per-minor indexes are rebuilt with the widened risky set. Expect coverage in the per-minor indexes to *drop* slightly as newly-recognised risky packages are dropped rather than served from a mismatched minor; those then need per-minor builds, either through the normal pipeline or the targeted workflow in devxy/build-cran-binaries#198.

Reviewed-on: #199
2026-09-04 10:34:49 +00:00