chain-studio/CHANGELOG.md
flemming-it 06f023aada
Some checks failed
Security / Security check (push) Failing after 2s
fix: survive corrupt preferences at startup; drop CocoaPods leftovers
A black window on launch, no error anywhere: main() awaited
loadPersistedEndpoint before the first frame, and
SharedPreferences.getBool threw 'int is not a subtype of bool?' —
the store is writable from outside the app and hub.secure had been
written as int 0. Pref reads now go through defensive typed helpers
(int coerces to bool, wrong types fall back to defaults), and every
pre-frame restore step is failure-isolated: a broken store can cost
a preference, never the first frame. Regression tests stage the
corrupt store (the exact observed value and worse).

Also removes the CocoaPods leftovers from the macOS project
(Podfile, [CP] script phases, Pods framework references, xcconfig
includes): the project builds via Swift Package Manager, and the
dual wiring ran both dependency managers on every build — Flutter's
persistent 'removing CocoaPods will improve build time' warning.
Verified: clean profile build produces a launchable bundle (plugins
statically linked via SwiftPM), suite green, analyze clean.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-15 10:46:22 +02:00

18 KiB
Raw Blame History

Changelog

All notable changes to chain_studio recorded here. Pubspec version + kStudioVersion in lib/main.dart stay in lockstep.

Unreleased

Fixed (startup + build time)

  • Black window on launch. A corrupt preference value (hub.secure stored as int 0 by an external defaults write) made SharedPreferences.getBool throw inside main() before the first frame — the app sat as a black window with no visible error. Pref reads now tolerate wrong types (int coerces to bool, garbage falls back to the default), and every pre-frame restore step is failure-isolated so nothing can prevent runApp again. Regression tests reproduce the corrupt store.
  • CocoaPods integration removed (macOS). The project builds via Swift Package Manager; the leftover Pods wiring (Podfile, [CP] script phases, Pods framework refs, xcconfig includes) made every build run both dependency managers — exactly what Flutter's own "will improve the project's build time" warning was about.

Added

  • Settings → Security shows the hub's auth policy. New panel backed by the hub's read-only AuthStatus RPC: active token validator (static / JWT-RS256 with issuer, audience and JWKS source), anonymous-access warning, and per-token cards with scope grants, env-var presence and rate limits — T4/T5 security administration finally visible outside YAML. Non-admin tokens get a localized denied story instead of an error.
  • Permanent accessibility + responsive test gates. Every page must pass WCAG text contrast and labeled-tap-target guidelines in both themes (test/a11y_test.dart) and lay out without overflow from 800 to 1920 px (test/responsive_test.dart).

Fixed

  • Daemon start with a wrong token no longer misreports. Both start paths (welcome CTA, sidebar) treated an auth-rejected hub as "daemon dead" and showed a start-failure dialog while the banner above correctly blamed the token; an auth rejection now counts as "daemon alive".
  • Token fixed outside Studio heals the connection. On an auth-rejected poll the shell re-reads ~/.chain/hub-auth-token and reconnects when the file changed — following the banner's own advice no longer requires re-saving in Settings or a restart. An endpoint switch also resets the failure streak, so a stale in-flight probe can't blame the new endpoint.
  • Security panel stays fresh. The auth-policy view re-queries after saving or clearing the hub token in the panel above, and renders the hub's new reload_required flag as a plain-language pending-reload warning (DE+EN).
  • Auth-rejected hub no longer reported as "unreachable". With token auth active, a wrong or rotated token got UNAUTHENTICATED from a perfectly reachable hub, but the sustained-failure banner said "can't reach the hub" — pointing the operator at the endpoint instead of the token. The shell now probes with the SDK's failure-kind-aware probe() and switches the banner to "rejected the sign-in — check the access token" (key-off icon).
  • Light theme accent was below WCAG contrast. Filled buttons and the active sidebar label rendered white-on-sky-500 (2.8:1); the light scheme now uses sky-700 (~5.9:1). FABs follow the same accent instead of Material 3's tonal default.
  • Audit page at narrow window widths. The app-bar filter chips collapse into a checkmark menu below 900 px, and the live-status bar shrinks gracefully (copyable disconnect error gets the full row width).
  • Consistent formal address in German. ~20 strings still used du-forms next to the Sie-forms on welcome/setup; the audit event-type chip "Step" is now "Schritt"; the doctor page's event count pluralises correctly ("1 Ereignis") in both languages.
  • Stored tokens reached the wrong directory. ~/.fai/ rename leftovers: the hub-auth token and registry token were read from / written to ~/.fai/ while the hub reads ~/.chain/ — a stored registry token never reached the hub. Today-stories and UI texts still advertising the retired .fai bundle extension fixed too.

