SolScore
Back

Release Notes

What actually changed and why it matters to you. Full commit history at the bottom for transparency.

May 29, 2026

Full-stack hardening pass — fund-flow, trust, mobile, Phantom Blowfish, dependency vulns

Field-reported on a live mainnet sweep: the success card displayed nonsense numbers (660,500 SOLSCORE for a 660-score wallet; 6,830,544 SOL reclaimed for 0.068 SOL of lifetime reclaim) AND Phantom showed a 'malicious dApp' warning on every signing prompt. Spent the night running five parallel adversarial audits across fund-flow safety, security, type-confusion bugs, UX/accessibility, and Phantom Blowfish reputation. Shipped 31 fixes across 19 files in priority order. Nothing here is cosmetic — every bullet either closes a fund-flow risk, removes a trust-killing UI lie, or drops a vulnerability.

  • ·Money math: BIGINT columns returned as strings by the Neon driver are now normalized to JavaScript numbers at the data-layer boundary (db.ts toNum + normalizeNumericCols) so client `+` arithmetic adds instead of concatenates. Throws loudly if any value ever exceeds Number.MAX_SAFE_INTEGER. The 660,500 and 6,830,544 display bugs both root-caused here.
  • ·Money math: the SystemProgram fee transfer in signed transactions is now read as BigInt (capped at 1000 SOL) instead of Number — closes a 9-quadrillion-lamports precision-loss class on the fee-enforcement comparator.
  • ·Consent: the in-app confirm dialog now computes the fee for the SELECTED subset of accounts (calculateFees(prev+selected) - calculateFees(prev)) instead of the scan-time fee for ALL accounts. After /api/build-transactions returns, if the server's actual fee exceeds the disclosed amount (race vs another tab), the client aborts BEFORE the wallet prompts — you'll never sign a tx charging more than the modal showed.
  • ·Consent: /api/build-transactions now re-scans the wallet and rejects any pubkey the scanner wouldn't have offered (non-empty balance, frozen, delegated, foreign close-authority). A malicious or buggy client can no longer build a sweep tx for accounts it didn't show you.
  • ·Trust: post-sweep card redesigned. Each stat now reads 'lifetime (+this-sweep delta)' with an explicit 'Lifetime' label. The '+N points' celebration also names the this-sweep amounts (closed / SOL reclaimed) so the lifetime number below can never be mistaken for the sweep result.
  • ·Trust: formatSol refuses any value above 100,000 SOL (renders '—' + console.warn); formatNumber refuses above 100M. If a future type bug ever ships wild data to the UI, users see a missing-data dash instead of a fabricated number on a money screen.
  • ·Trust: SweepHistory, GlobalStats, and LeaderboardTable now show explicit error states when their fetch fails, instead of rendering nothing or 'No history yet' which looked indistinguishable from a real empty state.
  • ·Trust: scoring.ts getGradeFromScore is now defensive against non-numeric inputs (was silently returning F via lexicographic string comparison).
  • ·Trust: sweep error categorizer now preserves SubmitSimulationError.userMessage on the outer catch path — actionable 'Wallet does not have enough SOL to pay transaction fees' messages no longer get overwritten with generic 'Sweep failed' when the throw bubbles past the inner per-tx loop.
  • ·Privacy: NEXT_PUBLIC_TREASURY_WALLET is no longer baked into the client bundle. The treasury address was previously recoverable via view-source despite never appearing in rendered UI. Server-side verifyAllSignedTransactions is the authoritative destination gate; tip-jar still verifies the transfer AMOUNT it asked for, just not the address.
  • ·Phantom Blowfish mitigations: every sweep tx now carries an SPL Memo (`SolScore: close N empty token accts (M/total)`) — Phantom's confirm dialog + Solscan/SolanaFM now show explicit context instead of an opaque blob. Reduces drainer-pattern false-positives on close+outbound-transfer txs.
  • ·Phantom Blowfish: site now ships robots.txt, sitemap.xml, JSON-LD Organization + SoftwareApplication structured data (Schema.org), Twitter site/creator handles, stronger Open Graph copy, and an OG-image route fallback so a Neon outage doesn't blank the preview thumbnail wallet reviewers scrape.
  • ·Mobile: nav at 360px no longer overflows. Primary actions (Sweep, Leaderboard) inline; secondary routes (Fees, Stats, Security, Changelog) behind a hamburger Sheet. Every touch target now ≥44px (WCAG/Apple HIG).
  • ·Mobile: leaderboard table no longer hides Swept + Reclaimed columns on small screens — they're now stacked as a muted secondary row under the wallet, so phone users actually see the SOL numbers that make the leaderboard interesting.
  • ·Accessibility: confirm-sweep dialog rewritten on Radix Dialog (shadcn) — proper focus trap, return-focus on close, aria-describedby. Previous hand-rolled overlay had role=dialog but none of the actual focus management. Account-selector checkbox now has a visible focus-ring. Sweep dashboard has sr-only h2 landmarks. Wallet-deeplink emoji are now aria-hidden. --muted-foreground lightened from oklch(0.65) to oklch(0.74) to clear WCAG AA contrast on small text.
  • ·Rate limits: /api/build-transactions now per-wallet rate-limited (was per-IP only — the more expensive endpoint deserves the tighter budget). /api/scan correctly upgrades to the batchScan tier (3/60s) when the request actually contains multiple wallets (previously every scan landed in the lighter scan tier, so attackers could 10x their RPC burn rate by batching).
  • ·Rate limits: missing forwarding headers now bucket by user-agent fingerprint instead of collapsing every header-stripped client into a single 'unknown' token — one attacker can no longer saturate the shared bucket and DoS every Tor/VPN exit out of the budget.
  • ·Telegram webhook hardening: signature verification moved outside the outer try block so a 403 can never be silently rewritten to ok:true by the catch. Buffers padded to equal length so timingSafeEqual never throws on mismatched-length tokens.
  • ·Copy: the 'always free' badge on /fees and the 'First 10 accounts are always free' line in the in-app fee-breakdown both replaced with posted-rate language. The fees page no longer says 'And we're telling you' after 'We take less' (transparency theater — the page IS the transparency).
  • ·Dependency vulns: swapped @solana/wallet-adapter-wallets (the meta package that hauls in every adapter — Keystone, Particle, Reown/WalletConnect, Torus) for the 5 individual per-wallet packages we actually register. Dropped npm audit from 56 vulns / 1 critical / 13 high to 11 / 0 critical / 3 high. Remaining vulns require absurd downgrades (Next.js to v9, spl-token to 0.1.8) that don't fix anything in practice — their attack vectors aren't reachable from our usage. Next.js bumped to 16.2.6 to clear the App Router XSS / SSRF / cache-poisoning advisories.
  • ·Polish: MatrixRain on /security now plays once per session (sessionStorage flag) instead of every visit blocking content for 2.2s. Security page got a 'Last reviewed' timestamp.

May 14, 2026

Sweep + tip errors now name the actual reason

When a transaction fails, the page used to say a generic 'All transactions failed to submit' — same string whether your wallet was out of SOL, a wallet quirk fired, or a real bug ran. The submit path now pre-simulates each transaction and, on the small set of definitively-deterministic Solana errors, surfaces a specific reason.

  • ·If your wallet doesn't have enough SOL to pay the transaction fee, the error now says exactly that instead of the generic 'failed to submit' line. Same for a handful of other deterministic failures (signature invalid, fee account malformed, transaction already processed).
  • ·Pre-simulation is conservative on purpose. Anything that could be a transient race (blockhash not seen yet, account in flight, RPC lag) still falls through to normal submission so a flaky RPC moment doesn't reject a perfectly good transaction.
  • ·Belt-and-suspenders: our database-layer duplicate-signature guard (FORT-MNY-003 from the audit backlog) is now active in production. Two concurrent sweeps trying to claim the same on-chain signatures will fail loudly at the database, not silently double-record. App-layer dedup already prevented this, but a backstop never hurts on a real-money path.
  • ·Test infrastructure: a real-Postgres integration test harness and a Playwright end-to-end suite landed alongside this. Neither runs against production data — but every future change to the sweep / scan / fee paths now has a place to pin its invariants before shipping.

May 11, 2026

Slightly higher priority fee on sweeps — for better tx-land reliability

