docs: integrate static frontend architecture

This commit is contained in:
2026-08-16 21:02:42 +08:00
parent b14b4fced7
commit bb50d06d1d
13 changed files with 243 additions and 82 deletions

View File

@@ -19,19 +19,27 @@ The project exists to give organizations an Alibaba Cloud ACK-deployable AI crea
- This project does not aim to be a model-training, dataset, or labeling platform.
- It is not a public social sharing site; assets stay account and organization scoped.
- In the current version it is not a horizontally auto-scaled multi-region SaaS: one Web replica until generated assets move to shared OSS.
- In the current version it is not a horizontally auto-scaled multi-region
SaaS: the static Web is stateless, but Go remains one replica until generated
and uploaded assets move to shared OSS.
## Core Constraints
- Same-origin browser authentication through signed, chunked `zhinian_session` cookies with per-request account/organization/sessionVersion revalidation.
- Production persistence fails closed: explicit RDS PostgreSQL through a server-only adapter; local JSON is development/test only.
- Production persistence fails closed: explicit RDS PostgreSQL through the Go
PostgreSQL Adapter; local JSON is development/test only.
- Production Web is a static export on Nginx. Browser runtime requests stay
same-origin and all API/file/auth behavior belongs to Go.
- Cross-instance concurrency stays in PostgreSQL: `claim_generation_jobs` for job claims and `billing_post_wallet_entry` for wallet idempotency; no process-local lock replacements.
- Chinese-first product surfaces; production deployment targets Alibaba Cloud ACK.
## Quality Bar
A good solution should preserve current HTTP/Cookie/authorization behavior, keep provider, billing, and storage semantics idempotent and tenant-scoped, pass the executable contract tests under `contracts/`, and remain reversible through a single-writer cutover.
A good solution should preserve current HTTP/Cookie/authorization behavior,
keep provider, billing, and storage semantics idempotent and tenant-scoped,
pass the executable contracts under `contracts/`, and keep the static Web/Go
runtime boundary mechanically testable.
## Last Reviewed
2026-08-14
2026-08-16

View File

@@ -2,7 +2,10 @@
## Project Success
- Production cutover of the Go backend passes the executable contract suites under `contracts/` with real RDS/OSS/provider/Webhook dependencies, without visible user-facing behavior change.
- The first production deployment serves the static Next.js export reliably,
routes every runtime API/file request to Go, and passes executable contracts
with real RDS/OSS/provider/Webhook dependencies without user-facing behavior
regressions.
## Task Completion Standard
@@ -11,6 +14,8 @@
## Quality Checks
- `npm test` (full Vitest suite), `npx tsc --noEmit`, and `npm run build` pass.
- Static architecture checks reject Next Route Handlers, Middleware,
request-time page dependencies, and production `next start`.
- `go test -count=1 ./...` and `go vet ./...` pass for backend changes.
- `node scripts/check-ack-manifests.mjs` and `npm run deploy:check` pass for deployment changes.
- `check_project_docs.py` and `check_doc_drift.py --task-id <task_id>` pass for documentation changes.
@@ -18,4 +23,4 @@
## Last Reviewed
2026-08-14
2026-08-16

View File

