Qwentun
PlannedNot yet shipped
  • Clearing-account picker (Settings) and GL account picker (/code) only list accounts typed Expense / Cost of Goods Sold / Other Expense / Credit Card / Other Current Liability (matches the original Flask app's filter). Flagged 2026-09-18 as needing to change โ€” exact new behavior not yet decided.
v1.55
Allowed email senders are now editable in SettingsFeature
  • Settings has a new "Email Inbox" panel where the list of email addresses allowed to send receipts in can be edited directly โ€” no code or environment changes needed.
  • Supports exact addresses or a whole-domain wildcard (like *@yourcompany.com), one per line.
v1.45
Email receipts with no attachment now work; unsupported email attachments are flagged instead of vanishingFeature
  • If a forwarded email's receipt is just the message text with no attachment, it's now still processed automatically โ€” the email content is turned into a document and parsed the same way as any other receipt.
  • An emailed attachment type the app can't read (a Word or Excel file, for example) used to disappear with no notice at all. It now shows up on Receipt Inbox as a dismissible alert explaining what happened and who sent it.
v1.40
Upload renamed to Receipt Inbox; shows whether each item was uploaded or emailed inFeature
  • The Upload page and sidebar item are now called Receipt Inbox.
  • Every pending item now shows whether it was uploaded manually or emailed in โ€” and if emailed, which address it came from.
  • Receipt Inbox now displays the email address receipts can be sent to directly.
v1.35
Fixed: PDF receipts wouldn't preview in the appPatch
  • Viewing a PDF receipt in the in-app preview showed a broken-file icon, even though downloading the same file always worked fine. Caused by a security header (added in v1.18) that was stricter than the app's own preview feature needed. Fixed without weakening the original protection โ€” nothing outside this app can embed a receipt file either way.
v1.30
Fixed: some emailed receipts with a real attachment weren't showing upPatch
  • A genuine file attached to a forwarded email could be mistaken for an inline signature image (depending on how the sending mail provider tagged it) and silently skipped. Fixed so a real attachment is always kept, regardless of that tagging.
v1.25
Email receipts in directlyFeature
  • Receipts can now be emailed in โ€” forward or send one to the Receipt Inbox address and it's parsed and added to the queue automatically, exactly like a manual upload.
  • Only mail from an approved sender is processed, to keep spam or junk mail from triggering real parsing costs.
v1.20
Content-Security-Policy switched from report-only to fully enforcingFeature
  • Ran the CSP in report-only mode against the live app for a day, then checked production's actual DevTools Issues panel โ€” zero CSP violations of any kind (the 98 flagged issues shown there were unrelated pre-existing form accessibility warnings, not CSP). Switched the header from Content-Security-Policy-Report-Only to Content-Security-Policy, so it now actually blocks anything that would violate it instead of just logging it.
v1.19
v1.18's new security headers weren't actually reaching the browser โ€” moved them to middlewarePatch
  • Checked v1.18's headers against the live site and found X-Frame-Options, Permissions-Policy, and the report-only CSP were silently missing (Cache-Control and X-Content-Type-Options worked fine). Traced it to Netlify's own Next.js runtime dropping those three specifically from public/_headers for dynamic pages โ€” confirmed by curling the raw Netlify domain directly (bypassing Cloudflare entirely) and seeing the same gap at the origin. Moved those three to the app's own middleware instead, which does reach the browser now, confirmed the same way.
v1.18
Security headers, from an OWASP ZAP baseline scanPatch
  • Ran an OWASP ZAP baseline scan against local dev (the deferred item from the Intuit go-live security review) โ€” 0 real failures, 53 passes, 14 warnings, mostly Next.js's own bundled framework code rather than anything in this app's own code.
  • Fixed the real, easy findings: added X-Frame-Options, X-Content-Type-Options, and a Permissions-Policy header, and turned off the X-Powered-By header that revealed the framework.
  • Added a Content-Security-Policy in report-only mode (logs violations without blocking anything) as a first, safe step toward a fully enforced CSP โ€” will switch it to enforcing once confirmed clean.
v1.17
OAuth endpoints now come from Intuit's discovery documentPatch
  • The authorization and token endpoint URLs were hardcoded (verified correct, but not future-proofed against Intuit ever rotating them). Now fetched from Intuit's official OAuth2/OpenID discovery document (sandbox and production have separate URLs), cached for 24 hours, with the old hardcoded values kept only as a fallback if the discovery fetch ever fails.
v1.16
QuickBooks reconnect prompts, error logging, and a support link (Intuit go-live security review)Feature
  • If your QuickBooks connection expires or is revoked, every failing action (Review, Coder, Upload's "Try to match now", Save) now shows a clear "Reconnect to QuickBooks" button instead of a raw error message โ€” the stale connection is also automatically cleared so the sidebar and Settings correctly show "not connected" right away.
  • Every QBO API error is now logged (status code, the `intuit_tid` header Intuit's own support team asks for, and the error detail) so a real failure can be shared with Intuit support for troubleshooting โ€” never logs tokens or credentials, only the same information already shown in the on-screen error.
  • Added a "Contact support" link on Settings that emails [email protected].
v1.15
Fixed: changing the date range on "Review everything" bounced back to "Needs attention"Patch
  • Clicking "Fetch transactions" after adjusting the date range while on the "Review everything" tab silently dropped back to "Needs attention" โ€” the date form only submitted the date fields, so the tab selection (and any active vendor/memo filter) got lost from the URL every time. The form now carries the current tab and filter along with it, so fetching a new date range keeps you on whichever tab you were using.
v1.14
Re-saving a line now visibly confirms it โ€” not just the first savePatch
  • v1.13 made a saved line stay editable, but re-saving it after further edits looked identical to before โ€” the "โœ“ Saved" indicator never changed, so there was no way to tell a second save actually went through. It now shows the time of the most recent save and briefly flashes green every time Save succeeds, including the second, third, etc.
v1.13
A saved line stays editable โ€” Save again instead of lockingPatch
  • Once a transaction was saved, its vendor field and GL account/class/location selects all locked โ€” the only way to fix a mistake or update it further was to leave and come back. Every field on a saved row now stays fully editable, and the button reads "Save again" so it can be re-saved as many times as needed. The green "โœ“ Saved" tint from v1.12 stays as the indicator that it was saved before.
v1.12
Saved and "no receipt needed" rows no longer gray outPatch
  • A saved row, and a row marked "no receipt needed," both faded to low opacity โ€” meant as a "this one's done" cue, but it read as disabled/unreadable instead, especially since the coding fields on a "no receipt needed" row are still meant to be used. Replaced with a light tinted background and a colored accent bar on the left edge of the row (green for saved, gray for no receipt needed) โ€” the row stays fully legible and its fields stay visually active.
v1.11
Fixed: marking "No receipt needed" removed the ability to keep coding that transactionFeature
  • v1.10's "No receipt needed" button immediately dropped the transaction out of Review's "Needs attention" list the moment it was clicked โ€” which also removed the GL/class/vendor/location fields and Save button for it, since the row itself disappeared. The mark only means "don't ask for a receipt," not "I'm done coding this," so the row now stays put and fully editable; it only drops out of "Needs attention" the next time that view is actually re-fetched.
  • Upload's "Try to match now" used to attach a found match exactly as QuickBooks already had it, with no way to fix anything first. It now shows an editable vendor name and GL account/class/location for the matched transaction, so a wrong vendor or GL account can be corrected right there before attaching โ€” no trip to Review required.
v1.10
"No receipt needed" โ€” mark a transaction so it stops showing up as missing backupFeature
  • Since Review's "Needs attention" view scans every transaction in the clearing account/date range for missing backup, some of those will never have a receipt (bank fees, transfers, etc.) and kept cluttering the list. Any transaction missing backup can now be marked "No receipt needed" right from its row โ€” it immediately drops out of "Needs attention," and can be un-marked ("Undo") if that turns out to be wrong.
  • "Review everything" gained a Backup filter (All / Missing / Has receipt / No receipt needed) so marked and settled transactions are still easy to find and audit, rather than just disappearing.
  • Coder shows the same "No receipt needed" option/state, since it draws from the same transaction pool.
v1.09
Review now defaults to "Needs attention" instead of dumping every transaction in rangeFeature
  • Review was showing every QBO purchase in the date range with equal weight, whether or not it needed anything โ€” the AI receipt-matcher only ran quietly in the background to suggest backup on rows missing it, so the list itself never got any smaller. Review now defaults to a "Needs attention" tab that narrows down to transactions missing backup documentation (the ones the matcher actually has a shot at), with a "Review everything" tab alongside it for the old unfiltered browse โ€” useful for bulk recoding/edits across a whole date range.
v1.08
Actually fixed the QBO throttle error โ€” batched the backup-document check into one request instead of one per transactionFeature
  • v1.06 and v1.07 tried pacing out and retrying the one-request-per-transaction backup check, but the real problem was the total number of requests, not how fast they were sent โ€” a large date range still exceeded the sandbox's quota. Now checks for backup documents on every transaction in one batched request (or a small handful for very large lists) instead of one request per transaction, which should eliminate the throttle error rather than just work around it.
v1.07
v1.06's throttle fix wasn't enough โ€” added automatic retry-with-backoff for every QBO requestPatch
  • Still hit "ThrottleExceeded" (429) on Review even at the lower concurrency from v1.06 โ€” this sandbox's real rate limit is stricter than expected. Every QBO request now automatically waits and retries a few times on a throttle response instead of failing outright, on top of the lower concurrency already in place.
v1.06
Fixed QBO rate-limit errors on Review/Coder, and delete failures that looked like nothing happenedFeature
  • Review and Coder were firing one QuickBooks request per transaction all at once to check for existing backup documents โ€” fine for a handful of transactions, but a date range (or "Show all") with dozens of transactions could trip QuickBooks' own rate limiter ("ThrottleExceeded", HTTP 429), showing an error instead of the transaction list. Requests are now sent a few at a time instead of all simultaneously.
  • The Delete button (on Upload) could fail silently โ€” if the delete failed for any reason, nothing told you, so it looked exactly like the button "sometimes doesn't work." It now shows the actual error when a delete fails.
v1.05
v1.04's delete fix was incomplete โ€” a second linked record was still blocking itPatch
  • Deleting a receipt could still fail after v1.04, because every successfully-parsed receipt also has a linked API-usage log record (one gets written on every Claude API call), which has the same kind of foreign key that was blocking the delete. Delete now clears that record too, alongside the match record v1.04 already handled โ€” this should cover every receipt now, not just ones with a leftover match record.
v1.04
Fixed a server error when deleting a receiptPatch
  • Deleting a receipt could fail with a server error if it had any linked match record โ€” most likely a stale "pending" one left over from the old pre-v1.00 batch-matching system, which was never cleaned up when that system was removed. Delete now clears any linked match record first.
v1.03
Fixed invisible "Show all" button on Coder/Review; cleaned up the transaction grid's visual densityPatch
  • "Show all (any date)" on Coder and Review was rendering as plain unstyled text instead of a button (it only got real button styling once already active) โ€” now a proper visible secondary button.
  • Removed a redundant vendor display in the transaction grid โ€” vendor name was shown twice per row (a static label, then the same value again in the editable field right below it). Now shown once as the editable field itself.
  • Added a clearer visual break between different transactions in the grid โ€” a heavier bottom border after each transaction's last line, so a multi-line transaction reads as one clustered group instead of blending into the row below it.
v1.02
Document Inbox retired โ€” it was showing the exact same list as UploadPatch
  • Removed the separate Document Inbox page โ€” it turned out to be genuinely duplicative, showing the identical pending-receipts list Upload already displayed, just with a different subset of actions and its own confusingly-different count on the sidebar badge.
  • Skip and "Find in Review" (a link pre-filtered to the receipt's vendor) moved onto Upload's own rows alongside the existing card-assignment, "Try to match now", "Save for later", and Delete actions โ€” Upload is now the one place for everything not yet placed on a transaction.
  • The sidebar's Upload badge and the Home page's counter are now both the same number (total pending receipts) instead of two different counts that measured different things (one counted only card-less receipts, the other counted all pending ones).
v1.01
Upload and Assign merged into one screen; Document Inbox repositioned; Cache-Control hardened for Intuit go-liveFeature
  • Upload and the old separate Assign-a-card screen are now one page. Drop a file, and every receipt still needing attention shows right there with its card dropdown, a suggested-card banner when applicable, and two new actions: "Try to match now" (searches QBO immediately for a likely transaction and offers a one-click attach) and "Save for later" (no-op โ€” it already just sits in the list until you deal with it).
  • A receipt "Try to match now" can't place gets no special failure state โ€” it just stays in the pending list exactly like before, visible on both Upload and Document Inbox.
  • Document Inbox moved in the sidebar to sit with Review and Coder instead of grouped under Upload, since it's the same pending-transactions backlog those screens also draw from.
  • Fixed Cache-Control missing "no-store" on every page (was "no-cache, must-revalidate" only) โ€” added via a public/_headers rule at the Netlify CDN layer, since both a next.config.ts headers() rule and a middleware-set header were found to get silently overridden by the framework/hosting runtime. Found while reviewing the app against Intuit's go-live security requirements.
v1.00
One engine instead of three: Review is now the flagship, Coder is a filtered view of it, Matcher/Backup Sweep is goneFeature
  • Rebuilt Review as the flagship workflow: it now browses every QBO purchase in a date range โ€” clearing-coded or already coded to a real GL account โ€” in a single dense, spreadsheet-style grid. Every codable line is pre-filled with its CURRENT GL/class, so "leave the coding as-is" and "change it" are the same Save, not two different paths.
  • Every row also gets a backup-document control: a suggested receipt (same fuzzy vendor/amount/date matching as before), a dropdown to pick a different uploaded receipt, or a plain file upload โ€” attaching and (re)coding happen together in one Save, not as separate steps.
  • Removed the old two-step "run a matching pass, then review a queue" flow โ€” /match is gone. There is no more persisted "pending match" state; everything is computed live from QuickBooks and this app's own database on every page load, the same way Coder already worked.
  • Coder is now the exact same Review grid, just pre-filtered to transactions still coded to the clearing account โ€” not a separate codebase, a dedicated lens onto "what still needs to move out of clearing."
  • Matcher/Backup Sweep is retired. In its place: Document Inbox (/inbox) โ€” a plain list of uploaded receipts not yet attached to or skipped from a transaction. It does no matching of its own; view, skip, delete, or jump into Review to place one manually by filtering to its vendor.
  • "Skip" moved from the old Review flow to Document Inbox, since it's fundamentally a decision about a document ("this will never be matched"), not about a QBO transaction.
  • Removed manual-link search (/review/manual/[id]) and "cast a wider net" โ€” Review's own filter and per-row receipt picker now cover both: type a vendor to find the transaction, then pick any pending receipt for it, regardless of card.
  • This closes out real duplication that existed between the three previous modules (Match & Review, Coder, and Matcher) โ€” all three used to independently run the same fuzzy-matching logic and could each attach the same receipt to the same transaction; now there is exactly one place that does that.
v0.99
Matcher renamed to Backup Sweep, scoped to card-less receipts onlyPatch
  • Matcher is now called "Backup Sweep" to better describe what it does โ€” it wasn't about matching in the fuzzy-scoring sense so much as sweeping QBO for already-coded transactions still missing a backup document. Same page (/matcher), no other functional change from the rename itself.
  • Backup Sweep's suggested-receipt pool is now scoped to card-less receipts only โ€” previously it drew from every pending receipt regardless of card assignment, which meant a card-assigned receipt could be independently attached via either Backup Sweep or Match & Review. Card-assigned receipts are Match & Review's exact territory (matched against that specific card's own transactions); Backup Sweep now only handles the card-less receipts Match & Review doesn't have enough information to place with a single card.
v0.98
Suggested card assignment on Upload/Assign โ€” fuzzy last-4 match + vendor historyFeature
  • Claude now also extracts the card network (Visa/Mastercard/Amex/Discover) from a receipt when visible, alongside the last-4 digits it already read.
  • A receipt whose printed last-4 digits are one digit off from a configured card (an OCR/print misread) now gets that card suggested on /assign โ€” previously it was silently left unassigned instead of auto-assigned or suggested.
  • A receipt with no card digits visible at all now falls back to vendor history โ€” if that exact vendor has been assigned to a card before, the most common one is suggested.
  • Suggestions appear as a "๐Ÿ’ก Suggested: <card> โ€” <reason>" banner with a one-click "Use this card" button on /assign, separate from the manual dropdown. Exact last-4 matches are still auto-assigned automatically, unchanged from before.
v0.97
Coder now suggests uploaded receipts ยท Home page step countersFeature
  • Coder now runs the same vendor/amount/date fuzzy-matching Matcher uses against your uploaded receipts โ€” a clearing-account transaction missing backup gets a suggested receipt pre-selected, with a dropdown to pick a different uploaded receipt, alongside the existing plain file upload.
  • Attaching an uploaded receipt while recoding in Coder now also records it as a match (same as Matcher/Review), so it shows up in History and won't be suggested again elsewhere.
  • Home page step boxes for Upload and Review now show the same item-count badges as their sidebar entries.
v0.96
Fixed uneven step-box sizes on the new Home workflow diagramPatch
  • Every step box on the Home page now has a fixed width and height, regardless of how long its description text is โ€” previously a longer description (e.g. "Match") made that box visibly taller than the others in the row.
v0.95
New home page: a clickable wireframe map of the app's three workflowsFeature
  • The home page ("/") is now a wireframe-style diagram of the app's three independent workflows โ€” Match & Review, Coder, and Matcher โ€” each shown as a row of connected steps you can click straight through to.
  • Upload moved from "/" to its own "/upload" route (same page, unchanged) now that "/" is the workflow map; the sidebar's Upload link and every in-app "back to upload" link were updated to match.
  • Added a "Home" item at the top of the sidebar.
v0.90
New module: Matcher โ€” backup docs for already-coded transactions ยท Code transactions renamed to CoderFeature
  • New "Matcher" module: surfaces QBO transactions already coded to a real GL account (not the clearing account) that are still missing a backup document โ€” the inverse pool from Coder's clearing-account items.
  • Matcher auto-suggests a match from your uploaded receipts (same vendor/amount/date scoring as Match+Review) for each transaction missing backup, with one-click attach, a manual "pick a different receipt" dropdown, or a plain file upload when the document isn't in the Upload queue at all.
  • Matcher supports "Show all (any date)" and sort/filter, same as Coder, plus a toggle to hide transactions that already have backup attached (on by default).
  • "Code transactions" renamed to "Coder" throughout the sidebar and page header, to read clearly alongside the new Matcher module โ€” no functional change to that screen in this release.
  • Match+Review (the original per-card/clearing-account receipt matching) is unchanged โ€” Matcher is a separate, additional entry point, not a replacement.
v0.85
Code transactions: show-all, sort/filter, vendor editing, attachments ยท History: view/edit current codingFeature
  • Code transactions: added a "Show all (any date)" link to list every unaddressed clearing-account item regardless of date, instead of only what falls in the selected range.
  • Code transactions: added sort (date/amount/vendor) and a text filter (vendor, memo, ref #) above the transaction list, computed client-side against the already-fetched set.
  • Code transactions: the vendor name is now editable per transaction โ€” pick an existing QBO vendor from a dropdown or type a new one, which is created in QBO on save.
  • Code transactions: existing QBO attachments on a transaction (e.g. a receipt already attached during Review) now show as download links on its card โ€” previously not shown at all.
  • History: added a "Current coding" toggle per item with a linked QBO transaction โ€” fetches that transaction's coding directly from QBO on demand (not eager-loaded for the whole list) and shows its current GL/class per line, vendor, and location.
  • History: that current coding is now editable in place and can be pushed back to QBO with "Save to QBO", reusing the same recode path as Code transactions.
v0.80
Fixed "Save & recode" failing with a QBO validation errorPatch
  • QBO rejected the recode request with "Property Name: failed to parse json object" (error 2010). Root-caused against Intuit's official Purchase API reference: CustomExtensions on each line isn't part of the documented schema (stripped); CurrencyRef is only valid when multicurrency is enabled (stripped otherwise); and the real cause โ€” Location (DepartmentRef) was being set per-line when it's actually documented as a transaction-level field, now set on the transaction itself.
v0.75
Fixed clearing-account detection (real bug, not a design choice)Feature
  • Code transactions and clearing-account matching now correctly find transactions where the clearing account is used as a per-line category, with the real card as the payment account โ€” the previous version only looked at the transaction's payment account itself, so real transactions (card as payment account, clearing account as the line category) never showed up at all.
  • Code transactions now only shows and requires coding for lines actually categorized to the clearing account, leaving already-correctly-coded lines and the payment account untouched.
v0.70
Clearing-account matching + adjustable search windowFeature
  • A card no longer has to be assigned to a receipt before matching โ€” receipts with no card are now matched against the designated clearing account instead of being stuck unmatchable.
  • /match now runs both per-card matching and clearing-account matching for card-less receipts in the same pass.
  • Added a "Cast a wider net" control on /review โ€” re-searches QuickBooks for still-unmatched receipts with an adjustable ยฑday tolerance (default 3), without disturbing existing matches.
  • Added a "No card" filter tab on /review for card-less matches/unmatched receipts.
v0.65
Connected company name + manual QBO refreshPatch
  • Sidebar and Settings now show the connected QBO company's actual name, so it's clear which sandbox/company is active.
  • Added a "Refresh QBO data" button on Settings and Code transactions, for when a change made directly in QBO (like a new chart-of-accounts entry) hasn't shown up yet.
v0.60
History, Usage, and ChangelogFeature
  • /history โ€” last 100 processed receipts, filter by vendor/card/amount, undo (reopen) a match back to Review.
  • /usage โ€” lifetime/MTD/YTD Claude API cost, daily usage chart (Recharts), recent calls table.
  • /changelog โ€” this page, replacing the original Flask app's own v15.x version history.
v0.55
Loading indicators for QBO-fetching pagesPatch
  • Added loading.tsx to /code, /setup, and manual-link โ€” all three call QBO before rendering and had no pending state.
  • Added a pending state to /match's "Run matching" button.
v0.50
Clearing-account codingFeature
  • /code screen โ€” fetch clearing-account transactions by date range, per-line GL/class coding, transaction-level location, optional receipt attachment.
  • Ported getClasses, getLocations, getClearingTransactions, recodeAndAttach into the QBO client.
v0.45
Upload nav badgePatch
  • Sidebar Upload item now shows a count of receipts parsed but not yet assigned to a card.
  • Fixed a count mismatch where the home page banner included failed-parse receipts that never actually showed on /assign.
v0.40
Upload feedback + receipt preview overlayPatch
  • Upload drop zone now shows a pending state while Claude parses each receipt, instead of looking frozen for several seconds.
  • "View receipt" opens an in-page lightbox (image/PDF, download button) instead of a new tab, on /assign and /review.
v0.35
Matching + reviewFeature
  • /match โ€” date-range QBO purchase fetch, ported matching/scoring logic (fuzzball in place of fuzzywuzzy).
  • /review โ€” matched and unmatched lists, attach/skip/change-card/discard, filter by card.
  • /review/manual/[receiptId] โ€” manual transaction linking with a vendor/amount filter.
  • Skip now actually excludes a receipt from future review passes (the original only hid it client-side).
v0.30
Scaffold cleanup + architecture auditPatch
  • Fixed all routes being statically frozen at build time โ€” added dynamic rendering so live data (QBO status, receipt counts) never goes stale.
  • Removed the default create-next-app favicon shadowing the real branded one, and fixed a receipt logo file mislabeled .jpg that was actually a PNG.
  • Committed a netlify.toml instead of relying on dashboard-only build config.
v0.20
Setup screen fixesPatch
  • Fixed the clearing-account picker visually reverting to "not configured" after a successful save.
  • Added save confirmations to the card-accounts and clearing-account forms.
v0.15
QBO OAuth + Setup screenFeature
  • Connect/disconnect flow, credit-card-account mapping, clearing-account picker.
  • OAuth tokens encrypted (AES-256-GCM) before being stored, since they now live in a shared Postgres table instead of a server-only .env file.
v0.10
Upload, parse, and assignFeature
  • Receipt upload to Netlify Blobs, Claude vision parsing, auto card-assignment by last-four digits, manual assign screen.
  • Base layout matching the original app's branding โ€” navy sidebar, Aboreto wordmark, Miranda Sans body.
  • proxy.ts restricts access to the custom domain, so the raw Netlify subdomain can't bypass Cloudflare Access.