Fixed (wizard live-run findings 2026-07-14)

Field test of the setup wizard surfaced three trust breaks in one run; all were reproduced against a stale CLI and fixed:

  • Errors surfaced behind the wizard. chain init failures were shown as a SnackBar, which lands BEHIND the wizard's modal barrier: dimmed, clipped, its copy button unreachable — and the operator's click at it hit the barrier, which (dismissible by default) closed the whole wizard with all answers. Now: failures open a modal error dialog ABOVE the wizard (copy button works, verbatim CLI output behind "Details"), and the wizard is no longer barrier-dismissible — leaving it is explicit via Abbrechen/Zurück.
  • CLI version skew explained. When the resolved chain binary is older than Studio and rejects --plan-json, the wizard now names the skew in plain language — which binary was executed, that it predates the assistant, and the update path — instead of leaking a raw clap usage error. A missing binary gets the same treatment plus a hint on step 3 before anything runs.
  • macOS folder prompt pre-explained. Step 3 now states which chain binary the preview will execute; when that binary physically lives (symlinks resolved) in a TCC-protected folder (Documents/ Desktop/Downloads), the wizard says up front that macOS may ask for folder access — instead of a bare permission prompt appearing in the middle of setup.
  • FriendlyError values now pass through friendlyError() unchanged so call sites can route precise, localized stories through the shared error presentation; SystemActions gained a public resolvedChainBinary() and test seams for the run/resolve paths.

Added (guided setup on grade-1 — steps A4/A5/B1 + doc automation)

  • Clickable next steps. After apply, the wizard renders real Studio actions instead of CLI text: start-hub button (polls until the daemon answers), per-module install buttons with progress/done states (capability-name install via the hub's store index), and an open-the-starter-flow button navigating to Flows.
  • Signature dead end resolved. 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 (allow_unsigned_modules) that re-assembles the plan. Air-gapped plans point to the offline-bundle path instead.
  • Fresh-install auto-open + honest framing. On a fresh hub (no config, no setup-plan.yaml) the wizard opens by itself, once per run; the welcome CTA is now "In 3 Fragen loslegen" / "Get started in 3 questions". After the wizard closes, the onboarding checklist re-probes and states what the assistant already covered (applied profile from setup-plan.yaml).
  • Free-text AI path (phase 1.2). "Or just describe what you want to do": the goal goes to the configured system AI, the reply is validated against strict enum whitelists and comes back as an editable "this is how I read your task" reflection feeding the same preview/apply. Privacy line states local vs. provider processing; without a system AI the menu path stands alone.
  • Nav manifest guard. test/nav_manifest_test.dart generates docs/nav.generated.json from the sidebar truth (ids, order = Cmd numbers, DE+EN labels); the platform repo checks the operator guide against the mirrored copy.
  • Guide screenshot harness. integration_test/guide_shots_test.dart boots a hermetic hub, seeds demo projects, walks every nav page, the workspace switcher and the setup wizard, and writes the guide PNGs — driven by the platform repo's scripts/regen-studio-guide.sh.
  • Fixed: the integration-test hub fixture still looked for the pre-rename fai binary and chain_platform/ path, so its tests silently skipped since the rename; it now resolves $CHAIN_BIN, chain on PATH, and ../fai_chain/target/{release,debug}/chain.

Added (guided setup — persona re-audit fixes, grade-1 round)

  • Regulated path finishes without a terminal. The post-apply signed-source state now offers "Add a signed source…" (the stores dialog with its pin-a-key field) plus the per-module install buttons, instead of a hint with no affordance; a plain-language trust hint explains why pinning the publisher's key matters.
  • Apply warnings surface. Warning lines from chain init --apply (e.g. the empty-trusted-publishers caveat) are shown selectable in the done state instead of being swallowed on success.
  • Truthful preview. New plan lines state which machine is being set up (server/container targets configure THIS machine — said explicitly), that regulated profiles get the hash-chained audit log even when WORM is off, and that a curated reading list is stored with the setup record.
  • Language pass. Onboarding checklist switched to Sie-form and "System-KI" (was du-form + "System-AI" next to the formal wizard); "Audit-Sperre" jargon replaced with "Schreibschutz für das Prüfprotokoll"; answers file now lives in a private per-dialog temp dir instead of a fixed world-readable name.

Added (multi-project, stage ③ — sealed areas)

  • Sealed-area connection switch. The workspace switcher now lists the operator's sealed areas (read from ~/.chain/sealed/ manifests, the same source the CLI uses) below the shared projects, each with a lock icon and a running/stopped status. Selecting one is a real connection switch: Studio reconnects its hub client to the area's own port with a full state reload — one window, one truth. A stopped area is started first (chain project start) with a visible notice; a failure surfaces as a copyable error and rolls back to the shared hub.
  • Identity bar. While connected to a sealed area, a strip under the AppBar is painted in the area's accent colour and names it, with a one-click Leave back to the shared hub. The area colour is marking, not theming — Studio's blue stays the app accent. (The window-title tint is a small follow-up; the identity bar is the primary signal.)
  • Selecting a shared project or "All projects" from inside a sealed area switches the connection back to the shared hub first. The sealed connection is never persisted across restarts — Studio always launches on the shared hub and the operator re-enters an area deliberately.

Added (detached-runs monitor — T3 parity)

  • Runs page. A new sidebar destination lists detached invocations (submitted with detach: true) with their phase, current step, project and a Cancel button while pending/running. Workspace- scoped like Audit and Approvals; polls every 2 s. Detached runs are opt-in (detached.enabled), so the empty state explains how to turn them on. Inline help doc (DE+EN). Backed by the SDK's listInvocations() + cancelInvocation().

Added (multi-project, stages ① + ②)

  • Workspace switcher. The Audit and Approvals AppBars carry a workspace control listing the hub's project registry (colour dot per project, a shield for protected, an honesty tooltip). "All projects" stays reachable — a filter, not a jail. The selection is persisted and shared across pages; it re-scopes the audit list AND live stream hub-side, scopes approvals (pending + history), and drives the sidebar approval badge. Runs launched from the editor are stamped with the active workspace — unless the flow file declares its own project:, in which case the file wins (CLI semantics).
  • Editor project chip + file-wins guard. A flow file's own project: shows as a chip; on mismatch with the active workspace an amber pill offers a one-click switch (the file still wins for the run). Backed by editor package 0.22.0.

Fixed (usertest 2026-07-10 findings)

  • Approval prompts localize. An approval whose flow step gave no prompt: (and legacy rows carrying the hub's old baked-in English sentence) now renders the localized fallback "Freigabe für diesen Schritt erforderlich" / "Approval required for this step" — no more English inside the German approvals UI.
  • Approving without review data asks first. When the approval step attached no show: payload, "Freigeben" opens a calm confirmation ("Ohne Prüfdaten freigeben?") explaining that the flow deliberately attached no data, with an explicit "Trotzdem freigeben".
  • Studio error log moved to ~/.chain/logs/. Writes went to the pre-rename ~/.fai/logs/studio-errors.log while the Doctor page and chain doctor read ~/.chain/…. Studio now writes to .chain and migrates the old file (+ rotation sibling) over once.
  • Honest audit wording (legal review). DE strings no longer claim "manipulationssicher" — the audit log is manipulationserkennend (tamper-evident); "warum WORM-1 für KRITIS reicht" became a neutral what-it-does-and-does-not sentence (EN too); the Doctor chain pill says "Integritätskette v1" instead of "WORM-1"; the federation enrollment hint says the CA authenticates the first connect.
  • WCAG-AA secondary text on dark. De-emphasised text was 3.7:1 on cards; the muted token is now ≥ 4.5:1 against canvas, cards and elevated surfaces.

Added

  • Live audit feed. The Audit page subscribes to streamEvents and refreshes instantly on each new event (debounced); the 2 s poll stays as the safety net and re-subscribes after a clean stream close.
  • Channel switcher in the sidebar. The active-channel pill (and the collapsed chip) is now click-to-switch: a menu of every channel with its running state + a check on the active one; switching writes ~/.chain/current-channel, restarts that channel's daemon, and Studio repoints to it.
  • Module-store manager is prominent + bilingual. The store page gains a labelled "Add store" button (was a bare icon) opening a fully localized dialog: configured stores, a curated Suggested stores shelf with one-click add/remove (probed for reachability — shows "not available yet" until a store's index is published), and an optional per-store pinned public key field.
  • Approval payload clarity. The approval card always shows the payload section: a present payload scrolls inside a height-capped copyable box; an absent one explains that the flow's approval step chooses what to surface via its show: field.

Fixed

  • Errors are copyable everywhere. System-AI test-connection, the Settings dialog, and the Audit status bar rendered failures as non-copyable text; all now route through ChainErrorBox / SelectableText.
  • Filter dialog crash on the store page — a Spacer inside AlertDialog.actions (an OverflowBar, not a Flex) threw; the buttons now sit in a Row.
  • Welcome docs grid tidied into equal-height paired rows.
  • Approval card leads with the human prompt; the flow step id is demoted to a metadata line.
  • Pulsing sidebar connection dot restored when connected.

0.70.0 — 2026-06-13

Added

  • Federation panel. A new "Föderation" destination shows the satellites connected to this hub (name, region, version, wire version, advertised capabilities) and adds them in one step: press Add satellite, name it, and the hub issues a single-use bootstrap token bundled with its CA as a ready-to-paste satellite config — the bundled CA makes the satellite's first connect tamper-proof. Localized (EN + DE) with an in-app help doc. Backed by new HubClient.listSatellites / issueBootstrapToken in the Dart SDK.

0.68.0 — 2026-06-09

Added

  • Inline approval driver. StudioFlowRunDriver implements the three new methods the editor 0.21.0 introduced (pendingApprovalIdForStep, approveApproval, rejectApproval) — all delegate to the existing HubService approvals RPCs. End result: the Run tab now hosts a complete Approve / Reject form inline, removing the tab-switch detour to the standalone Approvals page.

0.67.0 — 2026-06-09

Added

  • Inline help icons in the Approvals, Audit, and Doctor app-bars open the matching bundled doc in the existing bottom-sheet reader via the new public helper showFaiDoc(BuildContext, slug) exported from welcome.dart.
  • New assets/docs/approvals.md (+ _de.md) explains the approval concept end-to-end with a YAML example.
  • friendlyError hub-pattern matching. Six hub-specific failure shapes (approval rejected / timed out, output too large, host service not declared, missing value reference, MCP unreachable) get specific localised headlines + hints before falling through to the gRPC-code default. Five new test cases pin the matchers.

Changed

  • Settings dialog sidebar fully localised (Allgemein / Darstellung / System-KI / Integrationen / Sicherheit / Wartung). Per-panel titles + descriptions also.
  • Daemon action labels localised: enable autostart, disable autostart, restart / start / stop / status + the OK / Failed result line.

0.66.0 — 2026-06-08

Added

  • Add-module-source dialog for private modules that aren't in the public store. Asks for URL or local .fai bundle path; carries an explainer block + chain install --link example.
  • Store catalogue passed to the flow editor so the analyzer can decide between Install (in store) and Add source (not in store).

0.65.x

  • Editor 0.18.0 pickup; analyzer-error block on Run; diagnostic strip persistence across tabs.

0.64.0 — 2026-06-08

Added

  • Flow editor quick-fix install handler. _onInstallCapability wires the editor's "Install " button to HubService.installModule and refreshes the capability list on success.

0.63.0 — 2026-06-04

Changed

  • Settings dialog refactored from one 800-line vertical scroll into a macOS-style sidebar with six categories.

0.62.x — 2026-06-03

Added

  • FaiLog + central error helpers (showFaiErrorSnack, showFaiErrorDialog).
  • Inline FaiLogViewer modal for tail-viewing log files.
  • Today CTAs in the Store carousel actually re-run search after a filterCategory / runQuery story.

0.61.x and earlier

See git log.