This release branch starts from the latest origin/main and folds in the
current origin/dev snapshot so the PR to main can follow the repo's
publish flow without opening directly from dev. Conflict-heavy files
were normalized back to the dev snapshot where necessary so the release
branch reflects the code currently being carried on dev instead of a
line-merged hybrid.
Constraint: Publication flow requires a clean release branch from latest origin/main rather than a PR directly from dev
Constraint: The branch must preserve the current dev snapshot even when main and dev have drifted substantially
Rejected: Open the PR directly from dev | violates the repo publication flow
Rejected: Manually redesign every historic dev/main conflict during release prep | too broad for a publish branch
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Treat this branch as a publication snapshot of dev-on-top-of-main, not as a general cleanup pass over old divergence
Tested: update-center focused vitest suite on release branch; typecheck; build:web; docs:build; repo:drift-check
Not-tested: Full npm test remains red from inherited tmp/sub2api frontend suites and an existing firstByteTimeout unhandled error
The update center previously surfaced stable Docker Hub candidates but
left dev and branch-tag rollouts stranded in SSH and Helm commands.
This adds a repo-native manual Docker tag entrypoint in Settings so
operators can deploy dev, branch, temporary, or sha tags through the
existing helper flow without changing the backend deploy contract.
Constraint: Keep the existing helper API and digest-aware Helm contract unchanged
Constraint: Preserve stable Docker Hub candidate discovery for default reminders
Rejected: Expand automatic Docker Hub discovery to all branch tags | would blur stable release reminders with operator-only rollout targets
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep automatic candidate detection stable-first; manual tag deploy is the escape hatch for non-stable tags
Tested: update-center focused vitest suite; typecheck; build:web; docs:build; repo:drift-check
Not-tested: Full npm test remains red due to unrelated tmp/sub2api frontend suites and an existing firstByteTimeout unhandled error
The root checkout already contained a large in-progress proxy, transformer,
and settings refactor. This commit captures that exact work on a dedicated
local dev branch without disturbing the original dirty worktree, so the
changes can be continued or split from dev instead of living only as
uncommitted state.
Constraint: The source checkout was already dirty on another branch, so the move had to preserve that worktree while excluding local .idea and .omx residue from the commit
Rejected: Switch the dirty root checkout directly to dev | risked disrupting the original branch and in-progress state
Confidence: medium
Scope-risk: broad
Reversibility: clean
Directive: Treat this as a transfer snapshot; fix the failing oauth/accountTokens/normalized/docs test regressions before merge or publication
Tested: git diff --check; npm run typecheck; npm run repo:drift-check
Not-tested: Clean test pass; npm test currently fails in oauth routes, accountTokens sync, shared normalized helpers, gemini route expectations, architecture-boundaries, and docs vitepress config
* Expose more payload-rule upstream types in Settings
The first payload-rules UI only offered a narrow set of protocol labels, which
made live troubleshooting confusing once real playground traffic routed through
platforms like sub2api instead of codex. This expands the selectable upstream
types, extracts the option list into one small helper, and renames the field to
上游类型 so the UI matches what the runtime matcher actually uses.
Constraint: Must preserve the existing payload-rules schema key (`protocol`) even though the UI wording is now upstream-type oriented
Rejected: Leaving the dropdown codex/openai-only and telling operators to hand-edit JSON | too easy to misconfigure during live routing diagnosis
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If new canonical site platforms are added, update payloadRuleProtocolOptions.ts so the visual editor stays aligned with runtime matching
Tested: npx vitest run --root . src/web/pages/settings.payload-rules.test.tsx src/web/pages/settings.payload-rule-platform-options.test.ts
Tested: npm run typecheck:web
Tested: npm run typecheck:web:test
Tested: npm run repo:drift-check
Not-tested: Manual dropdown interaction in a browser
* Keep payload-rule upstream types aligned with one-api backend support
Code review caught that the visual editor still omitted one-api even though the
backend continues to treat it as a valid upstream platform. This adds the
missing option and extends the focused option-set test so operators can create
payload rules for one-api without dropping to raw JSON.
Constraint: Must preserve the runtime payload-rules schema and only close the UI/backend option gap
Rejected: Removing one-api from the backend in this PR | unrelated behavioral change and broader migration risk
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: When backend platform support changes, update payloadRuleProtocolOptions.ts and its focused test in the same PR
Tested: npx vitest run --root . src/web/pages/settings.payload-rules.test.tsx src/web/pages/settings.payload-rule-platform-options.test.ts
Tested: npm run typecheck:web
Tested: npm run typecheck:web:test
Tested: npm run repo:drift-check
Not-tested: Manual browser check of the expanded dropdown list
* Make payload request overrides configurable from Settings
The payload-rules engine already existed in the proxy path, but operators had
no supported runtime UI to manage CPA-style overrides. This wires the setting
through the runtime settings API, adds strict validation, and ships a
low-friction visual editor with an advanced JSON fallback so common cases like
Codex high reasoning can be configured without hand-editing backend state.
Constraint: Must reuse the existing payload-rules execution path and settings table without schema changes
Constraint: Must fit the existing metapi Settings-page patterns rather than introducing a standalone config surface
Rejected: JSON-only editor as the primary UX | too long and too easy to misconfigure for common cases
Rejected: A brand-new backend rule format for the UI | would duplicate the existing payload-rules source of truth
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep visual-rule serialization and advanced JSON editing in sync before extending the rule model
Tested: npm run typecheck
Tested: npx vitest run --root . src/server/services/payloadRules.test.ts src/server/routes/api/settings.events.test.ts src/web/pages/settings.payload-rules.test.tsx
Tested: npm run repo:drift-check
Not-tested: Manual browser interaction smoke on the Settings page in this clean PR worktree
* Prevent payload-rules saves from violating review expectations
Code review surfaced two operator-facing edge cases in the first payload-rules
PR: successful rule parsing could still be committed before a later validation
error, and visual edits could silently overwrite unsaved advanced JSON. This
stages payload-rules until the request finishes validating and adds an explicit
confirmation gate before visual actions discard unsynced advanced edits.
Constraint: Keep the fix narrow to the reviewed payload-rules feature without refactoring unrelated runtime-settings atomicity behavior
Rejected: Silently skipping draft resync while keeping visual edits active | would leave save semantics ambiguous when advanced JSON stays dirty
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If the settings endpoint ever moves toward full request atomicity, re-check this staged payload-rules write path against the broader strategy
Tested: npm run typecheck
Tested: npx vitest run --root . src/server/routes/api/settings.events.test.ts src/web/pages/settings.payload-rules.test.tsx
Tested: npm run repo:drift-check
Not-tested: Manual browser smoke of the confirmation dialog text
* add k3s update center
* fix update center status timeouts
* Polish update center settings UI
* Document k3s update center
* Refocus update center docs for users
* Clarify k3s migration path in docs