130 Commits
Author SHA1 Message Date
mrhid6 d1769fc886 feat: Updated vuln style
Chart Release / chart (push) Successful in 12s
Server Deploy / deploy (push) Successful in 1m36s
2026-08-06 16:35:04 +01:00
mrhid6 5cee53dc5f feat: Better button description
Chart Release / chart (push) Successful in 20s
Server Deploy / deploy (push) Successful in 2m23s
2026-08-06 15:51:18 +01:00
mrhid6 81248bb159 style: bring the vulnerabilities page onto the house page shape
Every other page under app/(app) opens with `p-4 sm:p-6 lg:p-8` and the
layout adds none of its own, so this page alone sat flush against the shell
edge. Its h1 was text-xl where every other page is text-2xl.

The findings list was a stack of separately bordered cards; it is now rows
inside one Card, separated by border-border-soft, matching the monitors and
workflows lists. Loading is the shared spinner rather than a line of text,
the error is the shared danger strip, and the empty state uses the same
proportions as the monitors one.
2026-08-06 15:49:39 +01:00
mrhid6 9ba3d4a61f feat: Vulnerability Scanning feature on license page
Chart Release / chart (push) Successful in 12s
Server Deploy / deploy (push) Successful in 1m20s
2026-08-06 15:40:13 +01:00
mrhid6 84dfcfeac7 feat: vulnerability findings UI
Fleet board grouped by CVE, a per-server section on server detail, and
alert rules beside the channels they consume.

The server detail page has no tab pattern despite the plan saying to
follow one, so this adds a section in the existing vertical stack.

Three states are kept visually distinct because they are identical if
handled carelessly and only one is good news: never reported, no advisory
feed for the distribution, and scanned-and-clean. Database freshness sits
with the findings rather than in settings for the same reason.
2026-08-06 14:40:37 +01:00
mrhid6 5bba54f3e5 fix: Fixed style layout on workflow run page 2026-08-06 10:50:31 +01:00
mrhid6 85a8865892 feat: restyle the steps table and add 22 default steps
Chart Release / chart (push) Successful in 11s
Server Deploy / deploy (push) Successful in 2m46s
2026-08-04 17:34:18 +01:00
mrhid6 50a9ac5fdc fix: count tag-matched servers in the workflows list 2026-08-04 17:28:01 +01:00
mrhid6 3388d2f895 fix: Fixed padding on add step button
Chart Release / chart (push) Successful in 22s
Server Deploy / deploy (push) Successful in 41s
2026-08-04 17:24:40 +01:00
mrhid6 3a77fc2abd feat: edit target servers and tags together in the workflow modal 2026-08-04 17:21:12 +01:00
mrhid6 3d59836d0c feat: dual list box for workflow target servers
Chart Release / chart (push) Successful in 11s
Server Deploy / deploy (push) Successful in 5m19s
2026-08-04 17:13:50 +01:00
mrhid6 d9184312aa fix: schedule card placement, preview state, and scheduled-workflow docs 2026-08-04 17:08:11 +01:00
mrhid6 c2635ed51a fix: Fixed schedule workflow col
Chart Release / chart (push) Successful in 20s
Server Deploy / deploy (push) Successful in 41s
2026-08-04 14:42:10 +01:00
mrhid6 b21ac05547 feat: show workflow schedules in the list
Chart Release / chart (push) Successful in 24s
Server Deploy / deploy (push) Successful in 2m34s
2026-08-04 14:16:13 +01:00
mrhid6 484b620867 feat: schedule editor on the workflow page 2026-08-04 14:13:31 +01:00
mrhid6 439bc2ed7d feat: schedule methods on the web api client 2026-08-04 14:10:04 +01:00
mrhid6 2de7ac116b feat: filter the fleet by tag and target workflows by tag selector 2026-08-04 13:42:47 +01:00
mrhid6 fa1fd14ed1 feat: view and edit server tags 2026-08-04 13:38:42 +01:00
mrhid6 80f0afb28b feat: Updated monitors pages
Chart Release / chart (push) Successful in 13s
Server Deploy / deploy (push) Successful in 1m25s
2026-08-04 12:19:15 +01:00
mrhid6 1f08e90009 feat: Removed email alert settings
Chart Release / chart (push) Successful in 10s
Server Deploy / deploy (push) Successful in 5m15s
2026-08-03 14:40:15 +01:00
mrhid6 6881d92d0a fix: local-login toggle no longer reverts unsaved settings edits
Chart Release / chart (push) Successful in 26s
Server Deploy / deploy (push) Successful in 4m8s
server/internal/services/settings.go SaveSettings takes alerts and
email as required (non-pointer) values and writes them unconditionally
- absent fields would blank stored settings, not just leave them
alone. onLocalLoginChange was building its payload from the stale
loaded settings object instead of the in-progress form state
(thresholdMinutes/logRetentionDays) that handleSubmit uses, so editing
the offline threshold and then flipping the toggle silently reverted
the edit. Both paths now submit the same in-progress values.
2026-08-03 14:13:05 +01:00
mrhid6 37f2c1457e feat: manage multiple sign-in providers from settings 2026-08-03 11:00:25 +01:00
mrhid6 3a626922a5 feat: render one login button per configured auth provider 2026-08-03 10:56:03 +01:00
mrhid6 1eb98ef962 feat: Better debugging for console
Chart Release / chart (push) Successful in 12s
Server Deploy / deploy (push) Successful in 1m22s
2026-07-31 15:51:26 +01:00
mrhid6 165114471f fix: Fixes to running on kubernetes
Chart Release / chart (push) Failing after 13s
Server Deploy / deploy (push) Successful in 6m35s
2026-07-31 10:34:10 +01:00
mrhid6 487de34a50 docs: Updated docs
Server Deploy / deploy (push) Failing after 1m57s
2026-07-28 16:53:42 +01:00
mrhid6 5be9ddb2e5 fix: Fixed baked api url
Server Deploy / deploy (push) Successful in 7m8s
2026-07-28 16:18:50 +01:00
mrhid6 31e0000306 feat: default steps are read only
Server Deploy / deploy (push) Successful in 1m46s
2026-07-28 13:34:08 +01:00
mrhid6 f10e61cde4 feat: Updated marketing site 2026-07-28 12:46:28 +01:00
mrhid6 766dcabfde fix: Fixes to the console focus
Server Deploy / deploy (push) Successful in 43s
2026-07-28 12:02:48 +01:00
mrhid6 5e326335af fix(web): stop long tokens and button rows overflowing on mobile
Server Deploy / deploy (push) Successful in 1m40s
Three root causes behind five reported overflows:

