Commit graph

131 commits

Author SHA1 Message Date
flemming-it
5a3f00bb2c fix(docs): page help buttons open the right topic + wiring guard
The Federation and Runs help buttons opened the architecture doc:
federation.md/runs.md existed as assets but had no _DocEntry, so
showFaiDoc resolved the unknown slug to _kDocs.first. Register both
(onWelcome: false, so they don't clutter the newcomer grid but are
reachable), split the Welcome grid onto the curated subset, and make
the unknown-slug fallback assert in debug instead of silently opening
the wrong topic.

Guard (no-bugfix-without-a-guard): doc_help_wiring_test.dart scans
lib/ for every showFaiDoc('slug') call and asserts each has a
registered entry AND both assets/docs/<slug>[_de].md files. Exposes
kKnownDocSlugs for the test.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-20 02:00:56 +02:00
flemming-it
ed680c507a refactor(ui): one canonical segment control (ChainSegments) everywhere
Some checks failed
Security / Security check (push) Failing after 1s
The same single-select choice pattern appeared as four widgets:
audit's hover pills, the store's SegmentedButton, the store filter
dialog's ChoiceChips, and the approvals TabBar (usertest finding
#14 / night-log decision 'pill segment as canon'). The audit
pattern is promoted to a shared ChainSegments widget (optional
icons, hover, selected border, button+selected semantics) and all
four sites use it; approvals switches lists via IndexedStack so
both stay alive and switching does not refetch.

Guard per the no-bugfix-without-a-guard rule: widget tests for
selection + semantics, plus a canon sweep that bans
TabBar/TabBarView/TabController/SegmentedButton/ChoiceChip from
lib/ (comments exempt). Deliberately out of scope: the flow
editor's Graph/Text/Run tabs live in the separate editor package.
Studio 0.75.0; guide images regenerated, dark + light verified.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-19 02:58:54 +02:00
flemming-it
66b26304fd feat(test): hermetic hub fake + state-matrix sweep across all pages
The widget suites used to talk to whatever listens on the real
endpoint — results depended on the operator's machine (a running
hub fed real data into a11y/responsive runs and its gRPC channel
timers caused the historic flake). Hardening round:

- HubService.instance is now injectable (debugSetInstance);
  FakeHubService (test/support/fake_hub.dart) answers every member
  the pages touch with healthy-empty defaults and scripts per-RPC
  failures (UNIMPLEMENTED / UNAVAILABLE / detached gate) through a
  GrpcError-shaped fake. Unimplemented members are recorded and
  fail the sweep with the exact list.
- state_matrix_test.dart pins the app-wide invariants for every
  sidebar page x hub condition: healthy => no unreachable claims
  and no raw error text; hub gone => honest unreachable states;
  UNIMPLEMENTED => never 'not reachable' while the sidebar shows
  connected; detached gate => plain-language feature-off state.
- a11y + responsive sweeps now inject the fake (hermetic); the
  6-minute idle-timer drain workaround is gone with the cause.

Real bugs the new sweep caught immediately:
- every data page (store, doctor, audit, approvals, federation)
  folded ANY load failure into 'hub not reachable' — the runs-page
  bug class; they now share HubLoadErrorView, which classifies
  into unreachable / needs-newer-hub / load-failed-with-copyable-
  detail (new generic DE+EN strings)
- the approvals page's hidden tab had no future listener: a load
  failure there surfaced as an uncaught async error
- the audit status bar rendered the raw gRPC error wall verbatim;
  it now shows the classified friendly headline (still selectable)

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-19 01:02:51 +02:00
flemming-it
e67e0c9e73 feat(doctor): deep-link findings to the page where they are actioned
Doctor findings used to be dead-end statements — 'approvals
waiting for review' left the operator to find the approvals inbox
on their own. Every finding with a dedicated surface is now one
tap away from it:

- summary tiles: modules -> store, approvals -> approvals inbox,
  audit chain -> audit log (chevron affordance, tooltip + semantics
  button; the services tile stays plain — no dedicated page)
- modules/approvals panel rows link the same way
- the event-log headline opens the audit page next to the
  existing verify button
- host-services empty state gains a 'view the configuration'
  button opening the in-Studio config viewer the hint refers to
- the update banner's release-notes URL is now an underlined,
  clickable link instead of dead text

Tiles and the panel are public callback-driven widgets so the
widget tests pump them without a live hub. New DE+EN link labels.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-18 18:02:04 +02:00
flemming-it
383490027b fix(audit): cancel the live-stream reconnect timer on dispose
The onDone handler armed an anonymous 3 s reconnect timer that
nothing could cancel; when the stream closed right before the page
was disposed (no hub, connect ends in onDone instead of onError),
the timer outlived the tree. The a11y suite caught this as the
rare 'Timer is still pending' flake noted in the night log — the
failure reason is now captured and the timer lives in a field that
dispose() cancels.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-18 17:33:11 +02:00
flemming-it
ea2cd87b5e fix(runs): stop claiming the hub is unreachable on RPC-level errors
The runs monitor folded every load failure into 'hub not reachable',
contradicting the sidebar's green connected dot whenever the hub
answered but the RPC failed — most visibly against a pre-0.22 hub
whose version predates the ListInvocations RPC (UNIMPLEMENTED).

Classify the failure instead (top-level, unit-tested):
- UNIMPLEMENTED -> 'this view needs a newer hub version' with a
  doctor-page link (the update banner lives there)
- FAILED_PRECONDITION from the detached gate -> the regular
  feature-off empty state with the guide button
- UNAVAILABLE / DEADLINE_EXCEEDED / socket-level failures -> the
  honest 'hub not reachable' state (unchanged)
- everything else -> a load-failed state with the friendly error
  and a copyable detail box

The error view is a public callback-driven widget so the tests pump
each variant without a live hub. New DE+EN strings for the too-old
and load-failed states; grpcCodeOf/grpcMessageOf exposed from the
friendly-error mapper instead of duplicating the duck-typing.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-18 17:33:11 +02:00
flemming-it
b47d8c4646 feat(audit): full-history JSONL export in the actions menu
Some checks failed
Security / Security check (push) Failing after 1s
The menu so far only exported the current view (type + search
filter over the page 100-event window). A second action now fetches
the complete event history of the active project scope in one
EventLog call (the RPC has no cursor and no server-side cap) and
writes it as JSONL. Serialisation extracted to a top-level function
with unit tests; a stale comment advertising the never-shipped
"chain audit export" command now names "chain admin events --json".
Studio 0.73.0.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-18 01:49:20 +02:00
flemming-it
ae8fdcc762 fix(store,audit,workspace): usertest low-findings tail (0.72.1)
Some checks failed
Security / Security check (push) Failing after 1s
- Store hero: 'TODAY' badge only for an operator-accepted story; the
  rotating compiled-in fallback deck now says 'FEATURED' (no false
  freshness claim). Policy as a top-level function with unit tests.
- Audit filter chips: standard label typography instead of mono —
  mono stays reserved for paths and identifiers.
- DE chain wording: 'Hash-Kette geprüft' as the one confirmation term
  (audit header now matches the doctor pill); 'intakt' stays the
  state headline. EN was already consistent.
- Workspace switcher: contrast bump for the sealed-area 'stopped'
  label.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-18 01:08:09 +02:00
flemming-it
703d961cec fix(doctor): honest module count, temp-path audit warning, connection line
Some checks are pending
Security / Security check (push) Waiting to run
Three doctor-page findings from the usertest panel:

- Module tile no longer counts the hub's built-in 'system'
  pseudo-module — a fresh hub shows 0 modules, matching the
  welcome checklist's definition of an install. Counting is a
  top-level function with unit tests.
- When the audit DB lives in an OS-cleanable temp directory
  (/var/folders, /tmp, Windows Temp), the daemon-files panel
  says so instead of presenting the state as healthy. The
  classifier is a top-level function with unit tests.
- The daemon card states who-talks-to-whom-how in one line:
  endpoint, transport security (TLS / unencrypted-local /
  unencrypted), and whether a bearer token is attached (length
  only) — the auditor's baseline the green dot cannot answer.

Also syncs pubspec.yaml (0.70.0 -> 0.72.0) with kStudioVersion,
which had drifted to 0.71.0 while pubspec stayed behind.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-18 00:56:46 +02:00
flemming-it
b42003e600 fix(welcome,store): sticky flow-completed tick, carousel position text
Some checks are pending
Security / Security check (push) Waiting to run
- the 'start a saved flow' checklist tick no longer unticks once
  the flow.completed event scrolls out of the 100-event window —
  a local sticky marker keeps it honest to its wording