@@ -2,7 +2,8 @@
## Status
Accepted target; Go implementation merged into `main` on 2026-08-14 (see `.project-docs/30-worklog/current-state.md`); first production deployment pending — there is no legacy production instance, so no cutover applies (see `DEP-001` in the decision index)
Accepted and implemented in repository revision `b14b4fc` on 2026-08-16;
production rollout and live smoke tests remain pending (see `DEP-001`)
## Date
@@ -10,27 +11,41 @@ Accepted target; Go implementation merged into `main` on 2026-08-14 (see `.proje
## Context
The integrated application currently runs as a Next.js full-stack Web workload plus a Node process that periodically calls an internal Worker tick endpoint. Next.js owns browser rendering, HTTP routes, authentication, PostgreSQL access, task execution, billing, providers, storage, and Webhooks. This makes the deployment operationally compact, but keeps the UI framework and the complete business backend in the same runtime.
The original application was a Next.js full-stack Web workload plus a Node
process that periodically called an internal Worker tick endpoint. The Go
modular monolith subsequently took ownership of the HTTP and business backend,
while Next.js retained SSR and an internal Go identity bridge. That remaining
server-side frontend seam caused the first production login path to fail with
an RSC error and added Web-to-Go DNS/configuration coupling.
The user explicitly approved a long-term split in which Next.js is the frontend and a Go modular monolith owns the backend. The user later clarified that this integration records design and progress only; it does not authorize or claim a completed code migration.
The user explicitly approved a stricter boundary: the frontend is a static page
set and every runtime API is provided by Go.
## Decision
The approved target is a same-origin ACK topology with two long-lived workloads:
The approved topology has two long-lived same-origin ACK workloads:
- Next.js serves pages, static assets, and SSR. It calls Go over HTTP and does not own RDS, provider, OSS, billing, or migration credentials.
- Next.js is a build tool only. An unprivileged Nginx workload serves its static
`out/` pages and assets. Web has no SSR, Middleware, Route Handlers, runtime
ConfigMap, session Secret, database credential, or internal Go URL.
- The browser calls same-origin `/api/**`, `/uploads/**`, and
`/generated-results/**`; Ingress routes them directly to Go. Browser route
guards are presentation behavior, never an authorization boundary.
- Go owns the existing `/api/**`, `/uploads/**`, and `/generated-results/**` contracts; identity, administration, assets, jobs, billing, usage, providers, storage, Webhooks, readiness, and an initially embedded WorkerLoop.
- RDS PostgreSQL remains the source of relational truth and cross-instance concurrency.
- The one-shot, versioned PostgreSQL migration Job remains separate.
- Initial schema creation is a manual/CI operator action using the versioned SQL
plus application-role grants. No migration Job reuses the static Web image.
- Split the embedded WorkerLoop into a third workload only after independent scaling or failure-isolation needs are demonstrated.
The implementation must preserve the existing HTTP and Cookie Interface, multi-tenant authorization, idempotency, task state, wallet, storage, and Webhook behavior. It must continue calling `claim_generation_jobs` and `billing_post_wallet_entry`; Go process-local locks cannot replace these database functions.
Until the implementation is complete and verified, the existing ACK-001 Web/HTTP-polling-Worker architecture remains the deployed and source-code truth.
The checked-in source and ACK manifests implement this boundary. The live
cluster must still be verified after publishing new immutable Web and Go images.
## Rationale
- Establishes clear runtime and Secret ownership between UI and backend.
- Removes request-time frontend rendering and Web-to-Go internal transport.
- Allows backend lifecycle, testing, and future scaling to evolve independently of Next.js.
- Removes the internal HTTP tick seam once the Go WorkerLoop is production-ready.
- Keeps the initial workload count at two rather than introducing a separate API and Worker before evidence justifies it.
@@ -38,19 +53,26 @@ Until the implementation is complete and verified, the existing ACK-001 Web/HTTP
## Consequences
- The migration is a substantial behavior-compatible rewrite across TypeScript and Go, not a deployment-only change.
- Next.js can remain SSR but is database-free; static export is a separate future choice.
- Production pages are public static resources; all protected data and actions
must be authorized by Go on every request.
- API failures surface as client state instead of fatal RSC rendering failures.
- New runtime endpoints belong in Go. Reintroducing Next Route Handlers,
Middleware authentication, or request-Cookie SSR violates this decision.
- Go API replica count initially also changes WorkerLoop concurrency and provider/RDS load.
- Executable compatibility tests and reversible, single-writer cutover are mandatory.
- Current code, manifests, and configuration remain unchanged by this ADR.
- The Web workload can scale independently, but Go remains one replica until
generated/uploaded assets use OSS or another shared store.
- Executable HTTP/Cookie compatibility and static-boundary tests are mandatory.
## Supersedes
- ACK-001 after the Go implementation and cutover are complete. ACK-001 remains the transition-state operational decision until then.
- ACK-001. Production does not deploy the Node Worker or give Web database
ownership.
## Related
- `.project-docs/10-decisions/proposals/20260812-go-backend-migration-6f4a92__next-go-architecture.md`
- `.project-docs/30-worklog/tasks/20260812-next-go-architecture-4d81e2.md`
- `.project-docs/30-worklog/tasks/20260812-go-backend-migration-6f4a92.md`
- `.project-docs/10-decisions/proposals/20260816-static-frontend-go-api-4f8c2a7d__static-web-go-api.md`
- `.project-docs/30-worklog/tasks/20260816-static-frontend-go-api-4f8c2a7d.md`
- RDS-001 and RDS-002 in `.project-docs/10-decisions/decision-index.md`

View File

@@ -5,9 +5,9 @@
| ID | Decision | Status | Date | Applies To | Detail |
|---|---|---|---|---|---|
| RDS-001 | Production persistence uses explicit direct PostgreSQL through one server-only adapter; local JSON is explicit development/test mode. | Accepted | 2026-08-12 | Server stores and scripts | `ZHINIAN_DATA_BACKEND=postgres` fails closed and never silently falls back. |
| RDS-002 | Database changes use versioned, checksummed, advisory-locked migrations. | Accepted; execution amended 2026-08-14 | 2026-08-12 | Database schema and rollout | Initial production schema is executed manually from `database/migrations/*.sql` plus application-role grants; the one-shot Job manifest is retained but not part of the deployment path. |
| ADR-003 | Target architecture is a same-origin Next.js frontend plus Go modular-monolith backend with an initially embedded WorkerLoop. | Accepted target; Go implementation merged into `main` 2026-08-14; first production deployment pending | 2026-08-12 | Application and ACK architecture | First deployment runs the split topology directly; no legacy production instance exists. See `adr-003-next-go-target.md`. |
| DEP-001 | Production starts fresh: the first production deployment runs the ADR-003 split topology (Next.js frontend + Go backend), there is no legacy cutover or Node Worker, and the schema is initialized by manually executed SQL. | Accepted | 2026-08-14 | Deployment model and schema initialization | Human decision: no migration Job pod; super administrator is bootstrapped from `ZHINIAN_BOOTSTRAP_ADMIN_*` configuration at Go startup. |
| RDS-002 | Database changes use versioned, checksummed, advisory-locked migrations. | Accepted; execution amended 2026-08-14 | 2026-08-12 | Database schema and rollout | Initial production schema is executed manually from `database/migrations/*.sql` plus application-role grants; no migration Job manifest is shipped with the static Web image. |
| ADR-003 | Production is a same-origin static Next.js export on Nginx plus a Go modular-monolith backend with an embedded WorkerLoop. | Accepted; repository implementation complete in `b14b4fc`; production rollout pending | 2026-08-12, amended 2026-08-16 | Application and ACK architecture | Browser routes are static; all runtime API/file/auth responsibility belongs to Go. See `adr-003-next-go-target.md`. |
| DEP-001 | Production starts fresh with the ADR-003 static Web + Go topology, no legacy cutover or Node Worker, and manual SQL schema initialization. | Accepted; manifests updated 2026-08-16 | 2026-08-14 | Deployment model and schema initialization | No migration Job pod; Go bootstraps the super administrator, owns the session Secret, and receives all runtime/backend configuration. |
## Superseded Decisions

View File

@@ -1,28 +1,35 @@
# Data Flow
## Local Full-Stack Flows
## Development Flows
These repository flows remain available for local development and do not establish which Service currently owns a path in the live production cluster.
`next dev` serves the page development loop; runtime API behavior still belongs
to a separately running Go backend or an equivalent same-origin development
proxy. Legacy TypeScript server adapters remain unreferenced cleanup candidates
and are not a supported production path.
| Flow | Source | Destination | Notes |
|---|---|---|---|
| Web persistence | Routes/services/stores | PostgreSQL adapter -> RDS | Parameterized SQL; related statements share one Pool client transaction. |
| Worker processing | Worker process | Internal Web Service `/api/internal/worker/tick` | Authenticated by internal token; Worker has no RDS credentials. |
| Browser UI development | Browser | Next dev page server | Pages/components only; no Next API or Middleware. |
| Runtime API development | Browser/tooling | Go HTTP server | Same contracts as production; Go localstore is explicit non-production mode. |
| Schema rollout | Manual SQL execution by the deployment operator | RDS PostgreSQL | Versioned checksummed files under `database/migrations/`; 0001 then 0002, then application-role grants. |
| Readiness | ACK probe | Web `/api/ready` -> RDS | Verifies connection, 11 runtime tables, required privileges, and 2 functions. |
## Approved Target Flows
The Go implementation and desired ACK routing for these flows are present in the repository. Production is already online, but its exact live Service ownership has not been confirmed from cluster configuration or logs:
The implementation and desired ACK routing are present in `b14b4fc`.
Production is already online, but the static revision and exact live Service
ownership have not been confirmed from cluster configuration or logs:
| Flow | Source | Destination | Required behavior |
|---|---|---|---|
| Browser UI | Browser | Same-origin Ingress -> Next.js or Go by path | Preserve current URLs; avoid cross-origin Cookie/CORS changes. |
| SSR identity | Next.js `getOptionalAuthSession()` | Internal Go `GET /api/auth/me` | Implemented in `498c2fa` when `ZHINIAN_GO_INTERNAL_BASE_URL` is configured: forward only enumerated `zhinian_session` Cookie chunks, use no-store transport, strictly validate authenticated/anonymous response shape and identity binding, and fail closed on bridge errors. No unrelated Cookie or origin forwarding. Without the URL, local full-stack mode keeps direct-store authorization. The live revision does not yet contain this fix. |
| Browser UI | Browser | Same-origin Ingress -> Nginx static Web | Preserve current page URLs; Nginx performs no application logic. |
| Browser identity | Browser auth Module | Same-origin Ingress -> Go `GET /api/auth/me` | Browser automatically sends HttpOnly Cookie; validate anonymous/authenticated response shapes, keep no token in JavaScript, and use client guards only for UX. |
| Browser business/file requests | Browser components | Same-origin Ingress -> Go `/api`, `/uploads`, `/generated-results` | Go revalidates session/account/organization/sessionVersion and enforces every protected action. |
| Backend persistence | Go Modules | PostgreSQL Adapter -> RDS | Parameterized queries and transactions; fail closed in production. |
| Task execution | Embedded Go WorkerLoop | RDS claim -> provider -> OSS -> RDS -> Webhook | Bounded concurrency, recoverable leases, one owner for external side effects. |
| Asset lifecycle | Go Assets | OSS plus RDS metadata | Shared storage required before horizontal scaling. |
| Schema rollout | Migration Job | RDS | Existing version/checksum/advisory-lock contract remains unchanged. |
| Schema rollout | Manual operator or dedicated CI | RDS | Execute immutable versioned SQL plus grants outside long-lived workloads; no Web-image migration Job. |
| Web health | ACK probe | Nginx `/healthz` | Static process/container health only; no database implication. |
| Go readiness | ACK probe | Go `/api/ready` -> RDS | Database/schema/privilege-aware readiness. |
## State Ownership
@@ -35,11 +42,14 @@ The Go implementation and desired ACK routing for these flows are present in the
- Alibaba Cloud RDS PostgreSQL via its internal endpoint and verified TLS CA.
- Alibaba Cloud ACK resources under `deploy/ack/`.
- Live production at `https://nianxxaigc.nianxx.cn`; public `/api/ready` has returned HTTP 200 with PostgreSQL configured, without proving the owning Service.
- Internal Worker HTTP endpoint is cluster-internal and blocked from public Ingress routing.
- The legacy internal Worker prefix is denied by Ingress; production uses the
embedded Go WorkerLoop and ships no Node Worker manifest.
The accepted production topology uses the embedded Go WorkerLoop rather than the local-development Node Worker. The exact live workload set remains to be confirmed from the cluster.
The SSR identity bridge and ACK internal URL are merged but not yet deployed. The current live revision produces a production RSC error for authenticated `/create`; the repair rollout must deploy `498c2fa` and verify the flow with an authenticated smoke test.
The accepted production topology uses the embedded Go WorkerLoop. The current
live revision produces an RSC error for authenticated `/create`; the rollout
must deploy `b14b4fc` under immutable image references and smoke login,
authenticated routes, logout, roles, `/healthz`, `/api/health`, and
`/api/ready`.
## Last Updated

View File

@@ -4,30 +4,33 @@
| Path | Responsibility | Owner Notes |
|---|---|---|
| `lib/server/database.ts` | Server-only PostgreSQL Pool, TLS, queries, transactions, readiness | Only deep database transport boundary for runtime stores. |
| `lib/server/{data-store,account-store,billing-store}.ts` | Domain persistence with PostgreSQL/local implementations | Preserve exported interfaces for callers. |
| `database/migrations/` | Immutable versioned PostgreSQL schema changes | Executed manually for the first deployment (0001 initial schema, 0002 generation lifecycle fencing); the Node runner and Job manifest are retained but not part of the deployment path. |
| `scripts/postgres-client.mjs` | Validated database configuration for Node operations scripts | Shared by migration/bootstrap/import scripts. |
| `deploy/ack/` | ACK deployment resources and secret/config templates | Desired production split topology; the `498c2fa` Web configuration is pending rollout, and the migration Job manifest is deprecated (manual SQL). |
| `app/api/ready/route.ts` | Database/schema/privilege readiness endpoint | Separate from process-level liveness. |
| `lib/server/auth/current-user.ts` | In revision `498c2fa`, resolves the current SSR user through internal Go `/api/auth/me` when `ZHINIAN_GO_INTERNAL_BASE_URL` is set; otherwise uses the local direct-store authorization path | Sends only enumerated `zhinian_session` chunks, validates the Go response and identity binding strictly, and fails closed on bridge errors. The fixed revision is not yet live. |
| `backend/cmd/zhinian-api` | Go application entrypoint, configuration, HTTP server composition, readiness | Locally runnable and targeted by checked-in ACK routing; exact live request ownership remains unverified. |
| `backend/internal/*` | ADR-003 deep modules and adapters, 18 packages: `identity`, `administration`, `assets`, `billing`, `usage`, `jobs`, `providers`, `webhook`, `httpapi`, `publicapi`, `application`, `orchestration`, `postgres`, `localstore`, `logging`, `settings`, `templates`, `prompt` | Merged; production is online, but the deployed revision and live routing do not yet reflect the `498c2fa` repair configuration. |
| `app/**`, `components/**` | Statically exportable pages and browser UI | No Route Handlers, Middleware, server auth imports, or request-time page dependencies. |
| `components/browser-auth.tsx` | Browser identity context and presentation guards | Consumes validated same-origin state; guards are UX only. |
| `lib/client/browser-auth.ts` | Deep browser/Go auth Interface | Owns `GET /api/auth/me` parsing plus safe return-path validation. |
| `next.config.ts`, `Dockerfile`, `deploy/nginx.conf` | Static export and production Web runtime | Build emits `out/`; unprivileged Nginx serves files and rejects Go-owned paths when reached directly. |
| `database/migrations/` | Immutable versioned PostgreSQL schema changes | Executed manually/through dedicated operator CI; no migration Job reuses Web. |
| `deploy/ack/` | Seven ACK manifests plus Secret template | Static Web + Go topology; Web has no runtime config/Secret and Go owns the session Secret. |
| `backend/cmd/zhinian-api` | Go application entrypoint, configuration, HTTP server composition, health/readiness | Sole runtime API owner targeted by checked-in Ingress. |
| `backend/internal/*` | ADR-003 deep modules and adapters, 18 packages: `identity`, `administration`, `assets`, `billing`, `usage`, `jobs`, `providers`, `webhook`, `httpapi`, `publicapi`, `application`, `orchestration`, `postgres`, `localstore`, `logging`, `settings`, `templates`, `prompt` | Implemented in `b14b4fc`; publication of immutable images and rollout of the static Web + Go revision remain pending. |
| `contracts/**/*.json` | Language-neutral HTTP/Cookie/auth/jobs/billing/storage/webhook contract fixtures | Shared acceptance source for TypeScript and Go consumers. |
## Dependency Direction
- Routes and services depend on store interfaces; stores depend on the shared database adapter; the adapter does not depend on domain stores.
- Worker depends on the internal Web HTTP API, not the database module.
- Go modules depend on the PostgreSQL transport and storage/provider adapters; `httpapi`/`publicapi` depend on deep modules, never the reverse.
- Static pages/components depend on `lib/client/browser-auth.ts` and relative
same-origin HTTP paths; they never depend on `lib/server`.
- Go `httpapi`/`publicapi` depend on deep business Modules; Modules depend on
PostgreSQL/storage/provider Adapters, never on Web or HTTP presentation.
- The embedded WorkerLoop uses Go application/Module seams and PostgreSQL
claims; there is no Node-to-Web internal tick dependency.
## Approved Target Module Map
The target below is implemented in the repository. The first production deployment has occurred; the `498c2fa` repair rollout and confirmation of the live cluster shape remain pending:
The target below is implemented in `b14b4fc`; image publication, ACK rollout,
and confirmation of the live cluster shape remain pending:
| Target Module | Go package | Implementation notes |
|---|---|---|
| Next.js frontend | `lib/server/auth/current-user.ts` | In `498c2fa`, production SSR forwards only enumerated signed session Cookie chunks to Go `/api/auth/me`; the live revision does not yet contain this fix. Local full-stack mode uses direct stores when the internal Go URL is absent. |
| Static frontend | `components/browser-auth.tsx`, `lib/client/browser-auth.ts` | Browser calls same-origin Go `/api/auth/me`; no SSR bridge, request Cookie parsing, internal Go URL, or server fallback. |
| Go Identity | `internal/identity` | Login/logout/session/password/authorization; preserves the signed chunked Cookie and per-request account/organization/sessionVersion validation. |
| Go Administration | `internal/administration` | Organizations, accounts, settings visibility, logs, administrative usage; enforces super-admin and organization-admin rules. |
| Go Assets | `internal/assets` | Register/upload/list/get/delete/download; uses object-storage Adapter; preserves owner-scoped 404 and storage metadata. |
@@ -45,7 +48,10 @@ Real internal seams are PostgreSQL transport, object storage, generation provide
- Account authentication/password transactions and billing wallet idempotency.
- ACK Secrets, RDS CA mounting, Ingress protection for internal Worker routes, and pool connection budgeting.
- `backend/internal/{postgres,jobs,billing}`: claim and wallet correctness across Go replica scaling until WorkerLoop concurrency is deliberate.
- Live request-path ownership and deployed workload revisions must be confirmed from ACK configuration or logs; do not infer them from the public endpoint alone.
- Static Web image construction/container startup still needs CI smoke evidence.
- Go `emptyDir` file state is lost on Pod replacement when OSS is absent.
- Live request-path ownership and deployed workload revisions must be confirmed
from ACK configuration or logs; do not infer them from a public endpoint.
## Last Updated

View File

@@ -4,47 +4,60 @@
The first production deployment is online at `https://nianxxaigc.nianxx.cn`. The public `/api/ready` endpoint has been observed returning HTTP 200 with PostgreSQL configured. The exact live Service owner for each path has not been confirmed through cluster configuration or logs, so the deployed routing shape is not inferred here.
The live revision predates `498c2fa` and authenticated `/create` currently triggers a production RSC error. The fixed repository revision implements the ADR-003 boundary: Next.js serves pages/static/SSR without database credentials and refreshes authenticated SSR through internal Go `/api/auth/me`; the checked-in production topology assigns backend routes, database-backed authorization, RDS access, and the embedded WorkerLoop to Go. The updated Web image and ACK configuration have not yet been deployed, and the authenticated smoke test remains open. Local development remains a separate Next.js full-stack shape with explicit PostgreSQL or local JSON stores and the HTTP-polling Node Worker.
The live revision predates `b14b4fc` and authenticated `/create` currently
triggers a production RSC error. The repository now implements the stricter
ADR-003 boundary: Next.js statically exports pages, unprivileged Nginx serves
them, the browser reads identity from Go `/api/auth/me`, and Go owns every
runtime API/file route plus database-backed authorization and the embedded
WorkerLoop. The new images and ACK configuration have not yet been deployed.
## Approved Target Architecture
The accepted target in ADR-003 is a same-origin Next.js frontend plus Go modular-monolith backend:
The accepted target in ADR-003 is a same-origin static Next.js export on Nginx plus a Go modular-monolith backend:
| Target component | Responsibility | Constraint | Implementation state |
|---|---|---|---|
| Next.js frontend | Pages, static assets, SSR, browser UI | Calls Go over HTTP; no RDS/provider/OSS/business Secret. | Local dev also runs its API routes; production serves pages only. |
| Static Web | Next.js build output (`out/`) and browser UI served by Nginx | No SSR, Middleware, Route Handlers, runtime configuration, application Secret, or internal Go URL. | Implemented and statically verified in `b14b4fc`; deployment pending. |
| Go backend | Existing HTTP/file contracts, identity, administration, assets, jobs, billing, usage, providers, storage, Webhooks, readiness | Owns relational access and embeds the WorkerLoop in the approved topology. | Implemented in `backend/`; production is online, but exact live path ownership is not asserted without cluster evidence. |
| RDS PostgreSQL | Relational state and cross-instance concurrency | Retains versioned migrations and both concurrency-sensitive database functions. | Schema initialized by manual SQL (migrations 0001/0002) plus role grants. |
| Migration Job | Schema and application-role grants | Remains one-shot and separate from long-lived workloads. | Manifest retained but not used; initial schema is executed manually. |
| RDS PostgreSQL | Relational state and cross-instance concurrency | Retains versioned migrations and both concurrency-sensitive database functions. | Repository procedure requires manual SQL (migrations 0001/0002) plus role grants; live execution evidence remains to be confirmed. |
| Schema operator/CI | Schema and application-role grants | Runs versioned SQL outside long-lived workloads; never reuses the static Web image. | First-deployment procedure is manual; no migration Job manifest is shipped. |
| Alibaba Cloud OSS | Shared generated/uploaded assets | Must be production-ready before horizontal workload scaling. | Still behind a storage Adapter; not validated against real OSS. |
The checked-in Ingress routes page/static paths to Next.js and `/api`, `/uploads`, and `/generated-results` to Go. Production is already online; confirming that the live cluster matches this desired state is part of the repair rollout. The approved initial target is two long-lived Pods (`Next x1 + Go x1`).
The checked-in Ingress routes pages/static assets to Nginx and `/api`,
`/uploads`, and `/generated-results` to Go. The approved long-lived workload
set is static Web plus Go; Web can scale independently, while Go stays one
replica until file storage is shared.
## Main Components
| Component | Responsibility | Notes |
|---|---|---|
| Next.js Web | Local full-stack browser/API routes and stores; fixed production revision serves pages/static/SSR plus the internal Go identity bridge | Local development may use direct stores. The database-free production configuration in `498c2fa` is not yet deployed. |
| Worker | Periodically invokes the internal Worker tick endpoint | Local development only; production uses the embedded Go WorkerLoop. |
| PostgreSQL adapter | Backend selection, Pool lifecycle, TLS, parameterized queries, transactions, readiness | Server-only module at `lib/server/database.ts`. |
| Static Web | Next.js pages/components compiled to `out/`; unprivileged Nginx serves navigation and hashed assets | Browser auth Module calls same-origin Go; client guards are UX only. |
| Go backend | `cmd/zhinian-api` plus 18 `internal/` packages: identity, administration, assets, billing, usage, jobs, providers, webhook, httpapi, publicapi, application, orchestration, postgres, localstore, logging, settings, templates, prompt | Merged and contract-tested; checked-in manifests route backend paths to Go, while exact live routing remains to be confirmed from the cluster. |
| Contract fixtures | Language-neutral JSON contracts for auth, admin, assets, billing, http, jobs, logs, providers, settings, usage, webhook under `contracts/` | Shared executable acceptance source for TypeScript and Go consumers. |
| RDS PostgreSQL | Accounts, assets, jobs, usage, templates, billing state | Schema managed by versioned migrations (0001, 0002). |
| Migration Job | Retained one-shot migration artifact | Not used for the first production deployment; the operator executes versioned SQL and grants manually. |
| Runtime/object storage | Uploads, generated assets, and logs | Container-local/PVC by default; use OSS/shared storage before scaling horizontally. |
| Schema operator/CI | Executes versioned SQL and grants manually | No Node migration manifest or executable exists in the static Web image. |
| Runtime/object storage | Uploads, generated assets, and logs | Go `emptyDir` by default; use OSS/shared storage before scaling or replacing the Pod when persistence is required. |
## Important Boundaries
- Production backend selection is explicit and fail-closed; never turn a PostgreSQL configuration failure into local JSON fallback.
- Store callers depend on stable store interfaces, not `pg` or SQL details.
- Multi-statement consistency uses one transaction client; atomic job claim and wallet posting remain database functions.
- In the approved production split topology, database credentials belong to Go and the manual migration operator; the fixed Next.js Web configuration and any local-only Node Worker do not receive them.
- The live production environment requires post-deployment validation against RDS/OSS/provider/Webhook dependencies; Next Route Handlers stay in the repository for local development.
- Database credentials and the session-signing Secret belong to Go and the
manual schema operator; static Web receives neither.
- Browser requests stay same-origin, but Go authorizes every protected API and
file request; page visibility is not a security boundary.
- Next Route Handlers, Middleware, SSR Cookie access, and production
`next start` are prohibited by the accepted architecture.
- The live environment still requires post-deployment validation against
RDS/OSS/provider/Webhook dependencies.
## Related Decisions
- Current implementation: `RDS-001` and `RDS-002` (schema execution now manual SQL per `DEP-001`).
- Accepted target: `ADR-003`; production is online, but its exact live realization must be confirmed from cluster evidence.
- Accepted implementation: `ADR-003` as amended by `b14b4fc`; production is
online, but the new static revision and exact live routing remain unverified.
- First-deployment model: `DEP-001`.
## Last Updated

View File

@@ -14,10 +14,21 @@ This file is the integrated default-branch snapshot. Feature tasks record progre
- `ff055c9` (config-driven super-admin bootstrap in the Go backend, task `20260814-go-bootstrap-admin-6e2b7d9c`)
- `4a8f2d5` (Go workload deployment artifacts and split Ingress routing, task `20260814-go-deploy-artifacts-2a5f8e1d`)
- `498c2fa` (authenticated Next.js SSR-to-Go identity bridge and ACK Web internal Go URL, task `20260816-fix-authenticated-ssr-6c3f8a21`)
- `b14b4fc` (pure static Next.js export, browser-to-Go auth, Go-only runtime API
ownership, unprivileged Nginx Web, and first-deployment ACK cleanup; task
`20260816-static-frontend-go-api-4f8c2a7d`)
## Current Focus
The first production deployment is live at `https://nianxxaigc.nianxx.cn`. Its deployed revision does not yet include `498c2fa`: authenticated `/create` currently triggers a production RSC error, while the public `/api/ready` endpoint has been observed returning HTTP 200 with PostgreSQL configured. The repository now contains the authenticated Next.js SSR-to-Go identity bridge in `lib/server/auth/current-user.ts`; when `ZHINIAN_GO_INTERNAL_BASE_URL` is configured it refreshes identity through internal Go `/api/auth/me`, and without that environment variable local Next.js full-stack development retains the direct-store path. Current work is the production repair rollout: publish the updated Web image and ACK configuration, then complete an authenticated `/create` smoke test. The exact live Service owner for each request path remains unverified until confirmed from cluster configuration or logs.
The first production deployment is live at `https://nianxxaigc.nianxx.cn`; the
currently observed revision still fails authenticated `/create` with an RSC
error. Repository revision `b14b4fc` removes that request-time frontend seam:
Next.js now emits static `out/` files served by unprivileged Nginx, the browser
loads identity from same-origin Go `/api/auth/me`, and Ingress routes all
`/api`, `/uploads`, and `/generated-results` traffic directly to Go. Web has no
runtime ConfigMap, Secret, database credential, or internal Go URL. The new
images/manifests have not yet been deployed, and exact live Service ownership
still requires cluster evidence.
## Recently Completed
@@ -30,30 +41,49 @@ The first production deployment is live at `https://nianxxaigc.nianxx.cn`. Its d
- 2026-08-14: Recorded the first-deployment model: no production cutover, manual schema initialization without the migration Job pod (task `20260814-deploy-model-reconcile-9b4c2e7f`).
- 2026-08-14: Built the Go workload deployment artifacts: `backend/Dockerfile`, `deploy/ack/go-api.yaml`, split-path Ingress routing, non-root/read-only-filesystem workload config, and updated manifest assertions (task `20260814-go-deploy-artifacts-2a5f8e1d`).
- 2026-08-16: Implemented authenticated production SSR identity refresh through Go `/api/auth/me`, forwarding only enumerated `zhinian_session` chunks, strictly validating the response, preserving the local direct-store path when the internal URL is absent, and keeping the updated ACK Web configuration database-free (task `20260816-fix-authenticated-ssr-6c3f8a21`, commit `498c2fa`; not yet deployed).
- 2026-08-16: Replaced production SSR/Middleware/Next Route Handlers with a
static export and browser auth Module, made Go the only runtime API owner,
replaced the Web runner with unprivileged Nginx, removed deprecated Node
Worker/migration manifests, and added static/deployment regressions (task
`20260816-static-frontend-go-api-4f8c2a7d`, commit `b14b4fc`; not yet
deployed).
## In Progress
- Release `498c2fa` to the existing production environment and verify authenticated `/create` SSR; the live revision still exhibits the RSC failure.
- Build, publish, and deploy immutable Web and Go images for `b14b4fc`, then
verify the static Web + Go-only runtime boundary in the live ACK cluster.
## Next Recommended Steps
1. Build and push the updated Web image containing `498c2fa`, and validate the updated ACK configuration with a server-side dry run on the production cluster.
2. Apply the updated Web image and ACK configuration without assuming the current live Service ownership beyond what cluster configuration and logs confirm.
3. Smoke-test an authenticated request to `/create`, confirming the production RSC error is resolved and SSR refreshes the user through internal Go `/api/auth/me`.
4. Recheck public `/api/ready` after the rollout; it currently returns HTTP 200 with PostgreSQL configured.
5. Continue real RDS/OSS/provider/Webhook validation and confirm the public `/api/v1` compatibility promise for external consumers.
1. Build and smoke the pinned unprivileged Nginx Web image in CI or another
host with Docker, then publish Web and Go images under new immutable tags or
digests.
2. Create/verify the `zhinian` Namespace, run target-cluster server-side dry
runs, apply the production Go-owned Secret and six checked-in resource
manifests (not `secrets.example.yaml`), and confirm live Ingress/Service
ownership from cluster state.
3. Smoke anonymous login, authenticated `/create?mode=video`, logout, and each
admin role; verify Web `/healthz`, Go `/api/health`, and Go `/api/ready`.
4. Configure OSS or another shared/persistent store before any Go Pod
replacement that must preserve current local uploads/generated results.
5. Continue real RDS/provider/Webhook validation and confirm the public
`/api/v1` compatibility promise for external consumers.
## Open Questions / Blockers
- Canonical memory does not yet record the live RDS PostgreSQL version, connection budget, endpoint, TLS/CA details, database roles, ACK network policy, or confirmed request-path Service ownership.
- Real OSS bucket/credential configuration is still needed for shared asset storage.
- Public `/api/v1` support promises for external consumers need explicit confirmation.
- The static Web Docker image has not been built or container-smoked in this
workstation because its Docker daemon is unavailable.
## Risky Areas
- Database grants and least-privilege roles still require documented validation against the live RDS instance.
- The current image runs as root; moving to a non-root user requires an explicit writable-path ownership design.
- Real provider, OSS, RDS, and Webhook coverage is not fully documented; do not infer which live workload owns those paths without cluster evidence.
- Go currently stores local uploads/results on `emptyDir` when OSS is absent;
Pod replacement or rolling update loses them, not only horizontal scaling.
- Real provider, OSS, RDS, and Webhook coverage is not fully documented; do not
infer which live workload owns paths without cluster evidence.
## Last Updated

View File

@@ -18,6 +18,8 @@
| 2026-08-14 | `20260814-go-deploy-artifacts-2a5f8e1d` | Go workload deployment artifacts: `backend/Dockerfile`, `deploy/ack/go-api.yaml`, split-path Ingress, database-free Web workload, updated manifest assertions. | Task record, deployment docs, READMEs |
| 2026-08-16 | `20260816-fix-authenticated-ssr-6c3f8a21` | Revision `498c2fa` implements authenticated SSR identity refresh through internal Go `/api/auth/me` using only enumerated session Cookie chunks; strict response validation, local direct-store behavior, and a database-free ACK Web configuration are preserved. The task performed no live deployment. | Task record |
| 2026-08-16 | `20260816-integrate-auth-ssr-9d7e4c2a` | Serialized integration of source commit `498c2fa` and canonical reconciliation for the authenticated SSR-to-Go identity bridge. No live deployment was performed. | Current state, task history, system overview, module map, data flow, commitments |
| 2026-08-16 | `20260816-static-frontend-go-api-4f8c2a7d` | Revision `b14b4fc` replaces production SSR/Middleware/Next APIs with a static export on unprivileged Nginx; browser runtime traffic goes directly to the Go-owned same-origin API/file surface. | Task record, proposal, application/deployment docs |
| 2026-08-16 | `20260816-integrate-static-frontend-2c7e91b4` | Serialized canonical promotion of the user-approved static Web + Go-only runtime architecture. | Positioning, success criteria, ADR-003, decision index, current state, architecture, domain rules, commitments, task history |
## Notes

View File

@@ -0,0 +1,60 @@
# Task: Integrate static frontend architecture into project memory
## Identity
- Task ID: 20260816-integrate-static-frontend-2c7e91b4
- Mode: Integration
- Branch: codex/20260816-integrate-static-frontend-2c7e91b4
- Worktree: D:\Datas\OthersProjects\NianAIGC-integrate-static-frontend-2c7e91b4
- Base commit: b14b4fced70775eb50fde5b83192b72b09e3d86f
- Owner: codex
- Status: Ready for Integration
## Scope
- Promote the accepted static Web + Go API architecture from source task
`20260816-static-frontend-go-api-4f8c2a7d` into canonical project memory.
- Reconcile current state, architecture, domain language, decisions, success
criteria, commitments, and task history with implementation commit
`b14b4fc`.
## Intent And Constraints
- Preserve historical task/proposal records while making canonical documents
describe the implemented target unambiguously.
- Record deployment as pending; do not infer live ACK routing or workload
revisions from the public endpoint.
- Keep Go authorization authoritative and record client guards as UX only.
- Preserve the one-replica Go constraint until file storage is shared.
## Outcome
- Canonical memory now describes a statically exported Next.js frontend served
by unprivileged Nginx, with all runtime API, file, authentication,
authorization, database, and WorkerLoop responsibilities in Go.
- ADR-003, DEP-001, module/data-flow documentation, domain terminology,
commitments, and current-state rollout guidance are aligned with `b14b4fc`.
- The deployment gap is explicit: immutable image publication, target-cluster
validation, and live authentication/file smoke tests remain outstanding.
## Verification
- `check_project_docs.py`: PASS.
- `check_doc_drift.py --task-id 20260816-integrate-static-frontend-2c7e91b4`:
PASS.
- `git diff --check`: PASS.
- Read-only `sol_reviewer` verdict: PASS after resolving the two identified
documentation inconsistencies.
## Follow-ups
- Publish immutable Web and Go image tags/digests, update ACK manifests, and
run server-side dry-run before rollout.
- Verify login, `/api/auth/me`, role boundaries, deep links, file routes, and
health/readiness probes against the deployed revision.
- Configure OSS/shared storage before Go Pod replacement or horizontal scale
if uploads and generated results must persist.
## Promotion Candidates
- None; canonical promotion is applied directly by this integration task.

View File

@@ -9,9 +9,12 @@
- Super administrators calculate and record generation cost without checking, freezing, or refunding organization quota.
- All new organization balance entries are organization-owned; generation charge/refund entries keep member attribution for consumption reporting.
- Logged-in users may change their own password; account management and organization member actions require admin roles.
- Public `/api/v1` access authenticates with API keys and stays outside browser SSO middleware; API data is partitioned by the API account owner.
- Public `/api/v1` access authenticates with API keys rather than the browser
session Cookie; API data is partitioned by the API account owner.
- Database schema changes stay versioned and checksummed in `database/migrations/`; the initial production schema is created by manually executing the SQL files plus application-role grants (no migration Job pod), and schema changes must never run inside long-lived pod startup.
- Generated and uploaded assets remain runtime/object-storage state; PostgreSQL does not make them shared for horizontal scaling.
- Client-side route guards are navigation/UI behavior only; Go authorizes every
protected API and file request.
## Open Questions
@@ -19,4 +22,4 @@
## Last Reviewed
2026-08-14
2026-08-16

View File

@@ -9,8 +9,9 @@
| Ledger | Append-only record of wallet movements (charge, refund, settlement, adjustment). | Replayable for reconciliation. |
| Quote | Server-side estimate for a generation request using the matched billing rule and parameter tiers. | Preview is quote-only; submission is balance-gated. |
| Engine / Provider | External generation service: 即梦 (Jimeng), EvoLink GPT Image 2, Seedance 2.0, Bailian. | Adapters isolate provider payloads and status mapping. |
| Worker | Process that periodically calls the internal Worker tick endpoint to claim and execute jobs. | Node Worker has no RDS credentials; Go embeds a WorkerLoop after cutover. |
| WorkerLoop | Embedded async task loop inside the Go backend. | Replaces the HTTP-polling Node Worker only after drain and verification. |
| Cutover | Single-writer routing of `/api`, `/uploads`, `/generated-results` to Go, Node Worker drain, then Next Route Handler deletion. | Must stay reversible; ACK-001 remains truth until it passes. |
| Worker | Legacy Node process that polled an internal HTTP tick endpoint to claim and execute jobs. | No longer shipped or deployed in the accepted static Web + Go architecture. |
| WorkerLoop | Embedded async task loop inside the Go backend. | The production job-execution path; it uses Go application/module seams without a Web tick endpoint. |
| Static Web | Next.js static export (`out/`) served by unprivileged Nginx. | Has no SSR, Route Handlers, Middleware, runtime application configuration, database access, or session Secret. |
| Cutover | Historical migration from Next-owned runtime routes and the Node Worker to Go-owned routes and WorkerLoop. | The first production rollout now deploys the static Web and Go revisions directly; no legacy drain sequence is required. |
| Contract fixture | Language-neutral JSON contract under `contracts/` for HTTP, Cookie, auth, jobs, billing, storage, Webhook behavior. | Executable by both TypeScript and Go consumers. |
| `zhinian_session` | Signed (HMAC-SHA256), chunked (3000 chars, up to 20 chunks) session cookie. | `HttpOnly`, `SameSite=Lax`, `Path=/`, production `Secure`. |

View File

@@ -5,15 +5,16 @@ Track future-facing memory: promised follow-ups, unfinished loops, timed checks,
| Date | Commitment | Trigger / Due | Owner | Status | Next Action |
|---|---|---|---|---|---|
| 2026-08-12 | Validate migration, TLS, permissions, and readiness against the real Alibaba Cloud RDS instance. | Production hardening follow-up | Deployment owner | Open | Record the live RDS roles/CA/network configuration and validation evidence; public `/api/ready` currently returns HTTP 200 with PostgreSQL configured. |
| 2026-08-12 | Keep each workload at one replica until generated assets use OSS or another shared store. | Before raising replicas | Deployment owner | Open | Configure and validate external object storage. |
| 2026-08-12 | Harden the runtime image to non-root after writable paths are designed. | Security hardening follow-up | Application owner | Open | Define ownership for runtime and settings paths, then update Docker/ACK security context. |
| 2026-08-12 | Keep Go at one replica until generated assets use OSS or another shared store; static Web may scale independently. | Before raising Go replicas or replacing a Pod whose local files must survive | Deployment owner | Open | Configure and validate external object storage; absent OSS, `emptyDir` files are lost on Pod replacement. |
| 2026-08-12 | Harden production runtimes to non-root with explicit writable paths. | Security hardening follow-up | Application owner | Completed | Go already uses UID 10001; `b14b4fc` moves Web to unprivileged Nginx UID/GID 101 with read-only root and a `/tmp` volume. |
| 2026-08-12 | Implement ADR-003 only after executable compatibility contracts exist. | Before starting the Go migration | Application owner | Completed | Contracts exist under `contracts/`; Go implementation merged 2026-08-14. |
| 2026-08-14 | Build the Go workload deployment artifacts: container image, ACK Deployment/Service manifests, and Ingress routing that sends page/static paths to Next.js and `/api`, `/uploads`, `/generated-results` to Go. | Before the first production deployment | Application owner | Completed | `backend/Dockerfile`, `deploy/ack/go-api.yaml`, and the split Ingress are merged (2026-08-14); remaining work is image build/push and cluster dry-run validation. |
| 2026-08-14 | Build the Go workload deployment artifacts and split Ingress routing. | Before the first production deployment | Application owner | Completed | Go artifacts merged 2026-08-14; `b14b4fc` completes static Nginx Web and direct browser-to-Go routing. Remaining work is image build/push and target-cluster validation. |
| 2026-08-14 | Confirm that the production schema was initialized by manually executing `database/migrations/0001_initial_schema.sql`, then `0002_generation_lifecycle_fencing.sql`, then the application-role grants. No migration Job pod is deployed. | Production configuration audit | Deployment owner | Open | Record execution evidence and application-role grant verification; do not infer completion solely from the public readiness response. |
| 2026-08-14 | Confirm the live status of `ZHINIAN_BOOTSTRAP_ADMIN_PHONE` / `ZHINIAN_BOOTSTRAP_ADMIN_PASSWORD` / `ZHINIAN_BOOTSTRAP_ADMIN_NAME`; the Go process creates the first super administrator exactly once. | Production configuration audit | Deployment owner | Open | Verify the deployed configuration and bootstrap outcome without exposing credentials. |
| 2026-08-14 | Confirm the live status of `ZHINIAN_BOOTSTRAP_ADMIN_PHONE` / `ZHINIAN_BOOTSTRAP_ADMIN_PASSWORD`; the Go process creates the first super administrator exactly once and uses the default name when `ZHINIAN_BOOTSTRAP_ADMIN_NAME` is absent. | Production configuration audit | Deployment owner | Open | Verify deployed configuration and bootstrap outcome without exposing credentials. |
| 2026-08-14 | Validate the Go backend against non-production RDS, real OSS, provider credentials, and external Webhooks. | Production hardening follow-up | Deployment owner | Open | Run the contract and recovery suites against representative external dependencies and record any live parity gaps. |
| 2026-08-14 | Confirm the public `/api/v1` support promise for external consumers. | Production compatibility follow-up | Product owner | Open | Product decision on which v1 endpoints and behaviors are guaranteed for partners. |
| 2026-08-16 | Release and smoke-test authenticated `/create` SSR through the internal Go identity bridge while confirming the updated production Web configuration remains database-free. | Before closing the `498c2fa` production repair rollout | Deployment owner | Open | Publish and deploy the updated Web image and ACK configuration, authenticate as a platform user, request `/create`, verify the RSC error is resolved through Go `/api/auth/me`, and recheck public readiness. |
| 2026-08-16 | Release and smoke-test authenticated `/create` SSR through the internal Go identity bridge. | Superseded by the static architecture decision | Deployment owner | Superseded | Do not deploy the SSR bridge as the target architecture; deploy `b14b4fc` static Web + Go instead. |
| 2026-08-16 | Publish and deploy `b14b4fc` static Web + Go under immutable image references, then smoke the full same-origin boundary. | Before closing the production login repair | Deployment owner | Open | Build/container-smoke Web, server-side dry-run ACK, verify live path owners, anonymous login, `/create?mode=video`, logout, role pages, Web `/healthz`, Go `/api/health`, and Go `/api/ready`. |
## Use