Covers the model authoring + publish contract via tRPC: model.upsert (draft) ->
modelVersion.upsert (baseModel SD 1.5) -> model.getById read-back -> model.publish
-> assert status Published -> best-effort delete cleanup. Fileless: publishModelById
has no file/scan precondition (scan gate is UI-only), and the binary B2 upload is
already covered by preview-post-upload.spec.ts. No rate limit on these procedures
(unlike article.upsert), so role tester. Mirrors preview-article.spec.ts. Report-only.