Skip to content

feat: stored logs, volumes, a guarded shell, backup schedule, secret filters and a reworked UI - #27

Merged
AmrMsCLL merged 4 commits into
mainfrom
feat/secret-filters
Nov 5, 2026
Merged

AmrMsCLL merged 4 commits into
mainfrom
feat/secret-filters

Conversation

@AmrMsCLL

@AmrMsCLL AmrMsCLL commented Nov 5, 2026

Copy link
Copy Markdown
Member

Everything asked of the console since #24, in one PR. It includes #25 (chart hover) and #26 (Backups alignment, scrollbar gutter); close those two. Goes with Project-Graphite/platform#46.

Secrets

  • A Filters menu (project, type, missing a required secret) with removable chips replaces the path and text fields.
  • Create is the right-most button, Delete beside it, and copying the selected names is an icon.
  • Each project header collapses its secrets with a chevron; on a Project page the whole Secrets section is collapsible, closed by default and remembered.
  • Redeploy and its hint leave the Secrets list (they stay on the Project page and the Overview).

Redeploy

  • The button is the status: Redeploy, Redeploying…, Redeployed (two seconds), back to Redeploy; a failure turns it red with the unit's last log lines in its tooltip. It has a fixed width and announces changes to screen readers.
  • A redeploy that finishes marks .applied with its exit time, so "needs redeploy" clears even when nothing had to be recreated (for example, secrets imported with the same values). The pill means: the project's env file is newer than its last rollout.

Logs

  • The console follows every running container and keeps every line for seven days (LOGS_KEEP_DAYS) in /logs/logs.db, on its own volume so it stays out of the nightly backup (platform#46), with level and stream. It resumes from the last stored line after a restart.
  • The Logs page browses them newest first: a filter-icon menu with nested filters (project, expanding to its containers; level; stream; time window), search, a Live tail, and Load older.

Alerts

  • Rule saves and the test email use action buttons that show Saving…, Saved and failure on themselves instead of a note that shifts the row.

Backups

  • The schedule is set on the page: on or off, every 1 to 168 hours from an hour in UTC, and days kept. The backup service reads it (platform#46). The late-backup alert follows it and stays quiet while backups are off.
  • Back up now and Upload are action buttons; Import picks the file with a button.

Volumes

  • Owners can create a volume, browse its files and download one, and delete an unused one. Every path is resolved and must stay inside the volume, links included. Docker has no way to rename or relabel a volume.
  • Each volume shows its size as a bar against the largest and an in-use pill.

Shell

  • The host shell now runs as the unprivileged graphite-ops user. Its sudo rule allows only read-only docker commands (ps, stats, logs, top, images, volume ls, network ls, compose ls, system df); the console creates the user and the rule on first use, checking the rule with visudo.
  • Owners can switch to a root shell after a confirmation.
  • Both run a bash guard (/usr/local/share/graphite/shell-guard.bash) on a DEBUG trap that blocks commands that would take down the VPS or the console (deleting system or Graphite paths, formatting disks, power, stopping docker, ssh or the agent, removing the console's container, volume or the edge network, pruning volumes, firewall flushes, removing users) and attempts to leave the guard (trap, a bare bash/sh, su, sudo -i); asks for "yes" before destructive ones (rm -r, docker rm/stop/prune, compose down, systemctl stop, kill, package removal, git reset --hard, overwriting /etc); and logs every command to the journal as graphite-shell with the login. The guard is a guard rail for the root shell; the operator user is the boundary.

UI

  • A stats rail with status pills on Alerts, Logs, Backups, Volumes and Admin.
  • Admin is a member table (role, last seen, access as pills) with an access dialog: area switches and a searchable table of projects with Operate and Secrets switches.
  • The descriptions under the page titles are gone. The page is wider (up to 120 rem) and reserves the scrollbar gutter.

Checks

tsc (server and web), oxlint, npm run build, and test/alerts.spec.ts, test/backups.spec.ts, test/logstore.spec.ts, test/volumes.spec.ts, test/shell.spec.ts, test/secrets.spec.ts, test/access.spec.ts, test/terminal.spec.ts, test/live.spec.ts, test/history.spec.ts. The guard was also parsed with bash -n, its 59 sample commands classified identically by GNU grep -E, and run interactively: a blocked command never ran and trap - DEBUG was refused. Not run: anything on the VPS (log following, volume browsing, the operator user, sudo), and the pages in a browser.

…that clears its hint

The Secrets list drops its path and text fields for a Filters menu (project,
type, missing a required secret) with removable chips; Create sits at the far
right, Delete beside it and copying the selected names is an icon. Each project
header collapses its secrets with a chevron. Redeploy and its hint leave the
Secrets list for the Project page and the Overview. A redeploy that finishes
marks .applied with its exit time, so the needs-redeploy hint clears even when
nothing had to be recreated.
…e and a reworked UI

Logs: the console follows every running container and keeps its lines for
seven days in logs.db on its own volume, with level and stream; the Logs page
browses them with nested filters (project and container, level, stream,
time), search, live tail and paging back.

Volumes: create, browse files (paths and links cannot leave the volume),
download a file and delete an unused volume, owners only, with a size bar per
volume.

Shell: the host shell runs as the unprivileged graphite-ops user, whose sudo
allows read-only docker commands only; owners can open a root shell after a
confirmation. Both run a bash guard that blocks commands that would take down
the VPS or the console or leave the guard, asks before destructive ones, and
logs every command to the journal with the login.

Backups: the schedule (on or off, every 1 to 168 hours from an hour in UTC,
days kept) is set on the page; the late-backup alert follows it.

UI: a stats rail with status pills on Alerts, Logs, Backups, Volumes and Admin;
action buttons that show saving, saved and failed on themselves; Admin as a
member table with an access dialog; collapsible secrets on a project page;
descriptions removed; a wider page.
… tooltip

The tooltip looked for a point exactly on the pointer's time rounded to the
step. History points sit on step boundaries, but live frames carry the
millisecond they were sampled, so none ever matched. It now takes the nearest
point within half a step, and the newest second no longer falls off the edge.
Every project's archive table, and the requests table, use fixed column widths,
so columns line up from card to card; actions sit on the right and narrow
screens scroll the table instead of squeezing it. The page and every scrolling
container reserve the scrollbar's space, so nothing shifts when a scrollbar
appears; the body padding MUI adds when a dialog locks scrolling is cancelled
because that space is already reserved.
@github-actions github-actions Bot added the size/xl Over 600 changed lines, excluding lockfiles label Nov 5, 2026
@AmrMsCLL
AmrMsCLL merged commit bf9eec2 into main Nov 5, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xl Over 600 changed lines, excluding lockfiles

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant