Skip to content

Adopt Framework beta: independent reads, typed uploads and JSONB - #101

Merged
andrewzolotukhin merged 5 commits into
mainfrom
feat/framework-october-beta-adoption
Oct 3, 2026
Merged

andrewzolotukhin merged 5 commits into
mainfrom
feat/framework-october-beta-adoption

Conversation

@andrewzolotukhin

@andrewzolotukhin andrewzolotukhin commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Original request

Adopt the applicable Framework improvements in Xpenser and provide a reviewable
PR environment. This follow-up adopts 0.0.0-beta-20261003175919 on the same PR:
define reusable queries independently of Knex and supply the injected connection
when executing them. The approved scope covers reusable reads and mappers, not
a rewrite of ad-hoc queries or ORM writes.

The PR targets main, as previously agreed because this repository has no
development branch. It retains the earlier typed uploads, compiled reads, CORS
and JSONB changes already reviewed here.

What changed

  • Pin every Framework dependency to 0.0.0-beta-20261003175919; retain one shared
    schema installation and unchanged non-Framework dependency versions.
  • Define budget access/members, API-key authentication, scan progress/results,
    entity projections and transaction list/attachment projections at module scope
    with query(Schema). Execute with (knex, ...parameters) or bind through
    .query(knex, ...parameters) before adding dynamic filters or native SQL.
  • Derive mapping schemas from connection-free rowSchema metadata and prepare
    synchronous DTO mappers once. Remove Knex/database arguments from pure mapping
    helpers and remove the now-unused perConnection utility.
  • Keep tenant predicates, public projections, transaction boundaries, fresh
    authorization checks, result decoding and HTTP contracts unchanged by this
    follow-up. Ad-hoc queries and ORM writes retain their existing APIs.
  • Extend feature-owned tests for separate connection configurations, transaction
    isolation, immutable count/page branches, and execution parameter inference.
    Update database-read guides and examples. No release-named test files.

Earlier changes retained in this PR:

  • Native route-aware CORS and typed multipart avatar/receipt uploads, preserving
    existing MIME/size limits and web chunking.
  • Separate retry-safe receipt image upload with budget authorization and SHA-256
    checking, followed by JSON-only review decisions; existing image storage stays.
  • Telegram saved-transaction checkpoints and duplicate-confirmation protection.
  • Reversible migration 021 for object-valued scan draft/correction JSONB,
    preserving dates, nulls and extension data while projecting public DTOs.

Reasoning

Framework now owns lazy SQL compilation caching per actual Knex instance, so the
application no longer needs a WeakMap of connection-bound definitions or mappers.
Connections and transactions remain caller-owned. Every invocation performs a
fresh database read; no permissions, credentials or query results are cached.
Binding reusable projections before dynamic composition keeps request data out
of shared definitions and preserves native Knex subquery/reference behavior.

Blog post

The existing receipt image uploads post
is retained, including source PR metadata and its real preview screenshot.
Target keyword: receipt image uploads. Public publication happens after merge
and deployment. No additional post for this internal query/mapping refactor.

Screenshots / preview evidence

PR environment

Earlier upload QA demonstrated synthetic receipt upload → durable scan → review
→ confirmation → saved image retrieval, plus avatar upload/removal and toasts.
The screenshot below documents that earlier upload feature, not the new query
implementation. This follow-up has no visual changes; fresh behavioral preview
QA and telemetry checks are tracked below.

Receipt review from earlier upload QA

Validation — connection-independent reads follow-up

  • Ordinary npm ci from the updated lockfile
  • One schema runtime; all Framework pins aligned; no unrelated version bumps
  • npm run lint
  • npm run typecheck
  • npm test — 1,953 tests across 124 files
  • npm run build
  • npm run test:queries:integration — 56 tests in UTC and America/Los_Angeles
  • Head 3da888e: Lint and test, Deploy PR environment, Playwright e2e
    — CI run, all 39 browser tests passed
  • Fresh preview QA: budgets, transactions, API-key auth, scan results and blog
  • Scoped SigNoz logs, traces and available metrics after preview QA
  • PR-ready notification sent successfully (HTTP 200)