One small user-facing change: the priority fee your wallet pays per sweep transaction went up about a tenth of a cent, in exchange for better tx confirmation reliability when Solana's network is congested. Everything else today was operational polish.

  • ·Sweep transactions now pay 50,000 microlamports per compute unit, up from 10,000. For a typical 19-close batch that's ~7,250 lamports (~$0.0014 USD) per tx in priority fee, up from ~1,450 lamports (~$0.0003). Absolute cost is still tiny; the bump improves tx-land odds during busy mainnet windows where the prior value had become marginal.
  • ·/api/healthz now compares Solana's live SPL token rent-exemption value to the constant our fee math depends on (RENT_PER_ACCOUNT = 2,039,280 lamports). Any future divergence shows up in the health endpoint's response and server logs — early warning if Solana ever changes rent math.
  • ·Observability: new OpenTelemetry counter on rejected sweep attempts, partitioned by reason (rate limit vs per-wallet lock contention vs Redis outage) so production dashboards can tell legitimate browser-tab races apart from infra hiccups.
  • ·Codebase hygiene: ~80 inline audit-ID tags (LOW-X, MED-X, FORT-MNY-XXX, SLOP-MX, etc.) stripped from comments and test names across 41 files. No behavior change — the audit IDs didn't trace anywhere a future reader could follow.

May 10, 2026

Big hardening pass — sweep mutex, RPC failover, PWA icons, much more

Multi-phase audit (custom Phase 1 + slopcheck + FORTRESS) shipped 27 fixes spanning correctness, security, and developer hygiene. Nothing here changes what you click; everything here makes the things you click more trustworthy.

  • ·Sweep concurrency: simultaneous sweeps for the same wallet now serialize through a per-wallet lock. Prevents the fee-tier from being read at a stale count when two browser tabs race the same wallet.
  • ·RPC failover: if the primary Solana RPC throws a network/timeout/5xx, we retry once on a secondary endpoint before failing the request. Survives a single-provider outage without ending the sweep flow.
  • ·PWA install icons fixed — 'Install as App' on iOS/Android no longer hits 404s for the icons.
  • ·/api/healthz already existed; added OTel custom spans around the sweep flow so production latency breaks down by phase (verify, submit, on-chain, record).
  • ·Behind the scenes: solana.ts split from one 700-line file into 10 focused modules; 15 new tests pin the transaction verifier's invariants (which programs are allowed, where fees must go, what shapes are rejected); db.ts gained a production-only assertion that DATABASE_URL uses the Neon pooler endpoint; honest 'service unavailable' messaging during DB outages instead of misleading 'already recorded' false positives.
  • ·Test coverage went from 57 to 111. Every new test pins a money-path invariant — anything that drifts in the future fails CI before it ships.

May 4, 2026

SOUL — chat assistant is live

The SOUL chat surface is now reachable from every page (floating button, bottom-right). The endpoint hardening called out on /security has been live for a while; now there's a UI to actually talk to it.

  • ·Click the floating Sparkles button in the bottom-right of any page to open SOUL. If you have a wallet connected, your score and rank are passed in as context — SOUL can reference them in answers.
  • ·20-message conversation cap (matches the server). Closing the panel doesn't lose the conversation; reopening picks up where you left off until you reset.
  • ·Replies stream in as they arrive. Closing the panel mid-reply aborts the stream cleanly so you're not paying for tokens you'll never see.
  • ·Beta. We'll iterate on placement, persona, and what context SOUL sees as we watch real usage. Feedback welcome.

May 4, 2026

/fees competitor cards — only what we could verify

Re-checked the four competitor entries on /fees against each tool's own primary surfaces (homepage, docs, terms). Where a percentage wasn't actually published anywhere on the competitor's site, we no longer publish one either.

  • ·Removed the back-solved percentage ranges from the §3 reveal cards and the §5 Hall of Opacity marquee. Where the number wasn't on the competitor's own site, it now reads 'undisclosed' instead.
  • ·Removed the RefundYourSOL entry entirely. Their domains were unreachable when we tried to verify, so we can't responsibly cite a specific section of their terms of service.
  • ·Renamed 'Claim Your SOL' → 'Claim Your SOLs' to match the brand string the project actually uses on its Phantom listing.
  • ·The page's argument is unchanged — the point is still that most tools don't publish their fee. We just made sure every claim on the page is one we can actually back up.

May 4, 2026

Hardening — internal cleanup

