feat: add direct PostgreSQL and ACK deployment support

This commit is contained in:
brother7 committed 2026-08-12 19:20:07 +08:00
1 parent d0192081c7
commit c44274f098
55 files changed
+3317 -1064

No files matched your search

+31
View File
@@ -569,3 +569,34 @@
- The create-page estimate card uses the compact `预估消耗` label and stays in the same parameter row at the tested desktop width; a live quote check showed EvoLink Image2 standard at `¥2.04` for one image.
- `调整倍率` now opens an in-app modal with the current multiplier, standard cost, current customer price, projected customer price, range validation, keyboard focus, and Escape dismissal. The browser `window.prompt` path is removed.
- Design polish followed the taste-skill direction: compact enterprise information hierarchy, shared alignment grid, restrained motion, and an in-context dialog instead of a browser-owned prompt.
## 2026-08-12 - Alibaba Cloud RDS PostgreSQL Refactor
### Confirmed facts
- The current production database path is not a direct PostgreSQL connection. `data-store`, `account-store`, and `billing-store` use `@supabase/supabase-js` over PostgREST and fall back to local JSON when Supabase variables are absent.
- `scripts/worker.mjs` remains an HTTP poller and does not connect to the database; in the current architecture only Web pods require a database pool.
- The existing SQL model uses PostgreSQL-compatible tables, JSONB/array/timestamp types, indexes, `FOR UPDATE SKIP LOCKED`, and two PL/pgSQL functions. Its application coupling is Supabase client semantics, not Supabase-only SQL namespaces.
- Existing tests intentionally clear Supabase variables and exercise local JSON; there is no real PostgreSQL or RDS integration test and no live RDS credential is available in this workspace.
- The existing `/api/health` route reports process/configuration state but does not probe database connectivity.
### Decisions
- Introduce explicit `ZHINIAN_DATA_BACKEND=local|postgres`. Production defaults must fail closed when the backend is missing or invalid; PostgreSQL mode must fail when `DATABASE_URL` is absent.
- Preserve local JSON for development/tests, but never silently fall back from an explicitly selected PostgreSQL backend.
- Centralize `pg.Pool`, TLS certificate loading, numeric environment validation, transactions, query execution, connection shutdown, and readiness in one server-only module.
- Keep current store exports stable so routes, services, and components do not learn database transport details.
- Preserve database-side `claim_generation_jobs` and `billing_post_wallet_entry` functions for concurrency correctness.
- Use an independent versioned migration runner with advisory locking; ACK runs it as a one-shot Job before Web rollout, not as a per-pod init container.
- Web receives database/session/provider/storage secrets; Worker receives only its internal token and internal Web URL.
### Unverified assumptions and external boundaries
- The target RDS PostgreSQL major version, instance connection limit, internal endpoint, TLS enforcement setting, CA bundle, database/user names, and network ACL/security-group rules are unknown and must be supplied/verified during deployment.
- Without live credentials or an ACK context, code/build/schema checks can verify implementation shape but cannot prove real RDS connectivity, migration success, or cluster rollout.
### Implementation and audit findings
- Direct PostgreSQL now uses a lazy process-level `pg.Pool`, explicit backend selection, validated integer limits, verified CA TLS, parameterized queries, a single-client transaction helper, and schema/privilege-aware readiness. Connection-string SSL query parameters are rejected so they cannot silently override the mounted CA policy.
- The three stores and both account scripts no longer use Supabase/PostgREST. Local JSON remains explicit for development/tests; production without a valid backend or PostgreSQL URL fails closed.
- The migration runner serializes with a session advisory lock, verifies immutable checksums, wraps each version in a transaction, provisions exact current-object grants for a constrained application role, revokes public function execution, and deliberately avoids blanket/default future-object grants.
- Read-only audits found and implementation fixed four concurrency/semantic defects: concurrent duplicate wallet idempotency, concurrent failed-login count loss, PostgreSQL billing-update 23505 mapping, and JSONB condition-array canonicalization.
- ACK templates now keep Web at one replica until storage is externalized, separate Web/Worker/DB secrets, isolate the public internal-worker prefix through a selectorless Service, mount the RDS CA, disable service-account token mounts, and split liveness from database/schema readiness.
- The first final Sol review returned FAIL and uncovered additional production risks. All reported code findings were addressed before re-review: wallet idempotency is organization-scoped and binds immutable account/job/kind/amount/currency fields while treating description/metadata as mutable audit detail; destructive usage deduplication became a fail-safe preflight; app grants are explicit with no future-object defaults; readiness covers all runtime tables; password changes use a row-lock transaction; server-only imports are enforced; and npm/pnpm resolve the same pinned Next/React toolchain.
- Main-thread final verification passed 31 test files / 119 tests, TypeScript, the Next production build, all 8 ACK manifest assertions, frozen lockfile validation, script syntax, diff hygiene, and documentation drift. The final independent Sol review returned `PASS`; live RDS/ACK/Docker verification remains explicitly outside the available environment.