Address review feedback and UX issues on the file browser.
Editor
- Replace the TipTap editor with Monaco, reusing the self-hosted assets. The
editor is kept mounted (wire:ignore) and preloaded on page init, and receives
content + language via the load-file-editor event, applying the language with
setModelLanguage so highlighting is correct without recreating the instance.
- Keep the Monaco instance on the DOM node, not in Alpine reactive state, so its
object graph is never proxied (that hung and crashed the tab).
- Drop @tiptap/*, lowlight and highlight.js; remove the TipTap CSS and JS.
- Broaden guessLanguage to Monaco ids and common extension-less/dotfiles.
Listing / read (perf)
- List a directory in one stat call instead of a per-entry loop (embedding a
real tab, since stat -c does not expand \t), and surface owner/group columns.
- Fold the read size-cap, binary probe and base64 into one SSH round trip.
Actions
- Collapse the per-row Edit/Download/Rename/Delete buttons into a 3-dots menu.
- Fix actions silently failing on names with apostrophes: the entry name now
lives in the row's Alpine scope instead of passing @js() through a component
attribute (which double-encodes the quotes).
Hardening
- Lock client-controllable state (container/type/resource) with #[Locked].
- Re-check guard() in open/goTo/refresh; sanitize upload filenames; clean up the
download temp file and report errors; route >96KiB writes through docker cp.
Tests updated and extended (32 passing). Frontend rebuild (npm run build) is
still needed only to drop TipTap from the bundle; the editor works without it.
- Escape dynamic file/path names with @js() in Livewire click handlers
instead of interpolating raw strings, and lock resource/container
properties to prevent client-side property tampering
- Route writes over ~96 KiB through docker cp instead of an inline
base64 shell argument, which was capped by MAX_ARG_STRLEN
- Treat empty files as editable text instead of misclassifying them
as binary
Validate audit event API pagination and filters, serialize paginated responses, and restore the prior audit-logging state after nested suppression callbacks.
Suppress model audit logging during API application saves while preserving the explicit event, and improve audit log actor display spacing and token tooltips.
Add an admin-only audit-events API endpoint and restrict audit-log UI access. Record integration token and secret manager changes, key access, and references in audit events.
Extract database start command execution into a shared service and job, preserving activity tracking and status events while supporting resolved secret credentials.
Add secret manager integration links and API support, resolve referenced credentials in database startup commands, and improve environment variable handling and filtering.