0.32.0: a call the host makes, and the renderer does not
`a81384d4`, ruled by Max 2026-08-18 as option (a). Found starting
mnw-server's audio upload, which is the first description in the tree
whose destination a renderer cannot call.
`f7261a5a` settled the four axes of an upload and this is none of them.
The accept list, the multiplicity, the destination and the progress were
all expressible; who performs the destination was not. An MNW upload is
three requests, not one -- ask the server to sign a URL, PUT the file to
storage with it, tell the server it landed -- and thirteen files across
`static/` and `frontend/src/` run that chain against three route
families. A renderer posting the field to the first of those is wrong
about the response shape and about where the bytes go.
`Action::by_host` says so, and it is `Action::saves`' shape rather than a
new principle: a named attribute the host acts on, because there are
calls a renderer cannot make and the alternative to saying so is a host
reaching around the description to a control the description owns.
quasi-webview emits `data-sends` with the address and no transport at
all -- no verb, no trigger, no href. `data-sends` and not `data-action`:
what is named is where the thing goes, which is the half the description
knows.
Two things that would have been silent if they were wrong, so both have
a test. The payload travels as `data-vals`, since `hx-vals` is htmx's and
htmx is not involved here; dropping it would be the description saying
something the markup did not carry. And the wait survives while the lock
does not -- `data-awaiting` is a fact about the call, `hx-disabled-elt`
is htmx locking a control on a request it is making, and this is not one.
That split the old block in two, so `awaiting_attrs` is now its own
function.
quasi-tui refuses one rather than making it wrongly. Pressing a control
marked this way says "this app cannot do that here" and calls nothing:
the address is a signing endpoint that answers JSON, and a terminal
asking it for a screen would swap the signature it got back. Announced on
the spot, because no navigation is coming to carry the message later.
The cost is written onto the member rather than left to be discovered: a
call marked this way is not portable, and that is permanent. A terminal
meeting a described upload learns the accept list, the multiplicity and
that it waits, and has nothing to perform. That is what the ruling bought
for keeping the file going browser-to-storage instead of through the
production box, which would otherwise proxy half-gigabyte bodies it does
not proxy today.
- Co-Authored-By
- Claude Opus 5 (1M context) <noreply@anthropic.com>
17 files changed,
+264 insertions,
-52 deletions
| 6191 |
6191 |
|
name = "makeover-build"
|
| 6192 |
6192 |
|
version = "0.46.0"
|
| 6193 |
6193 |
|
|
| 6194 |
|
- |
[[patch.unused]]
|
| 6195 |
|
- |
name = "quasi-type"
|
| 6196 |
|
- |
version = "0.1.0"
|
| 6197 |
|
- |
|
| 6198 |
|
- |
[[patch.unused]]
|
| 6199 |
|
- |
name = "synckit-client"
|
| 6200 |
|
- |
version = "0.8.0"
|
| 6201 |
|
- |
|
| 6202 |
6194 |
|
[[patch.unused]]
|
| 6203 |
6195 |
|
name = "kberg"
|
| 6204 |
6196 |
|
version = "0.1.0"
|
| 6214 |
6206 |
|
[[patch.unused]]
|
| 6215 |
6207 |
|
name = "tagtree"
|
| 6216 |
6208 |
|
version = "0.4.0"
|
|
6209 |
+ |
|
|
6210 |
+ |
[[patch.unused]]
|
|
6211 |
+ |
name = "quasi-type"
|
|
6212 |
+ |
version = "0.1.0"
|
|
6213 |
+ |
|
|
6214 |
+ |
[[patch.unused]]
|
|
6215 |
+ |
name = "synckit-client"
|
|
6216 |
+ |
version = "0.8.0"
|
| 1 |
1 |
|
[package]
|
| 2 |
2 |
|
name = "quasi-axum"
|
| 3 |
|
- |
version = "0.31.0"
|
|
3 |
+ |
version = "0.32.0"
|
| 4 |
4 |
|
description = "The axum host adapter for quasi-router: an HTTP request in, a rendered description out"
|
| 5 |
5 |
|
edition.workspace = true
|
| 6 |
6 |
|
rust-version.workspace = true
|
| 13 |
13 |
|
workspace = true
|
| 14 |
14 |
|
|
| 15 |
15 |
|
[dependencies]
|
| 16 |
|
- |
quasi-router = { path = "../quasi-router", version = "0.31.0" }
|
| 17 |
|
- |
quasi-http = { path = "../quasi-http", version = "0.31.0" }
|
|
16 |
+ |
quasi-router = { path = "../quasi-router", version = "0.32.0" }
|
|
17 |
+ |
quasi-http = { path = "../quasi-http", version = "0.32.0" }
|
| 18 |
18 |
|
axum = "0.8.8"
|
| 19 |
19 |
|
http = "1.3.1"
|
| 20 |
20 |
|
tokio = { version = "1.50.0", features = ["rt"] }
|
| 21 |
21 |
|
|
| 22 |
22 |
|
[dev-dependencies]
|
| 23 |
|
- |
quasi-webview = { path = "../quasi-webview", version = "0.31.0" }
|
|
23 |
+ |
quasi-webview = { path = "../quasi-webview", version = "0.32.0" }
|
| 24 |
24 |
|
tokio = { version = "1.50.0", features = ["macros", "rt-multi-thread"] }
|
| 25 |
25 |
|
tower = { version = "0.5.3", features = ["util"] }
|
| 26 |
26 |
|
http-body-util = "0.1.3"
|
| 1 |
1 |
|
[package]
|
| 2 |
2 |
|
name = "quasi-basics"
|
| 3 |
|
- |
version = "0.31.0"
|
|
3 |
+ |
version = "0.32.0"
|
| 4 |
4 |
|
description = "The first-party widget set: named assemblies of primitives, shared across our apps"
|
| 5 |
5 |
|
edition.workspace = true
|
| 6 |
6 |
|
rust-version.workspace = true
|
| 13 |
13 |
|
workspace = true
|
| 14 |
14 |
|
|
| 15 |
15 |
|
[dependencies]
|
| 16 |
|
- |
quasi-router = { path = "../quasi-router", version = "0.31.0" }
|
|
16 |
+ |
quasi-router = { path = "../quasi-router", version = "0.32.0" }
|
| 17 |
17 |
|
makeover-layout = "0.31.0"
|
| 18 |
18 |
|
|
| 19 |
19 |
|
[dev-dependencies]
|
| 20 |
20 |
|
# A widget's guarantees are claims about what a renderer draws, so they are
|
| 21 |
21 |
|
# tested against a real one rather than by walking the tree the assembly just
|
| 22 |
22 |
|
# built. The webview is the renderer that recognises names today.
|
| 23 |
|
- |
quasi-webview = { path = "../quasi-webview", version = "0.31.0" }
|
| 24 |
|
- |
quasi-http = { path = "../quasi-http", version = "0.31.0" }
|
|
23 |
+ |
quasi-webview = { path = "../quasi-webview", version = "0.32.0" }
|
|
24 |
+ |
quasi-http = { path = "../quasi-http", version = "0.32.0" }
|
| 1 |
1 |
|
[package]
|
| 2 |
2 |
|
name = "quasi-bench"
|
| 3 |
|
- |
version = "0.31.0"
|
|
3 |
+ |
version = "0.32.0"
|
| 4 |
4 |
|
description = "What a described screen costs to render, in time and in allocations"
|
| 5 |
5 |
|
edition.workspace = true
|
| 6 |
6 |
|
rust-version.workspace = true
|
| 22 |
22 |
|
count = ["dep:dhat"]
|
| 23 |
23 |
|
|
| 24 |
24 |
|
[dependencies]
|
| 25 |
|
- |
quasi-router = { path = "../quasi-router", version = "0.31.0" }
|
| 26 |
|
- |
quasi-webview = { path = "../quasi-webview", version = "0.31.0" }
|
| 27 |
|
- |
quasi-tui = { path = "../quasi-tui", version = "0.31.0" }
|
|
25 |
+ |
quasi-router = { path = "../quasi-router", version = "0.32.0" }
|
|
26 |
+ |
quasi-webview = { path = "../quasi-webview", version = "0.32.0" }
|
|
27 |
+ |
quasi-tui = { path = "../quasi-tui", version = "0.32.0" }
|
| 28 |
28 |
|
# `Serves` is the trait carrying `screen` and `fragment`, which is what the
|
| 29 |
29 |
|
# webview is measured through. Taken directly rather than through quasi-webview
|
| 30 |
30 |
|
# because a bench calling a trait method should name the trait it calls.
|
| 31 |
|
- |
quasi-http = { path = "../quasi-http", version = "0.31.0" }
|
|
31 |
+ |
quasi-http = { path = "../quasi-http", version = "0.32.0" }
|
| 32 |
32 |
|
makeover-layout = "0.31.0"
|
| 33 |
33 |
|
makeover-tui = { version = "0.30.0", features = ["theme"] }
|
| 34 |
34 |
|
# Only to load a bundled theme file. `makeover_tui::Theme` is `#[non_exhaustive]`,
|
| 1 |
1 |
|
[package]
|
| 2 |
2 |
|
name = "quasi-http"
|
| 3 |
|
- |
version = "0.31.0"
|
|
3 |
+ |
version = "0.32.0"
|
| 4 |
4 |
|
description = "The http-shaped seam quasi's webview host adapters share: decoding in, a rendered description out"
|
| 5 |
5 |
|
edition.workspace = true
|
| 6 |
6 |
|
rust-version.workspace = true
|
| 13 |
13 |
|
workspace = true
|
| 14 |
14 |
|
|
| 15 |
15 |
|
[dependencies]
|
| 16 |
|
- |
quasi-router = { path = "../quasi-router", version = "0.31.0" }
|
|
16 |
+ |
quasi-router = { path = "../quasi-router", version = "0.32.0" }
|
| 17 |
17 |
|
http = "1.3.1"
|
| 18 |
18 |
|
form_urlencoded = "1.2.2"
|
| 1 |
1 |
|
[package]
|
| 2 |
2 |
|
name = "quasi-immediate"
|
| 3 |
|
- |
version = "0.31.0"
|
|
3 |
+ |
version = "0.32.0"
|
| 4 |
4 |
|
edition = "2024"
|
| 5 |
5 |
|
description = "The immediate-mode renderer for quasi-router: a described screen in, an egui frame out. Immediate mode is the constraint that matters, not the library."
|
| 6 |
6 |
|
license = "MIT"
|
| 12 |
12 |
|
categories = ["gui"]
|
| 13 |
13 |
|
|
| 14 |
14 |
|
[dependencies]
|
| 15 |
|
- |
quasi-router = { path = "../quasi-router", version = "0.31.0" }
|
|
15 |
+ |
quasi-router = { path = "../quasi-router", version = "0.32.0" }
|
| 16 |
16 |
|
# The node drawing, which is the makeover layer's and not this crate's. Every
|
| 17 |
17 |
|
# widget here that is not a container comes from it: a screen walk that painted
|
| 18 |
18 |
|
# its own meter would be the divergence the suite exists to end, one copy per
|
| 1 |
1 |
|
[package]
|
| 2 |
2 |
|
name = "quasi-notifs"
|
| 3 |
|
- |
version = "0.31.0"
|
|
3 |
+ |
version = "0.32.0"
|
| 4 |
4 |
|
description = "Declared notification kinds and the registry that holds them: what a notification says and what it is for, apart from how it reaches a person"
|
| 5 |
5 |
|
edition.workspace = true
|
| 6 |
6 |
|
rust-version.workspace = true
|
| 24 |
24 |
|
describe = ["dep:quasi-router"]
|
| 25 |
25 |
|
|
| 26 |
26 |
|
[dependencies]
|
| 27 |
|
- |
quasi-router = { path = "../quasi-router", version = "0.31.0", optional = true }
|
|
27 |
+ |
quasi-router = { path = "../quasi-router", version = "0.32.0", optional = true }
|
| 28 |
28 |
|
synckit-config = { git = "https://makenot.work/git/max/synckit.git", version = "0.2", optional = true }
|
| 1 |
1 |
|
[package]
|
| 2 |
2 |
|
name = "quasi-router"
|
| 3 |
|
- |
version = "0.31.0"
|
|
3 |
+ |
version = "0.32.0"
|
| 4 |
4 |
|
description = "Host-agnostic router: a request in, a renderer-agnostic description out"
|
| 5 |
5 |
|
edition.workspace = true
|
| 6 |
6 |
|
rust-version.workspace = true
|