- Td below sm is a flex row, and a flex item's default min-width:auto is
  its min-content width. A fingerprint or target URL is one unbreakable
  token, so the value could not shrink and spilled out of the card. The
  value now sits in a min-w-0 break-words wrapper that is display:contents
  above sm, leaving the desktop table untouched. Fixes /keys, /monitors
  and the installed-keys table on /servers/[id] in one place.

- The ESO read URL and the secrets group endpoint are unbreakable tokens
  in prose with the default overflow-wrap:normal. Both paragraphs now
  break-words.

- Three page headers (servers/[id], keys/[id], monitors/[id]) held an
  unwrapped button row. They stack below sm and the clusters wrap. These
  used items-start, which is why the earlier responsive sweep — matching
  items-center — skipped all three; only one was reported.

Verified: tsc clean, next build clean, and the compiled stylesheet confirms
max-sm:min-w-0 / max-sm:break-words land in the below-640px query and
sm:contents in the above-640px one.
2026-07-27 23:28:53 +01:00
mrhid6 4be7d24aec feat(web): collapse remaining fixed layouts on small screens 2026-07-27 23:01:30 +01:00
mrhid6 dd4ce5bb3e fix(web): scope inspector top border to below lg 2026-07-27 22:57:53 +01:00
mrhid6 5ee3f14eed feat(web): single-column workflow builder below lg 2026-07-27 22:55:07 +01:00
mrhid6 5dcc1bf1be feat(web): bottom-sheet modals and collapsing component grids 2026-07-27 22:50:08 +01:00
mrhid6 facef270b7 feat(web): label table cells for the mobile card stack 2026-07-27 22:46:39 +01:00
mrhid6 e8c75e974d feat(web): responsive page padding and stacking page headers 2026-07-27 22:42:22 +01:00
mrhid6 60af88525c feat(web): offcanvas sidebar with hamburger below lg 2026-07-27 22:33:16 +01:00
mrhid6 74f6dca2f5 feat(web): card-stack tables below sm 2026-07-27 22:28:57 +01:00
mrhid6andClaude Opus 5 c4e6ad5485 feat(license): metered licensing — catalogue, entitlements, and enforcement
Server Deploy / deploy (push) Successful in 5m22s
Implements spec 7 tasks 2-10 on top of the six-plan payload from task 1.

