{"slug": "release-v1-0-0-loco-is-stable", "title": "Release v1.0.0 – Loco is stable", "summary": "Loco released v1.0.0, its first stable version, featuring Sea-ORM 2.0, first-class LLM/agent support, priority queues, and a major dependency modernization. The release introduces breaking changes including 64-bit primary keys, a Redis backend switch to Sorted Sets for priority queues, and the merger of MirrorStrategy and BackupStrategy into ReplicatedStrategy.", "body_md": "## 1.0.0 - 2026-07-25\n\n1.0.0 is the first stable Loco release — a single, intentionally-breaking\n\nmilestone. Its headline is the move to **Sea-ORM 2.0**, alongside first-class\n\nLLM/agent support, priority queues, a broad dependency modernization, and a deep\n\nhardening pass across the queue, storage, config, error, remote-IP, and\n\nmiddleware subsystems. Follow the step-by-step\n\n[0.16 → 1.0 upgrade guide](https://loco.rs/docs/extras/upgrades/).\n\n### Breaking Changes\n\n**Sea-ORM 2.0 + sqlx 0.9.** Bump`sea-orm`\n\n/`sea-orm-migration`\n\nto`2.0`\n\n(app +`migration`\n\ncrate), direct`sqlx`\n\nto`0.9`\n\n, update the Sea-ORM CLI, and\n\nregenerate entities. Raw-`Statement`\n\ncalls gain a`_raw`\n\nsuffix; runtime SQL\n\nstrings need`AssertSqlSafe`\n\n. MSRV is**1.94**(sea-orm 2.0.0 declares it).\n\n(Adopted from the SeaQL fork and\n\n[#1698](https://github.com/loco-rs/loco/pull/1698).)**Generated primary/foreign keys are now 64-bit (BIGINT /** Also the`i64`\n\n).\n\n`int`\n\n/`unsigned`\n\nfield types generate 64-bit columns. Only affects newly\n\ngenerated code; existing tables are untouched.**Priority queues — Redis backend change.** The Redis worker moved from Lists\n\nto Sorted Sets (ZSET) to support priority;**drain existing Redis queues before**. Postgres/SQLite auto-migrate a\n\nupgrading`priority`\n\ncolumn (no action).\n\n([#1693](https://github.com/loco-rs/loco/pull/1693))(`Worker::perform_later()`\n\nreturns the job ID`Result<String>`\n\n), and\n\n`Queue::enqueue()`\n\nreturns`Result<Option<String>>`\n\n. Existing\n\n`perform_later(...).await?;`\n\nkeeps working. ([#1624](https://github.com/loco-rs/loco/pull/1624), fixes[#1623](https://github.com/loco-rs/loco/issues/1623))instead of flat`PageResponse<T>`\n\nexposes`meta: PagerMeta`\n\n`total_pages`\n\n/`total_items`\n\n(also carries`page`\n\n/`page_size`\n\n). ([#1685](https://github.com/loco-rs/loco/pull/1685), fixes[#1683](https://github.com/loco-rs/loco/issues/1683))**View engine:** use`engines::TeraView::build_with_post_process(...)`\n\ninstead\n\nof`TeraView::build()?.post_process(...)`\n\nin`after_routes`\n\n.**Dependency majors:**`thiserror`\n\n1→2,`tower`\n\n0.4→0.5,`heck`\n\n→0.5,\n\n`byte-unit`\n\n4→5,`ipnetwork`\n\n0.20→0.21,`strum`\n\n→0.27,`redis`\n\n0.31→1,\n\n`bb8-redis`\n\n→0.26,`opendal`\n\n0.54→0.57;`serde_yaml`\n\n→`serde_yaml_ng`\n\n.\n\nTransitive for most apps.- Removed the dead\n`loco-cli`\n\ncrate (superseded by`loco-new`\n\n, the published\n\n`loco`\n\nbinary). The`ExtraDbInitializer`\n\nremoved; use`MultiDbInitializer`\n\n.\n\nsingle-extra-connection initializer (`initializers.extra_db`\n\n, which layered a\n\nbare`Extension<DatabaseConnection>`\n\n) is gone. Use`MultiDbInitializer`\n\nwith a\n\none-entry`initializers.multi_db`\n\nmap instead, and extract the connection with\n\n`Extension<MultiDb>`\n\n+`multi_db.get(\"<name>\")`\n\n. This collapses two\n\nnear-identical initializers into one named-connections abstraction.Construct it with`AppContext`\n\nis now`#[non_exhaustive]`\n\n.\n\n`AppContext::builder(environment, db, config)`\n\n(or`builder(environment, config)`\n\nwithout the`with-db`\n\nfeature) followed by optional\n\n`.queue_provider(..)`\n\n/`.mailer(..)`\n\n/`.storage(..)`\n\n/`.cache(..)`\n\n/`.shared_store(..)`\n\nand`.build()`\n\n. Direct struct-literal construction and exhaustive pattern\n\nmatches on`AppContext`\n\nfrom outside the crate no longer compile; field\n\naccess (`ctx.db`\n\n,`ctx.config`\n\n,`State`\n\n/`FromRef`\n\nextraction) is unchanged.\n\nThis makes future context fields non-breaking to add.**Storage**`MirrorStrategy`\n\nand`BackupStrategy`\n\nmerged into`ReplicatedStrategy`\n\n.\n\nThe two strategies were the same primary-plus-secondaries replication engine;\n\nthey are now one`storage::strategies::replicated::ReplicatedStrategy`\n\nwith a\n\nsingle`FailurePolicy`\n\nenum. Migrate:`MirrorStrategy::new(p, s, MirrorAll)`\n\n→\n\n`ReplicatedStrategy::mirror(p, s, FailurePolicy::FailIfAny)`\n\n;\n\n`BackupStrategy::new(p, s, BackupAll)`\n\n→`ReplicatedStrategy::backup(p, s, FailurePolicy::FailIfAny)`\n\n. Old`FailureMode`\n\nmaps:`AllowMirrorFailure`\n\n/\n\n`AllowBackupFailure`\n\n→`AllowAll`\n\n,`AtLeastOneFailure`\n\n→`AllowSingleFailure`\n\n,\n\n`CountFailure(n)`\n\n→`FailAtFailures(n)`\n\n. Secondary writes for the former\n\nbackup strategy now run concurrently (previously sequential); the collected\n\nerrors and failure decision are unchanged.**Local storage driver no longer defaults its root to**`/`\n\n.\n\n`storage::drivers::local::new()`\n\npreviously rooted the filesystem store at\n\n`/`\n\n, so any key — including one derived from user input — resolved against the\n\nwhole disk (e.g. downloading key`etc/passwd`\n\nread`/etc/passwd`\n\n). It now roots\n\nat the current working directory. Apps that relied on absolute-path keys should\n\nswitch to`local::new_with_prefix(\"/your/root\")`\n\nto opt back into an explicit\n\nabsolute root.**Background queue reworked into a** The`QueueProvider`\n\nadapter interface.\n\n`bgworker::Queue`\n\nenum (`Postgres`\n\n/`Sqlite`\n\n/`Redis`\n\n/`None`\n\n) is now a newtype\n\nover`Arc<dyn QueueProvider>`\n\n, so backends are pluggable (implement\n\n`QueueProvider`\n\nand wrap with`Queue::from_provider`\n\n). All existing methods\n\n(`enqueue`\n\n,`register`\n\n,`run`\n\n,`ping`\n\n,`cancel_jobs`\n\n,`clear_by_status`\n\n,\n\n`requeue`\n\n, …) keep the same signatures and behavior. Only two source-level\n\nchanges affect callers: construct a no-op queue with`Queue::empty()`\n\ninstead\n\nof`Queue::None`\n\n, and code that pattern-matched the enum variants (e.g.\n\n`Queue::Postgres(pool, ..)`\n\nto reach the raw pool) no longer compiles — use the\n\nprovider methods instead.**Fallback middleware defaults to** When the built-in fallback is`404`\n\n.\n\nenabled without an explicit`code`\n\n, it now returns`404 Not Found`\n\n(matching\n\nits docs and the bundled not-found page) instead of`200 OK`\n\n. Apps that relied\n\non the enabled fallback returning`200`\n\nmust set`code: 200`\n\nexplicitly. The\n\nfile-based fallback is unaffected (`ServeFile`\n\nreports its own status).Previously the first`{env}.local.yaml`\n\nnow deep-merges over`{env}.yaml`\n\n.\n\nexisting file won and the other was ignored, so a`.local.yaml`\n\nhad to restate\n\nthe whole config. Both files are now layered with local precedence: mappings\n\nmerge recursively; scalars and sequences in local replace the base value\n\n(sequences are not concatenated). Base keys now persist unless explicitly\n\noverridden.**More accurate HTTP status codes for errors.**`IntoResponse for Error`\n\npreviously collapsed ~28 of 35 variants to`500`\n\n.`Model(EntityNotFound)`\n\nnow\n\nreturns`404`\n\n,`Model(EntityAlreadyExists)`\n\nreturns`409`\n\n, model validation\n\nand form-body rejections return`4xx`\n\n(matching JSON rejections) instead of\n\n`500`\n\n. Genuinely-internal errors still return a generic`500`\n\n. Handlers that\n\nasserted on the old`500`\n\ns will observe the corrected codes.It now takes a new`JWT::algorithm()`\n\nrestricted to the HMAC family.\n\n`loco_rs::auth::jwt::JWTAlgorithm`\n\nenum (`HS256`\n\n/`HS384`\n\n/`HS512`\n\n) instead of\n\n`jsonwebtoken::Algorithm`\n\n. Asymmetric algorithms — which could never work with\n\nLoco's shared base64 secret and silently produced broken tokens — are no longer\n\nrepresentable.Previously this middleware walked`remote_ip`\n\nmiddleware rebuilt on`axum-client-ip`\n\n;`trusted_proxies`\n\nremoved.`X-Forwarded-For`\n\nright-to-left,\n\nskipping any address in a configurable`trusted_proxies`\n\nCIDR list (or a\n\nbuilt-in RFC-1918 + loopback list), so it could see through a chain of one or\n\nmore trusted proxies. It now trusts exactly**one** configured source\n\n(`source: ClientIpSource`\n\n, default`RightmostXForwardedFor`\n\n) and does**no**\n\nCIDR filtering — for the default it takes the last comma-separated value of the\n\nlast`X-Forwarded-For`\n\nheader verbatim, private or not. Single reverse-proxy\n\ndeployments are unaffected.**Multi-hop topologies (CDN → LB → ingress) must**\n\nnow configure their innermost hop to set the client IP (e.g. nginx\n\n`set_real_ip_from`\n\n/`real_ip_recursive`\n\n), or point`source`\n\nat a provider header\n\n(`CfConnectingIp`\n\n,`CloudFrontViewerAddress`\n\n,`XRealIp`\n\n,`ConnectInfo`\n\n, …).\n\nNote: an old config's`trusted_proxies:`\n\nkey is silently ignored (unknown\n\nfield), so review`remote_ip`\n\nbefore upgrading — this is a silent\n\nsecurity-relevant behavior change, not a load error. The`RemoteIP`\n\nextractor\n\nand its`Display`\n\noutput are unchanged.Update`auth_jwt`\n\nfeature renamed to`auth`\n\n.`features = [\"auth_jwt\"]`\n\n→`[\"auth\"]`\n\n(it gates JWT auth and the`ApiToken`\n\nextractor, as before).**Background-queue features collapsed.**`bg_pg`\n\n/`bg_sqlt`\n\n→`worker`\n\n(Postgres+SQLite; free once`sqlx`\n\nis compiled),`bg_redis`\n\n→`worker_redis`\n\n(adds`dep:redis`\n\n).`default`\n\nnow has`worker`\n\n(not Redis). A Redis queue needs\n\n`worker_redis`\n\n; the queue backend is selected at runtime by`queue.kind`\n\n.**Mailer**(call`Template::new(dir)`\n\nnow returns`Result`\n\n`Template::new(dir)?`\n\n).\n\nEmail templates render through a full Tera instance so they support inheritance\n\nand shared templates. Standard usage via`Mailer::mail_template`\n\nis unchanged.\n\n([#1694](https://github.com/loco-rs/loco/pull/1694))(was`Vars::cli_arg`\n\nreturns`Result<&str>`\n\n`Result<&String>`\n\n). Callers that\n\nrelied on`&String`\n\n(e.g.`.clone()`\n\ninto a`String`\n\n) should use`.to_owned()`\n\n.\n\n([#1732](https://github.com/loco-rs/loco/pull/1732))\n\n### Added\n\n**First-class LLM / agent support.** Root`AGENTS.md`\n\nteaches agents to build\n\nLoco apps;`llms.txt`\n\n/`llms-full.txt`\n\nare served from the site\n\n(llmstxt.org). Every`loco new`\n\napp ships an app-level`AGENTS.md`\n\n.**Priority queues** with`Worker::perform_later_with_priority(...)`\n\n; mailer\n\njobs default to priority`100`\n\n. ([#1693](https://github.com/loco-rs/loco/pull/1693))**Mailer implicit TLS (SMTPS / port 465)** via`mailer.smtp.tls`\n\n. ([#1774](https://github.com/loco-rs/loco/pull/1774), fixes[#1773](https://github.com/loco-rs/loco/issues/1773))**Run the scheduler without a worker**—`--scheduler`\n\nflag +\n\n`StartMode::ServerAndScheduler`\n\n/`WorkerAndScheduler`\n\n. ([#1742](https://github.com/loco-rs/loco/pull/1742), fixes[#1737](https://github.com/loco-rs/loco/issues/1737))- Email headers support in the mailer (\n[#1700](https://github.com/loco-rs/loco/pull/1700)). **Multi-recipient emails.**`Mailer::mail_multi`\n\n/`mail_template_multi`\n\nand the\n\n`MultiEmail`\n\n/`MultiArgs`\n\ntypes send one email to multiple To/CC/BCC\n\nrecipients (processed by a dedicated`MultiMailerWorker`\n\n). ([#1764](https://github.com/loco-rs/loco/pull/1764))**Email template inheritance & shared templates.** Mailer templates support\n\nTera`{% extends %}`\n\n/`{% block %}`\n\nand can share a common layout via\n\n`Mailer::mail_template_with_shared`\n\n/`Template::new_with_shared`\n\n.`loco generate mailer`\n\nnow scaffolds a`src/mailers/shared/`\n\nbase layout that the welcome\n\ntemplate extends. ([#1694](https://github.com/loco-rs/loco/pull/1694))- \"Create user\" task (\n[#1670](https://github.com/loco-rs/loco/pull/1670)). `UuidUniqWithDefault`\n\nand`UuidWithDefault`\n\ntypes ([#1642](https://github.com/loco-rs/loco/pull/1642)).- Allow overriding a secure header (\n[#1659](https://github.com/loco-rs/loco/pull/1659)). `Mailer::deliver_now`\n\n/`mail_template_now`\n\nfor synchronous sends.\n\nComplements`Mailer::mail`\n\n/`mail_template`\n\n(which enqueue via the background\n\nworker, like Rails`deliver_later`\n\n) with an inline send that bypasses the\n\nqueue (Rails`deliver_now`\n\n).Inside`MiddlewareStackExt`\n\nfor surgical middleware-stack edits.\n\n`Hooks::middlewares`\n\n, tweak the default stack instead of rebuilding it:\n\n`stack.insert_before(\"cors\", ..)`\n\n,`.insert_after(..)`\n\n,`.replace(..)`\n\n, and\n\n`.delete(\"logger\")`\n\n— matched by middleware name (Rails'\n\n`config.middleware.insert_before`\n\n/`delete`\n\n). Available via the prelude.**Optional JWT extraction.**`JWT`\n\nnow implements`OptionalFromRequestParts`\n\n,\n\nso a handler can take`Option<JWT>`\n\nto serve authenticated and anonymous\n\ncallers from one endpoint (`Some`\n\nwhen a valid token is present,`None`\n\notherwise).**Ergonomic verb-explicit route methods.**`Routes`\n\nnow has`get`\n\n/`post`\n\n/\n\n`put`\n\n/`delete`\n\n/`patch`\n\n/`head`\n\n/`options`\n\n/`trace`\n\nbuilder methods —\n\n`Routes::new().get(\"/ping\", ping)`\n\nalongside the existing\n\n`.add(\"/ping\", get(ping))`\n\n. They record the HTTP verb directly (exact\n\n`cargo loco routes`\n\noutput without relying on the debug-format regex).\n\nPurely additive;`add`\n\nis unchanged.**Opt-in background-job reaper (visibility timeout).** Each queue backend's\n\nconfig accepts a`reaper: { age_minutes, interval_seconds }`\n\nblock. When set,\n\nthe worker periodically requeues jobs stranded in`Processing`\n\n(e.g. by a\n\ncrashed worker) back to`Queued`\n\n, instead of requiring a manual\n\n`cargo loco jobs requeue`\n\n. Disabled by default — existing behavior is unchanged.**TLS to managed Postgres and Redis.** Postgres TLS works via the connection\n\nURL (`sslmode=require`\n\n,`sslrootcert=...`\n\n) with no feature flag, and a new\n\n`redis_tls`\n\nfeature enables`rediss://`\n\nfor both the queue and cache Redis\n\nbackends (webpki roots, pure-Rust`ring`\n\nprovider — no C toolchain). New\n\nhow-to: \"Connect to Postgres and Redis over TLS\". ([#1191](https://github.com/loco-rs/loco/issues/1191),[#1341](https://github.com/loco-rs/loco/issues/1341))**Typed, streaming**— counterpart to`db::dump::<A>()`\n\n`db::seed::<A>()`\n\nthat\n\nstreams rows through their entity`Model`\n\nstraight to disk (memory bounded to\n\na single row) with full type fidelity. New`Hooks::dump`\n\n(default dumps every\n\ntable; override it to call`db::dump`\n\nper entity) backs`cargo loco db seed --dump`\n\n. ([#1691](https://github.com/loco-rs/loco/issues/1691))building`logger::init_layer`\n\n/`logger::init_env_filter`\n\nare now public\n\nblocks, so an app overriding`Hooks::init_logger`\n\ncan reuse Loco's formatting\n\nand filter policy while adding its own layers (e.g.`tracing-flame`\n\n, OTLP).\n\n([#1753](https://github.com/loco-rs/loco/issues/1753))\n\n### Changed\n\n- Wrap\n`TeraView`\n\nin`Arc`\n\nto reduce runtime memory usage ([#1703](https://github.com/loco-rs/loco/pull/1703)). - Refactor users model to reuse\n`find_by_api_key`\n\nin`Authenticable`\n\n([#1706](https://github.com/loco-rs/loco/pull/1706)). - Split error detail generic parameters (\n[#1709](https://github.com/loco-rs/loco/pull/1709)). - Update\n`loco-new`\n\nfor the new Rhai version ([#1704](https://github.com/loco-rs/loco/pull/1704)). - Replaced hand-rolled\n`Cargo.lock`\n\nparsing with the`cargo-lock`\n\ncrate; retired\n\n`duct_sh`\n\n. The`Error`\n\n→ HTTP-status mapping is now exhaustive.`IntoResponse for Error`\n\nmatch dropped its trailing`_ => 500`\n\nwildcard: every variant (and every\n\nnested`ModelError`\n\nvariant) is now classified explicitly, so adding a new\n\nerror variant is a compile error until its status is chosen — it can no longer\n\nsilently default to`500`\n\n. The`Error`\n\nenum is also reorganized into\n\nclient-facing vs internal/infra regions. Behavior is unchanged (all infra\n\nerrors still map to`500`\n\n); no variant was renamed, so existing code is\n\nunaffected.**Rust edition 2024.**`loco-rs`\n\n,`loco-gen`\n\n,`xtask`\n\n, and the`loco`\n\nnew-app\n\ngenerator now compile on edition 2024 (MSRV floor unchanged at 1.94; edition\n\n2024 needs ≥ 1.85). Editions are per-crate, so apps depending on Loco need not\n\nchange. Newly generated apps stay on edition 2021 for now.- Deduplicated the Postgres and SQLite background-queue providers: the shared\n\n`Job`\n\n/`JobRegistry`\n\n/`RunOpts`\n\nnow live in one module behind a`Driver`\n\ntrait\n\n(internal refactor, no behavior or API-path change). - In-memory cache now uses\n`moka::future::Cache`\n\ninstead of wrapping the\n\nsynchronous cache behind`#[async_trait]`\n\n(removes a sync-behind-async smell;\n\nno API change). - Cookie token extraction now uses\n`axum_extra`\n\n's`Cookie::value()`\n\ninstead of\n\nhand-parsing the cookie string (byte-identical behavior). - Internal de-duplication pass (no public-API-path or behavior change unless\n\nnoted): the response helpers in`format`\n\nare now single-sourced through\n\n`RenderBuilder`\n\n; the`JWT`\n\n/`JWTWithUser`\n\nextractors share one validate/decode\n\nhelper; the six validate extractors are generated from shared decoder fns +\n\ntwo error-tier macros; the byte-identical`Job`\n\nstruct is shared across the\n\nSQL and Redis queue backends; the twin`cli::main`\n\nfunctions share one\n\n`dispatch_common`\n\n; and duplicate env-var name constants were removed. `format`\n\n's two response paths were converged onto axum's canonical behavior:\n\n`RenderBuilder::json`\n\nand`RenderBuilder::redirect_with_header_key`\n\nare now\n\ninfallible with respect to bad input (they return a`500`\n\nresponse, matching\n\n`axum::Json`\n\n/`axum::response::Redirect`\n\n) instead of returning`Err`\n\n.\n\n### Fixed\n\nLoco's timestamptz columns`db seed --dump`\n\ndatetime round-trip on SQLite.\n\ndefault to`CURRENT_TIMESTAMP`\n\n, which SQLite stores as space-separated text\n\n(`\"YYYY-MM-DD HH:MM:SS\"`\n\n); dumps captured that verbatim and then failed\n\nchrono's RFC3339 parse on re-seed (`Json(\"premature end of input\")`\n\n). Dumps now\n\nnormalize such datetimes to RFC3339 (already-RFC3339 text is untouched).\n\n([#1736](https://github.com/loco-rs/loco/issues/1736),[#1691](https://github.com/loco-rs/loco/issues/1691))`cargo fmt`\n\nerror in`loco-new`\n\n([#1669](https://github.com/loco-rs/loco/pull/1669)).- UUID pattern in form field generation (\n[#1665](https://github.com/loco-rs/loco/pull/1665)). - Clippy warnings for recent Rust (\n[#1705](https://github.com/loco-rs/loco/pull/1705)). - Add tests for the auth extractor (\n[#1671](https://github.com/loco-rs/loco/pull/1671)). **Postgres/SQLite queue backends now behave consistently.** Two divergences\n\nbetween the Postgres and SQLite job backends are fixed: (1)`enqueue`\n\non\n\nPostgres previously*swallowed*a tag-serialization error (storing`tags = null`\n\n); it now propagates the error like SQLite. (2)`complete_job`\n\nwithout a\n\nrepeat interval on Postgres stamped`run_at = NOW()`\n\non the completed row while\n\nSQLite left it untouched; Postgres now leaves`run_at`\n\nas-is, matching SQLite\n\n(the interval path still reschedules`run_at`\n\non both). The shared`to_job`\n\nrow\n\nmapper is now single-sourced across both backends.**Storage mirror fan-out no longer stops at the first failing secondary.**\n\n`rename`\n\n,`copy`\n\n, and`upload_stream`\n\nchecked the failure mode*inside*the\n\nsecondary loop and returned early on the first failure, silently leaving later\n\nmirrors stale (`upload`\n\n/`delete`\n\nwere already correct). All five mutating\n\nmethods now share one helper that attempts every secondary (concurrently) and\n\napplies the failure mode once.**Postgres** The`BOOLEAN`\n\ncolumns are no longer dropped from`dump_tables`\n\n.\n\ndecode probe chain had no`bool`\n\narm, so PG booleans (which don't fall back to\n\nthe numeric arms like SQLite's integer-backed booleans) were silently omitted.`Hooks::on_shutdown`\n\nnow runs in worker-only start modes.`WorkerOnly`\n\nand\n\n`WorkerAndScheduler`\n\nbypassed`H::serve`\n\n(the hook's only caller); the shutdown\n\nhook is now invoked on their shutdown path too.**Postgres admin/maintenance URI is derived with the** Building it`url`\n\ncrate.\n\nvia`db_uri.replace(db_name, \"/postgres\")`\n\ncorrupted the URI when the database\n\nname also appeared in the host or credentials.**Foreign-key names are normalized consistently.**`reference_id`\n\nreceived a\n\nnormalized table name in`create_table`\n\nbut raw names in\n\n`add_reference`\n\n/`remove_reference`\n\n, so irregular plurals produced mismatched FK\n\ncolumn/constraint names between creation and later add/remove.`ViewEngine`\n\nextractor now rejects gracefully (HTTP`500`\n\n) when the opt-in Tera\n\nlayer is absent, instead of declaring`Infallible`\n\nand then panicking.`cargo loco routes`\n\nlists every HTTP verb of a multi-method route (route\n\nintrospection previously reported only the first).- Removed a fossilized 3-second\n`sleep`\n\non every Redis queue boot (a leaked\n\ntest-isolation artifact; Postgres/SQLite had no equivalent). - Password redaction in test snapshots (\n`cleanup_user_model`\n\n) now targets the\n\nquoted value precisely; the previous pattern had a degenerate quantifier that\n\nswallowed the field following`password`\n\n. - Postgres test-database cleanup now completes synchronously (a joined worker\n\nthread) instead of a fire-and-forget task, so parallel test runs no longer\n\nleak databases;`PostgresTest`\n\nalso builds its connection strings with the\n\n`url`\n\ncrate rather than a corruption-prone substring replace. `RenderBuilder::template`\n\nnow threads the builder's chained`status`\n\n/`header`\n\n/\n\n`etag`\n\n/`cookies`\n\nthrough to the response; it previously delegated to the free\n\n`html()`\n\nand silently dropped them.`llms.txt`\n\n: two`Core concepts`\n\nlinks pointed at doc pages that don't exist\n\n(`the-app/configuration/`\n\n,`the-app/testing/`\n\n); repointed to the sections that\n\nactually document them. A new`cargo xtask llms-check`\n\nCI step now verifies the\n\ncurated LLM docs against the docs tree so these links can't drift silently.\n\n### Removed\n\nRemoved four low-value/dependency-leaking variants`Error`\n\nenum narrowing.\n\nthat all mapped to HTTP 500 and were never matched:`Error::EnvVar`\n\n,\n\n`Error::SemVer`\n\n,`Error::TaskJoinError`\n\n, and`Error::Hash`\n\n(hashing errors now\n\nsurface as`Error::Message`\n\n).`Error`\n\nremains`#[non_exhaustive]`\n\n, so exhaustive\n\nmatches already require a wildcard arm and are unaffected.- Deleted shipped-but-dead code: the never-compiled\n\n`controller/middleware/_archive/content_etag.rs`\n\nmodule and a commented-out\n\nblock of backtrace-blocklist regexes.", "url": "https://wpnews.pro/news/release-v1-0-0-loco-is-stable", "canonical_source": "https://github.com/loco-rs/loco/releases/tag/v1.0.0", "published_at": "2026-07-29 13:05:59+00:00", "updated_at": "2026-07-29 13:22:52.576851+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence", "ai-agents"], "entities": ["Loco", "Sea-ORM", "Redis", "Postgres", "SQLite", "SeaQL"], "alternates": {"html": "https://wpnews.pro/news/release-v1-0-0-loco-is-stable", "markdown": "https://wpnews.pro/news/release-v1-0-0-loco-is-stable.md", "text": "https://wpnews.pro/news/release-v1-0-0-loco-is-stable.txt", "jsonld": "https://wpnews.pro/news/release-v1-0-0-loco-is-stable.jsonld"}}