- the Today carousel shows 'n/m' next to the 6-px dots so the
  position is readable without aiming at them

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-18 00:36:00 +02:00
flemming-it
5578c32710 fix(store): localized category labels, 'Studio & Designs' tab in German
Some checks are pending
Security / Security check (push) Waiting to run
'document' rendered as a raw lowercase English token next to
localized neighbours; unknown categories at least capitalize.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-18 00:34:28 +02:00
flemming-it
32e2510c63 feat(store): license pill on the module card
Some checks are pending
Security / Security check (push) Waiting to run
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-18 00:29:07 +02:00
flemming-it
eab58c0b68 fix(ux): quick wins from the usertest medium list
Some checks are pending
Security / Security check (push) Waiting to run
- audit type filter: 'Alle'/'All' capitalized like every other label
- settings -> setup wizard: close Settings first (one modal layer),
  stronger wizard scrim
- try-out setup profile discloses the upgrade path to a regulated
  profile
- store maturity pills explain themselves on hover (experimental/
  published/planned)

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-18 00:24:13 +02:00
flemming-it
ae97b88257 fix(runs): honest empty state — feature off vs. no runs yet
Some checks are pending
Security / Security check (push) Waiting to run
The empty state unconditionally claimed background runs were
switched off, even on hubs where the operator had enabled them.
The hub now reports the flag on the list RPC (detached_enabled);
the hint picks the truthful variant.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-18 00:20:43 +02:00
flemming-it
5aa69104e7 feat(audit): free-text search, JSONL export of the view, labeled dev reset
Some checks failed
Security / Security check (push) Failing after 1s
- search field over flow/step/module/error/detail/project/id backs
  the list and the export ('current view' semantics); match logic
  is a top-level function with unit tests
- export writes one JSON object per line via the save dialog; the
  CLI stays the canonical WORM-grade export
- the bare trash icon on the audit toolbar read as 'delete
  evidence' (security-auditor finding) — the dev-only reset now
  sits in a labeled overflow menu next to the export action

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-18 00:08:51 +02:00
flemming-it
0e53572589 fix(federation): primary action in the app bar and empty state, no FAB
Every other page carries its primary action top right (New flow,
Add store) — the lone Material FAB bottom right broke the pattern
and sat far from the empty-state text asking for exactly that
action. The empty state now offers the button in place too.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-18 00:08:51 +02:00
flemming-it
b52590c7d3 fix(doctor): copy button per path row, readable chain count, cased source kinds
Some checks are pending
Security / Security check (push) Waiting to run
- every daemon file row gets a copy-to-clipboard action next to
  view/open so terminal users can grab the raw path
- audit stat subtitle says 'n of m events verified' instead of the
  cryptic 'n/m chain'
- capability source-kind breakdown renders display names
  (Bundle/MCP/System) instead of raw lowercase wire tokens

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-18 00:04:05 +02:00
flemming-it
039f11b6bc feat(store): trust gate before every module install
Some checks failed
Security / Security check (push) Failing after 2s
One-click installs showed no trust signal at all (top security
finding of the usertest panel). Every install path — store card,
detail sheet, and the flow list's quick fix — now routes through
one confirmation dialog showing what the hub actually knows
before download: origin store, version, license, maturity, and
required services/capabilities, plus the sandbox model and an
honest note that per-entry signature status is not in the store
index yet (verification happens hub-side at install). Widget
tests cover content and confirm/cancel semantics.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-17 23:44:14 +02:00
flemming-it
c436e12601 feat(nav): discoverable sidebar — instant tooltips, shortcuts made visible, pinnable rail
Some checks are pending
Security / Security check (push) Waiting to run
The icon-only rail forced first-time users to guess (usertest:
Senior, a11y, UX personas). Three changes:
- Nav tooltips appear instantly and carry the page shortcut
  (Cmd+1..9, Ctrl on non-mac — Ctrl activators added); expanded
  labels show the same hint. Explicit button semantics for
  screen readers on every destination.
- A visible 'Search & commands' row above the footer opens the
  existing Cmd+K palette, which nothing in the UI advertised.