Quiet maintenance pass. No user-facing behavior changed. Internal code consolidation + the start of a test suite to keep future changes honest.

  • ·Stood up a unit test suite for the critical money-math (fee calculation, tip calculation, score calculation, grade tiers, formatting helpers). 57 tests; runs as `npm test`. Future refactors will run against this safety net.
  • ·Single source of truth for the wallet address validator and the per-transaction close-account count — both used to be repeated in many files where one drift would have broken validation somewhere weird.
  • ·The two error-boundary pages share their layout now; only the heading + body sentence differ between them.

May 3, 2026

Audit cleanup batch 2 — auto-dated /fees, /api/healthz, telegram rate limit, polish

Second pass on the same-day audit, picking up the 'task #4 + #7 backlog + smaller polish' items. No money-flow behavior changes — these are defense-in-depth and quality fixes.

  • ·/fees 'Last updated' stamp now auto-derives from git at build time. Was hardcoded to a date that drifted every time the page changed without a hand-edit. Reads `git log -1 --format=%cI src/app/fees/page.tsx` in next.config.ts and inlines the value into the bundle.
  • ·Tip flow defensive guards: calculateTip and buildTipTransaction now reject bad inputs (NaN, negative, zero) explicitly instead of producing a malformed transaction. The treasury env is also re-validated at build-tip time as defense-in-depth (production already has a module-load guard).
  • ·On-chain error messages now truncate cleanly when bubbling to the UI. Verbose RPC error structures (instruction indices, full program IDs) stay in server-side console.error; the user sees a 80-char prefix instead.
  • ·Bulk-paste wallet add now tells you when wallets didn't fit. Pasting 30 addresses with a 10-wallet cap previously showed '10 added' silently — now reads '10 added, 20 didn't fit (10-wallet max)'.
  • ·Footer Privacy / Terms / Disclaimer links use client-side navigation (no full page reload).
  • ·Stats endpoint cache: /api/stats now sets a 60-second edge cache + 5-minute stale-while-revalidate header. Reduces DB hits on the homepage Global Stats panel during traffic spikes.
  • ·Telegram webhook: per-chat rate limit (10/min) added to cap our outbound sendMessage spend if a chat floods commands.
  • ·Terms page: contact section now actually links to @solscoreUS on X and the solscoreus@gmail.com address (was vague 'reach out on X' text).
  • ·New /api/healthz endpoint probing RPC + Neon DB + Upstash Redis + treasury env. Returns 200 when all healthy, 503 when any dependency is down. For ops visibility before considering an RPC failover layer.
  • ·Behind the scenes: schema.sql cleaned up (dead `referrals` table removed, unused `total_users` column removed from global_stats), incrementGlobalStats no longer writes the dead column, dead `mode='batch'` branch removed from FeeBreakdownDisplay, shortenAddress guards against short input, chat route now imports the shared getClientIP helper from proxy (was duplicated inline), token-balance check uses string compare to avoid future precision-loss footguns on memecoin amounts.

May 3, 2026

Audit cleanup — live USD on /fees, accurate error messages, brand fixes

