Commit Graph
296 Commits
Author SHA1 Message Date
stroblmeandClaude Opus 5.5 235a9201a8 Merge remote-tracking branch 'origin/main'
Docs / docs (push) Successful in 22s
Playwright Tests / test-playwright (1, 2) (push) Failing after 4m39s
Playwright Tests / test-playwright (2, 2) (push) Successful in 2m17s
pre-commit / pre-commit (push) Failing after 2m37s
Test Backend / test-backend (push) Failing after 3m37s
Compose Smoke Test / test-compose (push) Successful in 33s
Playwright Tests / merge-reports (push) Successful in 1m38s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WgBfkm4rCmtd1T4vHWjEPx
2026-10-15 08:20:11 +02:00
Melvin Strobl 36fafae065 Merge remote-tracking branch 'origin/main'
Docs / docs (push) Successful in 49s
Playwright Tests / test-playwright (1, 2) (push) Failing after 4m41s
Playwright Tests / test-playwright (2, 2) (push) Successful in 2m16s
pre-commit / pre-commit (push) Failing after 4m23s
Test Backend / test-backend (push) Failing after 4m54s
Compose Smoke Test / test-compose (push) Successful in 38s
Playwright Tests / merge-reports (push) Successful in 1m41s
2026-10-15 07:47:21 +02:00
stroblmeandClaude Opus 5.5 278a480a5c Endpoint labels sweep instead of pulse: left to right on a label publishing into the flow, right to left on one reading out of it, one pulse long, off under reduced motion; snapshot values are marked prior so catching up sweeps nothing
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WgBfkm4rCmtd1T4vHWjEPx
2026-10-15 00:23:01 +02:00
stroblmeandClaude Opus 5.5 98416dc516 Dashboard editor undo: ⌘Z / ⇧⌘Z over a 50-entry history of commits, folding keystrokes and the grid's own correction as the flow editor does
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WgBfkm4rCmtd1T4vHWjEPx
2026-10-15 00:07:58 +02:00
stroblmeandClaude Opus 5.5 0a9ea24b93 Stored state lists its keys, each with a two-press delete beside Clear
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WgBfkm4rCmtd1T4vHWjEPx
2026-10-15 00:04:03 +02:00
stroblmeandClaude Opus 5.5 f2305ef619 Phone header: assistant button in the corner, gated on an available provider as the sidebar entry is; header triggers on the right at 44px
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WgBfkm4rCmtd1T4vHWjEPx
2026-10-14 23:41:30 +02:00
stroblmeandClaude Opus 5.5 b0c07a35e9 Locked slider dims its rail: :has() on the slider, since the rail comes before the input and no sibling selector reaches it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WgBfkm4rCmtd1T4vHWjEPx
2026-10-14 23:41:29 +02:00
stroblmeandClaude Opus 5.5 43fb446297 Stat unit sized against the hero numerals: dui-hero on the readout's outer span, so the unit's 0.4em is of the hero rather than the 14px body text
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WgBfkm4rCmtd1T4vHWjEPx
2026-10-14 23:41:28 +02:00
stroblmeandClaude Opus 5.5 9145b7d1c0 ValueSource kind includes panel; Panels dialog no longer suggests the screen port openpanel does not serve
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WgBfkm4rCmtd1T4vHWjEPx
2026-10-14 23:32:32 +02:00
stroblmeandClaude Opus 5.5 f2b7a23b4f Socket snapshot carries the nodes waiting for a machine, so a reconnecting browser restores their queued dots
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WgBfkm4rCmtd1T4vHWjEPx
2026-10-14 23:31:54 +02:00
Melvin StroblandClaude Opus 5.5 78498cbbf8 Dashboard name pill opaque: the look's card colour with a hairline border, no blur
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016ezWcLmBCtTVKFPxfdK2MK
2026-10-14 22:19:34 +02:00
Melvin StroblandClaude Opus 5.5 2a9b39ddb1 Dashboard name pill on a round panel: 56 high, icon and title at 24, at most 280 wide
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016ezWcLmBCtTVKFPxfdK2MK
2026-10-14 22:16:00 +02:00
stroblmeandClaude Opus 5.5 b18cb30492 Add websocket node: client or served socket, listener or sender
Docs / docs (push) Successful in 26s
Playwright Tests / test-playwright (1, 2) (push) Failing after 3m56s
Playwright Tests / test-playwright (2, 2) (push) Successful in 2m1s
pre-commit / pre-commit (push) Failing after 2m38s
Test Backend / test-backend (push) Failing after 3m18s
Compose Smoke Test / test-compose (push) Successful in 46s
Playwright Tests / merge-reports (push) Successful in 1m35s
ws:// and wss:// URLs dial out and hold a supervised connection; a path is
served under /hooks/<flow>/ with an optional secret. Outputs only listen,
inputs send. Frames are JSON keyed by port, with json_key and on_connect.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CT3mowxKeZywDCH4fS1gt
2026-10-14 18:42:19 +02:00
Melvin StroblandClaude Opus 5.5 0bf2b12268 Round panel: the dashboards either side drawn in advance and live, on the face they open on, and dragged in up and down as faces are sideways; the name pill only on landing
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:20:22 +02:00
Melvin StroblandClaude Opus 5.5 603635f947 Round paging follows the finger: faces and dashboards on a track, swiped one to one with the next beside it, turned or sent back on release, rubber-banded at the ends; keys and dots slide the same track; the reading dot a smaller companion of the handle
Docs / docs (push) Successful in 24s
Playwright Tests / test-playwright (1, 2) (push) Failing after 4m14s
Playwright Tests / test-playwright (2, 2) (push) Successful in 2m11s
pre-commit / pre-commit (push) Failing after 2m2s
Test Backend / test-backend (push) Failing after 3m23s
Compose Smoke Test / test-compose (push) Successful in 34s
Playwright Tests / merge-reports (push) Successful in 1m33s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:08:51 +02:00
Melvin StroblandClaude Opus 5.5 541dbce584 Round faces: a bar as concentric arcs with a legend in the middle; larger title, gap line and face text; Read-only in the ring's gap; a round dashboard unpadded on a phone; reduced-motion ring assertion
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 16:52:46 +02:00
Melvin StroblandClaude Opus 5.5 f5412d2f7d Marks as dots inside the track: ticks, a selector's options and a slider's reading on the track's midline and the ring's centre line, coloured by the fill or the handle over them; the selector ring fills to its option
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 16:42:56 +02:00
Melvin StroblandClaude Opus 5.5 b500af84ec Dashboard motion: round dashboards page up and down, the ring eases to a notch or a reading, the slider tile to a value set elsewhere; reduced motion honoured by every tween; motion spec in the docs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 16:34:10 +02:00
Melvin StroblandClaude Opus 5.5 5b2769c141 Slider: the set value to its step's decimals; the reading marked on the track and on the ring; mark geometry in the docs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 16:00:53 +02:00
Melvin StroblandClaude Opus 5.5 a6a1f2a2c3 Slider reading in a tile: a line under the value in every look, row and fader; Beside it on every dashboard; tile geometry in the docs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 15:51:04 +02:00
Melvin StroblandClaude Opus 5.5 84071ee106 Round dashboards: one face at a time, a face per widget type, paged by swipe, dots and keys; slider reading; face row in the editor
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 15:24:25 +02:00
Melvin StroblandClaude Opus 5.5 8b8cb5cda9 Round dashboards: shape and ring, the ring drawn and turned in every look, Knob preset and face guide in the editor
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 14:23:55 +02:00
Melvin StroblandClaude Opus 5.5 f067fb60d4 Gauge: no value arc at the minimum
Docs / docs (push) Successful in 22s
Playwright Tests / test-playwright (1, 2) (push) Failing after 3m53s
Playwright Tests / test-playwright (2, 2) (push) Successful in 1m57s
pre-commit / pre-commit (push) Failing after 2m37s
Test Backend / test-backend (push) Failing after 3m6s
Compose Smoke Test / test-compose (push) Successful in 30s
Playwright Tests / merge-reports (push) Successful in 1m55s
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.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:29:07 +02:00
Melvin StroblandClaude Opus 5.5 28a44853e3 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.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 08:44:38 +02:00
Melvin StroblandClaude Opus 5.5 c462f9acab Panel I/O: PanelDef.io ports, scoped publish and upload, I/O section in the Panels dialog
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:10:54 +02:00
stroblmeandClaude Opus 5.5 8d97b8ffaa Open in dashboard: searchable Command list
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 22:07:17 +02:00
stroblmeandClaude Opus 5.5 cfd2556053 Dashboard message picker: searchable combobox instead of a plain select
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 22:06:31 +02:00
stroblmeandClaude Opus 5.5 0ef7d027b8 Dashboard palette: switch dashboard, publish, settings; ⌘S publishes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 22:05:39 +02:00
stroblmeandClaude Opus 5.5 72b4cf3556 Shared Dock, PublishButton, DiscardButton, DiscardDraftDialog for the flow and dashboard editors
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 22:04:34 +02:00
stroblmeandClaude Opus 5.5 8d158169e5 Button icon-touch/sm-touch sizes replace the repeated touch-target classes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 22:02:35 +02:00
stroblmeandClaude Opus 5.5 9c75d7ae13 Dashboard add widget: searchable command palette with ⌘P, as on flows
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:59:16 +02:00
stroblmeandClaude Opus 5.5 9a84d27347 Embed widget: Image option scales a camera stream to the tile
Docs / docs (push) Successful in 19s
Playwright Tests / test-playwright (1, 2) (push) Failing after 3m41s
Playwright Tests / test-playwright (2, 2) (push) Failing after 2m21s
pre-commit / pre-commit (push) Failing after 2m36s
Test Backend / test-backend (push) Failing after 2m58s
Compose Smoke Test / test-compose (push) Successful in 31s
Playwright Tests / merge-reports (push) Successful in 1m36s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 20:23:37 +02:00
stroblmeandClaude Opus 5.5 022079728c Dashboard icons: add cctv
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 20:20:54 +02:00
stroblmeandClaude Opus 5.5 cb2a6315c9 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.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
2026-10-07 09:32:07 +02:00
stroblmeandClaude Opus 5.5 0869e5b156 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.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
2026-10-07 09:32:06 +02:00
stroblmeandClaude Opus 5.5 e85253a3dc 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.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
2026-10-07 09:31:49 +02:00
stroblmeandClaude Opus 5.5 5259b8db0a Authenticate sockets by header or one-time ticket instead of ?token=
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
2026-10-07 08:58:22 +02:00
stroblmeandClaude Opus 5.5 21537e2eb6 Bind a worker's name and labels into its token; list and revoke tokens by jti
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
2026-10-07 08:42:14 +02:00
stroblmeandClaude Opus 5.5 847abd67d6 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.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
2026-10-06 17:19:48 +02:00
stroblmeandClaude Opus 5.5 b086d5d22b 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.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
2026-10-06 12:33:00 +02:00
stroblmeandClaude Opus 5.5 6c0ab2049b 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.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
2026-10-06 12:30:47 +02:00
stroblmeandClaude Opus 5.5 7f06260c1a 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.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
2026-10-06 12:01:53 +02:00
stroblmeandClaude Opus 5.5 48b87cc16e 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.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
2026-10-06 11:50:35 +02:00
stroblmeandClaude Opus 5.5 7370105cd8 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.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
2026-10-06 11:36:30 +02:00
stroblmeandClaude Opus 5.5 de7ee759f9 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.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
2026-10-06 11:24:27 +02:00
stroblmeandClaude Opus 5.5 4d63f58806 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.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
2026-10-06 07:24:53 +02:00
stroblmeandClaude Opus 5.5 c7e91ef234 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.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
2026-10-06 07:24:53 +02:00
stroblmeandClaude Opus 5.5 457b88ed14 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.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
2026-10-06 07:24:43 +02:00
stroblmeandClaude Opus 5.5 4f4de1fd9d Draw charts from one categorical palette, --chart-1…8
The one-hue ramp told lines apart by lightness alone. --chart-1 is now
--primary and slots 2-8 are distinct hues (orange, violet, green, orchid,
ochre, teal, magenta) that clear 3:1 on --card and stay apart under
protanopia and deuteranopia; red and sage are left out as the status
colours. A chart takes the slots in order instead of spreading a ramp,
and a dashboard's own palette continues after its primary and listed
colours with slots 2-8 rather than tints of its scheme. Line charts stay
at five series. Tokens mirror index's, as design-check requires.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
2026-10-06 07:05:09 +02:00
stroblmeandClaude Opus 5.5 d7ca933478 Float the dashboard rail along the bottom on a phone
Below md a dashboard stacks to one column and dropped its rail. The rail is
now a horizontal row in the dashboard's own look, floated over the bottom
of the screen on /panel/{id} and above the dock in the app's view, with
44px items, sideways scrolling when it overflows, and padding so the last
tile clears it; a panel's read-only notice moves up out of its way. The
three looks share the geometry from ui/core.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
2026-10-06 00:22:28 +02:00