feat(studio): localise Settings sidebar + add inline help docs + Approvals doc
Some checks failed
Security / Security check (push) Failing after 1s
Some checks failed
Security / Security check (push) Failing after 1s
Three operator-UX gaps closed:
- Settings dialog's six-category sidebar (General / Appearance /
System AI / Integrations / Security / Maintenance) was
hardcoded English; now flows through AppLocalizations
("Allgemein" / "Darstellung" / "System-KI" / "Integrationen" /
"Sicherheit" / "Wartung"). Same for the per-panel title +
description.
- Per-channel daemon-action labels ('enable autostart' /
'disable autostart' / 'daemon restart' etc.) and the
OK / Failed result line in the toast also moved to l10n,
so the system-action feedback reads as one language.
- New 'Approvals' doc bundle (en + de) under assets/docs/,
registered as a fifth doc card on Welcome plus exposed via
the new public helper. The
Approvals, Audit and Doctor app-bars grow a Help icon button
next to Refresh that opens the matching doc in the existing
bottom-sheet reader — no extra screen, no learning curve.
Studio bumped to 0.67.0; editor path-override pulls in 0.20.1
(flow-list row polish).
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
parent
2be7d241bf
commit
28fafce7dc
15 changed files with 681 additions and 36 deletions
81
assets/docs/approvals.md
Normal file
81
assets/docs/approvals.md
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# Approvals
|
||||
|
||||
An approval is a deliberate human-in-the-loop checkpoint inside
|
||||
a flow. When a step needs a human decision before it proceeds,
|
||||
the flow pauses at that step until a reviewer approves or
|
||||
rejects it.
|
||||
|
||||
## When to use one
|
||||
|
||||
Add an approval step before:
|
||||
|
||||
- writing to a system of record (cases, contracts, mailings)
|
||||
- spending money (LLM tokens above a threshold, API quotas)
|
||||
- destructive actions (delete, archive, send)
|
||||
- anything the operator's compliance owner asked you to gate
|
||||
|
||||
The approval is a recorded event — every approval shows up in
|
||||
the audit log with the reviewer, decision, and reason.
|
||||
|
||||
## How a flow declares one
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- id: classify
|
||||
use: text.classify@^1
|
||||
|
||||
- id: review
|
||||
use: system.approval@^0
|
||||
with:
|
||||
title: "Review the classifier output"
|
||||
details: "$classify.response"
|
||||
reviewer: "$inputs.reviewer"
|
||||
timeout_seconds: 600
|
||||
|
||||
- id: write
|
||||
use: erp.write@^1
|
||||
with:
|
||||
record: "$review.payload"
|
||||
```
|
||||
|
||||
`system.approval` is a built-in capability — no module install
|
||||
needed. It blocks the flow's run until the matching approval
|
||||
record reaches a `decision` (approved / rejected) or the
|
||||
configured `timeout_seconds` elapses.
|
||||
|
||||
## How an operator answers one
|
||||
|
||||
The Approvals page lists every pending approval. Click an
|
||||
entry, read the title + details, decide:
|
||||
|
||||
- **Approve** — the flow resumes from this step with the
|
||||
approval's `payload` as the step output.
|
||||
- **Reject** — the flow fails at this step with the reviewer's
|
||||
reason; the audit log records the rejection.
|
||||
|
||||
## Timeouts
|
||||
|
||||
If no decision arrives within `timeout_seconds`, the engine
|
||||
returns `ApprovalTimedOut` and the flow fails. Set a timeout
|
||||
that reflects how long a reviewer can realistically take.
|
||||
|
||||
## What gets logged
|
||||
|
||||
Every approval write hits the audit log:
|
||||
|
||||
- approval requested (with the title + details snapshot)
|
||||
- reviewer-decision recorded (with reason on reject)
|
||||
- payload + signature on accept
|
||||
|
||||
The hash chain catches tampering — an entry that was approved
|
||||
yesterday can't be quietly flipped to rejected today without
|
||||
breaking the chain.
|
||||
|
||||
## Architecture trade-off
|
||||
|
||||
Approvals are stored alongside events in the SQLite audit DB.
|
||||
For higher-assurance deployments, mirror the audit DB to a
|
||||
WORM sink (Compliance Gap 3, option 2). The approval contract
|
||||
is the same either way — the WORM sink just makes the audit
|
||||
trail tamper-evident to outside reviewers, not just to the
|
||||
hub itself.
|
||||
88
assets/docs/approvals_de.md
Normal file
88
assets/docs/approvals_de.md
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
# Freigaben
|
||||
|
||||
Eine Freigabe ist ein bewusster Human-in-the-Loop-Checkpoint
|
||||
innerhalb eines Flows. Wenn ein Step eine menschliche
|
||||
Entscheidung benötigt, pausiert der Flow an dieser Stelle, bis
|
||||
ein Reviewer freigibt oder ablehnt.
|
||||
|
||||
## Wann nutzen?
|
||||
|
||||
Setze eine Freigabe vor:
|
||||
|
||||
- Schreibzugriffe auf Bestandssysteme (Akten, Verträge,
|
||||
Versand)
|
||||
- Geldausgaben (LLM-Tokens jenseits einer Schwelle, API-Quotas)
|
||||
- destruktiven Aktionen (löschen, archivieren, senden)
|
||||
- alles, was dein Compliance-Verantwortlicher abgesichert sehen
|
||||
möchte
|
||||
|
||||
Die Freigabe ist ein protokolliertes Ereignis — jeder
|
||||
Freigabe-Vorgang landet im Audit-Log mit Reviewer,
|
||||
Entscheidung und Begründung.
|
||||
|
||||
## So deklariert ein Flow eine Freigabe
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- id: classify
|
||||
use: text.classify@^1
|
||||
|
||||
- id: review
|
||||
use: system.approval@^0
|
||||
with:
|
||||
title: "Klassifikations-Output prüfen"
|
||||
details: "$classify.response"
|
||||
reviewer: "$inputs.reviewer"
|
||||
timeout_seconds: 600
|
||||
|
||||
- id: write
|
||||
use: erp.write@^1
|
||||
with:
|
||||
record: "$review.payload"
|
||||
```
|
||||
|
||||
`system.approval` ist eine eingebaute Capability — keine
|
||||
Modul-Installation nötig. Sie blockiert den Flow-Lauf, bis der
|
||||
zugehörige Freigabe-Eintrag eine `decision` erhält
|
||||
(freigegeben / abgelehnt) oder das konfigurierte
|
||||
`timeout_seconds` ausläuft.
|
||||
|
||||
## So beantwortet der Operator eine Freigabe
|
||||
|
||||
Die Freigaben-Seite listet jede ausstehende Freigabe. Klick
|
||||
auf einen Eintrag, Titel + Details lesen, entscheiden:
|
||||
|
||||
- **Freigeben** — der Flow läuft ab diesem Step weiter, das
|
||||
`payload` der Freigabe wird zum Step-Output.
|
||||
- **Ablehnen** — der Flow scheitert an diesem Step mit der
|
||||
Begründung des Reviewers; die Ablehnung wird im Audit-Log
|
||||
protokolliert.
|
||||
|
||||
## Timeouts
|
||||
|
||||
Wenn keine Entscheidung innerhalb `timeout_seconds` eintrifft,
|
||||
liefert die Engine `ApprovalTimedOut` und der Flow scheitert.
|
||||
Setze einen Timeout, der zeigt wie lange ein Reviewer
|
||||
realistisch brauchen darf.
|
||||
|
||||
## Was protokolliert wird
|
||||
|
||||
Jeder Schreibvorgang einer Freigabe landet im Audit-Log:
|
||||
|
||||
- Freigabe angefordert (mit Titel + Details-Snapshot)
|
||||
- Reviewer-Entscheidung aufgezeichnet (mit Begründung bei
|
||||
Ablehnung)
|
||||
- Payload + Signatur bei Freigabe
|
||||
|
||||
Die Hash-Chain fängt Manipulationen ab — ein gestern
|
||||
freigegebener Eintrag kann nicht heimlich heute auf
|
||||
"abgelehnt" gedreht werden, ohne die Kette zu brechen.
|
||||
|
||||
## Architektur-Abwägung
|
||||
|
||||
Freigaben liegen in derselben SQLite-Audit-DB wie die
|
||||
Ereignisse. Für Deployments mit höherem Sicherheitsbedarf
|
||||
spiegelt man die Audit-DB auf eine WORM-Senke (Compliance-Gap
|
||||
3, Option 2). Der Freigabe-Kontrakt bleibt gleich — die
|
||||
WORM-Senke macht den Audit-Trail nur tamper-evident gegenüber
|
||||
externen Prüfern, nicht nur für den Hub selbst.
|
||||
Loading…
Add table
Add a link
Reference in a new issue