Commit Graph
2548 Commits
Author SHA1 Message Date
jimmyleocn dfd3cd8930 fix(web): hide system settings from non-root admins (#7513) 2026-09-30 22:32:30 +08:00
Schwa[R]z 8112120673 fix(web): Add class to wrap the long strings at auto-disable status tooltip content in channel manage page (#7604) 2026-09-30 21:50:28 +08:00
CaIon 2035a82aeb feat(web): add a refresh button to the channels table
A Refresh button next to the sensitive-data toggle reloads the channel
list with the current search, filters, sorting and page. It is marked
busy and its icon spins while the list is loading.
2026-09-30 20:52:57 +08:00
CaIon 4924361aef feat(auth): edit the name and permissions of an access token
The token menu now opens an edit dialog instead of a rename prompt.
Renaming still needs no verification. Changing the permissions requires
step-up verification bound to the token id and the new grant, so a
proof cannot be replayed for another token or another set of
permissions; the grant is checked against what the owner can do, the
same as at creation. PATCH /api/user/access_tokens/:id takes an
optional scopes list and is rate limited like the other token routes.

A token that holds permissions the catalog no longer offers can still
be renamed and keeps them; a new grant only contains offered
permissions. Edit stays disabled until the permission catalog has
loaded.

Grant changes are audited as access_token.update with the previous and
new scopes, and audit details show both as permission names.

The permission picker for tokens and admin users now uses toggle
buttons. Token permissions are grouped by personal, administration and
system, each group collapsible with a selected count and select-all or
clear.
2026-09-30 20:52:36 +08:00
CaIon caca52f8de feat(auth): replace the dashboard access token with scoped access tokens
Each user can now hold up to 20 named access tokens in the
user_access_tokens table instead of a single token on the user row.
Tokens are shown once at creation (nap_ prefix) and stored as a SHA-256
digest. They expire after 30 days by default; a token without expiry is
allowed with a warning.

A token only reaches the routes its scopes allow. Scopes are picked from
the same permission matrix as admin permissions and are limited to what
the owner can do; every management route declares the scope it needs,
and routes without a declaration reject tokens. Token management itself
always requires a browser session.

Tokens can complete step-up verification, so verified actions such as
changing a password or 2FA settings work with a token; such changes sign
out all browser sessions. Disabling a user keeps their tokens, deleting
the account removes them.

The existing dashboard token keeps working for 30 days after the
upgrade. It can be revoked but no longer regenerated, and afterwards it
is rejected with ACCESS_TOKEN_LEGACY_RETIRED. The security page lists
tokens with their access records, and audit details show scope names.
2026-09-30 17:24:19 +08:00
CaIon 6cbb1c7edb feat(auth): require step-up verification for admin user management
Deleting a user, changing their status or role, setting a password or
admin permissions, creating an admin, resetting a passkey, disabling 2FA
and clearing a binding now need a single-use verification proof. The
proof context names the managed user (and the action or binding where
relevant), so it cannot be reused for another user or operation. Quota
adjustments and edits to display name, group or remark stay unchanged.

The admin.user.* scopes are issued only to admins. An admin with 2FA or
a passkey must use one of them; otherwise password or a bound OAuth
account is accepted. The users page asks for verification before sending
each gated request.
2026-09-30 17:24:19 +08:00
CaIon 3509ae7c19 fix(pricing): keep prices saved before a usage profile narrows editable
An unchanged model expression or provider override of a single-plugin
model stays saveable after the plugin drops a fact from its profile, so
a full pricing save is no longer blocked by existing prices. Shared
models still follow each provider's profile.

The task pricing table reads a dropped fact at the value a plugin keeps
reporting: price terms on dropped counts are omitted, tiers requiring a
dropped boolean to be true are skipped, and other conditions on dropped
facts are removed with the first matching tier kept. Existing prices
open in the table with only the remaining fields.
2026-09-30 17:24:19 +08:00
CaIon f5e54ccdb2 fix(web): revalidate marketplace fetches so stale caches do not fail integrity checks
Marketplace hosts serve versioned plugin sources as immutable. When a file
is republished in place, a browser that cached the earlier bytes keeps
reading them, while the index is fetched fresh and declares the new hash,
so the install dialog reports a sha256 mismatch for a correct source.

Fetch the plugin source, the sidecar icon and the index with
cache: 'no-cache' so each request revalidates with the host (a 304 when
unchanged).
2026-09-30 17:24:18 +08:00
zenor0 d04c118c88 fix(channel): preserve Responses WebSocket setting on save (#7468) 2026-09-23 21:00:00 +08:00
指短琴长 c76452d224 fix(playground): add break-all to playground input (#6600) 2026-09-23 17:06:35 +08:00
feitianbubu 6c14c0762d feat: highlight differing values in source price expressions (#7543) 2026-09-23 13:47:12 +08:00
feitianbubu a46f045d6d fix: match current price column width to source columns so expressions wrap alike (#7542) 2026-09-23 12:53:14 +08:00
RedwindA 996adffe51 fix(web): keep text selection when opening a model pricing row for editing (#7403) 2026-09-22 16:40:59 +08:00
feitianbubu 8cb88ebd17 fix: move force operation into confirm slot so plugin-in-use dialog has one cancel button (#7528) 2026-09-22 16:37:08 +08:00
Yorick 9310231b3c fix(logs): keep model badge text readable and compact (#7504)
* fix(logs): prevent model badge descenders from clipping

* fix(logs): constrain wrapped model badge width

* fix(logs): preserve compact model name line spacing

* fix(logs): give wrapped model names sufficient line height
2026-09-22 00:07:07 +08:00
CaIon b6809a52df fix(web): resolve safe constants in plugin metadata previews 2026-09-21 23:02:37 +08:00
CaIon 54eee488be fix(web): isolate theme preferences in local storage 2026-09-21 21:01:16 +08:00
CaIon c0cff23a3a fix(plugins): store task plugin source as longtext on MySQL and raise the upload cap to 8 MiB
A bare TEXT column holds 64 KiB on MySQL, and the shipped alibaba plugin
is already 73 KB, so uploading an override of it failed with "Data too
long for column 'source'" or was silently truncated. The 1 MiB upload
cap also blocks the larger plugins planned next.

Add model.LongText, a string type that picks longtext on MySQL and text
on PostgreSQL and SQLite through GormDBDataType, and use it for source
and icon. Neither type carries a length, so AutoMigrate leaves an
up-to-date column alone and widens the shipped MySQL text column once
without data loss. Raise the source cap to 8 MiB on the backend and in
the frontend picker, importers and locale strings.

Verified fresh and rc.39-upgrade startups twice each on SQLite, MySQL
5.7.44 and 8.4.11, PostgreSQL 9.6.24 and 17.11; the second start issues
no DDL and a 73 KB source round-trips on every engine.
2026-09-21 21:01:16 +08:00
CaIon e537dc380b fix(web): expose plugin activation after upload 2026-09-21 21:01:15 +08:00
CaIon 00e8a00cb4 fix(web): include provider icons in Windows builds 2026-09-21 21:01:15 +08:00
CaIon 9a0be8750a fix(web): keep task pricing editable after a plugin narrows its enum values
When a task plugin stops declaring an enum value (Seedance 2.0 mini now
offers 480p and 720p only), an expression saved with 1080p and 4k
branches no longer opened in the visual price table: the parser rejected
the whole tier chain on the first undeclared value, the editor fell back
to expression mode with a "cannot be represented" notice, and switching
to the visual editor reset every price to zero.

Treat a branch on an undeclared enum value as unreachable and skip it,
so the remaining tiers stay editable with their prices preserved. Nested
conditions in the pricing display treat such a comparison as never
matching. Editing a price regenerates the expression without the
unreachable branches; opening the editor alone leaves the stored
expression unchanged.
2026-09-20 23:27:57 +08:00
CaIon 9978ee1e25 feat(billing): configure trust threshold and input pre-consume multiplier 2026-09-20 22:17:20 +08:00
CaIon 2fddb863f2 feat(models): add bulk field selection to metadata sync 2026-09-20 19:27:37 +08:00
CaIon a5bf940220 fix(web): correct dialog viewport fallbacks and editor gutter alignment 2026-09-20 18:24:39 +08:00
CaIon 03563a4a79 feat(plugins): serve OpenAI Images API through task plugins
Add the synchronous openai_image host protocol so a task plugin can claim
POST /v1/images/generations and /v1/images/edits; the host submits the
task, polls it inside the request and lets the plugin render the OpenAI
image response. Unclaimed models still fall back to the HTTP image relay.

- Migrate Ali (Bailian) image models to the alibaba plugin and remove the
  ali channel image/wan adaptors and the qwen model setting
- Add Doubao Seedream image generation to the doubao plugin
- Support retainResult on routes and indexed multipart file references
- Settle image counts from upstream usage or image payloads; document the
  rule in the billing conventions and plugin API docs
- Show billing source and task artifacts in usage logs; rename the
  DoubaoVideo channel display name to Doubao and refresh the favicon
2026-09-20 17:58:45 +08:00
CaIon c49972441e fix(web): keep mobile dialog actions within visible viewport 2026-09-20 17:51:53 +08:00
CaIon 585c4610e5 feat(keys): show and copy configured API addresses 2026-09-20 17:51:53 +08:00
CaIon d904b97000 feat(settings): improve group configuration UX and drag sorting 2026-09-20 17:51:53 +08:00
CaIon da2540dda1 fix(channels): align card metrics and remove badge spacing 2026-09-20 17:51:53 +08:00
CaIon 3fdf9083dc fix(settings): move documentation link to site settings 2026-09-20 17:51:52 +08:00
CaIon 58a9eff4c8 style: refresh logo 2026-09-20 17:51:52 +08:00
CaIon db536ec8bc fix(channels): simplify model redirects and clarify panel controls 2026-09-20 17:51:52 +08:00
CaIon 6b638788c6 fix(channels): preview upstream model changes before applying 2026-09-20 17:51:52 +08:00
CaIon 2d7aef7414 fix(web): restore CC Switch model dropdown 2026-09-20 17:51:52 +08:00
CaIon 4c34f25a49 feat(channel): bind multiple task plugins to New API channels
A New API (type 60) channel proxies another gateway that may host many
task plugins, so the channel setting gains task_extend_plugin_keys; the
single task_plugin_key stays valid there as well. Channel selection,
shared-model candidate rebinding, the task_plugin.bind permission gate,
plugin usage counting and the disable cascade (which now unbinds gateway
channels instead of disabling them) all honour the union of both fields,
and plugins may no longer claim channel type 60 in channelTypes.

Plugins declare meta.upstreams and the host injects ctx.upstream into
every driver hook context. On a type-60 channel the driver addresses its
own prefixed native routes (doubao, alibaba, kling, jimeng) and the host
sends the channel key as a Bearer header for every auth type; polling
threads the channel type through ChannelMeta and tasks keep the key
that submitted them. Only plugins declaring new_api can be bound.

The channel form offers an "Upstream task plugins" selector for type-60
channels, MultiSelect options can carry an icon, and the plugin API docs,
type declarations and schema describe the additive apiVersion 1
extension.
2026-09-20 17:51:51 +08:00
CaIon 33320407f4 fix(web): isolate OIDC discovery when saving OAuth settings
Run discovery only when its URL changes or OIDC is enabled. Show URL validation errors beside the field and keep save actions disabled throughout submission. Correct Well-Known terminology in translations and cover provider-independent saves, validation, discovery failures, and loading state.

Validation from web/: bun run test src/features/system-settings/auth/__tests__/oauth-settings.test.tsx src/features/system-settings/auth/__tests__/passkey-settings.test.tsx (30 passed); bun run typecheck; bunx oxlint -c .oxlintrc.json src/features/system-settings/auth/oauth-section.tsx src/features/system-settings/auth/__tests__/oauth-settings.test.tsx; bunx oxfmt --check on both files; bun run build; bun run i18n:sync. In-app browser checked GitHub save and inline OIDC error using an isolated fixture with mocked API responses.

Security scope: settings form only. Consulted OWASP ASVS 5.0.0 section 8.3.1 and the Authentication, Session Management, and OAuth2 Cheat Sheets. Server authorization and authentication protocol flows are unchanged; this is not a full authentication compliance assessment.
2026-09-20 17:51:51 +08:00
CaIon 9c3d3aeb3c perf(web): lazy-load provider icons and reduce page rerenders 2026-09-20 17:51:51 +08:00
CaIon b932e6d876 fix(web): robustly display conditional task billing prices 2026-09-20 17:49:37 +08:00
CaIon a89037d0b9 fix(web): start linked-account verification from the provider button
When the security verification dialog only offers OAuth, the provider
button was a no-op selector for an already selected provider and the
actual OAuth popup only opened from the footer Verify button.

Make the provider button trigger verification directly, hide the footer
Verify button on the OAuth tab, and let onVerify accept an explicit
input so the clicked provider is used instead of stale state.
2026-09-20 17:46:33 +08:00
Seefs 972aed1972 fix(log): derive response model mismatch from names instead of a stored flag (#7464) 2026-09-19 13:51:18 +08:00
zuiho e04c05c2b9 fix(web): 修复小数输入限制和日志分组选项未遮挡的问题 (#7453)
* fix(web): accept fractional group ratios and tool prices

* fix(web): mask portaled group options in usage log privacy mode

* fix(web): limit pricing input steps to four decimal places
2026-09-19 02:28:28 +08:00
Calcium-Ion 96b0da2273 refactor(log): 恢复费用气泡并用图标区分订阅来源 (#7451)
* refactor(log): restore compact cost bubbles and source icons

* Delete .github/pr-previews/usage-log-cost-bubbles.png
2026-09-19 01:13:31 +08:00
Seefs ea336ed665 fix(log): hide funding source labels when subscriptions are not in play (#7450) 2026-09-19 00:39:38 +08:00
Seefs ed7c4e35d4 feat(log): flag upstream response model mismatches (#7418)
* feat(log): flag upstream response model mismatches

* fix(log): refine response model mismatch warnings

* fix(log): skip model details when no mapping or response difference exists

* fix(log): omit redundant response model metadata
2026-09-18 11:35:03 +08:00
Seefs 9e905a83e1 refactor: show subscription deductions and improve cost display (#7272)
* fix: subscription log

* fix(usage-logs): hide wallet labels when subscriptions are unavailable
2026-09-18 11:31:51 +08:00
CaIon 32ef6d216f feat(web): add channel passthrough controls and usage guidance 2026-09-18 11:24:31 +08:00
CaIon fa3cc1c6b9 feat(web): offer the Responses WebSocket toggle for advanced custom, sub2api and new-api channels
Gate the toggle, the quick option and the configuration marker through
one shared predicate that mirrors the backend allow list, add the
Sub2API channel type constant, and explain under the toggle that
advanced custom channels only use converter-free /v1/responses routes.
2026-09-18 11:24:31 +08:00
CaIon d806943661 fix(web): tidy channel health policy layout
Lay out the channel health form with the shared settings grid so switch
rows span the full width and inputs align in two columns instead of a
fixed three-column grid that stretched the switches. Nest the test mode
and interval under the scheduled tests switch, make the mode select fill
its column, and replace the alert boxes and channels link at the top with
plain hint text. Add a layout regression test and the new group label
translation.
2026-09-18 11:24:31 +08:00
CaIon 42cbe6206a chore(web): add intl-locale lint plugin and update agent rules
Enforce toIntlLocale() for every Intl call through a project oxlint
plugin with its own tests, adopt it in the billing time fields, add the
missing floating-window labels, and refresh the agent instructions.
2026-09-18 11:24:31 +08:00
CaIon e2471403c7 fix(pricing): adjust billing expression condition display 2026-09-18 11:24:31 +08:00