Commit Graph
580 Commits
Author SHA1 Message Date
Melvin Strobl be3446cb16 Round dashboards: shape and ring, the ring drawn and turned in every look, Knob preset and face guide in the editor 2026-10-14 14:23:55 +02:00
Melvin Strobl 9bed078c41 Gauge: no value arc at the minimum
At 0 the value arc is a zero-length dash (pathLength 0), and its round
caps still painted a primary dot on the dial in every look. The arc is
now transparent while its fraction is not above 0. The widget spec puts
a gauge at 0 on its panel and checks it in each look; its tile count,
stale since the buttons widget, is 11.
2026-10-14 12:29:07 +02:00
Melvin Strobl 13e885ee4b Docs: panels without a browser (openpanel), device-interpreted I/O ports 2026-10-14 11:33:27 +02:00
Melvin Strobl 13a0c69edc Colour widget: commit the value being released
The brightness column changes and commits in one handler, so the commit
read the render's draft (still null) and sent nothing; the queued draft then
stuck and rode along with the next release. The pending colour lives in a ref
now. color-drag.spec gains a column drag.
2026-10-14 08:44:38 +02:00
Melvin Strobl a5afd88a5e LAN proxy: no 1 MB upload cap 2026-10-14 08:14:19 +02:00
Melvin Strobl 0264310d4f Defer ffmpeg in the image; record the decision 2026-10-14 07:33:59 +02:00
Melvin Strobl 1964c5b2e8 Clip transcoding: ffmpeg in the backend image, panel recipe in the node docs 2026-10-14 07:30:36 +02:00
Melvin Strobl 659799d1e5 Panel I/O: PanelDef.io ports, scoped publish and upload, I/O section in the Panels dialog 2026-10-13 21:10:54 +02:00
stroblme 80e595c02e docs 2026-10-13 10:02:20 +02:00
stroblme a93f865e91 Open in dashboard: searchable Command list 2026-10-12 22:07:17 +02:00
stroblme 530a4b602e Dashboard message picker: searchable combobox instead of a plain select 2026-10-12 22:06:31 +02:00
stroblme 4463007736 Dashboard palette: switch dashboard, publish, settings; ⌘S publishes 2026-10-12 22:05:39 +02:00
stroblme 88c80bdb60 Shared Dock, PublishButton, DiscardButton, DiscardDraftDialog for the flow and dashboard editors 2026-10-12 22:04:34 +02:00
stroblme 237b9d96c6 Button icon-touch/sm-touch sizes replace the repeated touch-target classes 2026-10-12 22:02:35 +02:00
stroblme 59272299f5 Dashboard add widget: searchable command palette with ⌘P, as on flows 2026-10-12 21:59:16 +02:00
stroblme bb63601fad Docs: getting started mirrors the README quick start 2026-10-12 21:50:21 +02:00
stroblme dd91954a21 Docs: make init in the setup steps 2026-10-12 21:41:39 +02:00
stroblme a86eb3051e Add make init for a standalone setup 2026-10-12 21:39:59 +02:00
stroblme d7c6e27a2a Embed widget: Image option scales a camera stream to the tile 2026-10-11 20:23:37 +02:00
stroblme 79e3908a76 Dashboard icons: add cctv 2026-10-11 20:20:54 +02:00
stroblme d482b32970 Do not check a pinned certificate's dates
A pin trusts one exact certificate, so an expired one or an engine clock
that is off no longer locks a device out (X509_V_FLAG_NO_CHECK_TIME).
2026-10-07 10:11:08 +02:00
stroblme cd6f8fec55 Lift certificate pinning into the connector contract
fluksio.flow.connector_tls: trust the certificate a device presented on
first contact, kept in ConnectorNode.store, and name the new fingerprint
when another one is refused. Additive, so no contract version bump; hue
and wfrac use it.
2026-10-07 09:48:24 +02:00
stroblme e9c3d0944d Portal link: send the instance credential as Authorization: Bearer
Not ?token= in the tunnel URL, which access logs keep. The hub has to be
upgraded first; websockets>=14 for additional_headers on the asyncio client.
2026-10-07 09:41:44 +02:00
stroblme 1424e1e8a8 Drop --token from the hand-started worker examples
The worker reads FLUKSIO_WORKER_TOKEN itself; on the command line the
token shows in ps. The --token row in the options table says so.
2026-10-07 09:35:00 +02:00
stroblme c1a6a89e13 Make alert dialog footer buttons 44px below md
The same treatment `ui/dialog.tsx` got: every footer button is a 44px
target on a phone; desktop keeps its sizes.
2026-10-07 09:32:07 +02:00
stroblme 7d6cc5b0bf Serve index.html no-cache on every route; check the theme script's CSP hash
`try_files` served the SPA fallback inside `location /`, so `/` and every
client route went out without `Cache-Control: no-cache`. The fallback is now
the last argument, an internal redirect to the exact no-cache location.