A three-pass audit (manual line-by-line + /slopcheck + /fortress) surfaced one HIGH finding and a stack of mediums. None were exploits, but several affected what you actually saw on the site. Fixes shipped together.

  • ·/fees calculator USD figure is now live. The page used to fetch the SOL/USD price from CoinGecko in your browser, but our Content-Security-Policy didn't allow that domain — so every visitor saw a hardcoded fallback of $86/SOL on every load. Now we proxy the price through /api/sol-price (60-second cache) and the displayed USD reflects the actual market.
  • ·/fees calculator footnote added: the cascade (10 free, then 6 / 8 / 10 %) is per-wallet-lifetime, not per-sweep. A wallet that's already swept 10+ accounts pays the next tier on its next sweep. The /sweep flow always handled this correctly; the calculator just wasn't disclosing the assumption.
  • ·Scan errors now show the actual reason (rate limit, invalid address, RPC issue, etc.) instead of a generic 'Something went wrong'. Same anti-pattern as the 2026-04-23 sweep fix, applied to the scan flow this time.
  • ·DB-down state now reads 'Service temporarily unavailable, please retry' instead of the misleading 'Transactions already recorded' (which made an infra outage look like a duplicate-submission error).
  • ·Multi-wallet sweep score display: when you sweep a wallet that wasn't the first one you added, the post-sweep card now stacks the new totals onto the connected wallet's prior stats. Previously it was always pulling from whichever wallet you added first.
  • ·Disclaimer copy fixed: it used to say the treasury address was visible on the Security page (it isn't, intentionally). Now correctly says the treasury is visible on chain in every sweep transaction.
  • ·@solscoreUS used everywhere — the Share button tweet text and the Privacy page contact link were both pointing at older handles.
  • ·Tab-switching on the Leaderboard, Stats, and Sweep History no longer flashes stale data when you click quickly between periods or wallets. Every fetch now cancels its predecessor.
  • ·Behind the scenes: 280 lines of dead component code removed, the chat assistant moved to Claude Haiku 4.5, the SOUL prompt no longer claims access to dust data it never had, Open Graph card images now cache correctly at the edge, .env.example rewritten to match what the code actually reads, and a dead CSRF cron exemption removed from the request proxy.

May 1, 2026

New /fees page + clearer sweep error messages

A dedicated transparency page at /fees, plus a small but real fix to how we tell you when a sweep fails.

  • ·New page: /fees. A scroll-driven walk-through of what we actually charge, what others charge (the ones who tell you), interactive math run against your own account count, our flat Pro tease, and a same-day-fix promise if a fee in the app ever doesn't match what's on this page.
  • ·The calculator on /fees uses the exact same library that runs your real sweep (src/lib/fees.ts) — no separate copy that could drift. What the slider shows is what the app charges.
  • ·Sweep error messages: when a sweep fails for an internal reason (DB, RPC, etc.), you now get a categorized message like 'Service temporarily unavailable, please retry' instead of a generic 'Sweep failed.' The real error is still logged on our side for diagnosis; only the public message changes.

April 23, 2026

Critical sweep fix — Phantom users unblocked + no more silent failures

Hunted down a nasty bug where Phantom-signed sweeps were rejected at verification and the UI hid the error behind a generic success checkmark. Fully fixed. Your SOL was never at risk — the transactions simply weren't landing, and the UI wasn't telling you.

  • ·Root cause: Phantom automatically injects 'Lighthouse' guard instructions into every transaction you sign — a read-only state-assertion program that aborts the tx if on-chain state doesn't match what the wallet preview showed (Phantom's anti-scam feature). Our transaction verifier didn't know about Lighthouse and rejected it as an unknown program, blocking every Phantom user. Now allowlisted by exact program ID.
  • ·Fix 1 — Phantom's Lighthouse assertion program is now allowed in sweep transactions (read-only, cannot move funds, so it's safe).
  • ·Fix 2 — treasury env validation is now fail-fast in production: a whitespace or invalid-base58 value causes startup refusal instead of silently disabling fees. Transaction builder also throws loudly if asked to build a fee-bearing sweep without a configured treasury, so a broken tx can never reach the signer.
  • ·Fix 3 — /api/build-transactions returns 503 when treasury is missing, matching the /api/sweep and /api/tip gates.
  • ·Fix 4 — post-sweep screen now shows an explicit red failure banner with the real reason when a sweep doesn't land. No more ✅-on-failure. Unknown wallet-injected programs now show their full program ID so new guard programs (Solflare, Backpack, MEV shields) can be identified in one retry.
  • ·Fix 5 — tip button had a truncated program-ID constant that made every tip client-side-reject as 'Unexpected transaction contents'. Fixed; tips now actually work.
  • ·Treasury wallet moved to its own dedicated address (no longer shares with any dev wallet) so service revenue is clean and auditable.

April 20, 2026

Homepage polish + FORTRESS brag sheet

Small refinements to the homepage, plus a rewrite of the Security page's FORTRESS section with real numbers and links to the open-source framework.

  • ·Homepage hero: added a compact fee-ladder row under the CTAs (1-10 0% / 11-50 6% / 51-100 8% / 101+ 10%) so the whole pricing cascade is visible at a glance.
  • ·'Scan another wallet' demoted from a third button to a subtle text link so the primary CTA stands out more.
  • ·Homepage step cards upgraded: flat 1/2/3 boxes replaced with Plug / Radar / Flame icon badges and a small number pip in the corner.
  • ·Global Stats heading now has a small live-indicator dot.
  • ·Security page FORTRESS section rewritten with authoritative numbers from the framework's own persona library: 446 attack personas, 25 squads, 9 phases.
  • ·FORTRESS section now explains the framework was built by SolScore's developer and open-sourced for the Claude Code community, with links to claudesuite.xyz and github.com/MavProDev/claude-fortress.
  • ·Standards-mapping chips added: CWE, CVSS 4.0, OWASP Web / LLM / Agentic, NIST 800-53, NIST SSDF, DISA STIG, MITRE ATT&CK, MITRE ATLAS.
  • ·FORTRESS section moved below the six main Security Layers, so visitors read the actual security details first and the audit framework brag sheet second.

