fix(approvals): usertest-panel hardening (0.81.0)

Panel findings against the reworked approvals page, fixed in place:

- Never fabricate the request time: ApprovalRecord.createdAt is
  nullable now; a missing created_at omits the line instead of
  rendering DateTime.now() (which drifted on refresh). Guard:
  approvals_origin_test pins the omit-on-null invariant.
- Copyable errors on approve/reject/batch via showChainErrorSnack
  (the hard project rule) — batch surfaces the first real cause.
- Reject requires a reason: ChainInlineHelp strip + confirm disabled
  while empty, no more silent close-and-nothing-happens.
- Batch approve applies the same no-data confirmation as the single
  path, naming how many selected requests carry no show: data.
- Plainer language: glossary "Vorgang (Flow)", history label FRAGE
  (was PROMPT), no-data hint drops developer jargon.
- One-click copy of the run id; history payload pretty-prints like
  the card.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-07-26 16:05:55 +02:00
parent 28f6fe1a9a
commit f7d7427d91
9 changed files with 411 additions and 122 deletions

View file

@ -1152,7 +1152,13 @@ class HubService {
stepId: e.stepId,
prompt: e.prompt,
payloadPreview: e.payloadPreview.isEmpty ? null : e.payloadPreview,
createdAt: DateTime.tryParse(e.createdAt) ?? DateTime.now(),
// Never fabricate the request time: a missing / unparseable
// created_at stays null so the card can omit the line
// instead of showing "now" (which would even change on
// every refresh) as if it were the truth.
createdAt: e.createdAt.isEmpty
? null
: DateTime.tryParse(e.createdAt),
expiresAt: e.expiresAt.isEmpty
? null
: DateTime.tryParse(e.expiresAt),
@ -1762,7 +1768,11 @@ class ApprovalRecord {
final String stepId;
final String prompt;
final String? payloadPreview;
final DateTime createdAt;
/// When the approval was requested. Null when the hub sent no
/// parseable timestamp the card omits the line rather than
/// inventing one.
final DateTime? createdAt;
final DateTime? expiresAt;
/// One of: pending / approved / rejected / expired.