- Settings -> Appearance gains 'Keep the navigation expanded':
  pins the rail with permanent labels (persisted preference).
Footer strip and pillar toggle made overflow-safe for the
animating rail; responsive test scrolls the by-design scrollable
destinations list.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-17 23:36:33 +02:00
flemming-it
3e1ce6e1fd fix(welcome): concept cards speak everyday language first
Some checks are pending
Security / Security check (push) Waiting to run
The Hub/Module/Flow cards explained the basics in the very
vocabulary they were supposed to introduce (Rust binary, WASM,
YAML, hash-chained). Each card now leads with a plain-language
explanation; the technical wording moved behind a per-card
'for the technically curious' toggle. DE and EN.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-17 23:24:46 +02:00
flemming-it
cc1618f512 fix(runs): plain-language empty state with a guide button
Some checks are pending
Security / Security check (push) Waiting to run
The empty state explained itself in operator jargon (detach,
detached.enabled, operator config) and offered no way forward.
Now it says what background runs are in everyday language and
opens the built-in guide — which carries the exact activation
steps — via a real button. DE and EN.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-17 23:23:15 +02:00
flemming-it
adb8d3f914 feat(flows): native file dialog for flow file inputs
Some checks failed
Security / Security check (push) Failing after 2s
Wires the editor's new onPickFile host callback to file_picker
(withData: the editor receives name + bytes, never a raw path).
Pins chain_studio_flow_editor to v0.23.0. No more typing absolute
paths to feed a flow a file.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-17 01:05:10 +02:00
flemming-it
065939be74 feat(setup): first-run gate, hub-first preview, honest wording — setup before the app
Some checks are pending
Security / Security check (push) Waiting to run
Stefan's live findings, all four addressed at the root:

- 'In 3 Fragen loslegen' read like ad copy → the entry is now plainly
  'Einrichtung starten' / 'Start setup'.
- The setup button sat permanently on the Welcome page of a running
  app ('setup after the app runs is backwards' — reported twice). A
  fresh install now starts INSIDE the setup: SetupGateScreen hosts
  the wizard embedded as the page (new embedded/onFinished modes on
  GuidedSetupDialog), with an explicit 'Später einrichten' skip.
  Welcome loses the setup button entirely and stays a calm intro.