Admin: plans re-keyed on (deployment, tier); new catalogue collection holds
every Paddle price ID (one row per priceable component); new entitlements
collection holds desired beside granted. admin/internal/catalogue owns both
folds — entitlement to licence limits, and entitlement to Paddle line items —
so the base allowance is subtracted in exactly one place. licensing.Issue now
snapshots the instance's granted entitlement, never desired. Free is enforced
per account AND deployment. Staff endpoints for plans, catalogue and
entitlements; Free self-hosted can be claimed and renewed on its annual term;
the reaper stays cloud-only.

Server: enforces the monitor cap, audit-log retention (daily sweep, skips
Unlimited and lapsed instances), and gates the OIDC callback. Unset limits are
filled from the seed plan at the single decode site so old blobs never read as
zero.

Frontends: adminsite gains a catalogue price-ID editor, six-plan allowance
screen, and a catalogue-driven PlanConfigurator mounted on the staff instance
page. web shows monitors, audit retention and support level on the licence page.

Docs: CLAUDE.md, spec index and plan 5 preamble updated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 09:37:39 +01:00
mrhid6 dd306e4757 feat(license): the paste form is self-hosted only
Server Deploy / deploy (push) Successful in 2m14s
A cloud instance's licence is issued in HQ and written into the control
plane by admin/internal/inject, straight to the database. The customer has
nothing to paste, so /settings/license offered them a form that could only
ever fail — and on an expired cloud instance, failed at the exact moment
they were looking for a way out.

GET /license now reports `deployment`, and the page swaps the paste form
for a short panel saying where the licence comes from, with a link to the
portal when HQ_URL is set. That is the same treatment hq-managed members
already get in the members table: read-only here, and a pointer to where
it is actually managed.

POST /license refuses with 409 cloud_managed on a cloud deployment. Hiding
a form is a courtesy; this codebase's rule is that the API is the boundary,
and the endpoint was reachable regardless of what the page rendered. It
cannot break injection, which never goes through HTTP at all.

Verified: server builds and vets clean, web builds clean.
2026-07-26 20:42:53 +01:00
mrhid6 fa75d70475 fix(web): rebuild the licence page as the document it is
Server Deploy / deploy (push) Successful in 40s
This screen was never finished. It had no page padding, so it sat flush
against the sidebar while every other screen has p-8; it used raw button,
textarea and file inputs instead of the design system; and it rendered
state as "State: valid" in a sentence.

It also dropped `reason` entirely. An instance with an invalid licence was
told "State: invalid" and nothing else — not that the signature failed, not
that it was issued against a different instance, not what to do. That was
the real defect, and no layout survives having nowhere to put the most
important thing on the page.

A licence is a document: issued, dated, signed, carrying a reference you
quote to support. The page now reads that way, which is also how adminsite/
presents the same object from the issuing side — state as a label with a
shape, the reference on a mono record line, entitlement as keyed fields.

- a record panel opens the page: the state as a statement, the reason
  underneath in this app's own words rather than the API's identifiers,
  then Expires / Source / Instance ID as keyed fields. `source` and
  `days_remaining` were being returned and never shown
- counted limits become meters, because that is already how the console
  shows headroom on a server's disks — same question, same reading. They
  turn amber at 80% and red at the cap
- an unlimited allowance gets no bar. A full-width one would read as "at
  the limit", which is the opposite of what it means
- features render as included/not with a glyph as well as a colour
- the file input is a styled label over a visually hidden input, and now
  reports which file it loaded

Two things found reviewing my own work: Card's p-6 is emitted after p-4, so
`<Card className="p-4">` silently rendered at p-6 — the allowance cards pass
padding={false} instead. And the state had a coloured dot next to a coloured
word on a colour-ruled card, which is one telling too many; the dot is gone.

