chore: Update TRACE_COMPARE_TARGET_EPOCH to 275
To match new snapshots
To match new snapshots
fix(governance): verify/merge witnesses with core-cst (DRep-vote signature mismatch)
DRep votes (and any tx with Conway voting_procedures) failed client-side with "Wallet returned witness that does not verify against tx body hash", and would be rejected on-chain (InvalidWitnessesUTXOW). Root cause: the tx is BUILT with core-cst (MeshTxBuilder's default CardanoSDK serializer), so the wallet signs the body hash core-cst produces. But the witness verify + merge used core-csl (whisky) calculateTxHash / Transaction reconstruction, which re-serializes the body to different bytes (voting_procedures map order, set tag 258) → a different hash → valid witnesses fail to verify. The two serializers agree for ordinary txs, so only Conway-vote-shaped txs broke. Move the verify/merge/hash onto core-cst (the 2.0 stack, already a dependency), so build and verify use one encoder and the original body bytes every signer signed are preserved: - mergeSignerWitnesses: verify new witnesses against resolveTxHash(originalTx) and merge via addVKeyWitnessSetToTransaction (preserves body bytes). Drops the body-swap workaround — every co-signer now signs the same stored body. - filterWitnessesToScripts: rebuild the witness set with core-cst so dropping extraneous vkeys no longer re-encodes the body. - diagnoseTxWitnesses + the server signature check in transactions.ts: hash with resolveTxHash so vote signatures are recognised (equal to the old hash for ordinary txs). Verified invariants (tests): adding/filtering vkeys via core-cst preserves resolveTxHash; a witness over resolveTxHash verifies; co-signers accumulate without re-encoding. tsc clean; full suite 362 passed. Follow-up (not in this PR): the server v1 bot path (signTransaction.ts + addUniqueVkeyWitnessToTx) still uses core-csl calculateTxHash and needs the same core-cst migration for bot-submitted votes. Co-Authored-By: Claude Fable 5 <[email protected]>
docs(roadmap): month-by-month breakdown with per-owner tasks
- Break grouped quarters into individual Month 2–12 sections, each with Quirin/Andre task tables matching Month 1's format - Add Document Sign-Off flagship feature (MVP→v1→v2→v3) woven across months - Add Mesh 2.0 upgrade; extend FROST research to include Lemour PQC multi-sig - Shift schedule one month earlier (June work completed); April is buffer - Drop completed items (Aiken crowdfund, full address, pagination, collateral, 404) Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Production was 500ing every query with "(EMAXCONNSESSION) max clients reached in session mode - max clients are limited to pool_size: 15". Verified root cause (live + multi-agent audit): - src/server/db.ts created the @prisma/adapter-pg pool with no `max`, so node-postgres defaulted to 10 connections per warm Vercel instance. A couple of instances overrun Supabase's session-mode pool (15 client slots) -> EMAXCONNSESSION on every query, including user.createUser. - The retry wrapper amplified it: it called $connect() against the dead pool between retries and, once connectionTimeoutMillis is finite, would treat the "timeout exceeded when trying to connect" acquire error as a retryable connection error. Changes: - Cap the pool: max: 2, idleTimeoutMillis 10s, connectionTimeoutMillis 10s (finite timeout fails fast instead of pg's default infinite wait). - isConnectionError(): never retry pool-saturation errors (max clients reached / pool_size / EMAXCONNSESSION / connect-timeout). - Drop the $connect() reconnect between retries (the driver-adapter pool reconnects lazily; forcing connect just adds load). The Prisma globalThis singleton was verified correct and left unchanged. The 5 interactive $transaction blocks are pure-DB (no external I/O held), so no leak fix is required for this to hold. NOTE (maintainer action, env — cannot be done in code): point production DATABASE_URL at the Supabase TRANSACTION pooler (port 6543, ?pgbouncer=true) and keep DIRECT_URL on the direct connection (5432) for migrations. The session pooler (5432) is the wrong mode for serverless; this code change is the necessary client-side cap and works as an interim mitigation too. Co-Authored-By: Claude Fable 5 <[email protected]>
Release: preprod → main (stuck-loading auth fixes)
fix(auth): normalize all userAddress sources in layout to bech32 (stuck "Loading…")
THE root-cause fix for the stuck "Loading…": layout fed userAddress / the session check / createUser from hex-encoded addresses (react-2.0 useAddress() and raw CIP-30 getUsedAddresses/getUnusedAddresses), but user records and sessions are keyed by bech32 — so getUserByAddress(hex) returned null and the app hung. Confirmed live on preprod: getUserByAddress(addr1qyvgdy2…) finds the user; getUserByAddress(0118869144…) → null (same wallet). - Normalize `address` once at the useAddress() source so every consumer (store sync, walletAddressForSession/Check, createUser) uses bech32. - Normalize the getUsedAddresses()/getUnusedAddresses() setUserAddress sites. (The equivalent change was authored alongside #281 but merged after that PR was already squashed, so it never reached preprod — this carries it, plus the session/createUser hardening, with the required import.) Co-Authored-By: Claude Fable 5 <[email protected]>
Root cause of the stuck "Loading…": layout synced userAddress to the store from useAddress() and raw activeWallet.getUsedAddresses()/getUnusedAddresses() WITHOUT normalizing. react-2.0's useAddress and raw CIP-30 wallets return hex-encoded address bytes, but user records are keyed by bech32. So the store held the hex form, getUserByAddress(hex) returned null, `user` stayed null, and the connect button spun "Loading…" forever. Confirmed live on preprod: getUserByAddress(addr1qyvgdy2…) → user found; getUserByAddress(0118869144…) → null (same wallet). connect-wallet.tsx already normalized at its setUserAddress; layout's three call sites were missed. Normalize all of them via normalizeAddressToBech32. Co-Authored-By: Claude Fable 5 <[email protected]>
fix(auth): recover from stuck "Loading…" when wallet has no session
When a wallet connects but authorization doesn't complete (auto-authorize failed/cancelled — common when multiple Cardano extensions fight over window.cardano), layout sets hasCheckedSession=true and never reopens the auth modal. createUser stays 403 (no session), `user` stays null, and the Connect button spins "Loading…" forever with no recovery path. - Relabel that state: connected + user-query-resolved-empty now shows an actionable "Authorize" instead of an infinite "Loading…" spinner. - Add an "Authorize wallet" item to the connect dropdown (shown when connected but unauthorized) that bumps a new reauthNonce signal. - layout watches reauthNonce, clears the hasCheckedSession latch, and refetches the session so the existing session-check effect reopens the (now signData-fixed) WalletAuthModal. Additive and manual-trigger only — no change to connect/sign/session logic, no auto-retry loop. Co-Authored-By: Claude Fable 5 <[email protected]>
Release: preprod → main
- Fix for the lightmode using koios for getting the current dRep status - Minimum versions for the cardano-node and cardano-cli are now 11.0.0 - Update contains cardano-signer 1.35.0
Bumps [joi](https://github.com/hapijs/joi) from 17.13.3 to 17.13.4. - [Commits](https://github.com/hapijs/joi/compare/v17.13.3...v17.13.4) --- updated-dependencies: - dependency-name: joi dependency-version: 17.13.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] <[email protected]>