ALETHEIA API Changelog

Customer-facing release notes for the ALETHEIA Safety Intelligence API (api.aletheia.holisticquality.io).

For the data-layer change feed (new compounds, updated regulatory classifications, sub-processor changes) see /api/changelog.

The machine-readable form of this file is served at /api/release-notes.


2026-05-22 — v1.4.5: Pricing-surface coherence + legal containment hardening

> Released 2026-05-22. v1.4.4 → v1.4.5. Closes both technical-gate > preconditions from the 2026-05-22 board decision memo > (tracking/board/2026-05-22-board-distribution-decision-memo.md). > Mechanically additive; no breaking changes; the data layer is unchanged.

T-1: pricing-surface drift closed (MK #41)

The 2026-05-14 storefront price bump to Dev $79 / Pro $299 was missed by the API code itself across three successive releases (v1.4.2, v1.4.3, v1.4.4) — api/_lib/constants.js still encoded the old $29 / $99, and a shadow TIER_PRICES in api/_lib/admin-dashboard.js was the actual root cause of the admin dashboard showing wrong MRR numbers.

T-2: legal containment hardening (MK #42)

Net-new strategic-regulatory artifact ship gated on any future external customer signup. Three substantive additions:

Plus: terms.html adds a top-of-document conspicuous "Reference data, not professional advice" banner (UCC §2-316 conspicuousness); terms.js TERMS_META carries last_reviewed: '2026-05-22'; privacy.html footer shows the same review date.

Tests

24,716 / 24,718 passing (2 skipped, 0 fail). No deprecations.


2026-05-19 — v1.4.4: SCI-DAT-01 batch-1 + batch-2 chemical-identity data corrections

> Released 2026-05-19. v1.4.3 → v1.4.4. Data-only release — no API > contract, code, or middleware change. safety.holisticquality.io is > resynced by this release (66 compound records). The v1.4.3 export-surface > data-quality safeguard remains in force for records still under review.

Chemical-identity corrections (SCI-DAT-01)

Name-anchored corrections (PubChem PUG-REST resolved by name, never via the suspect cross-ref CAS/CID) landed across two operator-adjudicated batches:

66 compound records changed in total. Records that could not be safely resolved by the mandated name-anchored method are stamped _data_gaps: blocked for second-reviewer adjudication (e.g. the "RDP" abbreviation-name and glyphosate parent-vs-salt name-resolution traps) and remain covered by the v1.4.3 export safeguard. The deterministic SCI-DAT-01 ratchet floor burned 395 → 342 across the two batches. CI-3 and the wider SCI-DAT-01 remediation remain open (later batches).

2026-05-19 — v1.4.3: Export data-quality safeguard for compounds under chemical-identity review

> Released 2026-05-19 (api.aletheia only — safety.holisticquality.io is not affected by this release). v1.4.2 → v1.4.3. No breaking API contract change; one new advisory field on the bulk export.

Data-quality safeguard — structural-identity fields on bulk export

A defined set of compounds is undergoing a chemical-identity review (the SCI-DAT-01 work tracked publicly in our changelog feed). For those records, the structural-identity fields — smiles, inchi, inchi_key, exact_mass, molecular_weight, molecular_formula (under identity.</code> / <code>crossrefs.) — previously could return a value sourced from the wrong compound.

As of v1.4.3, on the bulk export endpoints those specific fields for those specific compounds are returned as the literal sentinel <code>[under-review:SCI-DAT-01]</code> instead of a value we cannot currently vouch for, and the record carries a new advisory <code>data_quality</code> array ({field, status:"under_review", finding:"SCI-DAT-01", reference}). This is a correctness safeguard: we would rather return an explicit "under review" marker than a structure that may be wrong. CAS number, name, IUPAC name and synonyms are not affected.

Scope (what changed / what did not):

Temporary by design. When the chemical-identity review completes and the underlying records are corrected, the sentinel and data_quality marker are removed and the corrected structural values are served normally. No client change is required in either direction; the marker is additive and the field type for affected cells is a recognizable string.

2026-05-16 — v1.4.2: SCI-DAT-01 mechanical partition + PC-2 tier-B cache + rebrand sweep

> Released 2026-05-16 (api.aletheia + safety.holisticquality.io). This is the "next data/audit batch deploy" the PC-2 hold (operator decision 2026-05-15) was waiting on — it ships the SCI-DAT-01 mechanical correction, the PC-2 edge-cache change, and the 2026-05-12 intelligence → reference rebrand sweeps together as one batch. v1.4.1 → v1.4.2.

Data correction — SCI-DAT-01 chemical-identity partition

33 PubChem-triple-verified <code>identity</code>/<code>crossrefs</code> corrections across 13 compounds (RDP → CID 93311, glyphosate IPA/ammonium crossrefs.inchi, ceftiofur, and 10 others). These rows previously served a different compound's structure on identity.</code> and/or <code>crossrefs.. Pinned by tests/sci-dat-01-residual-corrections.test.js (43/43) and gated against regression by a deterministic ratchet (scripts/sweep-sci-dat-01-residual.py --baseline, floor 395, its own CI job). The safety.holisticquality.io JSON-viewer mirror is synced to the same 13 corrected records in this release.

Still outstanding (operator-routed, NOT in this release): the non-mechanical SCI-DAT-01 remainder — 116 compounds / 184 manual_review rows incl. CI-2 (MeIQ/MeIQx mutual carcinogen-identity swap) — requires chemist judgement and is tracked in tracking/SCI-DAT-01-CHEMIST-QUEUE.md. It is not resolved by this deploy.

Rebrand — "Safety Intelligence" → "Safety Reference"

Customer-facing copy sweep across legal (/privacy, /terms), /docs, /playground, /og, release-notes, Postman, and the RapidAPI listing (aletheia-safety-intelligencealetheia-safety; "Safety Intelligence" → "Safety Reference"). No API contract change.

Performance — PC-2 / SCALE-2 Phase 3: tiered cache on /api/compound/{id} (unwatched compounds now edge-cacheable)

One-line: GET /api/compound/{id} previously emitted Cache-Control: private, max-age=3600 for every response. It now upgrades to public, s-maxage=3600, stale-while-revalidate=7200 on the 200 success path when classifyCompound() returns no watch matches — i.e. for ordinary compounds whose response is deterministic in (id, context) and carries no per-user redaction.

Watched compounds remain private. Explosives precursors, narcotics precursors, CWC precursors, acute toxins, and radiological precursors continue to return private, max-age=3600 so the origin can register every access via the misuse tracker. Error paths (400/404/422) and the CRITICAL-threat 403 also stay private.

Cache-key safety. Public responses carry Vary: X-API-Key, X-RapidAPI-Subscription (auth state keyed into the CDN slot, as enforced in SCALE-2 Phase 1) plus Surrogate-Key: tier-b compound:{id} (per-compound + global tier-B purge tags) so a compound added to the watch list later can be evicted without a global flush.

Why now: the response payload was the largest remaining hot-path that bypassed Vercel's edge. Carries ~3600s of free p95 reduction on repeat reads for the broad compound corpus.

Closes audit finding PC-2 from 2026-05-04 perfcost (carried as YELLOW through release-readiness 2026-05-09 + v1.4.1 follow-up). Regression-pinned in tests/cache-headers.test.js (Tier B contract — /api/compound/[id] tiered cache (PC-2 Phase 3)) with 4 assertions: unwatched 200 → public, watched → private, 404 → private, malformed ID 400 → private.


2026-05-12 — RAPIDAPI: POST /api/compounds/batch endpoint card now live on Hub

POST batch is now exposed on the rebuilt RapidAPI listing (). Closes RAPIDAPI-L5 carry-over from Session 52 (2026-04-23). Customers on Pro/Ultra who need URL-length relief for large ID lists can now POST a JSON body to /api/compounds/batch through the marketplace gateway instead of using GET with query-string IDs. Origin handler unchanged.


2026-05-12 — v1.4.1: regression fix — methodology_note surfaces on /api/product/{id}

One-line: v1.4.0 set methodology_note on disk for every synthesized product but the response shaper at api/product/[id].js:37-50 had an explicit field allowlist that omitted it, so the field was silently dropped before serialization.

Customer-visible: methodology_note (string, optional) now appears inside synthesis on every product response, matching the v1.4.0 CHANGELOG promise (CI-3 closure surface).

Why it slipped: test coverage at tests/product-e2e.test.js asserted synthesis_method and synthesis_version are present but did not assert methodology_note. v1.4.1 adds the missing regression test (it('3b. methodology_note surfaces in synthesis')) to prevent recurrence.

No data changes. No schema changes. No SDK schema changes — v0.9.0 typed the field as Optional[str], which is still correct.


2026-05-12 — v1.4.0: data expansion + audit-closure batch (23 phases shipped + 1 doc-sync, 19+ findings closed including 1 RED resolved)

> See tracking/DEPLOY-PLAN-2026-05-12.md for the deploy sequence and rollback plan. Deploy window: Tuesday 2026-05-12, 02:00–06:00 UTC.

> Paired SDK release: aletheia-safety v0.8.0 → v0.9.0 ships alongside this API release (Phase 73, 2026-05-09). Surfaces 166 lines of accumulated schema additions in TypeScript + Python types — methodology_note, _prior_agency, exposure_ocular, occupational_exposure, iupac_name, molecular_formula, tightened molecular_weight: number. Publishing to PyPI + npm happens after the API is live so types match production. Future cadence: SDK tracks API minor/major bumps only; patch deploys skip SDK.

Customer-visible behavior changes

New API response fields

Data deltas

Synthesis engine: regulatory-coverage expansion

The 2026-05-05 sci-verify audit found that the synthesis engine processed only ~40% of the regulatory classification text in the corpus, silently dropping the other ~60% with unmapped_classification warnings or Source must have year field rejections. v1.4.0 closes the largest single gap:

Corpus impact (verified post-application on all 1,287 products): +16 products escalated to 'severe' from previously-dropped CTX-derived signals (notably for compounds with disputed status where CTX-derived IARC/EPA OPP entries were the most authoritative recent classifications); balanced shifts in adjacent bands (-11 'high', -9 'low', -5 'moderate_to_high', +9 'moderate'); zero regressions to insufficient_data; zero change in extreme/negligible/insufficient_data counts. Closes engine-level audit finding SCI-ENG-01.

Performance: cold-start improvement on /api/openapi

The OpenAPI 3.1.0 spec lived as a 152 KB JS object literal inlined in api/openapi.js (3,642 lines). @vercel/node bundled the entire object into every cold start at ~150 ms parse cost. v1.4.0 separates spec authoring from runtime:

Expected first-byte latency improvement on cold-start /api/openapi requests; will be validated post-deploy via Speed Insights. Closes perf-cost finding PC-4.

Customer-invisible internal improvements

Security hardening (red-team Mediums + Hygiene Lows)

Four red-team Medium findings from the 2026-05-04 cross-audit were structurally non-functional pre-fix; v1.4.0 restores three claimed defense layers:

Plus three hygiene Lows from the Twelfth E2E review:

GDPR / coherence

Scientific accuracy (sci-verify follow-ups)

Claims hygiene (defamation / factuality calibration)

The 2026-05-04 claim-integrity audit flagged 5 areas where load-bearing factual claims about named entities needed inline citation, methodology disclosure, or framing tightening:

Spec / SDK / pricing

Operator notes (not customer-facing)


2026-05-07 — SCI-DAT-02 Phase 4: synonym decontamination across 60 records (data-only, lands at next major deploy)

Companion fix to the SCI-DAT-02 Phase 2 wrong-CID corrections shipped earlier the same day. The 59 Phase-2 compounds (plus Plutonium-239 from session-64 Gap-2 cleanup) had identity.synonyms arrays still populated from the wrong-CID-active window — auto-enrichment had stamped each record with the wrong molecule's PubChem synonyms list. Phase 2 corrected the cross-references; Phase 4 corrects the synonyms.

What changed

For 60 compounds, every synonym entry that appears in the OLD (wrong) PubChem CID's synonym list AND does NOT appear in the canonical (NEW) CID's list was stripped. Canonical synonyms not already present were backfilled. 1,605 old-molecule synonym entries removed, 5,804 canonical synonym entries added.

Notable per-compound results (before → after):

Customer impact

/api/search exact-match no longer returns the wrong compound for old-molecule queries:

The wrong-search-hit risk class is now closed for these 60 records.

Tooling


2026-05-07 — SCI-DAT-02 Phase 2: 59 wrong-CID corrections via InChIKey-prefix triage (data-only, lands at next major deploy)

Data-layer fixes only — no API behavior change. 59 compound records now carry correct PubChem cross-references (crossrefs.pubchem_cid, identity.smiles, identity.inchi, identity.inchi_key, identity.iupac_name, identity.exact_mass, properties.chemical_properties.{molecular_formula, molecular_weight, exact_mass}) where they had previously been mis-mapped to wholly unrelated molecules by a 2026-03-22 wrong-CID batch merge. Live API still serves pre-fix data until the next major deploy (manual-deploy policy).

Methodology

The 89 mismatch_recoverable rows from the SCI-DAT-02 name-lookup sweep (session 64) were re-triaged via PubChem InChIKey-prefix discriminator: same first-14 chars = same molecular connectivity (cosmetic / stereo difference); different prefix = different connectivity = genuine wrong-CID. Bucket distribution: 66 prefix_differs / 20 suffix_only / 3 key_matches / 0 fetch_error. Of the 66 prefix_differs, 59 had per-case PubChem Title showing wildly unrelated current_cid — those are this batch. 7 deferred as ambiguous (Phase-1 PeCDF dup; PCB 138; Phenylpropanol regio; Ambrettolide isomer; Ocimene specificity; Phenylpropionaldehyde regio; Satratoxin H untitled lookup).

Notable corrections

Tooling

safety.holisticquality.io mirror synced across all 59 touched files. Triage post-fix: HIGH=0 / MEDIUM=0 / CLEAN=1867. Tests 23,778 / 0 fail.


2026-05-07 — SCI-DAT-01 Gap 2 closeout: 13 compounds re-resolved against PubChem; Pu-239 wrong-CID fixed (v1.3.1)

Data-layer fixes only. No API behavior changes — the only thing customers will notice is that 13 compound records now carry correct identity.smiles, identity.inchi_key, identity.inchi, and identity.exact_mass where one or more of those fields was previously contaminated by a wrong-CID PubChem batch merge from 2026-03-22.

What changed

A second sweep of the SCI-DAT-01 contamination class flagged in the May-5 sci-verify audit cleared the 14 compounds remaining after the May-7 morning pass:

The Plutonium-239 case is worth a specific call-out: the wrong CID (61460) is disodium hydrogen arsenate heptahydrate, which had been silently donating its exact_mass: 311.962569 and inchi_key: KOLXPEJIBITWIQ-UHFFFAOYSA-L to Pu-239's record since the bad batch import. The canonical Pu-239 record (CID 61782) returns [239Pu] SMILES, exact mass 239.05216, InChI key OYEHPCDNVJXUIW-FTXFMUIASA-N — all of which now appear correctly in the API.

safety.holisticquality.io mirror synced to match across all 14 touched files.

Triage detail

Post-fix triage-pubchem-contamination.py reports HIGH=0, MEDIUM=0, CLEAN=1873/1880 (99.6%) — up from 1860/1880 (99.0%) at the start of the day. The original audit estimate of 50–200 contaminated files of the 1,230 touched by the 2026-03-22 PubChem batch turned out to be substantially inflated by SMILES canonical-vs-expanded rendering false positives; the residual real signal was 14 files, of which 13 are now fixed.

Operator notes (not customer-facing)


2026-05-07 — Scientific accuracy: methylmercury monograph + cancer-site correction; SCI-DAT-01 triage closed

Data-layer corrections following the 2026-05-05 sci-verify audit.

hq-c-ino-000006 Methylmercury — IARC monograph reference + cancer site

Two stale fields fixed in safety.carcinogenicity:

safety.holisticquality.io mirror synced to match.

Sci-verify P0 status

SCI-DAT-01 (chemical identity contamination) triage + Gap 1 / partial-class fixes

The 2026-03-22 PubChem batch enrichment merged data from the wrong CID into 4 confirmed compounds (Glyphosate IPA / K / ammonium salts; Ceftiofur). Those identity.* fields were stripped on 2026-05-05 with audit_tag: SCI-DAT-01 gap stamps.

Today's sweep with scripts/triage-pubchem-contamination.py scanned the remaining 1,876 compounds for the same shape using InChI-key, SMILES, and exact-mass-vs-MW signals:

Triage output at tracking/SCI-DAT-01-triage.md. Audit's original estimate of 50–200 contaminated files was inflated by SMILES canonical-vs-expanded rendering false positives — the real residual count is 16.

scripts/fix-sci-dat-01-identity-contamination.py extended and applied to close two further classes:

After apply, triage re-run: 16 → 14 MEDIUM (Ptaquiloside + Maitotoxin now stamped + excluded). The remaining 14 are: 1 mass/MW divergence (Pu-239 — needs human review on whether its exact_mass is a radionuclide-bookkeeping convention) + 13 SMILES-only mismatches needing per-compound PubChem-CID cross-check.

No customer-impacting data served wrong values for any of these — they're all identity.* cosmetic fields, not used in the synthesis or risk-scoring path.

CO-1: Stripe subscription lifecycle handlers (api/stripe/webhook.js)

The webhook previously listened for only checkout.session.completed and customer.subscription.deleted. Two new handlers added today, modeled on the existing deleted-subscription pattern (idempotency SET NX, customer→email lookup, per-key stripe_customer ownership guard):

Closes the carry-forward HIGH from the 2026-05-04 coherence audit (CO-1). Indefinite drift between Stripe state and local keyData.tier is no longer possible — a Pro→Developer downgrade through the Billing Portal now propagates within ~1 second.

11 new tests added covering source-level structural assertions (idempotency pattern, tier mapping, ownership guard, no accidental deactivation during dunning, analytics emission). 31/31 stripe-webhook.test.js tests pass.

⚠️ Required Stripe-side config to activate: the new event types must be enabled on the Stripe webhook endpoint (Dashboard → Developers → Webhooks → select endpoint → Update details → add customer.subscription.updated + invoice.payment_failed). Without that step, Stripe never delivers the events. See tracking/RUNBOOK.md §6.4 for the verification recipe. (Confirmed enabled by Levi 2026-05-07 14:13 UTC — endpoint now subscribes to all four events.)

SEARCH-Q1: Canonical-abbreviation alias map for /api/search

Search-quality fix surfaced in session 55 by a playground bug investigation: ?q=bpa was returning Bisphenol AF (score 76) instead of Bisphenol A (CAS 80-05-7) because the scorer ranks closest-by-substring without canonical-name semantics. Same pattern affected pfoa (could rank tetra-PFOAs above PFOA), pcb (mixture vs individual congeners), no2 (subscript-typeset name failed plain-text exact match), etc.

M-2: VERIFY_SECRET bypass observability (api/_lib/monitor.js, api/cron/monitor-push.js)

VERIFY_SECRET is the deploy-verification bypass that skips audit / shed / rate-limit / auth in one step (api/_lib/auth.js:481-518). Any leak of that secret is a full compromise; until today there was zero observability on its use.

Quarterly rotation cadence documented in tracking/RUNBOOK.md §5.4. Closes the carry-forward MEDIUM from the 2026-05-04 cross-audit (M-2).


2026-04-27 — Batch limits aligned with RapidAPI Hub plan configuration (v1.5.0)

OpenAPI spec version bumped from 1.4.0 to 1.5.0. Two functional changes that align the API's enforced behavior with what the RapidAPI Hub already advertises to subscribers.

Public tier now has batch access

GET /api/compounds/batch and POST /api/compounds/batch were previously gated to Developer tier and above (the public tier received 401 API key required). Public tier now receives a successful batch response, capped at 10 compounds per request to match the max_batch_size: 10 value configured on the RapidAPI Basic plan in the Hub Provider Dashboard. This was a Hub/code mismatch — Hub advertised batch on Basic, code rejected it.

Per-tier batch caps raised

The internal BATCH_LIMITS table is now:

| Internal tier | Batch cap | RapidAPI plan | |---------------|----------:|---------------| | public | 10 | Basic ($0) | | developer | 50 | Pro ($29/mo) | | pro | 100 | Ultra ($99/mo)| | enterprise | 100 | Enterprise (off-marketplace) |

Previous values (developer: 20, pro: 50, enterprise: 100) were inconsistent with the Hub's per-plan max_batch_size Feature configuration (10 / 50 / 100). Subscribers who composed batches at the Hub-advertised limit could receive 400 Too many compounds from the underlying API. That is now resolved.

What this means for subscribers

Synthesis cap unchanged

BATCH_SYNTHESIS_MAX = 10 (the cap when synthesize=true is requested) is unchanged. Synthesis still requires a Developer key or higher.

Files touched

Action for RapidAPI subscribers

None. Spec v2.3 is now live in the RapidAPI Hub Studio (set Current). The Definitions tab and the Plans tab Features panel both reflect the new caps; code BATCH_LIMITS matches what the Hub advertises. Existing subscriptions, API keys, and quotas are unchanged.


2026-04-27 — Marketplace listing v2.2: source transparency, sample response, conversion polish

OpenAPI spec version bumped from 1.3.0 to 1.4.0. The change is primarily customer-discovery and onboarding surface — no breaking changes to any endpoint or response shape.

Marketplace listing improvements (RapidAPI)

The RapidAPI listing description (auto-generated from the spec by scripts/export-rapidapi.js) was rewritten for conversion clarity based on a marketplace audit. Specifically:

Distribution-surface cross-references

The marketplace listing now points subscribers and evaluators to:

What did not change

Action for RapidAPI subscribers

None. The updated listing copy is now live at as version v2.2 in the RapidAPI Hub. Existing subscriptions, API keys, and quotas are unchanged.


2026-04-26 — Postman API Network listing + playground name-search fix

Availability

Bug fixes


2026-04-23 — RapidAPI launch

Availability

Security & reliability

Documentation

Known RapidAPI gateway note


Earlier history

This changelog begins with the RapidAPI launch. Earlier infrastructure and dataset changes are tracked in the internal tracking/ directory and were not published as customer-facing release notes.