Note the database review findings in the NOTEPAD

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-17 12:40:36 +02:00
co-authored by Claude Fable 5
parent aabe7bb147
commit 02d841e10c
+19 -5
View File
@@ -15,17 +15,28 @@ should reopen it.
- INFRA: ensure that all the packages/ dependencies needed to run fluksio are available on arm to make this software runnable on e.g. raspbian - INFRA: ensure that all the packages/ dependencies needed to run fluksio are available on arm to make this software runnable on e.g. raspbian
- INFRA: merge the philosophy statement at the beginning of vision.md into the rest of the document. Dissolve the decision dates and fold the decisions into a clean structure - INFRA: merge the philosophy statement at the beginning of vision.md into the rest of the document. Dissolve the decision dates and fold the decisions into a clean structure
- BUG/UI mobile friendly support is degraded: 1) toolbar in the "Flows" viewport extend mobile viewport width 2) position of nodes should never be static; always adjust such that there are as few as possible overlaps (of nodes and edge labels) and direction is left to right (desktop) or top to bottom (mobile) with a minimal (but clean) overall edge length 3) Dashboard view is not mobile friendly at all; as dashboard design is infeasible on mobile, render all widgets in a vertically stacked order. This allows to inspect each widget and make changes. Layout changes are not a feature on mobile 4) the home view is not responsive; all items shown there should re-order on mobile such that no scrollbars appear. Make sure the mobile support is anchored in the design such that future work does not break it - BUG/UI mobile friendly support is degraded: 1) toolbar in the "Flows" viewport extend mobile viewport width 2) position of nodes should never be static (holds true for desktop as well); always adjust such that there are as few as possible overlaps (of nodes and edge labels) and direction is left to right (desktop) or top to bottom (mobile) with a minimal (but clean) overall edge length. This should also remove the ability to drag nodes around; their position is fixed by an algorithm. This design choice is what enforces small atomic flows (different from nodered) 3) Dashboard view is not mobile friendly at all; as dashboard design is infeasible on mobile, render all widgets in a vertically stacked order. This allows to inspect each widget and make changes. Layout changes are not a feature on mobile 4) the home view is not responsive; all items shown there should re-order on mobile such that no scrollbars appear. Make sure the mobile support is anchored in the design such that future work does not break it
- FEAT/UI add a loading animation for the initial app load and when loading individual pages; make sure that elements e.g. in the home dashboard load independently to ensure a fast loading of the initial site but figures charts, tables, graph etc. follow after that - FEAT/UI add a loading animation for the initial app load and when loading individual pages; make sure that elements e.g. in the home dashboard load independently to ensure a fast loading of the initial site but figures charts, tables, graph etc. follow after that
- FEAT/UI introduce a graph panel which renders at the top right next to the graph view (to make more use of the horizontal space) and which allows (de-) selecting flows to be excluded from the graph view or search for individual nodes where only the flows containing this node should be shown (like slicing the brain) - FEAT/UI introduce a graph panel which renders at the top right next to the graph view (to make more use of the horizontal space) and which allows (de-) selecting flows to be excluded from the graph view or search for individual nodes where only the flows containing this node should be shown (like slicing the brain)
- FEAT/UI durations are written as a shortened number beside a fixed unit, so a slow run reads "1.2k ms" rather than "1.2 s". A duration formatter that steps the unit itself (µs/ms/s/min) would read better wherever `si` is followed by "ms" - FEAT/UI durations are written as a shortened number beside a fixed unit, so a slow run reads "1.2k ms" rather than "1.2 s". A duration formatter that steps the unit itself (µs/ms/s/min) would read better wherever `si` is followed by "ms"
- CHORE/UI `biome check ./src` reports an ineffective suppression at `FlowEditor.tsx:473` (`useExhaustiveDependencies` no longer fires there) - CHORE/UI `biome check ./src` reports an ineffective suppression at `FlowEditor.tsx:473` (`useExhaustiveDependencies` no longer fires there)
- FEAT/UI the brain's activity falloff is session-observed: a page just opened shows every neuron and connection at the same neutral base, and only sorts itself out as values arrive. A "last published" timestamp per node from the backend would let it open already sorted. - FEAT/UI the brain's activity falloff is session-observed: a page just opened shows every neuron and connection at the same neutral base, and only sorts itself out as values arrive. A "last published" timestamp per node from the backend would let it open already sorted.
- CHORE/UI the brain's hover labels have no touch equivalent — a tap navigates to the flow, and there is no hover to reveal a name first. The native `title` carries it on desktop only. - CHORE/UI the brain's hover labels have no touch equivalent — a tap navigates to the flow, and there is no hover to reveal a name first. The native `title` carries it on desktop only.
- BUG/UI slightly increase the margin between the top of a graph in the node/flow panel and the consumer/producer field
- FEAT/UI labels in flows (indicating dashboard widget connections) naturally can't pulse. Instead add an animation (enlightning fade) from either ltr or rtl depending if the label is in- or outbound - FEAT/UI labels in flows (indicating dashboard widget connections) naturally can't pulse. Instead add an animation (enlightning fade) from either ltr or rtl depending if the label is in- or outbound
- FEAT/UI (deferred until MCP lands): add a "bot" icon button to the home view (graph panel) which opens a chat window (reuse general concept of a side panel like in flows/nodes to make it a chat panel which can open on any screen (stacks below any other existing panel -> introduce stacking) to give support on errors/write code, generate dashboards etc) to explain the error(s) - FEAT/UI (deferred until MCP lands): add a "bot" icon button to the home view (graph panel) which opens a chat window (reuse general concept of a side panel like in flows/nodes to make it a chat panel which can open on any screen (stacks below any other existing panel -> introduce stacking) to give support on errors/write code, generate dashboards etc) to explain the error(s)
### Persistence and databases
From the 2026-08 database review. Verdict recorded under Deferred: the
Postgres + Redis + git-files split stays; the actionable part is durability.
- BUG/INFRA: `scripts/backup.sh` dumps Postgres only — the flow git repo, `secrets.enc`, `oauth-key.pem` (losing it invalidates every issued MCP token), `alerts.json` and the Redis AOF are not backed up. Extend it to tar `app-flow-data` and copy a `BGSAVE`'d Redis snapshot. Its header comment still claims "the flow engine keeps no on-disk state", which stopped being true when flows became a git repo.
- CHORE/FLOW: state backend and work queue share the `pipeline:` prefix in db 0, so `RedisState.clear()` would DEL the work-queue stream and `RedisState.keys()` enumerates queue keys — only callers filtering `__`-prefixed names keep it safe. A separate prefix (or db index) for the queue removes the hazard.
- CHORE/INFRA: Redis AOF runs at `appendfsync everysec`, so up to ~1 s of journaled work-queue entries can vanish on a crash — softer than "journaled before it runs" reads. Queue write volume is low, so `appendfsync always` is likely affordable; otherwise document the loss window.
- CHORE/INFRA: Redis has no auth (`requirepass` unset). Fine on the compose-internal network; a blocker for M5 remote workers, which turn Redis into a network-exposed shared bus.
- CHORE/INFRA: the SQLAlchemy engine sets no `pool_pre_ping`, so long-idle connections throw once after a Postgres restart before the pool recovers.
### Connector write paths ### Connector write paths
Needs someone watching the real hardware, so it is not a background task. This Needs someone watching the real hardware, so it is not a background task. This
@@ -89,13 +100,13 @@ Decisions taken up front, because most items below depend on them:
- Nothing e-ink-specific in the widgets. Panel access is a credential problem - Nothing e-ink-specific in the widgets. Panel access is a credential problem
(see below); the display's demands are a rendering profile, deferred. (see below); the display's demands are a rendering profile, deferred.
- FEAT/FLOW: declared structured dtypes — `series` (labelled ts/value pairs), - !FEAT/FLOW: declared structured dtypes — `series` (labelled ts/value pairs),
`record` (flat named scalars) and `list` (ordered items of a declared shape) in `record` (flat named scalars) and `list` (ordered items of a declared shape) in
`DType`, checked like the scalars are, with `WIDGET_DTYPES` extended so a `DType`, checked like the scalars are, with `WIDGET_DTYPES` extended so a
widget binds a shape rather than "some JSON". Everything a single number can widget binds a shape rather than "some JSON". Everything a single number can
say stays a `float`/`bool` message. Prerequisite for the agenda, forecast, say stays a `float`/`bool` message. Prerequisite for the agenda, forecast,
notification and queried-chart widgets. notification and queried-chart widgets.
- FEAT/UI+FLOW: charts that query. A chart owns a refresh interval, publishes a - !FEAT/UI+FLOW: charts that query. A chart owns a refresh interval, publishes a
request message (range, interval) exactly as a slider publishes a value, and request message (range, interval) exactly as a slider publishes a value, and
draws the `series` message a data node answers with. The answer carries the draws the `series` message a data node answers with. The answer carries the
range and interval it was computed for and the widget ignores one that does not range and interval it was computed for and the widget ignores one that does not
@@ -103,7 +114,7 @@ Decisions taken up front, because most items below depend on them:
overwrite each other's window. Costs a duplicate query rather than a wrong overwrite each other's window. Costs a duplicate query rather than a wrong
chart. Needs a floor under the interval and dedup of identical in-flight chart. Needs a floor under the interval and dedup of identical in-flight
requests. The alternative — a message name per widget — would mean dynamic requests. The alternative — a message name per widget — would mean dynamic
names in a namespace that is deliberately static. names in a namespace that is deliberately static. Overall idea is that visualization and data stays separate. The widget can make a query to an influx db node (with some python function in front of it to prepare the query) and the node then feeds the answer back to the widget (again with some python function to parse the response). This makes the widget agnostic of any database type
- FEAT/NODE: a series read mode for the InfluxDB node: return the whole - FEAT/NODE: a series read mode for the InfluxDB node: return the whole
aggregated window (`aggregateWindow`, function and interval from the request) aggregated window (`aggregateWindow`, function and interval from the request)
as one `series` message, instead of the single aggregated scalar it produces as one `series` message, instead of the single aggregated scalar it produces
@@ -204,7 +215,10 @@ Open on purpose. Each names what should bring it back.
- CHORE/INFRA: `bun run --filter frontend build` fails on this workspace with `crypto.hash is not a function` — Vite 7 wants Node 20.12+ and the host has 18. The Docker image builds fine, so it only bites local bundling; `bunx tsc` still type-checks. - CHORE/INFRA: `bun run --filter frontend build` fails on this workspace with `crypto.hash is not a function` — Vite 7 wants Node 20.12+ and the host has 18. The Docker image builds fine, so it only bites local bundling; `bunx tsc` still type-checks.
- FEAT/UI: an endpoint's edge routes straight across the graph, so it can pass behind a node that sits between the lane and the node it wires to. Readable, but a routed edge would be tidier. - FEAT/UI: an endpoint's edge routes straight across the graph, so it can pass behind a node that sits between the lane and the node it wires to. Readable, but a routed edge would be tidier.
- FEAT/UI: the node-panel and edge trend curves take no range, unlike the health block. They are drawn from a Redis ring of the last 120 values per message, which has no window to ask for — a hover caption names what the curve covers instead of a picker promising a span nothing can serve. Reopen if per-message history ever gains a time window. - FEAT/UI: the node-panel and edge trend curves take no range, unlike the health block. They are drawn from a Redis ring of the last 120 values per message, which has no window to ask for — a hover caption names what the curve covers instead of a picker promising a span nothing can serve. Reopen if per-message history ever gains a time window.
- FEAT/UI: a dashboard that demonstrates the time range concept, with an InfluxDB node as its data source. The range picker governs the health block, which is backed by minute rollups; a dashboard chart draws a message's 120-sample ring, and the InfluxDB node answers a query as one aggregated scalar over a `query_range` fixed in its params. So a range-aware dashboard chart is the *charts that query* item under wall-panel parity — the `series` dtype, the chart publishing its request, and an InfluxDB series read mode — not a dashboard anyone can assemble today. Reopen with that work.
- FEAT/UI: an e-ink rendering profile for a dashboard — motion off, hover-only affordances resolved to something visible, high-contrast palette, thick strokes, and a repaint cadence low enough for a display that takes a second to settle. Reopen when a panel with such a display is actually hung. - FEAT/UI: an e-ink rendering profile for a dashboard — motion off, hover-only affordances resolved to something visible, high-contrast palette, thick strokes, and a repaint cadence low enough for a display that takes a second to settle. Reopen when a panel with such a display is actually hung.
- CHORE/INFRA: Postgres stays. The 2026-08 review rejected YugabyteDB/CockroachDB (multi-node cluster systems, ~4 GB+ RAM per node, against the small-server target — the scaling story is remote workers, not a distributed DB) and found merging Postgres into Redis or vice versa buys little: the stores hold disjoint data and both sit behind abstractions. SQLite would fit the single-instance design and drop a container; reopen if the home-install footprint becomes a product concern.
- CHORE/INFRA: NATS JetStream as the work-queue backend — durable streams whose consumer semantics match the `WorkQueue` interface, in one small binary. Reopen with M5 remote workers, when the queue crosses hosts.
## Blocked ## Blocked