1434 Commits
Author SHA1 Message Date
Juan Denis db4c7f3623 Merge pull request #79 from jhd3197/dev
Review stamps and trust levels for the Marketplace
v1.7.56
2026-07-22 23:57:53 -04:00
github-actions[bot] 74421c254e chore: bump version to 1.7.56 [skip ci] 2026-07-23 03:26:21 +00:00
Juan Denis fbadc7d7df Merge branch 'dev' of https://github.com/jhd3197/ServerKit into dev 2026-07-22 23:26:02 -04:00
Juan Denis e8d84297f2 Marketplace trust: split 409 reasons, hide unreviewed outside dev mode
Review feedback + follow-up on the review-stamps feature:

- The 409 trust gate now distinguishes reason 'unreviewed' (community
  code not vetted) from 'unverified' (no pinned checksum, possible even
  for first_party), each with an accurate message; the risk dialog
  carries the reason and matches its title/body to the actual case
  instead of always claiming 'unreviewed community extension'
- Unreviewed registry entries are now developer-stage content: hidden
  from the Marketplace catalog and refused at the install endpoint
  (404) unless the panel runs in a development context (Flask debug /
  testing config, or the dev_mode setting). Hidden means not
  installable; the 409 acknowledgment flow only exists where they list
- dev_mode setting description mentions the Marketplace effect
- tests: reason assertions on both 409 cases; catalog visibility and
  404-on-hidden-install coverage (38 passing)
2026-07-22 23:18:33 -04:00
Juan DenisandClaude Opus 4.8 67cd0faec8 docs(readme): link serverkit-extensions registry repo in Roadmap + docs table
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 22:59:44 -04:00
github-actions[bot] 20bd0932c2 chore: bump version to 1.7.55 [skip ci] 2026-07-23 02:50:16 +00:00
Juan Denis 6c3df8ee76 Merge branch 'dev' of https://github.com/jhd3197/ServerKit into dev 2026-07-22 22:50:00 -04:00
Juan Denis 02bb7666e2 Marketplace: hash-bound review stamps and trust levels for registry extensions
The registry index (schema v3) can now carry a review object per entry
(reviewer, date, sha256, optional commit/notes) asserting that someone
inspected the exact artifact being listed. The stamp is bound to the
artifact hash: review.sha256 must equal the entry sha256, so any change
to the released zip invalidates the review.

- registry_service: keep review through normalization (validated),
  derive trust per entry: first_party, reviewed (stamp matches the
  pinned hash), or unreviewed
- marketplace install route: unreviewed (or sha256-less) entries return
  409 requires_acknowledgment unless the admin posts
  acknowledge_risk: true; acknowledged installs record trust in the
  audit log. Consent gate, consistent with ADR 0002
- Marketplace UI: Reviewed badge (reviewer + date tooltip) and
  Unreviewed warning badge on registry cards, plus a risk confirmation
  modal that retries the install with acknowledge_risk
- tests: trust derivation and the install gate (409 + acknowledge path)
- docs: EXTENSIONS_REGISTRY.md documents the field and the flow
2026-07-22 22:45:57 -04:00
Juan Denis 8899fb5b58 Merge branch 'dev' into main: serverkit update -x guard fix 2026-07-22 22:39:28 -04:00
github-actions[bot] 781a1c365a chore: bump version to 1.7.54 [skip ci] 2026-07-23 02:39:12 +00:00
Juan Denis 1b6cc38673 fix(cli): 'Updater not found' on serverkit update — check -f not -x
scripts/update.sh is tracked 0644 in git (invoked via bash), so the -x
guard in cmd_update rejected every update on a healthy install.
2026-07-22 22:39:02 -04:00
Juan Denis d7b3b8526e Merge pull request #78 from jhd3197/dev
The Deploy Console and runtime extension frontends
v1.7.53
2026-07-22 20:36:58 -04:00
github-actions[bot] d320cacb73 chore: bump version to 1.7.53 [skip ci] 2026-07-23 00:07:30 +00:00
Juan DenisandClaude Opus 4.8 3f3bff3132 test: bump BASELINE_COUNT ratchet 2507 -> 2534 for the batch's new suites
Locks in the proving tests added across plans 52/53/55 (runtime-frontend recovery
suites, db-snapshot relocation, generic fail2ban jail, gamekit framework, minecraft
install wiring, html-sink sweep) so they can't silently disappear.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 19:22:43 -04:00
Juan DenisandClaude Opus 4.8 28cece380f feat(security): HTML-sink sweep guard (D4) — keep XSS sinks swept
Plan 55 Phase 1. The sweep found zero vulnerabilities: every raw-HTML sink is
safe by construction (escape-first SQL/file highlighters, sanitizeSvgInner for
extension icons, the escape-then-allowlist markdown renderer) and the backend
has no |safe/Markup(/render_template_string.

To keep it that way: scripts/check-html-sinks.mjs (wired into npm run lint) and a
Python mirror test (test_html_sink_sweep.py, runs in the backend suite) fail on
any raw-HTML sink that neither references an allowlisted sanitizer nor carries a
'sink-safe:' annotation. Standardized annotations on the three variable-fed sinks
(markdown, SQL editor, marketplace icon) and documented the rule in SECURITY.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 19:22:43 -04:00
Juan DenisandClaude Opus 4.8 cf9cc5d662 fix(games): drop separate indexes on minecraft ext models
The index=True columns emitted separate CREATE INDEX statements that, once the
ext_serverkit_minecraft_* models register on the shared test metadata mid-session
(when the install test runs), collided during a later test's create_app schema
sync — aborting create_all before system_settings and cascading into errors
across the suite. A scaffold needs no secondary indexes; drop them (they can be
reintroduced with proper migration handling when the Docker create-flow lands).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 18:48:47 -04:00
Juan DenisandClaude Opus 4.8 fd6f1733c3 feat(games): serverkit-minecraft extension backbone + gamekit framework
First vertical of the game-server family (plan 53 Phase 0-1, backend core):

- gamekit/ — the reusable, dependency-free framework (D1): a Source RCON client
  (framing/auth/timeouts), a container-log event parser (join/leave/started/
  stopped/crashed, Java + Bedrock), a server.properties config-form builder over
  a JSON sidecar, and the save-aware hot-backup sequence (save-off -> flush ->
  zip -> save-on, always resumes) with retention.
- server_properties_meta.json sidecar (Phase 0 authoring task): grouped, labelled,
  restart-required metadata for the settings form.
- Extension scaffold: manifest (category 'games', models:register), ext_serverkit_
  minecraft_* models keyed by application (D9), and the /api/v1/minecraft blueprint
  (list/get, RCON proxy, backups).

Unit-tested (fake RCON socket, fixture logs, temp worlds) + install-wiring-tested
(install registers routes + creates ext tables + uninstall). The create/console/
UI/Docker flow is the dev-box phase and is intentionally not claimed here.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 18:14:35 -04:00
Juan Denis ee105d0dc6 Ignore graphify output directory
Adds `/graphify-out` to `.gitignore` so generated Graphify output files are not tracked in the repository.
2026-07-22 17:48:10 -04:00
Juan DenisandClaude Opus 4.8 b6692b798f refactor(security): generalize the Fail2ban jail engine beyond WordPress
Split the WP-specific jail service into a generic engine + thin WP wrappers:
enable_jail(key, filter_name, filter_content, logpath, port, ...), a generic
ensure_filter(name, content), remove_jail(key), and jail_name_for_key(). The
jail template's port is now parametrized. enable_wp_jail/disable_jail/get_status
keep byte-identical behavior (existing WP suites unchanged and green), so the WP
extension's callers are untouched. This gives other verticals (game-server
login/RCON jails, plan 53) a reusable per-service brute-force jail seam.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 17:37:20 -04:00
Juan DenisandClaude Opus 4.8 fb19778e7f docs(wordpress): correct extraction audit — frontend not yet extracted
The audit overstated the WP frontend as contributed by the extension; in the
tree the extension index.jsx is still a re-export shell over core pages/
components/SCSS. Corrected to match reality before plan 52 Phase 4 moves it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 17:31:29 -04:00
Juan DenisandClaude Opus 4.8 2ffab5bf86 refactor(models): relocate DatabaseSnapshot/SyncJob; untrack stale gui/email copies
Phase 1 housekeeping for the full-isolation round:
- Move DatabaseSnapshot + SyncJob out of models/wordpress_site.py into a neutral
  models/db_snapshot.py (pure module move, tables unchanged); wordpress_site.py
  re-exports both for import compatibility.
- Untrack the stale committed live copies of serverkit-gui (sibling repo, no
  in-tree source) and serverkit-email (source of truth: builtin-extensions/
  serverkit-email/), matching how every other extracted builtin is already
  gitignored. Files stay on disk; only removed from the index.
- .gitignore: add the email + gui frontend/backend artifact paths.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 17:31:18 -04:00
Juan DenisandClaude Opus 4.8 ffc1fd7728 feat(extensions): deliver runtime ESM frontends to production panels (#39)
Wire the server half of runtime-frontend delivery: get_active_contributions()
now emits panel sdk_version and a 'frontends' descriptor map {slug: {entry,
hashes, sdk_version}} for every active extension whose frontend_entry is a .mjs
ESM bundle. The bundle sha256 is pinned at install time into the plugin config
under the reserved _frontend_hashes key (no migration — reuses config_json);
update_plugin_config() and the config API preserve/hide reserved keys. Add the
extensions.runtime_frontend kill switch (default on). The client loader already
consumed this shape, so an installed extension's UI now renders on a pre-built
panel with no Vite rebuild. Un-skips the restored plan-25 recovery suites.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 17:24:36 -04:00
Juan DenisandClaude Opus 4.8 54204d69c5 test(deploy): bump CI test-count ratchet to 2507 for the Deploy Console suites
The Deploy Console adds test_run_log_stream.py and test_deploy_console.py
(+77 collected tests). Full backend suite green: 2454 passed, 53 skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 17:01:22 -04:00
Juan DenisandClaude Opus 4.8 6bf8c87b9d docs(deploy): document the Deploy Console; update CHANGELOG and ROADMAP
Add docs/DEPLOY_CONSOLE.md (the feature + architecture), an architecture section
in docs/ARCHITECTURE.md, a CHANGELOG (Unreleased) entry, and move the Deploy
Console into the ROADMAP's Recently Completed list with its Active Development
checkboxes ticked.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 16:43:50 -04:00
Juan DenisandClaude Opus 4.8 0c094aea8d feat(deploy): deployments index deep-links to the console + global "deploy running" pill
The /deployments index is now a single table whose rows open the full-page Deploy
Console (the old inline detail pane is removed). A small global pill appears while
any deploy is pending/running and links straight to its console — so you can
navigate away mid-deploy and always find your way back (plan 51 §1.3, task 26/28).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 16:43:43 -04:00
Juan DenisandClaude Opus 4.8 16518b55bd feat(deploy): route every deploy flow to the Deploy Console
Template install (InstallModal), New Service repo create, Service ▸ Deploy Latest
Commit, and the Build tab's Deploy Now all now navigate to /deployments/<jobId>
on job start instead of embedding progress or dropping the user on a page with no
watcher (plan 51 Phase 2). The template modal's embedded progress block is
removed; the deploy API client gains retryDeploymentJob and a plan option.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 16:37:35 -04:00
Juan DenisandClaude Opus 4.8 b0148d03f9 feat(deploy): the Deploy Console — full-page live install/deploy view
New /deployments/:jobId page (plan 51 §1.1, Phase 3): humanized title, status
pill, live elapsed timer and step counter; a step rail (✓ with per-step duration,
spinner, ✗, ○) that scrolls the log pane to a step; a dark monospace log pane
with follow/wrap/timestamps/level-filter/search/copy/download and a "Jump to live"
chip; a pinned error card (failed step, real failure tail, plain-language hint,
Retry / Copy / Ask-AI); a success banner (duration, step timings, Open app / View
service / View runtime logs); plus queued, degraded (poll-fallback) and history
states. Design-system SCSS only, bespoke .deploy-console__* BEM (D12).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 16:37:28 -04:00
Juan DenisandClaude Opus 4.8 a5247573e5 feat(deploy): live deploy transport — socket client + useDeployJobStream hook
Add the deploy_log/deploy_status handlers and subscribeDeploy/unsubscribeDeploy
to the socket singleton, and useDeployJobStream — one hook for the console, the
compact widget, the LogsTab banner and the topbar pill. It boots from a full
snapshot, prefers the live socket channel, de-dupes log rows by DB id, re-syncs
with after_id on every (re)connect, and falls back to 2s polling when sockets
are unavailable (plan 51 D2/§5.5). DeploymentJobProgress now consumes the hook
and links to the full console.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 16:37:16 -04:00
Juan DenisandClaude Opus 4.8 ebdb7cc16f feat(deploy): every deploy is a job — async deploy_app, retry endpoint, plan-in-GET
POST /builds/apps/<id>/deploy now enqueues an app_deploy job and returns 202 +
{deploy_job_id} so the UI opens the live Deploy Console; ?wait=true preserves the
old synchronous contract for CLI/tests (plan 51 D7). Deploy options (no_cache,
version_tag) ride the job plan through to the async runner.

Add POST /deployment-jobs/<id>/retry: clones a FAILED job (both kinds) and
enqueues a fresh run on a new console URL (D8). Extend GET /deployment-jobs/<id>
with ?plan=true so the console can render the step rail.

Tests cover the socket emit helpers (room + payload), the subscribe_deploy auth
guard, the 202/wait contract, retry guards + clone fields, plan-in-GET, and the
streaming-compose variant incl. a failure persisting a real stdout-bearing tail.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 16:37:08 -04:00
Juan DenisandClaude Opus 4.8 a1c5d17d78 feat(deploy): batched RunLogStream seam + streaming compose + deploy socket channel
Introduce app/services/run_log_service.py — the single crash-proof write seam
for all deploy-path logging (plan 51 D4/D5/D6/D10). It batches writes (one DB
commit + one socket emit per flush instead of commit-per-line), keeps a truthful
80-line in-memory failure tail, records per-step timings, sanitizes ANSI/\r,
caps persisted rows at 5000, and matches a plain-language failure hint. The
DeploymentPlanRunner now funnels log/step/close through it.

Add DockerService.compose_up_streaming (Popen + --ansi never --progress plain,
line callback) so template installs stream the real pull/build transcript live
and a failure persists a meaningful tail — the biggest reason install errors
were unreadable. The runner's local compose.up step adopts it.

Replace the orphaned build_* socket surface (zero subscribers, grep-verified)
with the Deploy Console channel: emit_deploy_log / emit_deploy_status to room
deploy_{job_id}, plus subscribe_deploy/unsubscribe_deploy (authenticated).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 16:36:58 -04:00
Juan DenisandClaude Fable 5 ab37bcca23 docs(roadmap): refresh to v1.7.x reality, add H2 2026 active-development section
The roadmap still said v1.6.0 / last-updated March 2026 while dev sits at
v1.7.52. Reframe the status note (actively developed, three tracks), refresh
Recently Completed with the actual 1.7.x highlights, add an Active Development
section (deploy console, extension platform, game server extensions, agent
streaming, release engineering), fix the milestones table incoherence, and
retitle the long-completed 'Upcoming Development' block.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 14:21:03 -04:00
github-actions[bot] 566c2b80d9 chore: bump version to 1.7.52 [skip ci] 2026-07-22 13:31:39 +00:00
Juan Denis 3628da8b79 Merge branch 'dev' into main: link panel tab in Add Server drawer v1.7.51 2026-07-22 09:31:29 -04:00
Juan Denis b50a008984 feat(ui): move linked-panel flow into the Add Server drawer as a third tab
The standalone card below the servers list was UI drift — the link flow
('Link panel') now lives inside the existing Add Server modal next to
'Connection string' and 'Pair code', using the drawer's own form styles.
2026-07-22 09:31:25 -04:00
github-actions[bot] cf045400bf chore: bump version to 1.7.51 [skip ci] 2026-07-22 13:08:39 +00:00
Juan Denis d80518966b Add Trendshift badge to all README variants
Adds the Trendshift repository badge to the main README and the Spanish, Portuguese, and Simplified Chinese README files so project visibility/trend metrics are shown consistently across all language entry points.
2026-07-22 09:08:26 -04:00
github-actions[bot] 4fc849da90 chore: bump version to 1.7.50 [skip ci] 2026-07-22 04:48:22 +00:00
Juan Denis 472dfab443 Merge branch 'dev' into main: linked-panel compose path fix v1.7.49 2026-07-22 00:48:15 -04:00
Juan Denis b0ccd2f5b5 fix(linked-panel): accept compose file path in project_path from remote runner
The deployment runner forwards the plan's compose_file in the project_path
field; the embedded agent now splits file paths into (dir, compose_file)
before calling DockerService, fixing '[Errno 20] Not a directory' on
remote template installs.
2026-07-22 00:48:13 -04:00
github-actions[bot] cef8a3697b chore: bump version to 1.7.49 [skip ci] 2026-07-22 04:35:45 +00:00
Juan Denis 5255d09658 Merge branch 'dev' into main: ServerKit-to-ServerKit peering v1.7.48 2026-07-22 00:35:36 -04:00
Juan Denis db3c29179d feat(servers): ServerKit-to-ServerKit peering — embedded agent mode
Lets a panel link itself to a master ServerKit panel as a worker WITHOUT
installing the standalone Go agent: the panel registers via the master's
existing token flow, then runs an embedded agent client (HMAC auth + HTTP
long-poll transport) that dispatches agent commands (file:write,
docker:compose:up/ps/logs, system:info/metrics) onto its own local
services. The master needs zero changes — a linked panel is just another
agent-backed Server row with scoped, revocable credentials.

- linked_panel_config table (migration 077) + Fernet-encrypted secret
- embedded agent client: connect/poll/result loop, heartbeat metrics,
  per-command threads, allowed-roots guard on file:write
- API: GET/POST/DELETE /api/v1/linked-panel (+ startup resume hook)
- Servers page: LinkedPanelCard (link form, live status, unlink)
2026-07-22 00:35:33 -04:00
github-actions[bot] 40a86928ab chore: bump version to 1.7.48 [skip ci] 2026-07-22 03:26:22 +00:00
Juan Denis be20b59820 Merge branch 'dev' into main: template bind-mount fix v1.7.47 2026-07-21 23:26:16 -04:00
Juan Denis 465a4ee9a1 fix(templates): only bind-mount absolute file paths; relative files are build-context only
A template file with a relative path (prompture-hub's Dockerfile) was
bind-mounted as './Dockerfile:Dockerfile', failing compose up with
'invalid mount config: mount path must be absolute'.
2026-07-21 23:26:13 -04:00
github-actions[bot] 343073c244 chore: bump version to 1.7.47 [skip ci] 2026-07-22 03:13:17 +00:00
Juan Denis 0e3bddf30b fix(templates): pin prompture-hub to 0.0.1 (0.0.2 was never published to PyPI) 2026-07-21 23:13:08 -04:00
Juan Denis c0c1d36456 Merge branch 'dev' into main: prompture-hub template pin fix 2026-07-21 23:12:42 -04:00
Juan Denis 79420e58ad fix(templates): pin prompture-hub to 0.0.1 (0.0.2 was never published to PyPI) 2026-07-21 23:12:39 -04:00
Juan Denis 9baa8f43ea Merge branch 'dev' into main: fix stuck deployments, repo-app auto-deploy, unified install UX 2026-07-21 22:57:59 -04:00