`Group` moves to components/settings/ so this page and /settings share the
band label rather than growing a second copy.
2026-07-26 20:35:31 +01:00
mrhid6 653bd5a755 refactor(web): members and SSO move onto the settings page
Server Deploy / deploy (push) Successful in 1m12s
/settings/instance held two cards — Members and Single sign-on — behind a
sidebar entry called "Instance", next to one called "Settings". Nothing in
either name told you which held what, and the split left both pages thin.

They are now the Access group at the top of /settings, above Monitoring and
Integrations. Six cards on one page needs sorting into groups or it reads as
a pile, so each group carries site/'s keyed-label eyebrow on a hairline.

The cards move to web/components/settings/ rather than into the page, which
would have made it ~600 lines. That is also where the Field and inputClass
pair now lives: the two pages each had a byte-identical copy, and folding
them together is exactly when three copies would have started to drift.

Members and SSO adopt SectionCard, which the rest of the page already used.
A card that kept its own header treatment would read as a different kind of
thing rather than another setting, which is the problem being fixed.

next.config.ts keeps a permanent redirect from the old path, so bookmarks
and any support reply linking it still land somewhere useful.
2026-07-26 20:19:04 +01:00
mrhid6 01eda1dbb0 feat(web): the console joins the shared design system
Server Deploy / deploy (push) Successful in 1m6s
web/ was the last app on its own palette — a neutral #0f1117 ground with an
indigo accent, unrelated to the logo navy that site/ and adminsite/ are built
on. It now draws from the same tokens, so all three apps are one system.

It stays locked to dark, taking site/'s dark values. That is what keeps
adminsite/'s light default meaningful: an operator with both open tells them
apart by the ground before clicking anything destructive, and now that both
are the same palette, the ground is the only thing left doing that work.

The colour names stay this app's own — text-primary, border, surface rather
than ink, rule, panel — because every screen already reads that way, and
adminsite/ already establishes that each app names the shared tokens after
its own subject.

Tokens are stored as RGB channels with the hex in a trailing comment. The
console leans on Tailwind opacity modifiers far more than the other two
(bg-danger/10, border-accent/50, ring-accent/30), and <alpha-value> only
compiles against channels; the comments keep the three token blocks
diffable by eye.

Beyond colour:
- radii collapse to site/'s 4px in tailwind.config.ts rather than rewriting
  ~140 rounded-lg classes; rounded-full is untouched for dots and pills
- badges become site/'s chip — mono, uppercase, tracked, currentColor rule,
  no fill — keeping their dot so state is never colour alone
- table column heads take the keyed-label idiom, at text-secondary rather
  than tertiary, which lands under 4.5:1 at that size
- sidebar marks the active item with an accent bar, the device site/ uses
  for the chosen plan, instead of a filled pill that reads as pressable
- filled accent and danger buttons take accent-ink; the dark accent is a
  light blue and danger a coral, and white on either was unreadable
- login's packet pulses shift from green to the accent, so the sign-in
  screen is the same two blues as the marketing hero

The last hex literals and stock-palette classes are gone; the only ones left
are NetworkBackground's canvas fills, which cannot read a CSS variable and
are commented with the token each came from.

Only the web image rebuilds from this.
2026-07-26 18:33:07 +01:00
mrhid6andClaude Opus 5 7b077905e2 feat(web): hq-sourced members are read-only here
Server Deploy / deploy (push) Successful in 2m56s
The lock is a courtesy — the API answers 409 either way. NEXT_PUBLIC_HQ_URL
defaults empty so a self-hosted install shows a plain label rather than a
link to a portal that does not serve them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-26 16:42:47 +01:00
mrhid6 8626898e5e feat(web): licence banner, settings page and feature gating 2026-07-24 15:25:29 +01:00
mrhid6 ee4dff09c9 feat: show the instance ID after setup 2026-07-24 15:20:00 +01:00
mrhid6 b70ccc97d4 refactor(web): rename Organisation to Instance 2026-07-24 14:01:19 +01:00
mrhid6 fd32c96d86 feat: Updated site
Server Deploy / deploy (push) Successful in 2m23s
2026-07-24 11:50:11 +01:00
mrhid6 b74cd10dfc fix: Fixed bg zoffset
Server Deploy / deploy (push) Successful in 51s
2026-07-24 11:23:36 +01:00