- Re-running the setup later lives in Settings → General ('Run setup
  again…'), the single post-first-run home.
- 'You must grant access first and only then see what will be done':
  the preview used to spawn the chain CLI, whose first run could pop
  the macOS permission prompt BEFORE the plan was ever shown. The
  preview now calls the new PlanSetup RPC over the live hub
  connection (no subprocess, nothing granted); the CLI remains only
  a fallback when no hub is reachable — and applying stays the
  explicit, separate step.

Widget tests: gate hosts the wizard + skip/cancel leave it; CLI-path
tests drive the fallback through the new hub-preview test seam.
Suite 76 green, analyze clean.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-17 00:59:22 +02:00
flemming-it
da58125f20 fix(ui): WCAG light-theme accent, overflow-safe audit page, formal address
Some checks are pending
Security / Security check (push) Waiting to run
Accessibility/responsive audit pass with two new permanent test
gates (test/a11y_test.dart: WCAG text contrast + labeled tap
targets on every page in both themes; test/responsive_test.dart:
no layout overflow at 800/960/1280/1920 px). Findings fixed:

- Light theme primary/tertiary sky-500 → sky-700: white text on
  the lighter accent only reached 2.8:1 (welcome CTA, active
  sidebar label); sky-700 clears WCAG AA at ~5.9:1. Dark theme
  unchanged (already compliant). FABs now follow the same accent
  instead of Material 3's washed-out tonal default.
- Audit page: filter chips collapse into a checkmark popup menu
  below 900 px window width (app bar overflowed); the live-status
  bar's left text is now Expanded with ellipsis so the row can
  shrink, and the disconnected state's copyable error gets the
  full remaining width.
- German strings now use formal address consistently (~20 strings
  still used du-forms next to Sie-forms on welcome/setup), the
  audit event-type chip "Step" is "Schritt", and the doctor
  page's event count pluralises correctly in both languages.

flutter analyze clean, 64 tests green. Screenshot pass light+dark
via the guide-shots harness (verified parity, no overflows).

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-15 04:34:19 +02:00
flemming-it
4ceb5bb567 fix(settings): reveal System-AI test result + refresh onboarding checklist
Some checks failed
Security / Security check (push) Failing after 1s
Two settings bugs the operator hit:

1. 'Test connection' appeared to do nothing. The result/error panel
   renders at the bottom of the System-AI editor's scrollable,
   600px-capped form, so on a tall dialog it lands below the fold —
   the footer button flickers 'Testing…' and nothing visible changes.
   The editor now holds a ScrollController and animates the content
   to reveal the outcome whenever a test result or error appears.

2. The welcome onboarding checklist kept 'connect System-AI'
   unchecked right after saving a working config. The checklist row
   opens the Settings dialog (an overlay, not a navigation), and on
   close the checklist never re-probed — so it showed the stale
   pre-config state. Both settings-opening rows (System-AI, MCP) now
   re-probe when the dialog closes; navigation-based rows already
   self-heal on return.

Studio suite green; flutter analyze clean.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-13 14:15:17 +02:00
flemming-it
1f1e050b42 feat: guided setup — clickable next steps, signature relaxation, fresh-install auto-open
Post-apply the wizard now renders real Studio actions instead of CLI
text: a start-hub button that polls until the daemon answers,
per-module install buttons (capability-name install via the hub's
store index) with done/progress states, and an open-the-starter-flow
button that navigates to the Flows page. Regulated plans explain in
plain language that modules come from a signed source; the preview
offers 'allow installing from the public store' as one deliberate,
reversible switch that re-assembles the plan (allow_unsigned_modules).

Fresh installs (no config, no setup-plan.yaml) auto-open the wizard
once per run — the wizard IS the onboarding — and it steps back once
a setup exists. The welcome CTA is framed honestly ('get started in
3 questions'), and after the wizard closes the onboarding checklist
remounts, re-probes, and says what the assistant already covered
(profile line from setup-plan.yaml) instead of acting as a second,
disconnected onboarding surface.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-12 23:18:41 +02:00
flemming-it
54ccd3936a feat: detached-runs monitor page (T3 parity)
Some checks failed
Security / Security check (push) Failing after 1s
New Runs sidebar destination listing detached invocations (detach:true)
with phase, current step, project and a Cancel button while
pending/running. Workspace-scoped like Audit/Approvals, polls every 2s.
Detached runs are opt-in (detached.enabled) — the empty state explains
how to enable them. Inline help doc DE+EN. DetachedRun model +
listDetachedRuns/cancelDetachedRun in HubService, backed by the SDK's
listInvocations()/cancelInvocation(). flutter analyze clean; 29 tests
green (sidebar Y-stability updated for the new destination, model
mapping unit-tested).

Screenshot verification (light+dark) deferred — shared desktop in use.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-12 14:43:37 +02:00
flemming-it
984c91f91d feat: editor project chip wiring (multi-project stage 2 host side)
Some checks failed
Security / Security check (push) Failing after 2s
FlowsPage passes the active workspace to the editor and switches the
workspace when the operator accepts a file-wins mismatch. Rebuilds the
chip live on workspace change. Editor package bumped to 0.22.0.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-12 14:21:20 +02:00
flemming-it
2592a23cc0 feat: workspace switcher, per-project filters and run stamping (stage 1)
Some checks failed
Security / Security check (push) Failing after 2s
Multi-project stage 1 against the shared hub (platform design
docs/architecture/projects.md, § Studio):

- ChainWorkspaceSwitcher in the Audit + Approvals AppBars: lists the
  registry (colour dot per project, shield for protected, honesty
  tooltip), 'All projects' stays reachable — a filter, not a jail.
  Selection is persisted and shared via the Workspace notifier.
- Audit page: list query AND live stream re-scoped hub-side on switch.
- Approvals page: pending + history scoped; the sidebar badge counts
  the active workspace's pending approvals.
- Flow runs are stamped with the active workspace; a flow file
  carrying its own project: keeps it (file wins, CLI semantics).
- Data layer: listProjects/ProjectRef; project fields on AuditEvent,
  PendingApproval(+Record), SavedFlow; project params through
  HubService. l10n DE+EN. Widget tests for the switcher contract.

Visual verification (light+dark screenshots) still pending — the
shared desktop was in active use; code paths are covered by
flutter test (26 green).

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-12 13:49:51 +02:00
flemming-it
7a38cd58aa refactor: FaiError -> ChainError (SDK stub rename lockstep)
Some checks failed
Security / Security check (push) Failing after 1s
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-11 23:14:33 +02:00
flemming-it
bb606a8b23 fix(approvals,l10n,theme): usertest findings — localized prompts, no-data confirm, .chain log path, honest wording, AA contrast
Some checks failed
Security / Security check (push) Failing after 2s
- approvals: empty/legacy hub prompts render the localized fallback;
  approving without show: data asks for conscious confirmation first
- chain_log: write to ~/.chain/logs/studio-errors.log (was .fai),
  one-time best-effort migration of the legacy file + rotation sibling
- l10n: 'manipulationssicher' -> 'manipulationserkennend', neutral
  WORM-1 blurb, doctor pill 'Integritätskette v1', federation hint
  says the CA authenticates the first connect (DE+EN)
- theme: muted text token now >=4.5:1 on canvas, cards and elevated
  dark surfaces (was 3.7:1 on cards)

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-11 02:38:24 +02:00
flemming-it
0fda2600ad fix(store,l10n): localize canonical category labels + store segment
The grouped store showed the hub's English category labels verbatim
(Documents, Data & Formats) even in German. Map the canonical slug to
DE/EN via l10n (storeCat*), and localize the Modules/Studio segment
(storeSegment*). Falls back to the hub label for an unknown slug.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-09 18:17:50 +02:00
flemming-it
4b30589962 feat(store): group grid by canonical category + Modules/Studio segment
The store grid was a flat jumble. It now renders labelled sections per
canonical category (App-Store style, fixed order, with counts), and a
top 'Modules | Studio & Themes' segment splits flow modules from Studio
plugins/themes. StoreItem carries the hub's canonical_category(+label);
falls back to the raw category label for a pre-0.21 hub.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-09 17:18:40 +02:00
flemming-it
5d511dcd99 fix(studio): promote guided-setup button + remove dead ModulesPage
Some checks failed
Security / Security check (push) Failing after 2s
The guided setup is the fastest path to a working first run, so lead
with a FilledButton instead of a low-emphasis outlined one (welcome
page). Delete pages/modules.dart — ModulesPage was never routed
(superseded by the Store 'Installed' filter) and nothing imports it;
flutter analyze stays clean.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-01 02:34:53 +02:00
flemming-it
27cf7e8382 feat(studio): show module origin store ('from <store>')
StoreItem gains source (mapped from StoreEntry.source); the store grid
shows a 'from <store>' label for operator-added stores (bundled seed
unlabelled). Foundation for grouping by store. EN+DE l10n.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-22 00:59:51 +02:00
flemming-it
255348c062 fix(studio): store grid uses _ModuleIcon (aligned icons + icon URLs)
The grid cell rendered a bare category glyph in a CircleAvatar; the detail
view uses _ModuleIcon (module icon URL with category fallback). Grid now
uses _ModuleIcon too — consistent, aligned, shows per-module icons.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-22 00:53:22 +02:00
flemming-it
c9fa068991 feat(studio): guided-setup wizard (reuses chain init engine)
A Welcome 'Setup assistant' button opens a wizard that collects
scenario / intent / target (+ approval & data-local toggles), then calls
`chain init --answers` to preview the assembled plan and `--apply --force`
to write the config — reusing the Rust deterministic engine, no logic
duplicated. New SystemActions.chainInit; copyable errors via
showFaiProcessError; EN+DE l10n. analyze clean; smoke test + existing
welcome/sidebar tests pass.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-21 21:04:13 +02:00
flemming-it
9bd5ddf8d2 feat(studio): live audit feed via streamEvents (poll stays as safety net)
Some checks failed
Security / Security check (push) Failing after 1s
The Audit page subscribes to streamEvents and nudges an immediate
(debounced) refresh on each new event, so the feed updates instantly
instead of waiting up to 2 s. Reuses the proven _refresh() path, so
list management + filtering + hash-chain ordering are unchanged. The
2 s poll remains the safety net: on a persistent stream error the page
is still fresh within the interval; a clean stream close re-subscribes
once after 3 s. Subscription + debounce cancelled on dispose.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-19 10:07:08 +02:00
flemming-it
97f3cb8560 feat(studio): approval payload — explain absence, cap height, accurate label
Some checks failed
Security / Security check (push) Failing after 1s
The approval card only rendered the payload section when a preview
existed, so a step with no 'show:' showed nothing and the reviewer
could not tell why. Now always show the section: a present payload
scrolls inside a height-capped, copyable box; an absent one shows an
explanatory hint (the flow's approval step chooses what to surface via
its 'show:' field). Relabel 'data to be released' -> 'data to review'
(the payload is review context, accurate to its source).

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-19 02:29:20 +02:00
flemming-it
8a40e8e315 fix(studio): make remaining non-copyable error sites copyable
Some checks failed
Security / Security check (push) Failing after 1s
Audit sweep after the System-AI fix: the Settings dialog rendered its
two _error states as a bare Text (hub-endpoint save, default-scope
edit), and the Audit live-status bar showed the raw load failure in a
non-selectable Text (the only place that failure surfaces — the
empty-state below shows just a generic hint). Route the Settings errors
through ChainErrorBox and make the Audit disconnected text a
SelectableText. Errors must always be clipboard-copyable.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-19 02:19:20 +02:00
flemming-it
5220f19ff8 feat(studio): clearer store + channel switcher + approvals & welcome polish
Some checks failed
Security / Security check (push) Failing after 2s
- store: repair the filter dialog crash (a Spacer lived directly in
  AlertDialog.actions, which is an OverflowBar, not a Flex — it threw
  and rendered a broken dialog). Buttons now sit in a Row.
- store: promote the module-store manager from a bare icon to a
  labelled 'Add store' button, and fully localize the dialog (DE/EN).
- store: add a curated 'Suggested stores' shelf with one-click
  add/remove (first entry: Recl∆Im). Each suggestion is probed for
  reachability and shows 'not available yet' until its index is
  published, instead of failing only on click. Fail-open on network
  errors so a transient hiccup never hides a real store.
- sidebar: the channel pill is now a one-click channel switcher
  (menu with per-channel running state + active check; switching
  writes ~/.chain/current-channel, restarts the daemon, and Studio
  repoints to the new channel).
- approvals: lead the card with the human prompt ('what am I
  releasing?') and demote the flow/step id to a metadata line; clear
  fallback when the step left the prompt empty.
- welcome: tidy the docs grid into equal-height paired rows with a
  full-width trailing card for the odd one out.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-18 21:29:39 +02:00
flemming-it
57dac3d999 feat(studio): module-store manager (list / add / remove)
Some checks failed
Security / Security check (push) Failing after 2s
A store icon in the Store app bar opens a dialog that lists the
configured module stores + the bundled seed (with per-source module
counts), lets the operator add a store by index URL (the hub fetches +
merges it live so its modules appear immediately), and remove a store.
Backed by the new ListStores/AddStore/RemoveStore RPCs + SDK methods.
This is how a domain app's published modules (e.g. reclaim's) become
visible in the Store without touching the CLI.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-18 15:54:04 +02:00
flemming-it
5f56abcf5f fix(studio): audit batch — debug.echo install, copyable errors, fast Diagnose
From a live-test audit:
- Install via the flow-editor 'Fix' sent 'debug.echo@^0' (version
  constraint included) as the install source; the hub resolves by bare
  name so it missed ('no store entry for debug.echo@^0'). Strip the
  @<constraint> like the Store page does — debug.echo now installs.
- Errors the operator could not copy: route the daemon-start failure
  (its stderr!), the flow-editor install failure and the federation
  issue failure through showFaiErrorSnack / a new showFaiProcessError
  helper, so every error is selectable, one-tap copyable and logged.
- Diagnose page opened slowly because doctor() Future.wait-ed on a live
  manifest fetch (8s server timeout); cap that one check at 2s so the
  page no longer waits on the network.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-18 13:02:21 +02:00
flemming-it
ee4a0f6c62 fix(ui): window title Ch∆In Studio (was F∆I); de-dup federation add-satellite
- linux/macOS window chrome read 'F∆I Studio' (rename leftover) → 'Ch∆In Studio'.
- The federation page showed 'Add satellite' twice when empty (FAB + empty-state
  button); drop the empty-state button, the FAB carries the action.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-18 12:53:35 +02:00
flemming-it
891acd2ba2 refactor: rename internal Fai* design system + fai_ helpers to chain
Some checks failed
Security / Security check (push) Failing after 2s
The Studio design system, widgets and helpers carried a Fai* / fai_
prefix (FaiSpace, FaiColors, FaiTheme, FaiLog, 17 fai_*.dart files, the
faiBinary* l10n keys). Studio is the Ch∆In product, so rename them to
Chain* / chain_ — carefully preserving English fail/failure/failed.
Also fix stale references: the 'fai' binary in l10n strings -> 'chain',
FAI_* env vars (FAI_BIN/DATA_DIR/MODULES_DIR/TODAY/BOOTSTRAP_TOKEN) ->
CHAIN_*, fai_platform -> fai_chain, fai_hub -> chain_hub. Vendor
security-hook tooling (FAI_BANNED_TERMS_FILE) + the .fai bundle ext left.
flutter analyze + test: clean (20 passed).

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-16 17:53:17 +02:00
flemming-it
68d23ab7dd refactor: rename app fai_studio -> chain_studio
Some checks are pending
Security / Security check (push) Waiting to run
Studio is the Ch∆In product's GUI, not a F∆I-vendor app. Rename the
Flutter package, all package: imports, and the build identity across
platforms: linux/windows CMake BINARY_NAME + project, Windows Runner.rc
fields, macOS PRODUCT_NAME / bundle id (ai.flemming.chain.chainStudio) /
.app + scheme BuildableName. Update the client-SDK + flow-editor deps to
their renamed chain_* packages (path + git URL). Company/copyright fields
now read Flemming.AI. flutter analyze: clean.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-16 17:48:11 +02:00
flemming-it
0f93d90963 fix(studio): chain config dir + spawn path + doc URLs
Some checks failed
Security / Security check (push) Failing after 2s
Track the platform rename: the hub spawn path is now ~/.chain/bin/chain
(was ~/.fai/bin/fai.exe on Windows — both dir and binary were stale, so
Studio could not launch the hub after the config-dir rename), the
~/.fai/* help strings become ~/.chain/*, FAI_REGISTRY_TOKEN ->
CHAIN_REGISTRY_TOKEN, and the two in-app doc URLs point at the public
fai/chain repo (fai/platform was renamed to the private fai/chain-private).
The .fai module bundle extension is left unchanged (format phase).
flutter analyze: no issues.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-16 09:38:30 +02:00
flemming-it
7ff4fda2a3 refactor(brand): rename F∆I -> Ch∆In + hub binary fai -> chain
Some checks failed
Security / Security check (push) Failing after 2s
Studio follows the platform rename: product branding F∆I -> Ch∆In in UI
strings, command examples fai -> chain, and — critically — the spawned
hub binary path ~/.fai/bin/fai -> ~/.fai/bin/chain so Studio launches
the renamed binary. The fai_* Dart identifiers (FaiLog, widget files,
the generated SDK) stay = vendor/internal namespace. flutter analyze:
no issues.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-15 16:22:22 +02:00
flemming-it
a0007b9178 fix: onboarding checklist ticks for any installed module, not just text.*
Some checks failed
Security / Security check (push) Failing after 2s
The doc'd first install is debug.echo, but the Welcome onboarding
checklist only went green for a text.* capability — so a user
following the quickstart saw the box stay unchecked. Match any
non-system (non-built-in) capability instead.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-13 14:44:31 +02:00
flemming-it
d0cfa5df05 feat: federation panel + Dart SDK federation methods (0.70.0)
Some checks failed
Security / Security check (push) Failing after 2s
A new 'Föderation' destination (primary side) lists connected
satellites — name, region, version, wire version, advertised
capabilities — and adds them in one step: 'Add satellite' issues a
single-use bootstrap token bundled with the primary CA as a
ready-to-paste satellite config (the bundled CA makes the first
connect tamper-proof). Localized EN + DE, in-app help doc. Uses the
new HubService.listSatellites / issueSatelliteToken wrapping the
SDK's federation methods.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-13 14:16:07 +02:00