Context
VaultPane is the shared Vault browser/editor used by GTM. Read failures already have a dedicated error state, retry action, and component coverage. Its tree-listing and mutation handlers also settle their loading flags with try/finally, but list, save, create, and delete failures are not caught or presented.
Problem
Network, authorization, storage, or validation failures are not rendered as actionable UI states:
- A rejected
listTree() leaves the initial tree empty or a previously loaded tree stale, and the discarded promise can produce an unhandled rejection.
- A rejected
writeFile() correctly leaves the draft dirty, but gives the user no explanation or retry feedback and can produce an unhandled rejection.
- Rejected
createFile() and deleteFile() calls leave their dialogs open and loading flags settle, but no failure reason is shown and the discarded promises can produce unhandled rejections.
- If create/delete succeeds but the follow-up tree refresh fails, the mutation has happened while the pane can show stale or inconsistent tree, dialog, or selection state.
- React error boundaries do not catch errors thrown from asynchronous event handlers.
Expected Behavior
Every Vault operation has a visible success/failure outcome, preserves recoverable editor state, and offers an appropriate retry without remounting the pane.
Actual Behavior
Read failures are already surfaced and retryable. Rejected list/save/create/delete operations and post-mutation refresh failures are not surfaced by VaultPane. Existing component tests cover the happy paths and the read rejection path, but not the remaining rejection paths.
Proposed Scope
- Add explicit tree and mutation error state to
VaultPane.
- Render list failures distinctly from an empty Vault, with a retry action.
- Preserve the current draft and dirty state when a save fails, while displaying the failure reason and allowing retry/dismiss.
- Keep create/delete dialogs, input, and selection deterministic when the mutation itself rejects.
- Handle a failed follow-up refresh after a successful create/delete as a partial-success state and allow the tree to be reconciled.
- Catch every operation promise at the pane boundary so failures do not escape as unhandled rejections.
- If products need telemetry or host-level presentation, expose an optional typed operation-error callback that identifies the operation and relevant path without coupling the pane to a product toast system.
Acceptance Criteria
Notes
Primary seams:
src/vault/VaultPane.tsx
tests/vault/vault-pane.test.ts
Context
VaultPaneis the shared Vault browser/editor used by GTM. Read failures already have a dedicated error state, retry action, and component coverage. Its tree-listing and mutation handlers also settle their loading flags withtry/finally, but list, save, create, and delete failures are not caught or presented.Problem
Network, authorization, storage, or validation failures are not rendered as actionable UI states:
listTree()leaves the initial tree empty or a previously loaded tree stale, and the discarded promise can produce an unhandled rejection.writeFile()correctly leaves the draft dirty, but gives the user no explanation or retry feedback and can produce an unhandled rejection.createFile()anddeleteFile()calls leave their dialogs open and loading flags settle, but no failure reason is shown and the discarded promises can produce unhandled rejections.Expected Behavior
Every Vault operation has a visible success/failure outcome, preserves recoverable editor state, and offers an appropriate retry without remounting the pane.
Actual Behavior
Read failures are already surfaced and retryable. Rejected list/save/create/delete operations and post-mutation refresh failures are not surfaced by
VaultPane. Existing component tests cover the happy paths and the read rejection path, but not the remaining rejection paths.Proposed Scope
VaultPane.Acceptance Criteria
Notes
Primary seams:
src/vault/VaultPane.tsxtests/vault/vault-pane.test.ts