Skip to content

fix(models): say model edits do not survive a restart, and log every override - #441

Merged
argszero merged 1 commit into
mainfrom
fix/admin-model-editor-overwrite-visibility
Oct 26, 2026
Merged

argszero merged 1 commit into
mainfrom
fix/admin-model-editor-overwrite-visibility

Conversation

@argszero

Copy link
Copy Markdown
Owner

Summary

The admin model editor lets an operator change a price or add a model, and the next startup undoes it: db::seed_models re-asserts config.toml's [[models]] over every price column and deletes every row config does not contain. Measured on db0160f in #440: an edited price reads back as its config value after a restart, and an added model disappears entirely.

Both halves of this fix are about visibility, not precedence.

1. The panel stops promising something the server undoes. admin.models.sub said edits "take effect immediately" and said nothing about a restart — the opposite of what happens. It now says that config.toml's [[models]] is the authoritative source, that a price changed in the editor and a model added there are overwritten at the next startup, and that an added model's row is deleted. Both language packs, the HTML default text, and the sentence in ui/README.md that repeated the same claim are updated; js/i18n.js's cache-bust token moves with them.

2. The startup seed stops being silent. seed_models is split into a reporting function and a thin logging wrapper. For every row whose stored price differs from the config value it emits one WARN naming the model and each changed column as old -> new; for every row it deletes it emits one WARN naming the model. The existing INFO summary line keeps its shape and gains the override count, so the two numbers an operator cares about sit on one line.

What this PR deliberately does not do: it does not decide which source wins. #440 leaves two ways out — make the write honest (this PR), or stop re-asserting prices over rows that already exist — and the second is a change of pricing authority that belongs to the owner. That question is left open in #440, so this PR names the issue without closing it.

Money impact

No arithmetic changes, no stored row rewritten, no bill moves. usage_records and transactions keep whatever they were settled at; nothing here touches settlement, dao::get_model_price, or the router's pricing gate. What changes is that the operator is told the truth in the panel, and the startup log records each override with its figures.

Evidence on a real binary

Temp data dir, temp config, admin API only — nothing near a real deployment.

Run 1: PATCH /api/admin/models/9 {"input_per_m": 1.23}, then POST a probe/probe-model-x.

Read input_per_m (claude-opus-5) probe rows
before the edit 5.0 0
after the edit, same process 1.23 1

Run 2: SIGTERM, restart on the same data dir.

Read input_per_m probe rows
after the restart 5.0 (restored) 0 (deleted)

And the restart's own startup log now says why. The process logs in Chinese, like the rest of this repository's logs, so these three lines are carried here in English translation:

WARN  models seed: overwrote the price of anthropic/claude-opus-5 -- input_per_m: 1.23 -> 5.0 (config.toml [[models]] is authoritative)
WARN  models seed: deleting models row probe/probe-model-x -- config.toml [[models]] does not contain it (this is where a model added in the admin panel disappears)
INFO  models seed: 24 rows upserted (source config.toml [[models]]), 1 row of prices overwritten, 1 config-removed row deleted

A startup over an untouched database reports 0 rows of prices overwritten, 0 config-removed rows deleted and emits no warning — the warnings are not noise on every boot, and that half is asserted by a test rather than by this paragraph.

Tests

  • db::tests::seed_models_reports_the_prices_the_config_overwrites — seeding an unchanged database reports nothing; after an admin-style UPDATE models SET input_per_m = 1.23 the next seed reports exactly that one column as 1.23 -> 4.5, the message carries both figures and names the model, and a third seed is quiet again.
  • db::tests::seed_models_reports_the_rows_it_deletes — a row config does not contain is reported by name and really deleted, and a deletion is not reported as an override.
  • Both fail with the reporting disabled: mutating the detection to report nothing turns them red (2 passed, 2 failed), so they pin the behaviour and not the prose.
  • cargo fmt --check clean, cargo clippy --all-targets -- -D warnings clean, cargo test 588 passed, 0 failed (baseline 586 plus the 2 new tests).

Boundary

PriceOverride compares the seven scalar price columns and the currency. It does not compare tiers_json: tier prices are a config-only field the admin interface does not express (patching a row clears it to []), and rendering that JSON in the startup log is not a figure a reader can use. The override of tier prices still happens; it is simply not part of this warning.

Refs #440 — the precedence question stays open there for the owner.

@argszero
argszero merged commit a6588f8 into main Oct 26, 2026
2 checks passed
@argszero
argszero deleted the fix/admin-model-editor-overwrite-visibility branch October 26, 2026 07:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant