# Progress Log ## Session: 2026-05-28 ### Phase 1: Repository Survey - **Status:** complete - **Started:** 2026-05-28 10:26 CST - Actions taken: - Read the planning-with-files skill instructions. - Confirmed no prior planning files existed. - Created lightweight planning files for this project understanding pass. - Inspected top-level directory, Git status, file inventory, and root package/config candidates. - Learned that this is not a Git repository and that the main app appears under `removed extracted runtime`. - Read root README, root package metadata, runtime README, runtime package metadata, and a filtered non-media source list. - Files created/modified: - `task_plan.md` - `findings.md` - `progress.md` ### Phase 2: Architecture Mapping - **Status:** complete - Actions taken: - Started tracing entry points and runtime structure from the extracted standalone bundle. - Read startup, health-check, runtime-info scripts, environment example, and extraction notes. - Ran `npm run info` and read bundle/app path manifests plus `.next` server/static file layout. - Inspected representative compiled API routes for projects, generations, uploads, and prompt assembly. - Searched compiled server chunks for Seedance/OSS/generation behavior. - Re-read quoted dynamic API route paths for generation polling/retry and project detail/delete behavior. - Summarized creation modes, starter catalog, planning cases, and avatar/outfit presets from content JSON. - Files created/modified: - `task_plan.md` - `findings.md` - `progress.md` ### Phase 3: Runtime & Verification - **Status:** complete - Actions taken: - Started the runtime with `npm start`; Next reported ready on `http://127.0.0.1:3000`. - Ran `npm run health`; health returned `ok: true`, `desktopManaged: true`, and both Seedance/OSS services unconfigured. - Verified `/studio`, `/api/projects`, `/api/reference-templates?mode=video_studio`, and `/api/billing` with `curl --noproxy '*'`. - Inspected the generated `.runtime/data/app-state.json`. - Stopped the runtime server after verification. - Files created/modified: - `.runtime/data/app-state.json` - `task_plan.md` - `findings.md` - `progress.md` ### Phase 4: Delivery - **Status:** complete - Actions taken: - Prepared the final Chinese project overview for the user. - Files created/modified: - `task_plan.md` - `progress.md` ## Test Results | Test | Input | Expected | Actual | Status | |------|-------|----------|--------|--------| | Runtime info | `npm run info` | Prints manifest/routes/content summary | Succeeded | pass | | Runtime startup | `npm start` | Starts Next standalone app | Ready on `http://127.0.0.1:3000` | pass | | Health check | `npm run health` | `ok: true` | `ok: true`, services unconfigured | pass | | Studio page | `curl --noproxy '*' -I /studio` | HTTP 200 | HTTP 200 | pass | | Projects API | `curl --noproxy '*' /api/projects` | JSON response | `{"projects":[]}` | pass | ## Session: 2026-07-02 - Account-Scoped Image Templates ### Phase 20: Account-Scoped Image Generation Templates - **Status:** complete - Actions taken: - Restored the existing planning-with-files context. - Confirmed the repo already has active planning files and no `.project-docs` folder. - Inspected current create-page image prompt flow, settings panel shape, image generation route, data-store owner filtering, app settings, and current-user helper. - Added `ImageTemplate` types, local/Supabase data-store helpers, input normalization, and first-party API routes. - Added template configuration to the settings page with preview URL, prompt, size, single-image, category, description, and sort-order fields. - Added image-template preview cards to the create page; selecting a template applies the preset prompt plus size and single-image settings. - Added focused tests for owner partitioning, cross-owner protection, and input normalization. - Verified settings/create UI through headless Chrome using a temporary demo template, then deleted the demo template. - Restarted the final dev server with normal auth-enabled `.env.local` behavior on `127.0.0.1:3001`. ## Test Results - 2026-07-02 Image Templates | Test | Input | Expected | Actual | Status | |------|-------|----------|--------|--------| | Focused template tests | `npm test -- image-templates.test.ts` | Template tests pass | 1 file / 3 tests passed | pass | | Full unit tests | `npm test` | All tests pass | 17 files / 50 tests passed | pass | | Production build | `npm run build` | Build succeeds | Build succeeded | pass | | Browser UI smoke | Headless Chrome `/settings` and `/create` on temporary auth-disabled dev server | Template appears, selecting it applies prompt, mobile has no horizontal overflow | `createPromptApplied: true`, `mobileOverflow: false` | pass | | Normal local server | `npm run dev -- --hostname 127.0.0.1 --port 3001` | Server ready with normal auth behavior | `/create` redirects to `/auth/login?next=%2Fcreate`; unauthenticated template API returns 401 | pass | ## Session: 2026-07-02 - Image Template Placement Revision ### Phase 22: Image Template Placement and In-Module Configuration - **Status:** complete - User feedback: - Templates should be placed on the right side of the generation console. - Template configuration should not live in global settings. - Users should enter template configuration from the image generation module itself. - Actions taken: - Removed the template tab, template state, and template form from `components/settings-panel.tsx`. - Moved template selection into a left-side rail inside the image generation panel. - Added an in-module add-template modal with preview URL, preset prompt, and generation parameter fields. - Kept the account-scoped `/api/image-templates` data model/API unchanged. - Added responsive layout so the template rail stacks above the prompt editor on smaller screens. - Verified that selecting a template applies its prompt, size, and force-single setting into the generation console. ## Test Results - 2026-07-02 Image Template Placement Revision | Test | Input | Expected | Actual | Status | |------|-------|----------|--------|--------| | Focused template tests | `npm test -- image-templates.test.ts` | Template tests pass | 1 file / 3 tests passed | pass | | Full unit tests | `npm test` | All tests pass | 17 files / 53 tests passed | pass | | Production build | `npm run build` | Build succeeds | Build succeeded | pass | | Browser UI smoke | Headless Chrome `/create` on temporary auth-disabled dev server | Create has a left template rail; thumbnail/name cards render; template apply works; add-template modal opens; mobile has no horizontal overflow | `heading: 模板选择`, `railLeft < mainLeft`, `cardHasOnlyName: true`, `promptApplied: true`, `mobileOverflow: false` | pass | | Normal local server | `npm run dev -- --hostname 127.0.0.1 --port 3001` | Server ready with normal auth behavior | `/create` redirects to `/auth/login?next=%2Fcreate` | pass | ## Session: 2026-05-28 - EvoLink Image Engine Settings ### Phase 1: Trace Current Settings and Provider Flow - **Status:** complete - Actions taken: - Restored planning context with the planning-with-files skill. - Inspected settings persistence in `lib/server/app-settings.ts`. - Inspected settings API and settings panel rendering. - Re-read image generation service and dynamic image polling route. - Findings: - Settings are persisted into root `.env.local` and applied to `process.env` immediately after saving. - Settings groups currently cover Jimeng/Volcengine Visual, Seedance, and OSS. - Image jobs already store `provider`, `providerTaskId`, request/response payloads, and import completed remote image URLs as assets. - Current provider type only allows `volcengine-visual`, `seedance`, and `mock`. ### Phase 2: Add EvoLink Provider Adapter - **Status:** complete - Actions taken: - Added `lib/evolink/image-client.ts` with image engine selection, EvoLink settings, submit/query calls, payload construction, task id extraction, status mapping, and result URL extraction. - Added `evolink` to the `GenerationJob.provider` union. - Updated image job submission to route `image.generate` and `image.inpaint` through EvoLink when `IMAGE_CREATION_ENGINE=evolink`. - Mapped existing image size presets to EvoLink ratio-style `size` values so `resolution` can control output tier. - Kept `image.upscale` on Jimeng even when EvoLink is selected. - Added EvoLink polling support inside the existing image sync flow. ### Phase 3: Expose Engine Settings - **Status:** complete - Actions taken: - Added settings fields for `IMAGE_CREATION_ENGINE` and EvoLink API/model options. - Updated settings status cards to show the active image engine and effective image interface mode. - Added EvoLink provider labeling in the asset manager. - Updated health response, README, and `.env.example`. ### Phase 4: Verification - **Status:** complete - Actions taken: - Added focused tests for EvoLink payload mapping, inpaint mask mapping, task id extraction, status mapping, and result URL extraction. - Ran `npm test`: 5 files passed, 12 tests passed. - Ran `npm run build`: production build completed successfully. - Started the local dev server and checked `/settings` in the in-app browser. - Confirmed the settings page opens on the new engine tab, the EvoLink tab renders credential/model fields, and the status tab shows active image engine and image interface state. - Stopped the local dev server after verification. ## Test Results - EvoLink Image Engine Settings | Test | Input | Expected | Actual | Status | |------|-------|----------|--------|--------| | Unit tests | `npm test` | All tests pass | 5 files / 12 tests passed | pass | | Production build | `npm run build` | Build succeeds | Build succeeded | pass | | Settings UI | Browser `/settings` | Engine/EvoLink/status tabs render | Confirmed visible content | pass | ## Error Log - EvoLink Image Engine Settings | Timestamp | Error | Attempt | Resolution | |-----------|-------|---------|------------| | 2026-05-28 20:58 CST | Browser wait for `EvoLink API Key` hit a transient detached element after tab click | 1 | Re-read the page body and confirmed the EvoLink tab rendered correctly | | 2026-05-28 21:03 CST | `npm start` failed because `.next` did not contain a production build after dev-server use | 1 | Added `prestart: next build` and made `npm start` bind to `127.0.0.1:3000` | ### Startup Fix - **Status:** complete - Actions taken: - Reproduced `npm run dev` and confirmed the dev server reaches `Ready`. - Reproduced `npm start` failure: `next start` could not find a production build in `.next`. - Updated `package.json` so `npm start` automatically runs `next build` first and then starts on `127.0.0.1:3000`. - Updated README startup notes. - Verified `npm start` now builds and starts successfully. - Verified `GET /api/health` returns `ok: true` and `/settings` returns HTTP 200. ### Status-Based Engine Management - **Status:** complete - Actions taken: - Replaced the standalone engine settings tab with per-capability engine assignments in the settings status tab. - Added `IMAGE_GENERATE_ENGINE` and `IMAGE_INPAINT_ENGINE` as configurable engine keys. - Kept legacy `IMAGE_CREATION_ENGINE` / `IMAGE_PROVIDER` as fallback defaults for backward compatibility. - Updated generation routing and health output to report/use per-capability engines. - Updated README and `.env.example`. - Ran `npm test`: 5 files / 12 tests passed. - Ran `npm run build`: production build succeeded. - Restarted production server after a rebuild and verified `/settings` renders status-based engine controls. ### Status Page Cleanup - **Status:** complete - Actions taken: - Simplified the status tab after user feedback that the page felt messy. - Replaced stacked per-capability cards with one compact table: function, engine, interface, model/key. - Kept API status as four compact badges above the table. - Ran `npm test`: 5 files / 12 tests passed. - Ran `npm run build`: production build succeeded. - Verified `/settings` visually on a temporary dev server at `127.0.0.1:3001`, then stopped that server. ## Error Log | Timestamp | Error | Attempt | Resolution | |-----------|-------|---------|------------| | 2026-05-28 10:26 CST | `git status --short` failed: not a Git repository | 1 | Continue as a plain project folder and inspect files directly | | 2026-05-28 10:27 CST | zsh `no matches found` for unquoted `[id]` route paths | 1 | Quote bracketed paths in future commands | | 2026-05-28 10:31 CST | Plain `curl` calls to localhost hit a local proxy and returned 502/empty output | 1 | Used `curl --noproxy '*'` and verification passed | ## Session: 2026-05-29 - UI/UX, Seedance Limits, and Branding ### Full Product UI/UX Polish - **Status:** complete - Actions taken: - Added `gsap` as the only new frontend dependency for motion. - Added `lib/ui/motion.ts` with scoped reveal, crossfade, modal enter/exit, feedback pulse, cleanup, and `prefers-reduced-motion` handling. - Reworked global UI tokens and responsive CSS in `app/globals.css`. - Improved global shell accessibility with skip link, active nav state, focus styling, and GSAP reveal. - Polished `/create`, `/assets`, `/settings`, and image editing screens while preserving backend API and route semantics. - Removed visible English module labels, title helper descriptions, and right-side module badges after user feedback. - Reduced topbar height and tightened mobile controls to avoid horizontal scrolling. - Files created/modified: - `package.json` - `package-lock.json` - `app/globals.css` - `components/app-shell.tsx` - `components/create-studio.tsx` - `components/asset-manager.tsx` - `components/image-editor.tsx` - `components/settings-panel.tsx` - `lib/ui/motion.ts` ### Seedance API Limits Alignment - **Status:** complete - Actions taken: - Checked official Volcengine/Ark Seedance docs for video generation parameter restrictions. - Confirmed Seedance 2.0 `duration` supports integer seconds from `4` to `15`, or `-1` for model auto duration. - Changed the video duration UI from a numeric input to a fixed dropdown of `4 秒` through `15 秒`. - Added video settings normalization for duration, ratio, and resolution in `lib/video-settings.ts`. - Added support for `21:9` and `adaptive` ratios. - Added model-aware resolution normalization so Seedance 2.0 fast falls back away from unsupported `1080p`. - Updated Seedance client and video service payload normalization before task creation. - Updated `.env.example`, README, and tests. - Files created/modified: - `lib/video-settings.ts` - `components/create-studio.tsx` - `lib/seedance/client.ts` - `lib/server/video-generation-service.ts` - `tests/video-settings.test.ts` - `.env.example` - `README.md` ### Product Branding and Logo - **Status:** complete - Actions taken: - Located logo assets under `/Users/inmanx/Documents/icon/logo`. - Renamed the product to `智念AIGC平台` across app metadata, topbar, package metadata, README, and app info output. - Initially used the white transparent logo with a dark frame, then revised after user feedback that the logo was hard to see and the frame changed the brand feel. - Generated a cropped transparent PNG from the black/blue logo variant and saved it as `public/logo/zhinian-logo.png`. - Removed topbar logo border, background, and shadow. - Desktop now shows logo plus `智念AIGC平台`; mobile hides the adjacent title and keeps the logo visible. - Files created/modified: - `public/logo/zhinian-logo.png` - `components/app-shell.tsx` - `app/globals.css` - `app/layout.tsx` - `package.json` - `README.md` - `scripts/print-app-info.mjs` - `lib/server/app-settings.ts` - `lib/server/generation-service.ts` ## Test Results - 2026-05-29 Product Polish | Test | Input | Expected | Actual | Status | |------|-------|----------|--------|--------| | Unit tests | `npm test` | All tests pass | 6 files / 16 tests passed | pass | | Production build | `npm run build` | Build succeeds | Build succeeded | pass | | Health check | `npm run health` and `/api/health` | `ok: true` | `ok: true` | pass | | Seedance video UI | Browser `/create?mode=video` | Duration choices are `4` to `15` seconds | Confirmed | pass | | Responsive overflow | Browser widths `375`, `768`, `1024`, `1440` | No horizontal overflow | Confirmed | pass | | Logo visibility | Browser `/create` | Logo loads without frame/background | Confirmed border `0px`, background `none`, shadow `none` | pass | ## Error Log - 2026-05-29 Product Polish | Timestamp | Error | Attempt | Resolution | |-----------|-------|---------|------------| | 2026-05-29 | Seedance build failed because resolution tuple typing narrowed fast-model choices too far | 1 | Switched resolution membership checks to readonly string arrays and build passed | | 2026-05-29 | Browser REPL variable names collided across verification cells | 1 | Reused or renamed persistent variables instead of redeclaring constants | | 2026-05-29 | White logo required a dark frame on the light topbar and looked off-brand | 1 | Switched to black/blue logo, generated a transparent cropped asset, and removed frame styling | ## Session: 2026-05-29 - Account Login and SSO Protection ### Phase 13: Account Login and SSO Protection - **Status:** in_progress - Actions taken: - Restored existing planning context and started a new Phase 13 for account login. - Read the provided SSO integration guide. - Confirmed the app currently has no login middleware/session helper and uses a fixed `demo-merchant` owner for first-party data. - Started tracing routes and data access boundaries. - Inspected first-party asset, generation, settings, health, upload, and file-serving routes. - Confirmed public API v1 and worker routes use separate token mechanisms and should be preserved. - Added auth config parsing, signed session cookies, OAuth2 authorize/callback/logout routes, JWT/JWKS verification, and current-user helpers. - Added login page and topbar login/user/logout state. - Added middleware protection for Web pages, first-party APIs, and local file-serving routes. - Threaded authenticated owner IDs through first-party asset and generation routes. - Added local file ownership checks through `storagePath`. - Added SSO settings fields, health/settings status, env examples, README docs, deployment notes, and focused auth tests. - Ran `npm test`: 8 files / 25 tests passed. - Ran `npm run build`: production build passed with middleware and auth routes included. - Browser-checked `/create` and `/auth/login` at desktop and 390px widths: no horizontal overflow, login config-missing state renders correctly. - Verified forced-auth middleware behavior with a temporary dev server: `/create` redirects to `/auth/login`, first-party `/api/assets` returns 503 when auth is missing config, and `/api/v1/openapi.json` remains public. - **Status:** complete ## Test Results - Account Login and SSO Protection | Test | Input | Expected | Actual | Status | |------|-------|----------|--------|--------| | Unit tests | `npm test` | All tests pass | 8 files / 25 tests passed | pass | | Production build | `npm run build` | Build succeeds | Build succeeded | pass | | Browser layout | `/create`, `/auth/login`, 1280px and 390px | No horizontal overflow | Confirmed | pass | | Middleware redirect | `GET /create` with `ZHINIAN_AUTH_REQUIRED=1` and missing auth config | Redirect to login | 307 to `/auth/login?next=%2Fcreate&error=auth_not_configured` | pass | | First-party API guard | `GET /api/assets` with required auth and missing config | 503 JSON | `{"error":"认证配置不完整。"}` | pass | | Public API preservation | `GET /api/v1/openapi.json` with required auth and missing config | 200 | 200 OK | pass | ## Error Log - Account Login and SSO Protection | Timestamp | Error | Attempt | Resolution | |-----------|-------|---------|------------| | 2026-05-29 | zsh expanded unquoted `[id]` dynamic route paths again while reading route files | 1 | Re-ran the reads with single-quoted route paths | | 2026-05-29 | `npm run build` failed because DOM `JsonWebKey` type does not include JWKS `kid` | 1 | Switched verifier typing to Node crypto `JsonWebKey` with a local `kid` extension | ## Session: 2026-05-29 - Password Captcha Login ### Phase 14: Password Captcha Login - **Status:** complete - Actions taken: - Safely inspected the provided captcha and password grant response shape without printing tokens. - Added `components/auth-login-panel.tsx` for account/password/captcha login on `/auth/login`. - Added `/api/auth/captcha` to proxy image captcha requests to the auth service. - Added `/api/auth/password` to call password grant server-side, verify the returned JWT, and set the same signed session cookie. - Kept the original OAuth Authorization Code link as a secondary login option. - Updated README, Chinese README, and deployment docs. - Ran `npm test`: 8 files / 25 tests passed. - Ran `npm run build`: production build passed. - Restarted the dev server on `127.0.0.1:3001`. - Browser-tested password captcha login with the user-provided test account; login reached `/create`, the topbar showed the authenticated username, and logout returned to `/auth/login?loggedOut=1`. ## Test Results - Password Captcha Login | Test | Input | Expected | Actual | Status | |------|-------|----------|--------|--------| | Captcha endpoint | `${AUTH_BASE}/code/image?randomStr=...` | Image response | PNG 100x40 | pass | | Password grant | Provided password grant sample | JWT token response | 200 with access/refresh tokens, sanitized in logs | pass | | Local password login API | `POST /api/auth/password` | Signed session cookie | 200 and `zhinian_session` set | pass | | Browser login | `/auth/login` form | Redirect to `/create` | `/create` rendered with authenticated username in topbar | pass | | Logout | Click topbar logout | Return to login | `/auth/login?loggedOut=1` | pass | ## Session: 2026-05-29 - Server One-Command Deployment Support ### Docker and Script Deployment - **Status:** complete - Actions taken: - Added `.dockerignore` to keep secrets, local runtime data, Next build cache, dependencies, and bulky legacy media out of Docker build context. - Added a multi-stage `Dockerfile` using Node 22 Alpine, `npm ci`, `next build`, production dependency pruning, and `next start` on `0.0.0.0`. - Added `docker-compose.yml` with `zhinian-aigc` service, `.env.local` env file, `APP_PORT` host mapping, persistent `./.runtime:/app/.runtime`, restart policy, and HTTP healthcheck. - Added `scripts/setup.sh` for local preparation. - Added `scripts/deploy.sh` for server deployment with Docker Compose detection, `.env.local` creation, runtime directory creation, image build, and background startup. - Added `start:server` npm script for non-Docker Node/PM2 deployment. - Updated `.env.example` with `APP_PORT`. - Expanded `README.zh-CN.md` with server deployment, Docker commands, Node deployment fallback, and backup notes. - Added a short deployment entry to `README.md`. - Files created/modified: - `.dockerignore` - `Dockerfile` - `docker-compose.yml` - `scripts/setup.sh` - `scripts/deploy.sh` - `.env.example` - `package.json` - `README.md` - `README.zh-CN.md` ## Test Results - Server Deployment Support | Test | Input | Expected | Actual | Status | |------|-------|----------|--------|--------| | Shell syntax | `bash -n scripts/setup.sh scripts/deploy.sh` | No syntax errors | Passed | pass | | Unit tests | `npm test` | All tests pass | 6 files / 16 tests passed | pass | | Production build | `npm run build` | Build succeeds | Build succeeded | pass | | Local health | `curl --noproxy '*' /api/health` | `ok: true` | `ok: true` | pass | | Docker CLI availability | `docker --version` | Docker version if installed | No Docker CLI output in current environment | not run | ## Session: 2026-05-29 - Deployable Handoff and Integration Surface ### Implementation - **Status:** complete - Actions taken: - Added `docs/DEPLOYMENT.md` for operations deployment, environment variables, health checks, runtime persistence, reverse proxy guidance, and validation checklist. - Added `docs/API.md` for partner authentication, task lifecycle, job creation, asset upload/register, asset query/download, idempotency, webhook signing, and error handling. - Linked deployment/API docs and the OpenAPI route from both README files. - Expanded `/api/v1/openapi.json` to document capabilities, assets, asset download, jobs, job detail, cancel, request schemas, response schemas, and API key auth. - Added authenticated `/api/v1/assets/:id` and `/api/v1/assets/:id/download` endpoints. - Restricted public asset listing/detail/download to assets visible to the authenticated API client. - Added API client tags to uploaded assets and API-generated output assets so long-lived integrations can query/download their own results. - Added a deploy-script health check and printed API documentation/OpenAPI hints after startup. ### Verification - **Status:** complete - Results: - `npm test`: 7 files / 21 tests passed. - `npm run build`: production build succeeded and included `/api/v1/assets/:id`, `/api/v1/assets/:id/download`, and `/api/v1/openapi.json`. - Local HTTP smoke test with a temporary API key returned `/api/v1/capabilities` and expanded OpenAPI paths. - Local HTTP smoke test uploaded a PNG through `/api/v1/assets`, fetched `/api/v1/assets/:id`, and downloaded matching binary bytes from `/api/v1/assets/:id/download`. - Mock-provider task flow created a queued job through `/api/v1/jobs`, Worker processed it to `succeeded`, generated output asset carried the API client tag, and download returned an attachment response. ## Session: 2026-05-29 - Engine-Aware Image Tuning ### Implementation - **Status:** complete - Actions taken: - Replaced the image generation text-influence range slider with select options. - Added create-page engine detection from `/api/health`. - For Jimeng image generation, the UI now shows `文本影响` options: `创意 35`, `均衡 50`, `贴合 70`, `严格 85`, and submits `scale`. - For EvoLink image generation, the UI now shows `生成质量` options: `快速`, `标准`, `精细`, and submits `quality`. - Added per-request EvoLink `quality` support in the payload builder. - Updated public API request typing, OpenAPI schema, API docs, and focused tests. ### Verification - **Status:** complete - Results: - `npm test`: 7 files / 22 tests passed. - `npm run build`: production build succeeded. - Agent-browser snapshot on `/create` showed current EvoLink mode rendering `生成质量` with `快速 / 标准 / 精细`. - Desktop and mobile screenshots showed the create-page controls fitting cleanly. - Browser page errors list was empty. ## Session: 2026-05-29 - Standalone Login Page Polish ### Implementation - **Status:** complete - Actions taken: - Updated the app shell so `/auth/*` pages render without the shared topbar and skip link. - Reworked `/auth/login` into a standalone branded surface with logo, platform name, and account/password/captcha login box. - Removed the visible `统一认证中心` login action from the login page. - Kept login motion on the existing GSAP helper layer for scoped reveal and feedback animation. ### Verification - **Status:** complete - Results: - In-app browser mobile-width check confirmed no topbar, no SSO link, logo/platform name present, login panel present, and no horizontal overflow. - Browser viewport checks at 1280x800 and 390x844 confirmed the same layout invariants. - `npm test`: 8 files / 25 tests passed. - `npm run build`: production build succeeded and included `/auth/login`. - After restarting the dev server on `127.0.0.1:3001`, the login page still rendered without the topbar or SSO entry. - Earlier auth verification for this session passed form login, redirect to `/create`, and logout back to `/auth/login`. ## Error Log - Server Deployment Support | Timestamp | Error | Attempt | Resolution | |-----------|-------|---------|------------| | 2026-05-29 | First `scripts/deploy.sh` draft had a shell quoting error while stripping quotes from `APP_PORT` | 1 | Simplified quote stripping and verified with `bash -n` | | 2026-05-29 | Docker CLI is unavailable in the current local environment | 1 | Documented that Docker build should be validated on the target server; local Next build/test/health passed | ## 5-Question Reboot Check | Question | Answer | |----------|--------| | Where am I? | Complete | | Where am I going? | No remaining planned phases | | What's the goal? | Understand and explain the whole project | | What have I learned? | This is an extracted standalone Next.js runtime for 智念创作助手, with local JSON persistence and optional Seedance/OSS integrations | | What have I done? | Completed repository survey, architecture mapping, and runtime verification | ## Session: 2026-05-29 - Task Management and Public API v1 ### Planning and Scope - **Status:** in progress - Actions taken: - Confirmed the current app already has `GenerationJob`, image/video submit routes, polling routes, Supabase/local JSON persistence, and Docker Compose deployment support. - Accepted the user decision that multi-task support should be implemented as task management logic, not a separate message queue system. - Set the implementation path: API Key auth, `/api/v1` public routes, task-state/locking fields, provider execution via Worker, and a Docker Compose worker service. ### Implementation - **Status:** complete - Actions taken: - Extended `GenerationJob` with external client, idempotency, priority, retry, lock, timing, and webhook fields. - Updated local JSON and Supabase mappings, plus `supabase/schema.sql` with queue indexes and `claim_generation_jobs`. - Changed image/video submit services so creation enqueues jobs only; provider dispatch and polling now happen through `advanceImageJob` / `advanceVideoJob`. - Added task manager, API Key auth, public idempotency helper, webhook signing/delivery, internal Worker tick route, and `scripts/worker.mjs`. - Added `/api/v1/capabilities`, `/api/v1/assets`, `/api/v1/jobs`, `/api/v1/jobs/:id`, `/api/v1/jobs/:id/cancel`, and `/api/v1/openapi.json`. - Added `npm run worker`, `npm run worker:once`, and a `zhinian-worker` Docker Compose service. - Updated README files and `.env.example` with API/Worker/Webhook configuration. ### Verification - **Status:** complete - Results: - `npm test`: 7 files / 21 tests passed. - `npm run build`: production build succeeded. - `npm run health`: returned `ok: true`. - Local `/api/v1/capabilities` with API Key returned capabilities. - Local `/api/v1/jobs` created a queued job with idempotency key. - `npm run worker:once` claimed the queued job and processed it to `succeeded` in mock mode. - Docker CLI is unavailable in this local environment, so `docker compose up --build` still needs server-side validation. ## Session: 2026-06-09 - Repository Sync and Local Startup Status ### Repository Sync - **Status:** complete - Actions taken: - Confirmed the current branch is `main` tracking `origin/main`. - Confirmed the remote is `https://git.nianxx.cn/wangxuming/NianAIGC.git`. - Overwrote local changes with `git fetch origin --prune`, `git reset --hard origin/main`, and `git clean -fd`. - Removed local untracked/stale files during clean, including prior auth docs/client/test additions and stale app route folders. - Verified the workspace is clean at `d98e58a docs: update public api docs`. ### Local Startup Verification - **Status:** complete - Actions taken: - Confirmed the project uses npm via `package-lock.json` and runs Next.js with `npm run dev`. - Confirmed local Node version `v22.22.1`. - Found existing local listeners on common ports: `3000` returned `502`, `3001` was an old stuck Next dev process, and `3002` was occupied. - Started the current project successfully with `npm run dev -- --hostname 127.0.0.1 --port 3003`. - Next.js reported Ready in 2.9 seconds on `http://127.0.0.1:3003`. - Verified `GET /` returned `307 Temporary Redirect` to `/auth/login?next=%2F`, which matches the authenticated app flow. - Rechecked current status on 2026-06-09: Git is still clean at `d98e58a`, and no `next dev` / `next-server` process is currently listening on `3003`. ## Test Results - 2026-06-09 Repository Sync and Startup | Test | Input | Expected | Actual | Status | |------|-------|----------|--------|--------| | Git status | `git status --short --branch` | Clean `main...origin/main` | Clean | pass | | Latest commit | `git log -1 --oneline` | Remote HEAD commit | `d98e58a docs: update public api docs` | pass | | Dev startup | `npm run dev -- --hostname 127.0.0.1 --port 3003` | Next Ready | Ready in 2.9s | pass | | HTTP smoke | `curl --noproxy '*' -I http://127.0.0.1:3003` | App responds | `307` redirect to login | pass | | Current runtime status | `lsof -nP -iTCP:3003 -sTCP:LISTEN` | Listener if server is running | No listener on 2026-06-09 | info | ## Error Log - 2026-06-09 Repository Sync and Startup | Timestamp | Error | Attempt | Resolution | |-----------|-------|---------|------------| | 2026-06-08 | Port `3000` already had a Next server returning `502` | 1 | Avoided that process and tried an alternate port | | 2026-06-08 | Port `3001` had an old stuck Next dev process with requests timing out | 1 | Avoided that process and selected a free port | | 2026-06-08 | Background `nohup npm run dev` attempt on `3003` exited without useful log output | 1 | Ran the dev command in the foreground and confirmed Next reached Ready | ## Session: 2026-07-01 - Account ID Data Partitioning ### Discovery - **Status:** complete - Actions taken: - Restored planning context with the planning-with-files skill. - Traced `ownerId`, `externalClientId`, first-party auth, public API auth, jobs, assets, and storage flows. - Confirmed first-party UI data is already scoped to authenticated users. - Found that public API jobs/assets are still stored under `DEFAULT_OWNER_ID` and only filtered afterward by `externalClientId` or `api-client:` tags. - Next step: - Add a stable API account owner id helper and use it for public API job, asset, idempotency, list, detail, cancel, and download paths. ### Implementation - **Status:** complete - Actions taken: - Added `publicApiOwnerId()` to derive stable owner ids from API account IDs as `api:`. - Routed public job creation and idempotency lookup through the derived account owner. - Routed public job list/detail/cancel checks through the account owner. - Routed public asset upload/register/list/detail/download checks through the account owner. - Updated OpenAPI, `.env.example`, README, deployment docs, and API docs to describe account ID partitioning. ### Verification - **Status:** complete - Results: - `npm test -- tests/task-management.test.ts`: 1 file / 7 tests passed. - `npm test`: 14 files / 34 tests passed. - `npm run build`: production build passed after the public API owner changes. - `npm run build`: production build passed again after adding `ownerId` to the OpenAPI job schema. ### Error Log | Timestamp | Error | Attempt | Resolution | |-----------|-------|---------|------------| | 2026-07-01 | zsh expanded unquoted `[id]` route paths while reading public API files | 1 | Quoted the dynamic route paths and re-read them successfully | ## Session: 2026-07-01 - Password Login Captcha Investigation ### Discovery - **Status:** complete - Actions taken: - Fetched `origin` without changing the dirty workspace and confirmed `origin/main` matches local `HEAD` at `d98e58a`. - Inspected auth-related commits `ce358df` and `288e31d`. - Confirmed current login UI has no captcha field and current password route does not require captcha. - Checked local auth configuration without printing secrets: auth base is `https://onefeel.brother7.cn/ingress/auth`, client id is `customPC`. - Confirmed `/auth/login` served by the running dev server contains no captcha controls. - Sent a fake-credential probe to local `/api/auth/password` and a direct fake-credential probe to the configured auth center token endpoint; both returned `验证码不能为空`. - Conclusion: - The captcha error is currently produced by the configured authentication center instance, not by this app's current validation or request-building code. ### SSO Guide Alignment - **Status:** complete - Actions taken: - Read `/Users/inmanx/Desktop/sso-integration-guide.md`. - Confirmed the guide defaults external clients to `app/app` and says captcha skipping is controlled by auth `security.ignore-clients`. - Probed the configured auth center with dummy credentials: `customPC` returned `验证码不能为空`; `app/app` returned `用户名或密码错误`. - Updated tracked defaults/docs to use `app/app` with AES-CFB password encryption key `thanks,pig4cloud`. - Updated local ignored `.env.local` to the same auth client settings. - Restarted the dev server on `127.0.0.1:3000`. - Verification: - `npm test -- tests/auth-password-route.test.ts tests/auth-login-panel.test.ts tests/auth-session.test.ts`: 3 files / 6 tests passed. - `npm test`: 14 files / 34 tests passed. - `npm run build`: production build passed. - Local dummy login now returns `用户名或密码错误`, not `验证码不能为空`. ## Session: 2026-07-01 - Internal RBAC and Account Management ### Discovery - **Status:** complete - Actions taken: - Tried to read `/Users/inmanx/Desktop/organization-external-api.md`; file is missing. - Listed Desktop and searched likely names under `/Users/inmanx`; no organization external API markdown file was found. - Read the updated `/Users/inmanx/Desktop/organization-external-api(1).md`. - Inspected middleware, app shell navigation, auth session, current-user helper, logs/settings routes, and admin-like pages. - Added authority-based admin helpers and local-dev admin fallback. - Hid admin navigation for ordinary users and protected admin pages/APIs through middleware plus server-side route guards. - Added `/accounts`, `/api/admin/accounts`, and `/api/admin/accounts/password`. - Wired organization member list/edit/status/delete through `basic-capability-services-biz`. - Wired enterprise user creation and password reset through `hotel-staff-server-biz` admin endpoints from the updated guide. - Added settings/env/docs for organization service and staff user service configuration. - Findings: - JWT `authorities` are already persisted in the signed session and can drive admin/ordinary-user access. - Ordinary/admin segmentation needs both UI hiding and server-side enforcement. - The updated organization guide adds enterprise user APIs: `/adminPcUser/createPlatformUser`, `/adminPcUser/getPlatformUserByPhone`, `/adminPcUser/resetPlatformUserPassword`, and `/adminOrganization/organizationMember/addOrganizationMemberAndCreatePlatformUser`. - Enterprise user APIs require the calling token to have administrator role `1`. - Verification: - `npm test`: 16 files / 40 tests passed. - `npm run build`: production build passed. - Restarted local dev server on `http://127.0.0.1:3000`. - Smoke checks: `/api/health` returned `ok: true`; unauthenticated `/accounts` redirects to login; unauthenticated `/api/admin/accounts` returns `请先登录。`. - Corrected the default admin username to `ceshiop` through `ZHINIAN_ADMIN_USERS`, with tests covering default and override behavior. - Re-ran `npm test`: 16 files / 42 tests passed. - Updated organization/staff API forwarding to use the current logged-in access token by default, with `ZHINIAN_ORG_API_TOKEN` and `ZHINIAN_STAFF_API_TOKEN` kept only as fallback tokens. - Re-ran `npm test`: 16 files / 44 tests passed. - Re-ran `npm run build`: production build passed after stopping the dev server, then restarted local dev on `http://127.0.0.1:3000`. ## Session: 2026-07-02 - Account Member List Route Compatibility ### Discovery - **Status:** complete - Actions taken: - Read `/tmp/zhinian-dev-server.log` and `.runtime/logs/server-events.jsonl`. - Confirmed `/api/admin/accounts?pageNum=1&pageSize=10` was returning 404 because upstream returned `No static resource organizationMember/organizationMemberList`. - Confirmed unauthenticated gateway probes are not enough to validate business route existence because even unknown paths are intercepted as token errors before controller routing. ### Fix - **Status:** complete - Actions taken: - Added organization path override support, including `ZHINIAN_ORG_MEMBER_LIST_PATH`. - Changed `/api/admin/accounts` to degrade missing organization/member list routes into warnings and empty fallback data instead of returning 404. - Kept the default organization ID fallback so configured `ZHINIAN_ORG_ID` can still drive the account page when organization list routing is unavailable. - Updated the account manager UI to show the warning and disable member search filters while member query routing is unavailable. - Updated `.env.example`, README files, and deployment docs with the unified `hotelStaff` base URL and member-list override note. - Verification: - `npm test -- tests/organization-client.test.ts`: 1 file / 7 tests passed. - `npm test -- tests/auth-session.test.ts tests/auth-permissions.test.ts`: 2 files / 9 tests passed. - `npm run build`: production build passed. - Restarted local dev server on `http://127.0.0.1:3000`. - Unauthenticated `/api/admin/accounts` returns `401 请先登录。`; server logs show logged-in `/api/admin/accounts` requests now returning 200 instead of 404. - `npm test`: 16 files / 46 tests passed. ### Updated Guide Alignment - **Status:** complete - Actions taken: - Read `/Users/inmanx/Desktop/organization-external-api(2).md`. - Confirmed member pagination is now externally exposed through `hotelStaff` at `/adminOrganization/organizationMember/organizationMemberList`. - Changed the default member-list path from the basic-service internal `/organizationMember/organizationMemberList` to the `hotelStaff` proxy path. - Kept `from: Y` only when `ZHINIAN_ORG_MEMBER_LIST_PATH` is explicitly pointed at the basic-service internal `/organizationMember/*` path. - Updated README, `.env.example`, deployment docs, and organization-client tests. - Verified `.env.local` does not override `ZHINIAN_ORG_MEMBER_LIST_PATH`, so the new default proxy path is active locally. - Verification: - `npm test -- tests/organization-client.test.ts tests/auth-permissions.test.ts`: 2 files / 13 tests passed. - `npm run build`: production build passed. - Restarted local dev server after clearing `.next`; `/api/health` returned 200. ### Upstream Permission Degradation - **Status:** complete - Actions taken: - Confirmed the new `hotelStaff` member-list proxy no longer fails as a static-resource path miss; it now reaches upstream authorization and returns `仅管理员角色允许调用` for the current token. - Added `isOrganizationPermissionDenied()` so the organization client can distinguish upstream administrator-role denial from route-not-found errors. - Changed `/api/admin/accounts` to degrade only the member-list permission denial into a warning and empty page result instead of returning 502 for the whole accounts page. - Updated the account manager warning and empty-state copy to explain that the current app admin is not yet authorized as upstream `hotelStaff` administrator role `1`. - Verification: - `npm test -- tests/organization-client.test.ts tests/auth-permissions.test.ts`: 2 files / 14 tests passed. - `npm run build`: production build passed. - Restarted local dev server on `http://127.0.0.1:3000` after clearing `.next`; `/api/health` returned 200. ## Session: 2026-07-02 - Large Auth Session Cookie Compatibility ### Login Loop Fix - **Status:** complete - Actions taken: - Read the dev server log and confirmed the changed account hit `/api/auth/password` with HTTP 200 but was redirected back to `/auth/login?next=%2Fcreate`. - Added chunked cookie helpers to split and reassemble large signed auth session payloads. - Updated middleware and server-side current-user lookup to read chunked `zhinian_session` cookies. - Updated password login and OAuth callback to write chunked session cookies, and logout to clear all session chunks. - Added a focused test for large session cookie chunk reassembly. - Verification: - `npm test -- tests/auth-session.test.ts tests/auth-password-route.test.ts tests/auth-permissions.test.ts`: 3 files / 11 tests passed. - `npm run build`: production build passed. - Restarted local dev server on `http://127.0.0.1:3000` after clearing `.next`; `/api/health` returned 200. ## Session: 2026-07-02 - Organization ID Correction ### Local Account Management Config - **Status:** complete - Actions taken: - Corrected local `ZHINIAN_ORG_ID` for `ceshiop` from the previously supplied organization ID to `1964660690235990058`. - Restarted the local dev server on `http://127.0.0.1:3000` after clearing `.next` so the updated `.env.local` value is active. - Verification: - `/api/health` returned 200 after restart. ## Session: 2026-07-02 - Account Action Icon Clarity ### Account Table Actions - **Status:** complete - Actions taken: - Clarified the duplicate power icons in account row actions. - Changed the in-service status toggle to use `CirclePause` for "设为休假" and `UserCheck` for "设为在岗". - Changed "停用成员" to use `UserX` instead of another power icon. - Verification: - `npm run build`: production build passed. - Restarted local dev server on `http://127.0.0.1:3000`; `/api/health` returned 200. ## Session: 2026-07-02 - Left Image Template Rail ### Phase 24: Left Template Rail for Image Generation - **Status:** complete - User feedback: - Template selection should be a left vertical scroll rail. - The rail header should be `模板选择`. - A button with an icon should add templates under the header. - Template list items should show thumbnail plus name. - Clicking a template should show selected state and bring template parameters into the generation console on the right. - Actions taken: - Replaced the image-mode right template sidebar with a left-side vertical template rail on `/create`. - Added the `模板选择` heading, icon `添加模板` button, thumbnail/name-only template cards, and selected-card state. - Moved template creation into an in-module modal with effect preview URL, preset prompt, image size, force-single, category, description, and sort fields. - Kept selected template application wired to the right generation console, including prompt, size, and single-image setting. - Verification: - `npm test`: 17 files / 53 tests passed. - `npm run build`: production build passed. - Browser smoke with a temporary auth-disabled dev server confirmed desktop left-rail placement, thumbnail/name cards, add-template modal, selected state, parameter application, and mobile no-horizontal-overflow layout. - Temporary verification template was deleted; normal auth-enabled dev server is back on `http://127.0.0.1:3001`. ## Session: 2026-07-02 - Department Creation in Account Management ### Account Department API - **Status:** complete - Actions taken: - Confirmed `/Users/inmanx/Desktop/organization-external-api(2).md` documents department creation at `/organizationGroup/createOrganizationGroup`. - Added `createOrganizationGroup()` to the organization client. - Added admin route `/api/admin/accounts/groups` to create a department and reload the group list for the selected organization. - Added a `新建` button beside the department selector in the account member form; after creation it refreshes and selects the new department when the upstream list returns it. - Fixed an existing JSX closing issue in `components/create-studio.tsx` that blocked production build. - Verification: - `npm test -- tests/organization-client.test.ts tests/auth-permissions.test.ts`: 2 files / 15 tests passed. - `npm run build`: production build passed. - Restarted local dev server on `http://127.0.0.1:3000`; `/api/health` returned 200. ## Session: 2026-07-02 - UI Layout Stabilization ### Create Page Stopgap - **Status:** complete - Actions taken: - Reverted the unfinished image-template rail layout from a two-column split back to a stable single-column flow. - Kept the template controls available above the generation console while avoiding a narrow rail that could squeeze or break the editor UI. - Verification: - `npm run build`: production build passed. - Restarted local dev server on `http://127.0.0.1:3000`; `/api/health` returned 200. ## Session: 2026-07-02 - Independent Image Template Column ### Phase 25: Independent Template Column for Image Generation - **Status:** complete - User feedback: - Template selection should be an independent column, not merged inside the generation console frame. - Actions taken: - Split `/create` image mode into a two-panel layout: independent left `模板选择` column and right generation panel. - Kept the add-template modal and template application behavior unchanged. - Removed the template column from the generation panel DOM tree so the two panels are siblings. - Verification: - `npm test`: 17 files / 53 tests passed. - `npm run build`: production build passed. - Browser geometry checks at 1280px and 390px confirmed the template column is a separate `panel`, sits left of the generation panel on the same row, is not contained by the generation panel, and has no horizontal overflow. ## Session: 2026-07-02 - Generation Console Mode Switch Ownership ### Phase 26: Generation Console Owns Mode Switch - **Status:** complete - User feedback: - The template module should be the far-left independent module. - The top image/video filter belongs to the generation console, not the template module. - Actions taken: - Moved the image/video/edit mode switch from the global create-page area into the right generation panel. - Removed the global sticky/floating mode-switch styling so it reads as the generation panel's internal toolbar. - Preserved the far-left independent template module and existing template selection/application behavior. - Verification: - `npm test`: 17 files / 53 tests passed. - `npm run build`: production build passed. - Browser geometry checks at 1280px and 390px confirmed the template module is far left, the mode switch is inside the generation panel, not inside the template panel, and there is no horizontal overflow. ## Session: 2026-07-02 - Template Upload Placeholders ### Phase 27: Template Upload Placeholders - **Status:** complete - User feedback: - Template preview images should use the same click-upload logic as the project upload flow because OSS is already integrated. - Remove template category and remark fields, add an intro field. - Preset prompts should support `@图片1` placeholders; applying a template should show the user where images must be uploaded. - Actions taken: - Reused `/api/assets/upload` from the template editor preview uploader, so preview images go through the same authenticated asset/OSS storage path as workbench uploads. - Removed category from new template input and UI; changed the previous remark-style field to `简介`. - Added shared `@图片1` / `@图1` / `@视频1` / `@音频1` placeholder parsing and reused it in prompt assembly requirements. - Added generation-console upload placeholder cards for missing prompt tokens; clicking a placeholder uploads the expected material type and binds it to that exact token. - Preserved prompt/material labels after removal so template token references do not silently change. - Verification: - `npm test -- tests/image-templates.test.ts tests/prompt-assembler.test.ts`: 2 files / 7 tests passed. - `npm test`: 17 files / 54 tests passed. - `npm run build`: production build passed. - Browser smoke with a temporary auth-disabled dev server confirmed the add-template modal has no category/remark or URL field, has an image upload control and intro field, and applying a template with `@图片1` shows an image upload placeholder while disabling submit until it is filled. - Browser geometry checks at desktop and 390px confirmed the template module remains an independent far-left panel, the mode switch remains inside the generation panel, and there is no horizontal overflow. - Temporary verification template was deleted; normal auth-enabled dev server is running on `http://127.0.0.1:3001`. ## Session: 2026-07-02 - Add Template Modal UX Polish ### Phase 28: Add Template Modal UX Polish - **Status:** complete - Skill used: - `ui-ux-pro-max` design system search for a professional SaaS creative-workspace modal form. - Actions taken: - Reworked the add-template modal from a flat field grid into a preview-first editor with header, left preview pane, right form, and sticky-feeling bottom actions. - Kept the existing OSS-backed preview upload and template save logic unchanged. - Added parsed placeholder chips below the preset prompt so `@图片1` / `@图片2` requirements are visible while editing. - Tightened desktop and mobile modal sizing, scroll behavior, hover states, and action placement. - Verification: - `npm test -- tests/image-templates.test.ts tests/prompt-assembler.test.ts`: 2 files / 7 tests passed. - `npm run build`: production build passed. - Browser verification on temporary auth-disabled dev server confirmed desktop preview-left/form-right layout, bottom actions, placeholder chips, no horizontal overflow, and 390px preview-above-form responsive layout. - `npm test`: 17 files / 54 tests passed. - Normal auth-enabled dev server is running on `http://127.0.0.1:3001`. ## Session: 2026-07-02 - Template Engine-Specific Parameters ### Phase 29: Template Engine-Specific Parameters - **Status:** complete - User feedback: - Add-template configuration must choose a generation engine because Jimeng and Image2 use different parameters. - Actions taken: - Added `engine`, Jimeng `scale`, and Image2 `quality` to image template settings. - Added per-request image engine override through `/api/generations/image` and `submitImageJob()`, so template-selected engines affect the actual provider payload instead of only the UI. - Added `生图引擎` selection to the add-template modal with conditional `文本影响` or `生成质量` controls. - Added the current engine selector to the image generation console so applied template engine choices are visible. - Applying a template now sets prompt, size, single-image mode, generation engine, and the matching engine parameter in the right-side console. - Verification: - `npm test -- tests/image-templates.test.ts tests/task-management.test.ts tests/evolink-image-client.test.ts tests/jimeng-capabilities.test.ts`: 4 files / 19 tests passed. - `npm run build`: production build passed. - Browser verification on temporary auth-disabled dev server confirmed the modal defaults to the configured active engine, switching to Jimeng changes the parameter field to `文本影响`, switching/applying a Jimeng template sets the generation console to Jimeng and the 70-scale preset. - Temporary verification template was deleted. - `npm test`: 17 files / 55 tests passed. - Normal auth-enabled dev server is running on `http://127.0.0.1:3001`. ## Session: 2026-07-02 - Template Rail Editing and Placeholder Confirmation ### Phase 30: Template Rail Editing and Placeholder Confirmation - **Status:** complete - User feedback: - Bare `@图片` input should not keep absorbing later text as a material placeholder. - Existing templates need second-pass editing. - The template rail should be much wider, support image click-to-preview, text click-to-select, and a top-right edit action. - Actions taken: - Tightened material placeholder parsing so only numbered tokens such as `@图片1`, `@图2`, `@视频1`, and `@音频1` create upload requirements. - Added explicit placeholder insertion buttons in the template prompt editor; each inserts a complete numbered token with spacing. - Added edit mode to the in-module template modal and save-through-PATCH behavior for existing templates. - Reworked template cards into separate preview, select, and edit click regions, with a larger preview dialog. - Widened the desktop left template column to 260-320px and kept narrow viewport layout free of horizontal overflow. - Verification: - `npm test -- tests/image-templates.test.ts tests/prompt-assembler.test.ts`: 2 files / 7 tests passed. - `npm run build`: production build passed. - `npm test`: 17 files / 55 tests passed. - Browser verification on temporary auth-disabled dev server confirmed desktop rail width 320px, preview dialog, select/apply behavior, missing `@图片1` upload slot, edit modal, PATCH save, and placeholder insertion boundary where bare `@图片这种普通文字继续写` creates no chip until clicking the explicit placeholder button. - 390px viewport check confirmed no horizontal overflow and visible preview/select/edit actions. - Temporary verification template was deleted. - Normal auth-enabled dev server is running on `http://127.0.0.1:3001`; `/create` redirects to login and `/api/image-templates` returns 401 when unauthenticated. ## Session: 2026-07-02 - Confirmed Material Draft Slot ### Phase 31: Confirmed Material Draft Slot - **Status:** complete - User feedback: - Instead of letting `@` typing continue directly inside the prompt body, show a temporary typing slot after `@`; pressing Enter confirms it into the body with an independent UI style. - Actions taken: - Added a shared `material-draft` prompt helper for detecting single-character `@` input, normalizing image/video/audio placeholder names, and inserting confirmed tokens with text boundaries. - Added a temporary material slot UI to both the generation prompt editor and the template preset prompt editor. - Pressing `@` now opens the slot and removes the raw `@` from the prompt body until the user confirms. - Enter/option click confirms valid values such as `图片`, `图片1`, `视频`, and `音频1` into numbered tokens like `@图片1`; invalid long text stays in the temporary slot and does not create chips. - Confirmed prompt tokens continue to render through the existing prompt token overlay and template placeholder chips, while upload placeholder cards still appear from parsed numbered tokens. - Added narrow-viewport styles so the slot remains usable when the template column squeezes the generation panel. - Verification: - `npm test -- tests/material-draft.test.ts tests/image-templates.test.ts tests/prompt-assembler.test.ts`: 3 files / 10 tests passed. - `npm test`: 18 files / 58 tests passed. - `npm run build`: production build passed after the UI changes. - Browser verification on temporary auth-disabled dev server confirmed: typing `@` in the main prompt opens the temporary slot with an empty prompt body; typing `图片` and pressing Enter inserts `@图片1`, shows a token highlight, and creates the `待上传图片` slot. - Browser verification confirmed the template prompt slot rejects `图片这种普通文字` without creating chips, and confirms `视频` into `@视频1`. - 390px viewport check confirmed the slot does not create horizontal overflow. - Normal auth-enabled dev server is running on `http://127.0.0.1:3001`; `/create` redirects to login and `/api/image-templates` returns 401 when unauthenticated. ## Session: 2026-07-02 - Inline Floating Material Draft Slot ### Phase 32: Inline Floating Material Draft Slot - **Status:** complete - User feedback: - The temporary material slot should float directly inside the prompt input, and confirmed placeholders should show a different colored UI inside the input area. - Skill used: - `ui-ux-pro-max` design system and Next.js guidance for a clean SaaS prompt-editor interaction. - Actions taken: - Moved the material draft panel into the prompt editor surface for both the main generation prompt and template preset prompt. - Added the prompt token overlay to the template prompt editor so confirmed template placeholders are highlighted inside the textarea itself. - Kept confirmed unbound placeholders such as `@图片1` and `@视频1` visually highlighted while preserving the raw prompt string for parsing and API submission. - Verification: - `npm test -- tests/material-draft.test.ts tests/image-templates.test.ts tests/prompt-assembler.test.ts`: 3 files / 10 tests passed. - `npm test`: 18 files / 58 tests passed. - `npm run build`: production build passed. - Browser verification on temporary auth-disabled dev server confirmed the main prompt `@` draft panel stays inside the input, confirms `图片` to highlighted `@图片1`, and shows the missing upload slot. - Browser verification confirmed the template prompt `@` draft panel stays inside the input and confirms `视频` to highlighted `@视频1` plus the template placeholder chip. - Browser console had no errors and default viewport had no horizontal overflow. - Normal auth-enabled dev server is running on `http://127.0.0.1:3001`; `/create` redirects to login and `/api/image-templates` returns 401 when unauthenticated. ## Session: 2026-07-02 - Wider Template Rail and Explicit Select Button ### Phase 33: Wider Template Rail and Explicit Select Button - **Status:** complete - User feedback: - Continue widening the template selection rail by 1.5x. - Reference images in both `9:16` and `16:9` should be browseable. - Selecting a template should happen through a separate button click. - Actions taken: - Widened the image template rail from `260-320px` to `390-480px` on desktop and from `210-250px` to `315-375px` on tablet layouts. - Changed mobile image mode to stack the template module above the generation panel so previews can use the full viewport width without squeezing the prompt editor. - Changed template thumbnails to a `4:3` preview viewport with `object-fit: contain`, so vertical and horizontal reference images are visible without crop. - Replaced text-area selection on template cards with a dedicated `选择模板` / `已选择` button; preview clicks still open the large preview dialog and card text is static. - Kept the left template rail visible in both image and video generation modes so switching to video no longer makes `模板选择` disappear; selecting a template still switches the console back to image mode and applies that template. - Verification: - `npm test -- tests/image-templates.test.ts tests/material-draft.test.ts`: 2 files / 7 tests passed. - `npm run build`: production build passed. - Temporary auth-disabled dev server on `http://127.0.0.1:3004` verified desktop rail width `480px`, mobile rail width `366px`, no horizontal overflow, `object-fit: contain`, preview/text clicks did not apply a template, and the dedicated select button did apply the template. - Temporary auth-disabled `3004` server was stopped after verification; a normal auth-enabled dev server was then started on `http://127.0.0.1:3004`, and `/create` redirects to `/auth/login?next=%2Fcreate` as expected. The existing `3001` listener was left untouched. - After follow-up verification, temporary auth-disabled `3005` confirmed `/create?mode=image` and `/create?mode=video` both render one `.image-template-column` at `480px` with no horizontal overflow; edit modes remain focused on the image editor. ## Session: 2026-07-02 - Fixed Template Cards and Internal Rail Scroll ### Phase 34: Fixed Template Cards and Internal Rail Scroll - **Status:** complete - User feedback: - A single template card should have a fixed smaller size. - The whole template rail should match the height of the generation panel on the right. - Only the template item area should scroll; the `模板选择` header and `添加模板` button should stay fixed. - Actions taken: - Added a right-panel `ResizeObserver` sync so the left template rail receives `--template-column-height` from the live generation panel height. - Changed the template column to an internal grid with fixed header rows and a `minmax(0, 1fr)` scrolling template-list row. - Converted template cards to fixed `138px x 184px` items with an `88px` contained preview, compact copy, and a full-width explicit select button. - Changed the template list to a fixed-card grid with internal `overflow-y: auto`; the outer rail now uses `overflow: hidden`. - Verification: - Browser verification on temporary auth-disabled `3005` with 12 mock templates confirmed desktop rail height `651px` equals right panel `651px`, mobile rail height `694px` equals right panel `694px`, no horizontal overflow, fixed card size `138px x 184px`, and only `.image-template-rail-list` scrolls while header/button positions remain unchanged. - `npm test -- tests/image-templates.test.ts tests/material-draft.test.ts`: 2 files / 7 tests passed. - `npm run build`: production build passed. ## Session: 2026-07-02 - Full-Bleed Glass Template Cards ### Phase 35: Full-Bleed Glass Template Cards - **Status:** complete - User feedback: - Template cards should use the image across the full card. - Selected cards should have a stronger dimensional shadow. - Title, intro, and the select-template action should float at the bottom in a highly transparent frosted-glass card. - The zoom icon should be removed, while the edit icon stays at the top right. - Actions taken: - Removed the zoom icon from the template card DOM. - Changed the template preview button to cover the full card and changed rail-card images to `object-fit: cover`. - Reworked the title/description/select area into a bottom-positioned translucent glass overlay with blur, saturation, border, and shadow. - Strengthened hover and active shadows, with active cards lifting slightly more and showing a heavier layered shadow/ring. - Kept the edit button absolutely positioned in the top-right corner above the full-card image. - Verification: - Browser verification on temporary auth-disabled `3005` confirmed zoom icon count `0`, card remains fixed `138px x 184px`, preview covers the card, image object-fit is `cover`, card padding is `0`, the glass overlay uses `rgba(255,255,255,0.46)` plus `blur(14px)`, the edit button remains top-right, selected button reads `已选择`, and active shadow/transform are applied without horizontal overflow on desktop or mobile. - `npm test -- tests/image-templates.test.ts tests/material-draft.test.ts`: 2 files / 7 tests passed. - `npm run build`: production build passed. ## Session: 2026-07-02 - Template Toggle Cancel and No Intro Field ### Phase 36: Template Toggle Cancel and No Intro Field - **Status:** complete - User feedback: - Remove the intro field. - Move the edit icon into the frosted-glass overlay. - Clicking an already-selected template should cancel selection and clear the right-side imported parameters. - Actions taken: - Removed the template `简介` input from the add/edit template modal and stopped sending `description` in the template UI payload. - Removed template description rendering from the card; card old-data descriptions remain ignored for display. - Moved the edit icon button into the bottom frosted-glass overlay and reserved title spacing so it does not overlap. - Added a template-console snapshot before applying a template, capturing mode, image prompt, image size, image engine, engine tuning, and single-image state. - Changed the selected template button text to `取消选择`; clicking it restores the captured right-side state, removes active selection, and clears template-derived missing upload placeholders. - Verification: - Browser verification on temporary auth-disabled `3005` confirmed no `简介` label in the editor modal or page body, hidden template descriptions are not displayed, the edit icon is inside and within the glass overlay bounds, selecting a template applies prompt/engine/size/tuning/single-image/placeholder state, and clicking `取消选择` restores the original prompt, engine, size, tuning, single-image value, button text, and placeholder state. - `npm test -- tests/image-templates.test.ts tests/material-draft.test.ts`: 2 files / 7 tests passed. - `npm run build`: production build passed. ## Session: 2026-07-02 - Template Card UI Density Polish ### Phase 37: Template Card UI Density Polish - **Status:** complete - User feedback: - The template-card UI still looked off after moving the edit action into the frosted-glass footer. - Actions taken: - Reduced each fixed template card from `138px x 184px` to `132px x 176px`. - Tightened the rail-list gap so the widened `480px` desktop template rail can show three template cards per row instead of leaving unused space. - Reworked the card footer into a two-row frosted-glass grid: title spans the full first row, while `选择模板` / `取消选择` and the edit icon share the second row. - Removed the remaining frontend `description` property from the create-studio template type so the template UI surface no longer carries an intro field. - Verification: - Browser geometry check on temporary auth-disabled `3005` confirmed card size `132px x 176px`, three columns, footer height ratio `0.338`, no select/edit overlap, and the edit icon remains inside the frosted-glass footer. - `npm test -- tests/image-templates.test.ts tests/material-draft.test.ts`: 2 files / 7 tests passed. - `npm run build`: production build passed. ## Session: 2026-07-02 - Right-Side Create Task Module ### Phase 38: Right-Side Create Task Module - **Status:** complete - User request: - Add an independent `任务模块` on the right side of the creation console. - The module should act as a task list showing generated asset image, task name, task status, elapsed time, and a detail link that jumps to the task page. - Actions taken: - Added recent task and asset loading to `components/create-studio.tsx`, combining image and video generation jobs with asset thumbnails. - Added the right-side `任务模块` panel beside the generation console with thumbnail, task name, status, elapsed time, refresh action, and `查看详情` link. - Added `/assets?view=tasks&taskId=...` deep-link support so the results page opens the task tab and expands the selected task. - Added responsive CSS for the three-column desktop layout, tablet wrapping, and single-column mobile behavior. - Verification: - `npm test -- tests/image-templates.test.ts tests/material-draft.test.ts`: 2 files / 7 tests passed. - `npm run build`: production build passed after a rerun; the first build attempt hit a transient local JSON parse failure during page-data collection. - `npx tsc --noEmit`: passed when run separately after build. - Browser verification on temporary auth-disabled `3006` confirmed desktop columns `480px / 416px / 320px`, task module height matching the generation panel, no horizontal overflow, mobile `390px` layout without overflow, and task detail links opening `/assets?view=tasks&taskId=...` with the `任务` tab active and the job detail expanded. - Normal auth-enabled dev server is running in screen session `zhinian-dev-ui` on `http://127.0.0.1:3006`; `/create` redirects to login as expected. ## Session: 2026-07-02 - Task Module Width and Preview Polish ### Phase 39: Task Module Width and Preview Polish - **Status:** complete - User feedback: - Widen the task list by one more step so task information does not wrap. - Running tasks should show a `生成中` placeholder thumbnail. - Completed generated-image thumbnails should open a large image preview when clicked. - Actions taken: - Widened the create-page task module from the previous `280-320px` range to `560-640px` on wide layouts and expanded the page/container max width. - Reworked task cards into a horizontal row: thumbnail, single-line task name/status/time, and a fixed `查看详情` action. - Added pending thumbnail UI for queued/running tasks without output assets. - Added a create-page asset preview modal for completed image thumbnails. - Verification: - `npm run build`: production build passed. - `npx tsc --noEmit`: passed after running separately from the build. - `npm test -- tests/image-templates.test.ts tests/material-draft.test.ts`: 2 files / 7 tests passed. - Browser verification on temporary auth-disabled `3007` confirmed default desktop task width `568px`, wide viewport task width `640px`, no horizontal overflow, task card columns remain one row, generated placeholders read `生成中`, and clicking a completed task thumbnail opens an image preview modal. ## Session: 2026-07-02 - Account Department Creation Split ### Phase 39: Separate Department Management From User Creation - **Status:** complete - User feedback: - Department creation should be a standalone function. - User creation should select an existing department directly. - A newly tested user did not appear in the list. - The new-user button should be more obvious. - Actions taken: - Moved department creation out of the user form and into a standalone `部门管理` panel. - Replaced prompt-based department creation with inline `部门名称` and `部门描述` inputs. - Kept user creation as a focused form that only selects an existing role and department. - Made the primary `新建用户` submit button larger and full-width within its submit area. - Clarified the post-create success message when the upstream member-list interface is unavailable, so successful creation is not confused with list visibility. - Verification: - `npm test -- tests/organization-client.test.ts tests/auth-permissions.test.ts`: 2 files / 15 tests passed. - `npm run build`: production build passed. - `git diff --check`: passed. - Normal auth-enabled dev server is running in screen session `zhinian-dev-ui` on `http://127.0.0.1:3000`; `/api/health` returned `ok: true`. ## Session: 2026-07-02 - Large Image Preview Download ### Phase 40: Download Action In Image Preview - **Status:** complete - User feedback: - Clicking an image to view the large preview should show a download button. - Actions taken: - Added a download action to the task-module large asset preview in `components/create-studio.tsx`. - Added a download action to template-image large preview when a template preview image exists. - Reused the existing `/api/assets/:id/download` route for generated task assets. - Verification: - `npm test -- tests/image-templates.test.ts tests/material-draft.test.ts`: 2 files / 7 tests passed. - `npm run build`: production build passed. ## Session: 2026-07-02 - Compact Creation Parameter Row ### Phase 41: Compact Inline Generation Settings - **Status:** complete - User feedback: - The parameter controls at the bottom of the middle creation console should default to one horizontal row. - The parameter boxes were too wide. - Actions taken: - Changed `.inline-settings` from wide grid tracks to a compact wrapping flex row. - Assigned smaller fixed widths to the inline parameter fields, with a narrower width for the short `画幅` field. - Kept small-screen behavior responsive by switching the parameter area to two columns, then one column on very narrow screens. - Verification: - `npm run build`: production build passed. - `git diff --check`: passed. ## Session: 2026-07-02 - Default Single Image Without Toggle ### Phase 42: Remove Single-Image Toggle - **Status:** complete - User feedback: - Remove the `单图` option; single-image generation should be the default. - Actions taken: - Removed the visible `单图` toggle from the middle creation console. - Removed the visible `单图` toggle and preview chip from the image-template editor. - Fixed image-generation submissions to send `force_single: true`. - Fixed template saves to store `forceSingle: true` by default. - Verification: - `npm test -- tests/image-templates.test.ts tests/material-draft.test.ts`: 2 files / 7 tests passed. - `npm run build`: production build passed. ## Session: 2026-07-02 - Live Elapsed Task Timer ### Phase 43: Auto-Updating Elapsed Time - **Status:** complete - User feedback: - The elapsed time display did not automatically increase. - Actions taken: - Added a lightweight one-second local timer while there are non-terminal generation jobs. - Updated the creation task module to render `已耗时` from the live timer instead of a static `Date.now()` call. - Updated the results task list and task detail panel to use the same live timer. - Kept API polling separate so status refreshes do not need to run every second. - Verification: - `npm test -- tests/image-templates.test.ts tests/material-draft.test.ts`: 2 files / 7 tests passed. - `npm run build`: production build passed. ## Session: 2026-07-02 - Full-Width Creation Workspace ### Phase 44: Remove Create Title And Tile Three Modules - **Status:** complete - User feedback: - Remove the `创作生成台` title text. - Tile the three creation modules across the full page. - Actions taken: - Removed the visible creation-page title from `components/create-studio.tsx`. - Added a `create-main` page class in `components/app-shell.tsx` for `/create`. - Expanded the creation page main area to near full viewport width without changing other pages. - Rebalanced the template, generation, and task modules into a three-column full-width desktop layout with responsive fallback. - Verification: - `npm run build`: production build passed. - `git diff --check`: passed. ### Phase 45: Rebalance Creation Workspace Height - **Status:** complete - User feedback: - The three-module proportions still felt wrong. - The lower area left too much empty space. - The middle module should be titled `制作中心`. - Actions taken: - Added a `制作中心` header inside the middle generation module. - Removed the JS height-sync behavior that forced side columns to follow the middle module height. - Rebalanced the desktop three-column ratio so the center work area has more priority while template/task columns stay usable. - Made the desktop creation workbench use the available viewport height with internal scrolling for each module. - Added a wider responsive breakpoint so narrower windows fall back before columns become cramped. - Verification: - `npm run build`: production build passed. - `git diff --check`: passed. ### Phase 46: Remove Default Center Scrolling - **Status:** complete - User feedback: - The `制作中心` module should not require scrolling by default. - Actions taken: - Removed internal scrolling from the center production module on desktop. - Kept viewport-height list scrolling on the template and task side columns. - Reduced the default prompt textarea height so the standard creation form fits more comfortably in the first view. - Verification: - `npm run build`: production build passed. - `git diff --check`: passed. ### Phase 47: Fix Template Rail To Three Cards - **Status:** complete - User feedback: - The left template selector should default to three fixed-size cards per row. - Actions taken: - Changed the `/create` desktop template rail to a fixed three-column grid using the existing template card dimensions. - Widened the desktop template column enough to hold three fixed cards cleanly. - Raised the responsive breakpoint so narrower windows switch layout before the three-column desktop rail becomes cramped. - Added a small-window fallback that returns the template rail to automatic wrapping. - Verification: - Stopped the dev server before running the production build to avoid `.next` cache contention. - Cleared the generated `.next` build output after the cache was corrupted by the earlier concurrent dev/build run. - `npm run build`: production build passed. - `git diff --check`: passed. ### Phase 48: Lock Create Page Scrolling - **Status:** complete - User feedback: - Typing in the center module caused the whole page to become scrollable. - The create page should not use page-level scrolling. - The left template selector should be just wide enough for three templates per row. - Actions taken: - Added a `/create`-only shell class and turned the create page into a fixed-height viewport workspace. - Locked the create page, main area, and three-column workbench with `overflow: hidden` so center input content cannot create body/page scrolling. - Made the prompt textarea a fixed-height, non-resizable input area with its own internal overflow for long text. - Set the desktop template column to a fixed width that fits exactly three existing fixed-size template cards per row. - Lowered the two-column responsive breakpoint so common desktop widths keep the three-card template rail. - Verification: - Stopped the dev server and cleared `.next` before running the production build to avoid cache contention. - `npm run build`: production build passed. - `git diff --check`: passed. ### Phase 49: Fix Center Parameter Bar To Bottom - **Status:** complete - User feedback: - The parameters at the bottom of `制作中心` should be fixed at the bottom with a fixed height. - Actions taken: - Changed the center creation column to a vertical flex layout. - Made the prompt/input area take the remaining center height. - Fixed the parameter controls as a 78px bottom bar with a top divider. - Kept long prompt text scrolling inside the textarea so it does not move the bottom controls. - Capped uploaded-material rows inside the center panel so they do not push the parameter bar out of place. - Verification: - Stopped the dev server and cleared `.next` before running the production build. - `npm run build`: production build passed. - `git diff --check`: passed. ### Phase 50: Widen Task Module - **Status:** complete - User feedback: - The right-side task module should be a little wider. - Actions taken: - Increased the desktop task column from `minmax(320px, 420px)` to `minmax(360px, 480px)`. - Kept the left template column fixed so it still fits exactly three template cards per row. - Verification: - Stopped the dev server and cleared `.next` before running the production build. - `npm run build`: production build passed. - `git diff --check`: passed. ## Session: 2026-08-11 - Platform-Owned Account System ### Phase 51: Requirements Confirmed and Implementation Started - **Status:** complete - User-confirmed scope: - Replace external OAuth2 account authentication with platform-owned phone/password accounts. - Use Supabase/Postgres in production and local JSON fallback in development. - Support `super_admin`, `organization_admin`, and `user` roles. - Enforce one account per organization; no cross-organization membership or switching. - Preserve legacy account/history through phone-based mapping; retain usage and archive assets/tasks on deletion. - Keep admin-created accounts, unified login, immutable phone identifiers, administrator password initialization/reset, and user self-service password changes. - Limit organization admins to their own ordinary-user management and aggregate usage; they cannot access logs/system settings or grant organization-admin roles. - Actions taken: - Read the current authentication, session, permission, account-management, data-store, and Supabase schema implementation. - Read and activated the file-based planning workflow for this multi-phase change. - Added this implementation phase and captured confirmed decisions/findings in the planning files. - Next: - For deployment, run the documented one-time super-admin bootstrap against the production Supabase database, then execute the operator-provided legacy account import file. ### Phase 51: Implementation and Verification Complete - **Status:** complete - Implemented: - Added platform organization/user/migration models to `lib/types.ts`, local JSON storage, and `supabase/schema.sql`. - Replaced browser OAuth/password-grant login with normalized phone + scrypt password verification, signed/chunked HttpOnly platform sessions, account lockout after five failures, and IP rate limiting. - Added role-aware access boundaries: super administrators control global logs/settings/organizations/accounts/usage; organization administrators are limited to ordinary users and their organization aggregate usage; ordinary users retain self-service creation and password changes. - Added organization lifecycle APIs/UI, administrator-created account APIs/UI, reset-password flow, self-service password change, disable/delete behavior, archive reassignment, and immutable unique phone login identifiers. - Preserved usage events during account deletion and added legacy import/bootstrap scripts with phone/legacy-owner mappings and history reassignment. - Kept `/api/v1/*` and worker authentication separate from browser platform sessions. - Verification: - `tsc --noEmit`: passed. - `vitest run`: passed, 22 test files / 80 tests. - Bootstrap/import script syntax checks: passed. - `next build`: passed. - `git diff --check`: passed. - HTTP smoke test on a temporary local account store: super-admin login and organization creation passed; organization-admin login passed; logs returned 403 for organization admin; ordinary-user self password change and relogin passed. - Project is running on `http://127.0.0.1:3000`; `/api/health` and `/auth/login` both returned 200 after the final restart. ## Session: 2026-08-11 - Enterprise Billing ### Phase 53: Official Provider Price Catalog - **Status:** complete - Added an auto-seeded, editable base catalog for Bailian Wan 2.7, EvoLink GPT Image 2, Jimeng Seedream 4.6 reference pricing, and Volcengine Ark Seedance 2.0 resolution tiers. - Standardized all ledger amounts in CNY fen. The final user charge is `ceil(base_fen × quantity × markup)`, with the default markup set to `1.5x`. - Fixed EvoLink conversion at `1 USD = 7.20 CNY`; the GPT Image 2 medium/1K/no-reference estimate becomes ¥0.34 per image. - Added `variantKey` resolution matching and source snapshots so later price edits do not change historical task charges. - Added official source links and pricing-basis notes to the super-admin table and deployment/API documentation. - Verification: `bun run test` passed with 23 files / 82 tests; `bun x tsc --noEmit`, `bun run build`, and `git diff --check` passed. ### Phase 54: Billing Center Taste Redesign - **Status:** complete - Read the current super-admin billing screenshot and identified the main issue as a long, repetitive vertical stack that mixed organization balance, pricing operations, account setup, and recharge review at the same visual weight. - Rebuilt `components/billing-manager.tsx` around a balance-first overview, a compact ledger, a dense but scannable price catalog, and role-specific action areas. Member recharge is separated from super-admin pricing and review actions; custom pricing creation is collapsed until needed. - Added a restrained B2B visual system in `app/globals.css`: one green accent, dark balance hero, quiet surfaces, compact list rows, explicit form labels, focus states, loading skeletons, responsive breakpoints, and reduced-motion handling. - Preserved existing API behavior and price-source links while improving hierarchy and mobile stacking. Browser smoke checks confirmed the super-admin page rendered at desktop and 390px viewport widths with no horizontal overflow. - Verification: desktop/mobile screenshots, `bun x tsc --noEmit`, `bun run test` (23 files / 82 tests), `bun run build`, and `git diff --check` all passed. ### Phase 55: Tabbed Billing Operations - **Status:** complete - Replaced the continuous super-admin/member billing stack with task tabs. Super admins now switch between 概览、价格与计费、余额管理、充值审核、收款设置; members switch between 概览、线下充值、账务流水. - Added `/api/admin/billing/account` so super admins can configure account name, bank, account number, and recharge contact directly in the billing center. It reuses the existing settings persistence path and updates the member-facing account immediately. - Added `/api/admin/billing/adjustments` for super-admin manual credit/debit entries. The organization wallet remains the only balance; an optional member selection only attributes the immutable ledger entry and does not create a personal wallet. - Extended `/api/admin/billing` with organization members and recent ledger data. The balance tab now shows per-member net consumption and a one-click member attribution action for the adjustment form. - Verification: browser tab and account-editor smoke checks, 390px mobile screenshot with no horizontal overflow, `/api/admin/billing` payload smoke, `bun run test` (23 files / 83 tests), `bun x tsc --noEmit`, `bun run build`, and `git diff --check` passed. ### Phase 56: Billing Error Recovery - **Status:** complete - Local `GET /billing`, `/api/billing`, `/api/admin/billing`, and `/api/settings` all returned 200 under the local fallback runtime; no new billing 500 was present in `.runtime/logs/server-events.jsonl`. - Added actionable detection for missing or outdated Supabase billing tables/columns, safe parsing for non-JSON proxy errors, and a billing route error boundary with migration guidance. - Verification: `bun x tsc --noEmit`, `bun run test` (23 files / 83 tests), `bun run build`, production API smoke (all 200), production browser tab smoke, and `git diff --check` passed. ### Phase 57: Super-Admin Billing Blank State - **Status:** complete - Reproduced the screenshot state: an unbound super-admin received 422 from the member-oriented `/api/billing`, while `/api/admin/billing` returned 200; the component then had no `billing` payload and hid every content section. - Changed super-admin loading to use the platform admin payload directly and synthesize an all-organization wallet/ledger summary. Member loading still uses the organization-scoped `/api/billing` route. - Verification: `bun x tsc --noEmit`, `bun run test` (23 files / 83 tests), `bun run build`, and production browser smoke confirmed the five super-admin tabs and overview render. ### Phase 58: Parameterized Billing Rules - **Status:** in_progress - User confirmed the structured rule-matrix approach: normalize user-selected parameters, match the most specific server-side rule, expose a quote preview, and reject real jobs without a matching rule. - Current code only derives `resolution` as a variant and derives quantity from `duration`/`n`; the new phase will cover quality, size, aspect ratio, reference-image count, and other provider request dimensions without trusting client-side prices. ### Phase 58: Parameterized Billing Rules - **Status:** complete - Extended price rules with structured JSON conditions, explicit quantity sources (`request`, `image_count`, `duration`), and priorities. Existing `variantKey` resolution rules remain compatible and are translated into conditions at match time. - Added server-side parameter normalization for model, resolution, size, aspect ratio, quality, duration, image count, reference-image count, scale, and audio flags. Matching now prefers exact `reqKey`, then the most-specific matching conditions, then priority; unresolved ties fail as an ambiguous configuration. - Added `/api/billing/quote` and shared image/video preparation helpers so the preview and real submission use the same provider payload and billing matcher. Billing snapshots now include normalized parameters, conditions, quantity source, quantity, and final amount in the job quote and ledger metadata. - Upgraded the super-admin price editor with condition fields for resolution, size, aspect ratio, quality, scale, reference-image count, duration, quantity source, and priority. The price table displays the configured scope; legacy rules remain editable. - Verification: `bunx vitest run` passed with 23 files / 86 tests; `bunx tsc --noEmit`, Node-backed `next build` (32 static pages), `git diff --check`, local `/api/health` HTTP smoke (200), and unauthenticated quote-route smoke (401 as expected) passed. Browser smoke reached the login gate without a render/500 error. ## Session: 2026-08-11 - Task Detail Modal and Result Directory Consolidation ### Phase 59: Discovery and Decision Gate - **Status:** complete - Inspected the current `/assets` result page, create-page task module, generation job shape, image/video submission payloads, asset download route, and local generated-result storage. - Confirmed that the visible result directory and the physical generated-result storage are separate concerns. - Confirmed that task records already retain the prompt, input material IDs/URLs, normalized generation settings, provider/task metadata, billing state, errors, and output asset IDs needed for an in-place detail modal. - User confirmed that the front-end result directory should be removed from the visible product flow, that the interaction should live in the task module, and that this is a desktop-only platform. ### Phase 59: Task Detail Modal and Result Directory Consolidation - **Status:** complete - Removed the `结果` navigation entry and changed `/assets` into a compatibility redirect to `/create`; the asset APIs, download route, local uploads, and `.runtime/generated-results` storage remain available. - Added task-card click and keyboard interaction with a desktop task detail modal covering task status, duration, prompt, input elements/material previews, normalized generation parameters, provider/request metadata, billing state, errors, and output previews. - Added direct result download actions to completed task cards and per-output download links inside the modal. Card-level download/detail actions stop propagation so they do not reopen the modal. - Updated product and deployment documentation to describe the task module as the single front-end location for task details and generated-result downloads. - Verification: desktop browser smoke on `/create` confirmed the trimmed navigation, 17 task cards, prompt/material/parameter rendering, and download action; `bun run test` passed (23 files / 86 tests); `bun x tsc --noEmit`, `bun run build`, and `git diff --check` passed. - Scope note: mobile layout work was intentionally excluded per the confirmed desktop-only product requirement. ### Phase 60: Direct Billing Top-ups — Started - Confirmed the new accounting rule: remove recharge review entirely; administrators post balance directly; future self-service payment success posts automatically. - Located the active request/review chain in the billing manager, `/api/billing`, `/api/admin/billing`, `/api/admin/billing/recharges/[id]`, billing store/service, schema, docs, and tests. - Confirmed the existing administrator adjustment endpoint can remain as the direct top-up implementation. - Removed member recharge form/history and the super-admin review tab/metric from the billing manager; the overview now points to balance operations instead of pending requests. - Removed recharge request listing/creation/review routes and active store/type mappings; direct credit adjustments now use `recharge` ledger entries through `postOrganizationTopUp`, while debits remain `adjustment` entries. - Updated README/API/deployment documentation to describe direct administrator posting and future automatic posting after payment success. ### Phase 60: Direct Billing Top-ups — Complete - Removed the recharge request table from the active Supabase schema definition without dropping any existing deployed table; old data, if present, is no longer part of the application workflow. - Renamed the super-admin operation to “余额与上账”, replaced the pending-review metric with organization cumulative charges, and kept corporate account settings as a future payment configuration surface. - Verification passed: no stale request/review references, `bunx tsc --noEmit`, `bunx vitest run` (23 files / 86 tests), Node-backed `next build`, `git diff --check`, `/api/health` 200, unauthenticated admin billing 401, and billing page auth redirect 307. - The local development server is running on `http://127.0.0.1:3000` after a clean restart. ### Phase 61: Simplified Billing Price Controls — Started - User clarified that provider standard prices and parameter tiers are platform-maintained; super administrators should only adjust the markup multiplier. - Current UI/API surface is broader than the intended responsibility, so this phase will collapse it to a read-only catalog with multiplier-only maintenance. ### Phase 61: Account Directory and Password Settings Consolidation — Started - Read the `design-taste-frontend` skill and applied its audit-first redesign protocol to this data-heavy product surface rather than its marketing-page-only patterns. - Audited the current account directory in the local desktop browser and found the password form only in `/settings`, admin-only `/accounts` access, and a cramped horizontal create-account row. - Confirmed implementation direction: `/accounts` becomes authenticated-user accessible, self password change moves there for every role, admin organization/member APIs remain protected, and the page is rebuilt around a modern light minimalist desktop hierarchy. ### Phase 61: Account Directory and Password Settings Consolidation — Complete - Removed `AccountSecurityPanel` from `/settings` and mounted it in `/accounts`; the existing `/api/auth/password/change` contract and session refresh behavior remain unchanged. - Made `/accounts` available to every authenticated user. Ordinary users see identity information and self-service password change; admin sessions additionally load the existing organization/member management APIs. - Rebuilt the account page as a desktop-first two-column utility surface: personal security and member directory on the main column, identity, account creation, and organization controls in the rail. Added explicit status badges, avatars, skeleton loading, focus states, empty/error feedback, and restrained green accent styling. - Updated navigation, middleware, README, Chinese README, and deployment notes to describe the new account access model. - Verification: desktop browser smoke showed the password form and loaded member directory, settings no longer contained the password form, `bun run test` passed (23 files / 86 tests), `bun x tsc --noEmit`, `bun run build`, and `git diff --check` passed. - Errors and resolutions: a hot-reload session held an obsolete client state and left the member skeleton visible; restarting the temporary dev server restored the expected list. The first production build emitted an autoprefixer warning for `align-items: end`; all new occurrences were changed to `flex-end`, and the final build completed without that warning. ### Phase 62: Account Workspace Information Architecture Correction — Complete - User feedback identified two concrete flaws in the first redesign: the current-user summary duplicated the “登录身份” card, and the account page was still fragmented into separate floating cards. - Removed the duplicate account/profile panel and kept one current-user identity summary in the page header. - Replaced the split main/rail composition with one continuous `account-workspace`, ordered as security settings, administrator organization/member management, and the member directory. Organization creation now sits beside account creation within the same administrator section. - Desktop browser verification at 1280px confirmed one identity surface, zero profile-card duplicates, a single 1180px workspace, and `bodyScrollWidth === clientWidth`. ### Phase 61: Simplified Billing Price Controls — Complete - Reduced price maintenance to the intended product model: platform-owned standard cost and parameter catalog, with super-admin control limited to the markup multiplier. - Replaced the multi-field rule editor with a compact read-only catalog showing service/parameters, standard cost, calculated customer price, multiplier, and a single `调整倍率` action. - Made the admin price collection route read-only and restricted item updates to `markupMultiplier`; structural pricing fields are rejected server-side. - Verification passed: `bunx tsc --noEmit`, `bunx vitest run` (23 files / 86 tests), Node-backed production build, `git diff --check`, browser legacy-form/overflow checks, and clean dev-server health (`/api/health` 200). ### Phase 63: Parameterized Billing Catalog — Started - User confirmed the recommended model: list parameter tiers under each service/model with platform-owned standard rates and multiplier controls; calculate the final quote from the selected parameter combination. - The current implementation only has one generic EvoLink image rule based on medium / 1K / 1:1 / no reference image, so high quality currently falls through to the same price. The next implementation step is to add dimension-aware catalog data and matching without exposing structural editing in the admin UI. ### Phase 63: Parameterized Billing Catalog — Complete - Added platform-owned parameter dimensions and tiers to billing rules. EvoLink GPT Image 2 now lists quality, resolution, aspect-ratio, and reference-image tiers; video resolution variants are grouped under their service/model. - Quote calculation now resolves every selected parameter, multiplies standard factors, applies one highest-selected markup multiplier, and snapshots the effective standard cost plus selected tiers into the task billing record. - Added a multiplier-only tier PATCH path and a backfill-safe catalog seed update that preserves existing multiplier values while synchronizing platform standard metadata and parameter dimensions. - Updated the billing center to show grouped service cards with child parameter rates, user prices, multipliers, source notes, and one `调整倍率` action per tier. No structural editor or custom rule form is exposed. - Verification: `bunx tsc --noEmit`, `bunx vitest run` (23 files / 88 tests), `bun run build`, browser checks at 1280px (5 service cards / 4 EvoLink dimensions / 15 tiers / no horizontal overflow / no legacy form), `git diff --check`, and clean dev-server health. ### Phase 64: Inline Generation Cost Estimate — Complete - Applied the ui-ux-pro-max form guidance: keep labels associated with controls, provide immediate state feedback, and put the result summary at the decision point. - Moved the generation quote from the top action bar into a compact `本次预估消耗` card beside the engine/parameter controls. The card shows the server-resolved amount, quantity, multiplier, and matched parameter tiers. - Added explicit unavailable/loading states and cleared stale loading state when the prompt or required materials are removed. - Added container-aware layout rules for the three-rail create workbench. At 1280px and 1440px the parameter controls and cost card align in one row; at narrower center columns they stack without horizontal overflow. - Browser verification observed EvoLink medium/2K/1:1 at ¥2.04, high/2K/1:1 at ¥8.16, and Seedance 5 seconds at ¥7.43 in the local configured environment. ### Phase 65: Billing UI Alignment and Native Multiplier Dialog — Complete - Reworked the price-source metadata row so the source link, platform note, and service-card content share a predictable baseline and available width. - Shortened the estimate card heading to `预估消耗` so the live amount, quantity, multiplier, and parameter summary remain aligned beside the controls. - Replaced browser prompt editing with a native in-app multiplier modal that previews standard cost/current price/new price and validates `1–1000×` input. - Verified parameter-driven quote refresh (`¥2.04` for the tested EvoLink Image2 configuration), Escape dismissal, `bunx vitest run` (23 files / 88 tests), `bunx tsc --noEmit`, `bun run build`, `git diff --check`, and `/api/health` HTTP 200 on the restarted port 3000 server. ### Phase 66: Fixed EvoLink 1K Quote and User-Facing Estimate — Complete - Fixed the EvoLink image payload to always request the platform-approved 1K resolution; removed the obsolete configurable resolution setting and synchronized the billing catalog default to 1K. - Removed internal pricing metadata from the ordinary-user estimate card. It now contains only `本次预计消耗额度` and the amount/loading placeholder. - Verified live values in the create page: standard quality `¥0.51`, high quality `¥2.04`; no `未开始`, automatic-calculation helper, platform multiplier, tier summary, or `2K` appeared in the user-facing page. - Verification passed: `bunx vitest run` (23 files / 88 tests), `bunx tsc --noEmit`, `git diff --check`, and browser quote checks. ### Phase 67: Unified Default Billing Multiplier — Complete - Changed `DEFAULT_BILLING_MARKUP_MULTIPLIER` to `1.2` and applied it across all built-in image/video rules and parameter tiers. - Synchronized `.runtime/data/billing-state.json` so the running local catalog no longer retains `1.5×` defaults. - Updated billing docs and built-in quote assertions; intentional test-specific multiplier overrides remain explicit. ## Session: 2026-08-12 - Seedance Native Usage Settlement ### Phase 68: Cross-Provider Pricing Audit — Complete - Reconciled Bailian image/video, EvoLink image, Jimeng reference, and Ark Seedance catalog entries against the supplied provider pricing sources. - Confirmed the shared 1.20× platform multiplier and identified Seedance as the only active provider whose official final price depends on returned usage rather than only the submitted parameter set. - Obtained confirmation to implement conservative submit-time reservation plus successful-task token reconciliation. ### Phase 69: Seedance Native Usage Settlement — Complete - Added official Seedance token rate mapping by resolution and input-video presence, with a formula-based conservative estimate for the initial reservation. - Added provider usage extraction for both top-level and nested Seedance response shapes. - Added idempotent final settlement: actual lower amount refunds the difference, actual higher amount charges the difference, and missing usage keeps the reserved amount. - Added the 4K catalog/resolution variant and updated product/API documentation. - Verification passed: `bunx vitest run` (24 files / 92 tests), `bunx tsc --noEmit`, `bun run build`, and `git diff --check`. ### Phase 70: Unbound Account Quote Preview — Complete - Traced the blank quote to the super-admin account having no organization binding; the quote request was incorrectly subject to the real-charge organization gate. - Added a quote-only bypass for organization lookup while preserving the strict organization requirement during actual task submission and wallet charging. - Added a regression test for the preview/charge boundary. - Browser verification now shows `¥1.64` for Image2 / 9:16 / 精细. Full verification passed: Vitest 24 files / 93 tests, TypeScript, production build, local health check, and `git diff --check`. ## Session: 2026-08-11 - Cross-Provider Pricing Audit ### Phase 68: Cross-Provider Pricing Audit — In progress - Audited `lib/server/billing-catalog.ts`, `lib/billing.ts`, `lib/server/billing-service.ts`, the provider payload builders, the runtime billing state, and current quote outputs. - Confirmed Bailian image/video baselines and the one-time 1.20× markup behavior against the current official Alibaba model pages. - Confirmed the Ark Seedance 2.0 sample values and identified the boundary: the official source is token-based and input-video dependent, while the current catalog is a no-input-video, 16:9, five-second reference estimate expressed per second. - Confirmed the active UI forces Jimeng single-image output; its ¥0.20/image entry remains a documented reference baseline because the official API page does not publish a stable per-call price. - No implementation changes made. Next step is to present the confirmed matches and the Seedance approximation decision to the user before changing the billing model. ### Phase 52: Discovery and Decision Gate - **Status:** complete - Read and restored the existing planning files before starting the new multi-step phase. - Inspected current types, generation services, data store, account roles, usage events/reports, routes, and package scripts. - Confirmed current usage is analytics-only: one event per non-mock first-party job, with no wallet or monetary ledger. - Confirmed organization identity and role boundaries are already available for billing integration. - Paused implementation at the required decision gate: billing unit/settlement semantics must be confirmed before changing financial state. ### Phase 52: Requirements Confirmed and Implementation Started - **Status:** in_progress - User confirmed the provider-native billing unit × super-admin markup model. - User added the requirement to remove 高清/智能超清 (`image.upscale`) and 局部重绘 (`image.inpaint`) capabilities. - Current removal targets and billing integration points are recorded in `findings.md`; implementation proceeds from the existing account-system worktree without resetting unrelated changes. ### Phase 52: Capability Removal and Billing Core - **Status:** complete - Removed `image.inpaint` and `image.upscale` from active capability types, provider matrices, generation UI, asset edit APIs, settings assignments, usage filters, public API validation/OpenAPI, tests, environment examples, and docs. - Kept historical `edited`/`upscaled` asset source values readable and labeled as historical results. - Added billing domain types, integer-fen pricing helpers, local billing store, Supabase billing schema/RPC, organization wallet operations, price rules, recharge requests, immutable ledger entries, and idempotent job charge/refund service. - Integrated pre-charge into image/video submission and final-state refunds into Worker failure handling, public API cancellation, and task deletion. - Added `/api/billing`, `/api/admin/billing`, price-rule CRUD, and recharge review endpoints. ### Phase 52: Billing Integration and Verification - **Status:** complete - Added organization-scoped integer-fen wallets, idempotent charge/refund ledger entries, provider-native quantity pricing, super-admin markup snapshots, recharge requests, review flow, and optional corporate-account display/configuration. - Real first-party image/video jobs quote and debit before provider dispatch; pending charges are recovered by the Worker after a process interruption; final failed/expired/cancelled jobs refund once, while successful deletion never refunds. - Added `/billing` for members to view organization balance, personal/org consumption, ledger, and offline recharge requests; super admins manage price rules, organization wallets, recharge review, and corporate transfer account details. - Removed active high-resolution/upscale and inpaint capabilities, routes, editor surface, settings assignments, public API definitions, and environment keys; the legacy `/image-edit` path now redirects to normal creation and historical asset source values remain readable. - Verification passed: `bun run test` (23 files / 81 tests), `bun x tsc --noEmit`, `bun run build`, `bun run info`, local `/api/health` HTTP smoke, `/billing` auth redirect, and OpenAPI stale-capability scan. ## Session: 2026-08-12 - Organization-Only Billing Top-ups ### Phase 70: Organization-Only Billing Top-ups — In progress - User confirmed that every top-up belongs to the organization; organization administrators and employees share the organization quota, with no personal top-up ownership. - Located the remaining personal-attribution path in the admin adjustment route, billing adjustment form, member “归属上账” action, and local/Supabase wallet-entry serialization. - Scope decision: preserve account IDs on generation charges/refunds for member consumption reporting; normalize new recharge/adjustment entries to organization-only and leave historical entries untouched. ### Phase 70: Organization-Only Billing Top-ups — Complete - Removed `accountId` from the direct organization top-up service contract and admin adjustment request path. - Normalized local wallet entries and the Supabase `billing_post_wallet_entry` RPC so `recharge` and `adjustment` rows never receive a personal account ID; generation `charge`/`refund` rows retain actor attribution. - Removed the billing-center member selector, “流水归属” field, and “归属上账” buttons. Member usage remains read-only and explicitly describes shared organization quota. - Updated the ledger renderer, API/deployment docs, and README wording to distinguish organization balance ownership from member consumption reporting. - Verification passed: focused billing tests 13/13, full Vitest 24 files / 92 tests, TypeScript, production build, and reviewed-file `git diff --check`. ### Errors encountered | Error | Attempt | Resolution | | --- | --- | --- | | `npm` was not available in the shell | First test command | Loaded the workspace runtime dependencies and used the bundled Node executable directly. | | Bundled `pnpm test` stopped at ignored `sharp` build scripts | Second test command | Invoked Vitest and TypeScript directly through the installed workspace dependencies, avoiding an install step. | ## Session: 2026-08-12 - Frontend Encoding Diagnosis ### Phase 71: Frontend Encoding Diagnosis — Awaiting reproduction - Checked source bytes, HTML/CSS response headers, and served HTML for common mojibake markers; all are valid UTF-8. - Used `agent-browser` to render `/auth/login` and an isolated auth-disabled `/billing` preview; Chinese labels and the billing screenshot rendered normally. - Found two existing Next dev-server processes associated with this workspace and port 3000, which may produce stale/mixed browser state. - No code change was applied because the reported garbling cannot yet be reproduced. Next input needed: the affected page URL and a screenshot or the exact garbled text. ## Session: 2026-08-12 - Autofilled Login Submission ### Phase 72: Autofilled Login Submission — In progress - User supplied a screenshot showing phone and password visibly filled while the login action could not be activated. - Traced the issue to the submit button depending on React state, which is not guaranteed to update for browser/password-manager autofill. - Updated `components/auth-login-panel.tsx` to use named required fields and native `FormData` values at submit time; updated the focused source regression test. - Browser check confirmed filled credentials trigger `POST /api/auth/password`; final test/build verification remains. ### Phase 72: Autofilled Login Submission — Complete - Focused auth-panel tests passed: 2/2. - Full Vitest suite passed: 24 files / 92 tests. - TypeScript and production build passed. - Browser check confirmed the filled login form is clickable and sends the password-login request. ## Session: 2026-08-12 - Next Development Cache Recovery ### Phase 73: Next Development Cache Recovery — Complete - Confirmed `.next/server/webpack-runtime.js` referenced missing chunk `9971.js`. - Stopped the two duplicate Next development processes associated with this workspace. - Moved the corrupted `.next` directory to `.next.corrupt-20260812-1042` for recovery and started one clean dev server on `127.0.0.1:3000`. - Verified `/create` compiles, `/auth/login` renders, `/api/health` responds, and clicking the login form sends `/api/auth/password` without the runtime overlay. ### Phase 74: Dev/Production Cache Isolation — Complete - Changed Next output selection so development uses `.next-dev` and production uses `.next`; added `.next-dev/` to `.gitignore`. - Moved the partially generated `.next-dev` cache to `.next-dev.corrupt-20260812-1108` instead of deleting it, then restarted one clean server on port 3000. - Verified `/auth/login` renders correctly, `/api/health` returns 200, `/create` redirects to `/auth/login` when unauthenticated, and the Lucide vendor chunk is regenerated in `.next-dev`. - TypeScript and diff checks remain clean for the cache-isolation change. ### Phase 75: Local Super-Admin Credential Recovery — Complete - Confirmed the requested account is the local super administrator `13800138000`; the previous plaintext password was not recoverable from its server-side hash. - Generated a new strong password and reset it through the running admin password API, so the old password is invalidated. - Saved the new credential as `super-admin` in the project browser vault, then cleared the browser cookies and verified the saved profile logs in automatically to `/create` with super-admin navigation. ## Session: 2026-08-12 - Quota Guard and Super-Admin Billing Exemption ### Phase 76: Quota Guard and Super-Admin Billing Exemption — In progress - User confirmed the recommended boundary: ordinary users are blocked by insufficient shared organization balance; super-admins calculate and record cost but do not consume organization quota. - Inspected the existing quote, submission, worker, Seedance settlement, usage-record, and UI error paths. Real platform submissions already reserve before provider dispatch, and `InsufficientBalanceError` already maps to HTTP 402; implementation will preserve that boundary. - Planned changes: add role-aware usage context, persist `quotaExempt` on billing snapshots, bypass wallet charge/refund for super-admin jobs, keep Seedance actual-cost settlement metadata, and expose the existing balance error in the create UI. ### Phase 76: Quota Guard and Super-Admin Billing Exemption — Complete - Added `role` to platform usage context and persisted it through generation jobs so the billing service can identify super-admin generation independently of organization binding. - Added `quotaExempt` to quote/job billing snapshots. Super-admin quotes work without an organization; submission marks them as calculated-but-not-charged, skips wallet charge/refund entries, and Seedance still reconciles actual completion-token cost in the job snapshot. Successful usage events retain `chargedAmountFen`. - Kept ordinary generation strict: wallet reservation runs before provider dispatch, and insufficient balance raises the existing HTTP 402 error with `余额不足,请先充值。`; the create UI surfaces that response and labels super-admin estimates/tasks as not counted against quota. - Updated README/API billing semantics and added regression tests for insufficient balance, unbound super-admin image billing, super-admin Seedance settlement, usage cost recording, and ordinary unbound rejection. - Verification: focused billing tests 17/17, full Vitest 24 files / 96 tests, TypeScript, production build, and `git diff --check` passed. - The repository-local test/typecheck wrappers initially could not find `node`; reran the same checks with the bundled workspace Node runtime and they passed. ## Session: 2026-08-12 - Alibaba Cloud RDS PostgreSQL Adapter ### Phase 77: Planning and Gate - Complete - Initialized project-memory templates on an isolated `codex/rds-postgres-adapter-7f2c1a` worktree and committed only that baseline so feature drift can be enforced without touching the dirty `main` worktree. - Claimed task `20260812-rds-postgres-adapter-7f2c1a`; Concurrent Task Gate and Planning Gate passed. - Read the active task, project memory entry set, relevant architecture/domain/evidence/commitment files, peer Docker task, and existing task planning history. - Confirmed no semantic conflict with the peer task: it only verifies the Docker build command and does not authorize or perform application changes. - Chose one deep PostgreSQL module with stable store interfaces, explicit backend selection, fail-closed production behavior, versioned migrations, and ACK workload-specific secret boundaries. - **Status:** complete ### Phase 77: Implementation - Added the server-only PostgreSQL adapter and replaced Supabase access in data, account, and billing stores while preserving local JSON mode and public store contracts. - Added versioned migration tooling, application-role grants, direct PostgreSQL bootstrap/import scripts, Docker migration assets, `/api/ready`, and ACK workload templates. - Completed two independent read-only audits and fixed all findings, including migration Job backend selection, application grants, public Ingress isolation, wallet idempotency concurrency, failed-login concurrency, billing conflict mapping, and JSONB condition normalization. - The first mandated Sol final review returned FAIL. Fixed every reported code item and started a clean second Sol review: tenant-safe payload-bound wallet idempotency, fail-safe historical usage duplicate detection, precise/no-default grants, full runtime privilege readiness, atomic password changes, server-only module guards, and aligned npm/pnpm runtime versions. - Verification passes: `npm ci --ignore-scripts`, frozen pnpm lock validation, `npm run deploy:check` for 8 manifests, 31 Vitest files / 119 tests, `tsc --noEmit --incremental false`, Next production build (including `/api/ready`), script syntax, SQL static assertions, documentation drift, and `git diff --check`. - External validation remains unavailable: no live RDS credentials, ACK kubeconfig, Docker daemon, or `psql`; these are deployment prerequisites, not locally claimed results. - The second mandated Sol review and the post-fix incremental review both returned `PASS` with no blocking findings. The last regression found by the main-thread verification was corrected so wallet idempotency binds immutable accounting fields while allowing description/metadata audit details to evolve across a retry. - **Status:** complete