`src/csp.check.ts` recomputes the inline theme script's sha256 and fails
`bun run check` with the new value when the CSP no longer names it.
2026-10-07 09:32:06 +02:00
stroblme ff3a31e515 Hand a provisioned worker its token in the environment, not argv
The generated batch script exported nothing and passed `--token`, which
any user on a shared compute node reads from `ps`. It now exports
FLUKSIO_WORKER_TOKEN after `prerun`, which the worker already reads.
2026-10-07 09:32:01 +02:00
stroblme 8f3e229c8f Sandbox website tiles by default; opt into same-origin per widget
A website tile now runs in an opaque origin (allow-scripts, popups, forms).
Its new "Trusted site" setting adds allow-same-origin for sites that need
their own cookies and storage, and a trusted tile pointing at the origin the
app runs on (its own, or the hub's) shows a notice instead of the frame.
2026-10-07 09:31:49 +02:00
stroblme ed8aee2387 Authenticate sockets by header or one-time ticket instead of ?token= 2026-10-07 08:58:22 +02:00
stroblme 094fed7cea Serve artifacts of a type that can run script with CSP sandbox and nosniff 2026-10-07 08:43:29 +02:00
stroblme 953a983919 Bind a worker's name and labels into its token; list and revoke tokens by jti 2026-10-07 08:42:14 +02:00
stroblme 9ef7f90dd8 Keep query-string tokens out of the uvicorn, nginx and Traefik access logs 2026-10-06 17:32:51 +02:00
stroblme 0a74845a7f Quote names put into SDK client URL paths; share the helper with MCP 2026-10-06 17:23:49 +02:00
stroblme 243d39b591 Give connectors a store that survives restarts, and a way to clear it
`ConnectorNode.store` keeps short strings per connector package in the
engine's database (`connector_state`, migration f8c3e5a91d27), so the nodes of
one package share them and `fluksio serve` needs nothing new: get, set and
delete, at most 64 kB a value and 256 keys a package. A superuser lists the
keys (never the values) and clears them through `/connectors/{node_type}/state`,
or under Stored state in a connector node's panel. Documented in the connector
contract.
2026-10-06 17:19:48 +02:00
stroblme 8a1685741b Show Secrets to superusers only, and guard its route as Admin is
The page reads GET /secrets/, which is a superuser's, so any other account
opened it onto a permission error.
2026-10-06 12:33:00 +02:00
stroblme 07d62e3ae6 Use a placeholder password in the docs; ignore *.pem and *.key 2026-10-06 12:30:57 +02:00
stroblme 4dfb1e1206 Send a CSP and security headers from the frontend's nginx
script-src admits the bundle and the pre-paint theme script by hash, with no
unsafe-inline or unsafe-eval; style-src keeps unsafe-inline for the <style>
elements Monaco, Radix and the toasts insert. frame-ancestors 'self',
nosniff and strict-origin-when-cross-origin go with it, and the Dockerfile
adds the API origin to connect-src when the bundle calls one elsewhere. Zod
runs jitless so its eval probe is not reported on every page. The embed
widget keeps allow-same-origin: the demo's weather map does not render
without it; the comment now says so and what it costs.
2026-10-06 12:30:47 +02:00
stroblme 3758415f21 Enrol over http only to loopback; serve the API docs to this machine
The enrolment exemption covered any *.local host, which mDNS answers with
whoever claims it; it is now localhost, 127.0.0.0/8 and ::1. /docs, /redoc
and openapi.json stay closed in production and otherwise answer only a
loopback caller unless API_DOCS_ENABLED is set, which the dev compose does,
so `fluksio serve --host 0.0.0.0` no longer hands the schema to the network.
2026-10-06 12:20:13 +02:00
stroblme db045770e8 Harden the remote worker: TLS off loopback, full digests, filtered env
fluksio-worker now refuses ws:// and http:// engine and artifact URLs unless
they are loopback or --insecure is given; the engine still accepts both.
An artifact reference must be sha256: plus 64 hex digits before it is joined
into a path, and node code gets the host environment through the engine's
credential denylist instead of all of it.
2026-10-06 12:18:30 +02:00
stroblme ae290b5421 Quote every path parameter the MCP tools put into a URL
httpx resolves `..` before sending, so save_flow("../ai/config") reached
PUT /ai/config. Each segment is now percent-encoded, dots included.
2026-10-06 12:16:48 +02:00
stroblme c5a8f170da Count per-address limits on the hop a trusted proxy added; limit signup
The limits read the leftmost X-Forwarded-For entry, which the client writes,
and the LAN nginx appended to it. The address now comes from uvicorn's
proxy-headers middleware (rightmost hop not in FORWARDED_ALLOW_IPS), applied
in the app too so tunnel-replayed calls resolve the same way; nginx sets the
header to $remote_addr and the compose backend trusts the Docker networks.
/users/signup gets a per-address limit of 10 an hour.
2026-10-06 12:15:58 +02:00
stroblme 8e928c3ffb Read secret names in the node panel only as a superuser
GET /secrets/ is a superuser's, so every node a non-superuser opened
showed "You do not have permission to do that". The query now runs only
for a superuser; anyone else gets no secret suggestions, silently.
2026-10-06 12:01:53 +02:00
stroblme a168bcbdee Refuse names that are not names at the store boundary
DELETE /flows/%2e%2e reached FlowStore.delete_flow(".."), which removed
the data directory, and /flows/_lib removed every shared node. Every
path the flow and dashboard stores build from a flow, node, library or
dashboard name now goes through checked(), which raises InvalidName
(400) for anything _validate_name refuses. _validate_name uses
fullmatch, so a trailing newline is refused too.
2026-10-06 11:59:25 +02:00
stroblme 6f6970d9d6 Upgrade dependencies flagged by pip-audit and bun audit
Backend: starlette 1.7.0, pyjwt 2.15.1, python-multipart 0.0.32,
aiohttp 3.14.4, anyio, idna, urllib3, click, lxml, mako, multidict,
pydantic-settings, pygments, python-dotenv, requests. pip-audit goes
from 121 findings in 16 packages to pytest alone (dev, needs 9.x).

Frontend: axios 1.20.0, form-data 4.0.6, dompurify 3.4.16 through an
override (monaco-editor pins 3.4.8), vite 7.3.7, the router packages
and the vite and router build-time dependencies within their ranges.
bun audit goes from 97 to 21, all through @hey-api/openapi-ts 0.73.0,
whose fix is a breaking 0.97 upgrade. The new router plugin reorders
routeTree.gen.ts.
2026-10-06 11:50:35 +02:00
stroblme 6802cd2203 Make changing engine-run code superuser-only
Writing node source, installing modules and any flow save that adds,
retypes or repoints a code node (Function, Command), edits a Command
node's settings or changes a node's resources.env now answer 403 for
everyone but a superuser. MCP tools and the assistant reach the same
routes, so they inherit the gate. Node types report runs_code.

The editor shows code read-only with a note, disables a Command node's
settings, leaves code nodes and reusable nodes out of the palette and
paste, and the Modules page offers no install.
2026-10-06 11:36:30 +02:00
stroblme 2914d860b1 Make self-service signup opt-in via SIGNUP_ENABLED
/users/signup answers 403 unless SIGNUP_ENABLED is set. A public
GET /utils/config/ tells the login page, which hides the sign-up link,
and the signup page explains that an administrator creates accounts.
2026-10-06 11:24:27 +02:00
stroblme a057b61859 Explain the terminal chart colours by the terminal theme
The docstring still justified the ANSI colours by the old one-hue web ramp.
The web now draws from the categorical --chart-1…8; the terminal keeps named
ANSI colours so it follows the user's terminal theme.
2026-10-06 07:24:54 +02:00
stroblme 70421c7454 Scroll the current dashboard to the middle of the phone rail
On mount and on every switch the horizontal rail scrolls itself (not the
page) so the active entry is centred, instantly under reduced motion.
2026-10-06 07:24:53 +02:00
stroblme eca2ccde2f Make dialog close and footer buttons 44px below md
The close button grows to a 44px target centred on where its icon already
sits, and every footer button is 44px tall, on a phone only; desktop keeps
its sizes.
2026-10-06 07:24:53 +02:00
stroblme b5513f8615 Edit json, record and list values in the JSON dialog
An inject's payload and a flow input's starting value of those types use
JsonField instead of a one-line text field. The field can now hold no value
(shown as the placeholder; an emptied editor saves null) and checks the shape:
a record must be an object, a list an array.
2026-10-06 07:24:43 +02:00