Commit Graph
969 Commits
Author SHA1 Message Date
Juan Denis d866de5439 feat(connect): apply the managed presentation profile (plan 25)
Panel side of the managed profile: the panel receives a presentation
profile from Cloud over the existing command channel, stores it,
acknowledges it, and hides or simplifies fleet-owner-only surfaces
until the profile is lifted or the link is revoked.

- ui.managed_profile command handler with managed-profile.json
  storage, audit entries, and ack-by-output; profile is cleared on
  disconnect and on consent revoke
- GET /api/v1/connect/managed-profile for the local UI
- ManagedProfileContext with capability-driven filtering of sidebar
  items, command palette actions, and sidebar settings; ManagedCard
  explains the managed state
- In-page collapses for Templates deploy, About self-update, and
  Backup schedules/storage (restore stays available)
- Settings gains a ServerKit Cloud tab showing link and profile state

Local verification: 153 backend tests pass, 198 frontend node tests
pass, lint clean, build ok. No live policy has been pushed to a real
panel yet.
2026-09-13 03:50:02 -04:00
Juan Denis fc5a041764 Fix first-run sidebar preferences and extension loading [skip version] 2026-09-11 00:17:39 -04:00
Juan Denis 2fd6f3c97c test(settings): await desktop footer actions before measuring [skip version] 2026-09-10 22:11:35 -04:00
Juan Denis 4dc281ce58 test(settings): await both mobile footer actions [skip version] 2026-09-08 09:40:06 -04:00
Juan Denis 8468ab79f2 test(ai): verify management UI and document completed integration 2026-09-08 04:10:21 -04:00
Juan Denis 7d5623bccb feat(settings): add connected AI model policies and usage views 2026-09-08 04:09:54 -04:00
Juan Denis 891666786c test(settings): cover AI controls and responsive settings surfaces in browsers 2026-09-08 03:03:43 -04:00
Juan Denis 8e9c4fa6b0 fix(settings): unify forms, notifications, and AI configuration controls 2026-09-08 03:03:19 -04:00
Juan Denis 5a4036e9b2 fix: resolve credential draft and backup fallback review [skip version] 2026-09-08 01:39:54 -04:00
Juan Denis 569b052659 feat(ai): expose Prompture providers and saved connections 2026-09-08 00:42:54 -04:00
Juan DenisandClaude Fable 5.1 bbce447e85 fix(nginx): serve /serverkit-vendor/*.mjs shims as text/javascript
Stock nginx (1.18-1.24 on Debian/Ubuntu) has no `.mjs` entry in mime.types,
so the runtime-extension vendor shims the import map points at came back as
application/octet-stream. Browsers refuse to execute an ES module with that
type, so every runtime-loaded extension (WordPress, Git, Mail, Fail2ban, ...)
failed on fresh installs with "Failed to fetch dynamically imported module:
blob:..." (Chrome) or "'application/octet-stream' is not a valid JavaScript
MIME type" (Safari).

Add a location block to the shipped vhosts (and the container frontend
config) that forces text/javascript for /serverkit-vendor/*.mjs. The regex is
anchored to that folder: a bare `\.mjs$` would also capture the
/api/v1/plugins/<slug>/assets/dist/index.mjs route and 404 every bundle.
update.sh already re-copies these vhosts, so existing installs pick it up on
their next update.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NWc84WDsWR7M55Mn7qtpie
2026-09-08 00:25:25 -04:00
Juan Denis 1ace946ab9 Keep service metrics stable across metadata refreshes [skip version] 2026-09-07 23:34:57 -04:00
Juan Denis ef0f9481af Update changelog for PRs #136/#137/#139 and fix hook dep warnings 2026-09-07 20:08:29 -04:00
Juan Denisandjrbertt 4f361fa3d1 Merge PR #136: fix(observability): resolve container runtime logs and metrics
Co-authored-by: jrbertt <joaorebertt0219@gmail.com>
2026-09-07 20:08:16 -04:00
Juan Denis d88f1cbf55 Make service detail chips scroll on mobile
Updates the service detail status chip layout for small screens from wrapped columns to a single horizontal, non-wrapping scroll row. It flattens group wrappers, hides group labels on phones, and prevents chip/ring clipping with small spacing and padding adjustments so pills remain readable and tappable.
2026-09-07 19:51:22 -04:00
Juan Denis 3c925f10fe fix: clear stale service metrics across runtime changes [skip version] 2026-09-05 15:24:58 -04:00
jrbertt 4ab6d37160 fix(docker): prevent inspector from covering actions 2026-09-05 15:22:32 -04:00
Juan Denis d67e5d07d0 fix: complete audit follow-ups and add regression coverage
Centralize backup schedule calculations and shared request/form flows, encode query values, and move repository finalization into its service. Add browser CI coverage, repair stale test fixtures, and provide opt-in request and build measurement tools.
2026-09-05 14:41:15 -04:00
jrbertt 81a56012c3 fix(observability): resolve container runtime logs and metrics 2026-09-05 08:44:39 -03:00
Juan Denis 92a3ffe6c3 refactor: consolidate frontend reuse and eliminate lint warnings 2026-09-05 05:24:35 -04:00
Juan Denis c62358de73 fix(settings): restore table surfaces and improve access review
Expose MFA and passkey enrollment, use shared confirmations and locale formatting, and guard pending user and invitation actions. Add Chromium regressions for both themes and failure states to frontend CI.
2026-09-05 04:30:05 -04:00
Juan Denis c8c93a8e0c fix(auth): enforce MFA, scoped keys, and revocable sessions
Add session-family revocation and migration 097, require current credentials for password changes, constrain API keys, and require verified WebAuthn authentication. Update browser token handling and add boundary regressions. Existing JWTs require fresh login; restricted keys deny undeclared endpoints.
2026-09-05 04:29:16 -04:00
Juan Denis 6c2220c5a1 Merge pull request #130 from jhd3197/dependabot/npm_and_yarn/frontend/humanfs/node-0.16.8
chore(deps-dev): bump @humanfs/node from 0.16.7 to 0.16.8 in /frontend
2026-09-05 01:07:51 -04:00
Juan DenisandClaude Fable 5.1 4a4742989e fix(frontend): keep CI green after the responsive-nav merge
- The scroll-fade masks added in #134 used `#000`, which the hex-literal
  ratchet in check-frontend-boundaries.mjs counts (design-system 2→6,
  databases 5→9). Masks only need an opaque colour, so use the keyword.
- intl.test.mjs compared "60 days ago" in en-US vs es; on any date whose
  month equals its day-of-month (7 July) the two short dates coincide and the
  test fails. Pin the date instead.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVRnRXqNMZagqQ3RTqG5pz
2026-09-04 22:35:20 -04:00
Rebertt RodriguesandJuan Denis f2f7a9294b fix: stabilize responsive navigation and database toolbar (#134)
* fix(navigation): stabilize overflow tab measurement

* fix(databases): prevent mobile toolbar overlap

* fix(navigation): keep mobile actions accessible

* fix(ui): refine mobile scroll affordance

* fix(layout): align status bar with expanded rail

---------

Co-authored-by: Juan Denis <jhd3197@gmail.com>
2026-09-04 22:20:25 -04:00
Rebertt RodriguesandJuan Denis a092ba1afe fix(dashboard): avoid content blockers on metrics history requests (#133)
Co-authored-by: Juan Denis <jhd3197@gmail.com>
2026-09-04 22:20:22 -04:00
Rebertt RodriguesandJuan Denis 763f555d9a fix(fonts): replace corrupted IBM Plex Sans assets (#132)
Co-authored-by: Juan Denis <jhd3197@gmail.com>
2026-09-04 22:20:19 -04:00
dependabot[bot] af11e98765 chore(deps-dev): bump @humanfs/node from 0.16.7 to 0.16.8 in /frontend
Bumps [@humanfs/node](https://github.com/humanwhocodes/humanfs/tree/HEAD/packages/node) from 0.16.7 to 0.16.8.
- [Release notes](https://github.com/humanwhocodes/humanfs/releases)
- [Changelog](https://github.com/humanwhocodes/humanfs/blob/main/packages/node/CHANGELOG.md)
- [Commits](https://github.com/humanwhocodes/humanfs/commits/node-v0.16.8/packages/node)

---
updated-dependencies:
- dependency-name: "@humanfs/node"
  dependency-version: 0.16.8
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-03 04:59:59 +00:00
Juan DenisandClaude Opus 5 4dfb468f77 chore(connect): regenerate the surface, inventory and locale files
Generated files the connect work moved and nobody re-ran:

- docs/API_SURFACE.md gains GET /connect/status
- docs/MIGRATION_INVENTORY.md: the hand-shaped error bodies count is 1145
  (ceiling 1150) for the 409 the backups PUT now answers when Cloud owns
  the destination
- en.json gains app.backups.storageManagedByCloud, so the sentence the
  read-only backup form shows is translatable like every other string

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018q56AfqpgKjio4n9KYubvZ
2026-09-03 00:19:35 -04:00
Juan DenisandClaude Opus 5 8fe469e1fe feat(connect): let ServerKit Cloud set where this server backs up
The panel can now run the signed commands Cloud sends, and the first four
of them are the Storage Hub's. A destination assigned in Cloud is tested
here before it is saved, written as `s3.path_prefix` (which every upload,
list and verify path already honoured), and reported back on a `storage`
stream. Unassigning hands it back and deletes nothing in the bucket.

- backend/app/services/connect_commands.py — verify a command JWT against
  ServerKit Cloud's JWKS (signature, audience, exp, nonce, consent scope), run the
  handler on its own thread, report running/succeeded/failed. An action
  this version does not know fails with a sentence saying so.
- backend/app/services/connect_storage.py — storage.assign/unassign/
  test/report, and the snapshot the storage stream carries.
- backend/app/services/connect_client.py — handle `command` opens, fetch
  the JWKS per connection, publish a storage snapshot on connect and
  every five minutes.
- backend/app/api/backups.py — GET /storage says when Cloud owns the
  destination; PUT answers 409 rather than letting two writers race.
- frontend/src/pages/Backups.jsx — the local form is read-only while
  Cloud manages it, with the sentence that says how to take it back.
- backend/tests/test_connect_storage.py — 23 tests, no network.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018q56AfqpgKjio4n9KYubvZ
2026-09-02 15:19:38 -04:00
Juan DenisandClaude Opus 5 bcb48d50e5 fix(plugins): keep a baked-but-uninstalled extension out of the legacy auto-render
The Walkthrough Studio page mounted globally on top of the dashboard on
panels where the extension is not installed. Its module is baked into the
bundle (eager glob), it carried a default export, and PluginLoader's
legacy auto-render only excluded plugins whose contributions appear in
the RUNTIME envelope - which an uninstalled extension never populates.

Three guards:
- drop the studio's default export (routes resolve the named
  WalkthroughStudioPage export; both the baked copy and the
  builtin-extensions source)
- PluginLoader now also excludes any plugin whose BAKED manifest
  declares contributions (declaresBakedContributions)
- regression test pinning both guards for every baked plugin

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 09:28:37 -04:00
Juan DenisandClaude Opus 5 7d477889e1 fix(walkthroughs): give the blue tone its own colour
`is-blue` resolved to var(--cyan), making it pixel-identical to `is-cyan`
while Walkthrough Studio offers both in its tone dropdown. The theme defines
no --blue token, so point it at --accent, the one remaining distinct hue
among the tones on offer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 00:46:47 -04:00
Juan DenisandClaude Opus 5 c181e72793 fix(walkthrough-studio): select the appended step from one snapshot
addStep() appended through a functional setDraft but then selected with
setStepIndex(draft.steps.length), reading the closed-over render snapshot.
The two can disagree under fast interaction, selecting the wrong step or an
index past the end of the list.

Build the list and derive the index from the same snapshot so they cannot
drift apart. Applied to the builtin-extensions source and the bundled copy
together; sync-builtin-frontends --check keeps them identical.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 00:46:47 -04:00
Juan DenisandClaude Opus 5 4beb439fa3 fix(walkthroughs): only the current step may complete on a signal
The signal handler searched the whole step list for a matching signal and
completed whichever step it found. These signals are ordinary product events
-- running a monitor check, creating a service -- so a later step's signal
fires readily while an earlier step is still current, marking it done out of
order and skipping every step in between.

Scope the match to currentStep, which is what the route effect directly above
already does. Normalization flattens an explicit `completion` block onto the
step (normalized.signal), so this covers both spellings.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 00:46:47 -04:00
Juan DenisandClaude Fable 5 ef2175d533 feat(i18n): translate walkthrough + studio backlog into all 16 locales
Migrates existing translations onto the consolidated common.* keys and
fills the ~399-key backlog (walkthrough guides, Walkthrough Studio, and
older gaps) in ar, bn, de, es, fr, id, it, ko, pl, pt, ru, th, tr, vi,
zh-Hans, zh-Hant. check-i18n: 6420 keys, 16 locales, no orphans or
placeholder drift.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 23:52:55 -04:00
Juan DenisandClaude Fable 5 d3f6f29ed6 refactor(i18n): consolidate duplicate strings into common.* keys
Duplicate page-scoped keys (Title, Duration, Publish, Live preview,
Move up/down) and Walkthrough Studio strings now reuse common.labels/
common.actions instead of re-declaring identical English text.
en.json regenerated: 6430 -> 6420 keys.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 23:52:49 -04:00
Juan Denis 3a34358ae1 feat: add Walkthrough Studio builtin extension
Visual authoring tool for walkthroughs: create and reorder steps, pick
highlighted UI targets, choose completion modes (route, signal, manual,
check), validate against the shared schema, preview in a live dock,
publish to the server library, and import/export JSON or copy an
extension contribution block. The Studio dogfoods the new system by
declaring its own getting-started walkthrough in its manifest.
2026-08-31 23:14:50 -04:00
Juan Denis 3708227d0e feat(frontend): dynamic walkthrough registry and SDK support
WalkthroughContext now merges built-in walkthroughs with extension
contributions and server-persisted custom guides through a shared
registry, so enabling or disabling an extension adds or removes its
guides at runtime. Adds the walkthrough contribution type to the plugin
SDK (with TypeScript types and vendor shim), Studio API methods, and
i18n strings.
2026-08-31 23:14:41 -04:00
Juan Denis b44f2439f9 feat: add optional walkthrough guides 2026-08-31 22:36:14 -04:00
Juan DenisandClaude Fable 5 27e6c0ba9a fix(i18n): prune the recycle-bin header keys the refactor orphaned
5bfb0f67 dropped the tab-local header but did not regenerate en.json,
so the lint gate failed on catalog drift. Regenerate en.json and delete
the three now-unused recycleBinTab keys from every locale bundle.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 20:55:35 -04:00
Juan DenisandClaude Fable 5 5bfb0f6747 refactor(recycle-bin): drop the page-local header
The tab-local title, retention blurb and standalone Refresh button
duplicated chrome the grid already provides (Refresh data lives in the
grid tools menu; per-row 'purges in Xd' carries the retention signal).
The page now leads with the view picker and table like other grids.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 19:35:53 -04:00
Juan DenisandClaude Fable 5 fc89a979ef i18n: translate panel self-update strings in all 15 remaining locales
The self-update feature commit added the 10 new app.aboutTab keys to en
and es only; every other locale fell back to English in an otherwise
fully translated About tab. Add ar, bn, de, fr, id, it, ko, pl, pt, ru,
th, tr, vi, zh-Hans and zh-Hant, matching each file's existing register
(Sie/vous/formal).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 08:17:47 -04:00
Juan DenisandClaude Fable 5 160bf6dab7 feat(panel): one-click self-update from the About tab
The About tab could only detect a new release and link to it; applying the
update meant SSH and scripts/update.sh. Wire that script to the UI:

- panel_update_service launches update.sh via systemd-run in its own
  transient unit — a plain subprocess child would be killed when the
  updater restarts the panel's own systemd unit. Status is stateless
  (transient-unit state + the updater's own update-*.log) so it survives
  the mid-update backend restart.
- Capability gates keep the button honest: root systemd installs only.
  Docker installs get the docker compose pull instructions; dev servers
  and hosts without systemd-run get a reason instead of a button.
- GET/POST /api/v1/system/update (admin_required, confirm-gated,
  audited). API surface doc regenerated.
- About tab gains Update Now with inline confirm, live log tail while
  the update runs, a restarting phase that tolerates the panel being
  briefly unreachable, and success/rollback/timeout outcomes. New
  aboutTab locale keys in en + es.

The heavy lifting (blue/green switch, migrations, health check,
automatic rollback) stays in update.sh, which is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 08:09:52 -04:00
Juan DenisandClaude Opus 5 b764418b09 fix(status): re-sync the pre-bundled frontend manifest
30b780f4 corrected the serverkit-status description in two of its three
copies. The extension's manifest also exists at
frontend/src/plugins/serverkit-status/plugin.json, which is generated from
the builtin-extensions/ source by scripts/sync-builtin-frontends.mjs --
so Extensions CI went red on the builtin-frontend drift check, and
bump-version failed downstream of it rather than on its own.

Regenerated with the sync script rather than hand-edited; the diff is the
one description line.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 00:44:04 -04:00
Juan DenisandClaude Opus 5 12c863b230 fix(templates): repo deploys send the build inputs the template declares
The deploy drawer posted only url/branch/app_type/build_method/port, so a
repo template's `build_command`, `start_command` and `dockerfile_path`
were decorative — declared in the YAML, read by nobody. The endpoint has
always accepted custom_build_cmd / custom_start_cmd / dockerfile_path;
only the caller was dropping them.

The visible cost was nixpacks builds: with no start command it falls back
to `npm start`, so any repo whose package.json has no `start` script
produced an image that built fine and could not boot.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 23:47:14 -04:00
Juan Denis 37cf8b6e84 Merge plan 52 cutover: the published extensions leave the tree
localkit, email, cloudflare-ops and git are now published, signed and in
the registry index, so the panel no longer needs in-tree copies of them.
This removes ~29k lines that existed in two places at once and flips the
bundled registry so they install from the catalog like any other
extension.

Unblocked by the operator publishing all nine repos (2026-08-30); the two
registry-mirror tests that plan 83 expected to stay red now pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

# Conflicts:
#	builtin-extensions/serverkit-cloudflare-ops/frontend/components/StoragePanel.jsx
#	frontend/src/plugins/serverkit-cloudflare-ops/components/StoragePanel.jsx
2026-08-30 22:13:01 -04:00
Juan DenisandClaude Fable 5 cea1770562 fix(review): posture installs survive unchecked overlaps; translatable storage empty-states
PR #121 review follow-ups. The setup summary de-duplicated the install
queue with recommendations winning, so a security-posture extension
that also appeared as an unchecked recommendation was silently dropped
— the posture half now wins regardless of checkbox state. The
Cloudflare storage panel templated English around a translated title
(`No ${title.toLowerCase()} yet.`); each section now passes a fully
translated emptyHint instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 20:25:17 -04:00
Juan Denis d764f50809 Merge branch 'dev' into feature/plan52-cutover
# Conflicts:
#	backend/app/data/registry_index.json
#	frontend/src/plugins/serverkit-git/plugin.json
2026-08-30 16:24:27 -04:00
Juan DenisandClaude Fable 5 91d464f871 chore: re-sync the pre-bundled serverkit-git plugin.json
The plan 52 Phase 6 git split updated the source manifest under
builtin-extensions/ (shell permission, entry_point, url_prefix,
min_panel_version) without running sync-builtin-frontends.mjs, so the
Extensions CI drift check went red on the next PR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 14:00:50 -04:00
Juan DenisandClaude Fable 5 d3e3564c7d fix(templates): surface validate-install errors in the deploy drawer
The API client throws on any non-2xx, so a 400 from validate-install
never reached the `!validation.valid` branch — and the catch only read
`err.data.error` (singular), while this endpoint returns an `errors`
array. The operator saw "Request failed (400)" instead of the actual
reason (e.g. the app name being reserved by the Recycle Bin).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 03:20:27 -04:00