Manual QA on the final preview verified budget creation/access and switching,
isolated empty results in a new budget versus Main, transaction search, and
concurrent page reads with stable totals and non-overlapping rows. A temporary
API key exposed only public fields, authenticated with both supported transports,
and failed immediately after revocation. A real synthetic receipt scan returned
USD 12.34, its date and duplicate warning; its draft was discarded without making
a transaction. The temporary budget was archived (recoverable), and the API key
was revoked. Blog index, article, source PR link and loaded hero image passed.
No browser exceptions occurred. There are no new visual changes to illustrate;
the existing upload screenshot above remains applicable.

Telemetry window: 2026-10-03 18:55:09–19:06:07 UTC, scoped to the PR's API/web
service names. No ERROR logs, error-marked spans or observed API HTTP 5xx series.
Three warning logs were the QA script's initial requests with an incorrect budget
ID; rerunning with IDs from the authenticated budget list passed. The expected
401 from the revoked-key check was also observed. API request logs have trace/span
correlation; both services have traces. No web log events appeared in this window,
and web HTTP metrics remain uninstrumented; available HTTP metrics cover the API.
Small-sample operation p95s: transactions 51 ms, budgets 23 ms, scan start 15 ms,
scan status 8 ms, budget access 7 ms, API-key list 2 ms. These are not production
benchmarks or claims of an improvement over a measured baseline.

Dependency note: deduplication encountered the existing Next.js prerelease peer
range mismatch. After restoring peer entries through npm, ordinary npm ci
passes; no persistent peer-dependency bypass or unrelated version change is added.

Rollout / risks

This follow-up adds no migration or HTTP contract change. The original PR's
upload wire-contract change still requires coordinated API/web/bot deployment:
back up the database, drain active work, stop consumers, apply migration 021,
then start the coordinated release. Invalid legacy documents abort migration.
For rollback, stop consumers, reverse only 021, and restore the prior release;
do not reverse scheduler migration 020. See docs/image-uploads.md.

Session checkpoints do not survive refresh/bot restart and cannot make an
ambiguous transaction-create timeout exactly-once. MIME checks validate declared
types, not file contents. The preview has no Telegram bot; live bot QA is not
available, with retry/duplicate-click behavior covered by unit tests.

Separate pre-existing observability follow-up: web fetch span names include scan
progress tokens in query strings. A count-only check found 11 such spans in the
earlier 13:20–13:45 UTC QA window, before this follow-up. Redact these tokens in
telemetry separately; no token values are included here or in committed artifacts.

No Framework source, production environment, credentials, local env files or
local-only framework-consumer-experience.md changes are included.

@andrewzolotukhin
andrewzolotukhin temporarily deployed to pr-101 October 3, 2026 13:21 — with GitHub Actions Inactive
@andrewzolotukhin
andrewzolotukhin temporarily deployed to pr-101 October 3, 2026 13:33 — with GitHub Actions Inactive
@andrewzolotukhin
andrewzolotukhin temporarily deployed to pr-101 October 3, 2026 13:40 — with GitHub Actions Inactive
@andrewzolotukhin
andrewzolotukhin temporarily deployed to pr-101 October 3, 2026 15:34 — with GitHub Actions Inactive
@andrewzolotukhin andrewzolotukhin changed the title Adopt Framework beta: compiled reads, typed uploads, and JSONB Adopt Framework beta: independent reads, typed uploads and JSONB Oct 3, 2026
@andrewzolotukhin
andrewzolotukhin temporarily deployed to pr-101 October 3, 2026 18:48 — with GitHub Actions Inactive
@andrewzolotukhin
andrewzolotukhin merged commit 35e259c into main Oct 3, 2026
4 checks passed
@andrewzolotukhin
andrewzolotukhin deleted the feat/framework-october-beta-adoption branch October 3, 2026 22:16

This branch was previously deployed

1 inactive deployment
pr-101 — 3da888e1 Deployed Oct 3, 2026 by andrewzolotukhin via Deploy PR environment #383
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant