What Tropical decides for an app, and what stays the app's. Each point is covered where its subject is, and linked from here.
if, in the island that decides
(Islands).[:remove id], rendered
per row, exists only for the rows the server rendered for this user. One action taking a value from the browser
vouches for less: the handler checks the value against what the island rendered.Everything from the browser is the user's to change, whatever the page's script would send.
:value) is checked against what the island rendered, since no token vouches for it.:valid?, falling back to its
default (State the browser owns).storage/decode, which returns nil unless the value passes :valid?.:arrived can check it, as with a HEAD on the stored object, and
refuse it. The browser knows an upload by the id the island gave it, never by the app's reference, so it can't make
the app take an object of its choosing, or another session's (Files from the browser).:max-signals-bytes, 1 MiB by default, and more gets a 413.use-session's :uid, never from signals or an
action's value (State shared on the server).observe's args decide who shares its resource. Data that differs per user needs the user, or their
account, among the args (Reading from outside the page).:uid returns the user a request is made on behalf of, and a page or action
without one gets a 403 (Serving pages).h/raw is the app's to make safe.data-on: or data-attr: attribute, runs as JavaScript.
Escaping protects the attribute, not the JavaScript inside it, so a value spliced into an expression with str can
become code. Build expressions from constants and the helpers' output (use-action, ui/signal, ui/attr). Data
goes into the page as text or an attribute's value, and a value an expression needs goes in through ui/json, as a
JavaScript literal, never as the string it is: (str "$tab = " (ui/json tab)).'unsafe-eval'. With the page's nonce on <html data-nonce=...>, Datastar compiles each
expression into a script carrying it, those patched in over the stream included, and a navigation's script runs with
it. Scripts the islands declare get it too (Serving pages, Scripts the page needs).navigate and navigate-element take a path on the page's origin and
throw for anything else, so a handler passing on what a client sent can't become an open redirect. A page elsewhere
takes {:external true} and an absolute http or https URL, never javascript:: the handler's word that it built
the URL (Actions).A compressed response carrying a secret and text an attacker can vary leaks the secret to someone watching its encrypted size (BREACH), and a stream, compressed in one window and flushed per frame, suits that better than a page. Tropical's own tokens in the stream are bound to their user, so one learned this way is no use without the user's session. What the app renders is the app's to judge, which is why the stream's compression is opted into (Serving pages, design).
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |