Some checks failed
Security / Security check (push) Failing after 1s
The trust-gate dialog replaces its generic 'no per-entry status yet (alpha)' note with the hub's classified verification statement — pinned store key / trusted publishers (green), installs without signature checking (amber), install would be refused (red), bridge entry (neutral) — via one shared describeInstallVerification mapping. Against a pre-0.23 hub the field is empty and the old honest wording stays (pinned by test). Information architecture: policy-off is a GLOBAL fact, so it appears as ONE ChainInlineHelp notice above the store grid instead of a warning pill on every card (card noise); only 'blocked' — a genuine per-source anomaly — earns a card pill. Doctor's host services show the hub-classified network reach per endpoint (local only / private network / publicly reachable with a protect-it hint / reach unknown). Verified end-to-end against the live dev hub (guide harness): the wire field arrives, the store page shows exactly one policy notice and quiet cards; trust-gate variants captured via the dialog harness. Suite 123 green. Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
578 lines
29 KiB
Markdown
578 lines
29 KiB
Markdown
# Changelog
|
||
|
||
All notable changes to `chain_studio` recorded here. Pubspec
|
||
version + `kStudioVersion` in `lib/data/about_info.dart` stay in
|
||
lockstep.
|
||
|
||
## Unreleased
|
||
|
||
### Added — real trust + exposure data (0.77.0)
|
||
|
||
- **Per-entry install verification.** The hub now reports (since
|
||
0.23) how an install of each store entry would be verified under
|
||
the CURRENT policy — computed with the same resolvers the install
|
||
gate enforces, so display and enforcement cannot disagree. The
|
||
trust-gate dialog replaces its generic "no per-entry status yet
|
||
(alpha)" note with the classified statement: signature checked
|
||
via pinned store key / trusted publishers (green), installs
|
||
without signature checking (amber, policy off), install would be
|
||
refused (red), or bridge entry without a bundle signature. Store
|
||
cards stay quiet on the good path and wear an "unsigned"/
|
||
"blocked" warning pill only when installs are unverified —
|
||
same philosophy as the provenance pill. Against a pre-0.23 hub
|
||
everything keeps the old honest wording.
|
||
- **Service exposure on the doctor page.** Every declared host
|
||
service shows its network reach as classified by the hub from
|
||
the endpoint host (local only / private network / publicly
|
||
reachable / reach unknown — no DNS lookups). Publicly reachable
|
||
endpoints get the warning tone with a "make sure it is
|
||
protected" hint.
|
||
|
||
### Added — explain it where it happens (0.76.0)
|
||
|
||
- **In-place help pattern.** New `ChainInlineHelp` (a one-sentence
|
||
intro strip that says what a surface is and what will happen, with
|
||
an optional "Learn more" link into the doc sheet) and
|
||
`ChainFieldHelp` / `ChainFieldLabel` (a "?" affordance for a single
|
||
field). First applied to the add-satellite dialog, which used to
|
||
ask for a "name" with no hint of what a satellite even is
|
||
(usertest): it now leads with a plain explanation + a federation
|
||
"Learn more", and the name field carries a "?".
|
||
- **Page help opens the RIGHT topic.** The Federation and Runs help
|
||
buttons silently fell back to the architecture doc — `federation`
|
||
and `runs` had markdown assets but no catalog entry, so
|
||
`showFaiDoc` resolved them to the first doc. Both are registered
|
||
now; a new `doc_help_wiring_test.dart` asserts every
|
||
`showFaiDoc('slug')` call has a registered entry AND both locale
|
||
assets, so a help button can never open the wrong topic again.
|
||
|
||
### Security (0.75.0)
|
||
|
||
- **Sealed-area names are confidential by default.** The workspace
|
||
switcher no longer lists sealed areas by name on a casual glance
|
||
(names often carry client/mandate identity — usertest security
|
||
finding): it shows one aggregated row ("2 sealed areas") and
|
||
reveals the named rows only after a deliberate click, per menu
|
||
opening. Settings → Security offers "list sealed areas with
|
||
their names right away" for single-operator machines.
|
||
|
||
### Changed (0.75.0)
|
||
|
||
- **One segment control everywhere.** The same single-select
|
||
choice pattern used to appear as four different widgets: the
|
||
audit page's hover pills, the store's Material SegmentedButton
|
||
(Modules / Studio & Designs), the store filter dialog's
|
||
ChoiceChips and the approvals page's TabBar. All of them now use
|
||
the canonical `ChainSegments` pill control (the audit pattern
|
||
promoted to a shared widget, with icons and a11y semantics);
|
||
the approvals page keeps both lists alive in an IndexedStack so
|
||
switching does not refetch. A canon-guard test bans
|
||
TabBar/SegmentedButton/ChoiceChip from lib/ for good. Guide
|
||
images + wording updated (dark and light verified).
|
||
|
||
### Hardening round (test strategy, 2026-07-19)
|
||
|
||
- **Hermetic widget suites.** `HubService.instance` is injectable;
|
||
a scriptable fake (`test/support/fake_hub.dart`) answers every
|
||
member the pages touch and scripts per-RPC failures. The a11y and
|
||
responsive sweeps run against it — results no longer depend on
|
||
whether a hub happens to listen on the operator's machine (which
|
||
was the root of the historic a11y flake).
|
||
- **State-matrix sweep** (`state_matrix_test.dart`): every sidebar
|
||
page × hub condition (healthy / gone / too old / feature off) with
|
||
app-wide invariants — no "unreachable" claims while the hub
|
||
answers, no raw error text in the UI, classified states only.
|
||
- **Shared load-error view.** Store, Doctor, Audit, Approvals and
|
||
Federation no longer fold every load failure into "hub not
|
||
reachable"; `HubLoadErrorView` classifies into unreachable /
|
||
needs-newer-hub / load-failed-with-copyable-detail (new DE+EN
|
||
strings). Also fixed: the approvals page's hidden tab surfaced
|
||
load failures as uncaught async errors; the audit status bar
|
||
rendered the raw gRPC error wall instead of the friendly headline.
|
||
- **Version-skew gate.** `integration_test/skew_smoke_test.dart`
|
||
(run via the platform repo's `scripts/skew-smoke.sh`) boots the
|
||
released hub binary and walks every page with the same
|
||
invariants — the dev-Studio-against-old-hub combination is now a
|
||
release gate instead of a live-bug generator.
|
||
|
||
### Added (0.74.0)
|
||
|
||
- **Doctor findings deep-link to their page.** Summary tiles and
|
||
panel rows jump to where the finding is actioned: modules → store,
|
||
"approvals waiting for review" → approvals inbox, audit chain →
|
||
audit log (chevron affordance, tooltip + semantics button). The
|
||
host-services empty state gains a "view the configuration" button,
|
||
and the update banner's release-notes URL is a real link now.
|
||
|
||
### Fixed (0.74.0)
|
||
|
||
- **Runs page no longer contradicts the sidebar.** Load failures are
|
||
classified instead of all reading "hub not reachable": an older hub
|
||
without the ListInvocations RPC gets "this view needs a newer hub
|
||
version" with a doctor link, the detached-off refusal shows the
|
||
regular feature-off empty state, and unknown errors surface a
|
||
copyable detail box. "Not reachable" is reserved for genuine
|
||
connection failures.
|
||
- **Audit page timer leak.** The live-stream reconnect timer is held
|
||
and cancelled on dispose.
|
||
- **a11y suite flake killed at the root.** The pending-timer failures
|
||
came from the gRPC channel's 5-minute idle timer being armed when
|
||
the last stream closes; the suite now closes the channel and pumps
|
||
past the idle timeout (6 consecutive full runs green).
|
||
|
||
### Added
|
||
|
||
- **Full-history audit export.** The audit page's actions menu gains
|
||
"Export full log as JSONL" next to the current-view export: fetches
|
||
the complete event history of the active project scope (independent
|
||
of the type chip, the search field and the page's 100-event window)
|
||
and writes it as JSONL. The current-view export is unchanged; the
|
||
CLI `chain admin events --json` remains the canonical tool for
|
||
WORM-guaranteed exports (a stale code comment still advertised the
|
||
never-shipped `chain audit export` — fixed).
|
||
|
||
### Changed (usertest low-findings tail)
|
||
|
||
- **Honest hero badge.** The store hero wears "TODAY"/"HEUTE" only
|
||
for an operator-accepted story; the compiled-in fallback deck has
|
||
no date binding and now says "FEATURED"/"EMPFOHLEN".
|
||
- **Audit filter chips in UI type.** The Alle/Flow/Schritt/Modul
|
||
chips drop the monospace styling — mono stays reserved for paths
|
||
and identifiers.
|
||
- **One verb for the chain check (DE).** "Hash-Kette geprüft" is the
|
||
confirmation everywhere (audit header, doctor pill); "intakt"
|
||
remains the state headline. English was already consistent.
|
||
- **Readable sealed-area status.** The "stopped" label in the
|
||
workspace switcher gets a modest contrast bump.
|
||
|
||
### Changed (usertest panel 2026-07-17, 14 personas — all confirmed findings)
|
||
|
||
- **Install trust gate.** One confirmation dialog before every module
|
||
install (store card, detail sheet, flow quick-fix): source, version,
|
||
license, maturity, required services — plus an honest signature note
|
||
(the hub does not report per-entry signature status yet; no fake
|
||
badge).
|
||
- **Settings → About.** Product, Studio + hub version (live), vendor
|
||
Flemming.AI / Dr. Stefan Flemming, Apache 2.0, contact, docs link —
|
||
every value copyable.
|
||
- **Discoverable sidebar.** Instant tooltips with the ⌘1–9/^1–9
|
||
shortcut, semantics labels, a visible "Search & commands ⌘K" row,
|
||
and a setting to keep the rail always expanded.
|
||
- **Plain-language empty states.** Runs page explains background runs
|
||
in plain words and — via the hub's new `detached_enabled` flag —
|
||
says truthfully whether the feature is off or simply unused;
|
||
approvals inbox explains human approvals without raw capability
|
||
syntax; welcome cards lead with everyday language (tech detail
|
||
behind a toggle).
|
||
- **One term per concept.** "Fähigkeiten" is the German lead term
|
||
(welcome, integrations, federation); "Registrierungs-Token" instead
|
||
of "Enrollment-Token"; category and source-kind labels localized
|
||
(no lowercase wire tokens like `document`, `1 system`).
|
||
- **Audit page.** Free-text search over the event list; JSONL export
|
||
of the current view; the dev-only clear action moved from a bare
|
||
trash icon into a labeled overflow menu.
|
||
- **Doctor page.** Copy button on every daemon path row; "n of m
|
||
events verified" instead of "n/m chain"; hash-chain wording unified.
|
||
The module tile no longer counts the built-in `system`
|
||
pseudo-module (a fresh hub shows 0 modules, matching the welcome
|
||
checklist); the daemon-files panel warns when the audit DB lives in
|
||
an OS-cleanable temp directory; the daemon card states endpoint,
|
||
transport security, and token status (length only) in one line.
|
||
- **Federation page.** Primary action in the app bar and in the empty
|
||
state (FAB removed); plain-language empty text.
|
||
- **Store.** License pill on the module card; maturity pills explain
|
||
themselves on hover; carousel shows a textual position; German tab
|
||
says "Studio & Designs".
|
||
- **Formal address guard.** A test now rejects informal German forms
|
||
including reader-addressed imperatives; literal markdown backticks
|
||
are gone from both catalogs.
|
||
- **Setup.** The wizard replaces the Settings dialog instead of
|
||
stacking on it, with a stronger scrim; the try-out profile names
|
||
the upgrade path to a regulated profile.
|
||
- **Welcome checklist.** The "start a saved flow" tick is sticky
|
||
instead of silently unticking once the event leaves the
|
||
recent-events window.
|
||
|
||
### Changed (setup lives before the app)
|
||
|
||
- **First-run gate.** A fresh install starts inside the setup: a
|
||
dedicated screen hosts the wizard before the app appears (embedded
|
||
mode + explicit "Später einrichten" skip). The Welcome page loses
|
||
its setup button entirely; re-running the setup lives in Settings →
|
||
General ("Run setup again…"). Wording de-ad-ified: "Einrichtung
|
||
starten" instead of "In 3 Fragen loslegen".
|
||
- **Preview before permission.** The plan preview now calls the new
|
||
PlanSetup RPC over the live hub connection instead of spawning the
|
||
chain CLI — whose first run could pop the macOS file-access prompt
|
||
BEFORE the operator ever saw the plan. CLI remains the no-hub
|
||
fallback; applying stays the explicit separate step.
|
||
- **Native file dialog for flow file inputs** (with flow-editor
|
||
v0.23.0): the Run tab's file inputs open a real picker; typing an
|
||
absolute path is now only the no-host fallback.
|
||
|
||
|
||
### 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 <cap>"
|
||
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.
|