April 20, 2026

Privacy page contact updated

  • ·Privacy page now links directly to our X account @solscore (confirmed live) for questions and concerns. The old copy hedged with 'if that handle is live' — that's cleaned up.

April 18, 2026

Trust & correctness pass

A forensic audit surfaced issues we fixed the same day. Plus pricing rebalanced and legal pages shipped.

  • ·Token-2022 users now get accurate credit. A parser bug was silently recording 0 closures for Token-2022 sweeps even though the chain closed them successfully. Your SOL always arrived; now your score reflects it.
  • ·Pricing rebalanced: 0 / 6 / 8 / 10% cascade. First 10 accounts free. 11-50 at 6%, 51-100 at 8%, 101+ at 10%. Still ~3x cheaper than the silent ~15% industry leader.
  • ·On-chain fee cross-check added as a second line of defense. If a fee shortfall is ever detected after confirmation, we alert instead of failing silently.
  • ·Fee preview is now honest for returning users. Previously the breakdown said 'all free tier' even if you were past it. Now matches what you'll actually pay.
  • ·Legal pages shipped: Privacy, Terms, Disclaimer. Low-opacity footer links. Plain-spoken, not wall-of-legalese.
  • ·Patch-notes page (this one) repaired. The Updates link in the nav had been silently 404-ing since a prior session.
  • ·Tips moved to their own rate limit. Previously, tipping could lock you out of a sweep retry for 5 minutes. Now tips live on a separate 5-per-minute budget.
  • ·Share card fallback domain fixed (was pointing to the wrong TLD under SSR).
  • ·Unused wallet-signing dependency removed from our build (supply-chain surface reduction).

April 6, 2026

Sweep pipeline deep-dive

Six compounding bugs had been causing occasional silent sweep failures — transactions never landed but the UI showed success. All fixed and verified.

  • ·Rate limiter would fail-closed when Redis was temporarily unavailable, silently rejecting every sweep.
  • ·Error messages weren't reaching the frontend — you'd see 'Complete' even when the backend had rejected the job.
  • ·Transactions had no priority fees and routinely dropped during Solana congestion. Now every write tx carries explicit compute-budget instructions.
  • ·Cumulative-fee math across sessions was inconsistent between scan / build / sweep. Now all three layers compute identically.
  • ·On-chain confirmation was ignoring error results from the RPC. Now we explicitly check for errors and surface them.

April 5, 2026

Uniform cascade pricing

Removed a batch mode that had a gameable 10% flat rate.

  • ·Security audit found users could split wallets across separate requests to avoid batch pricing. We removed batch mode entirely — all sweeps now use the transparent cascade.
Full commit history (11)

May 29, 2026

full-stack hardening — fund-flow, trust, mobile, Phantom Blowfish, dep vulns

Fix

May 14, 2026

feat(submit): surface ENH-1 hard-reject userMessage to end users

Update

chore(deps): install pg + Playwright as devDeps; integration tests + e2e now first-class

Update

chore(deps): pin @vercel/otel peer deps as direct deps to stabilize hoist

Update

feat(submit): ENH-1 pre-simulation with conservative-default classifier

Update

chore(gitignore): block apply-migrations.cjs from accidental commits

Update

May 13, 2026

feat(db): FORT-MNY-003 redesign — normalized sweep_signatures table + fan-out trigger

Update

test(e2e): Playwright scan-flow + error-state specs with mocked wallet adapter

Update

test(integration): pg harness against Neon test branch — recordSweepAtomic + lifetime count

Update

May 12, 2026

docs(migrations): defer FORT-MNY-003 — no Postgres path for text[] EXCLUDE

Update

May 11, 2026

stricter ESLint — no-console / eqeqeq / no-eval / no-cycle (L-9)

Chore

Updates generated from git. Commits are the primary source of truth; release notes above are the user-facing summary.