Commit Graph
1408 Commits
Author SHA1 Message Date
Juan DenisandClaude Fable 5 429eb7911a feat(deployments): dev-only Test deployment trigger + simulated console tag
/deployments gains a topbar 'Test deployment' action (shown only when the
backend demo gate is on) with a scenario-picker modal; the console titles
demo_deploy jobs 'Test deployment — <scenario>' and shows a dashed Simulated
pill.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 17:01:55 -04:00
Juan DenisandClaude Fable 5 3cc708a1e2 feat(deployments): simulated demo deploys through the real console pipeline
Dev-gated (DEMO_DEPLOYS_ENABLED) scripted DeploymentJobs — success/fail-build/
long/ansi/slow scenarios driven through RunLogStream so the Deploy Console is
fully exercisable locally with no Docker or server. GET/POST
/api/v1/deployment-jobs/simulate; retry + unified-job wiring; 12 proving tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 16:58:46 -04:00
github-actions[bot] 2febb54ecd chore: bump version to 1.7.59 [skip ci] 2026-07-23 16:20:43 +00:00
Juan DenisandClaude Fable 5 1783fb004f docs(readme): roadmap tracks use linked bold titles + read-more links
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 12:19:24 -04:00
Juan Denis 90f28fd160 Merge branch 'dev' of https://github.com/jhd3197/ServerKit into dev 2026-07-23 12:17:22 -04:00
Juan DenisandClaude Fable 5 31d13c6370 docs: theme screenshots live only in the serverkit-themes registry
Drop docs/screenshots/themes/ from the panel repo; THEMING.md and the
README roadmap now link to the registry's gallery instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 12:16:40 -04:00
Juan DenisandClaude Fable 5 66d57af129 docs(readme): add Themes to the Roadmap development tracks
Links the in-repo theme gallery and the serverkit-themes catalog beside
the extensions catalog.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 12:15:20 -04:00
Juan DenisandClaude Fable 5 24ee204294 docs(themes): add live screenshots of all 19 themes + gallery page
One dashboard capture per theme (mock-data rig, capture-themes.mjs) under
docs/screenshots/themes/ with a grouped gallery README, linked from
THEMING.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 10:42:14 -04:00
github-actions[bot] af50e2098d chore: bump version to 1.7.58 [skip ci] 2026-07-23 14:32:36 +00:00
Juan Denis 09fa65cdb8 Merge branch 'dev' of https://github.com/jhd3197/ServerKit into dev 2026-07-23 10:32:12 -04:00
Juan DenisandClaude Fable 5 7d4543312c feat(themes): add 11 bundled Venezuelan seed themes
Turpial, Araguaney, Orquídea, Apamate, Ceiba, Azulejo, Guacamaya, Cacao,
Papelón, Onoto (dual dark+light) and Tepuy (radius override) — named after
Venezuelan national symbols and nature. Authored in
frontend/src/data/themes/, synced to backend via sync-bundled-themes.mjs
(17 bundled themes total). check-theme-tokens + backend theme suites pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 10:22:23 -04:00
github-actions[bot] ab836482a3 chore: bump version to 1.7.57 [skip ci] 2026-07-23 13:30:13 +00:00
Juan Denis ad96423966 feat(themes): hardening — preview validation, registry caching, token wiring (plan 61)
- Validate preview swatches as colors server-side (closes url() smuggling
  via POST /import); import tolerates unknown metadata (license, image, modes)
- theme_registry_service: negative caching on fetch failure (TTL-stamped
  last-good + 60s failure backoff — no more 15s gallery stalls offline);
  drop dead base_url cache key; refresh stale comment
- .env.example: document SERVERKIT_THEMES_REGISTRY_URL/_TTL
- SCSS: route $success/$warning/$danger/$info through --green/--amber/
  --red/--cyan (raw twins for color-function call sites), $font-main/$font-mono
  through --sans/--mono, scrollbar track through --scrollbar-track
- Fix 5 undefined CSS var consumers (--radius-md/--card-bg/--danger/
  --accent-subtle/--accent-soft -> existing tokens)
- Nits: drop dead ThemeStudioTrigger export, dedupe lucide import,
  run check-theme-tokens in pre-commit hook
- docs/plans/61_THEMES_HARDENING_PLAN.md

23 backend theme tests pass; check-theme-tokens, lint (0 errors), build green
2026-07-23 09:25:01 -04:00
Juan Denis 8180ff4474 docs(mcp): recommend Faro Agent Bridge + faro-cli as primary server access 2026-07-23 08:55:57 -04:00
Juan DenisandClaude Opus 4.8 e09a6c2948 feat(themes): registry browse, import, panel default, and Theme Studio (plan 60 Phase 2-4)
- ThemeContext: fetch pre-auth panel default (/public/active) and follow it
  until a user picks a skin; ThemeSync bridge loads installed themes after auth
- Theme Gallery admin actions: set panel default, remove installed themes
- Browse modal: install community themes from the registry (offline-tolerant)
- Import theme.json (admin, paste/upload)
- Theme Studio: grouped color editor over the LIVE panel, start-from any
  installed theme, Export theme.json, Save-to-panel, and Submit = a prefilled
  GitHub new-file PR against serverkit-themes
- docs/THEMING.md (token reference + rules + submit flow); README docs table +
  ROADMAP "Recently Completed"

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 00:24:10 -04:00
Juan DenisandClaude Opus 4.8 c20a9f14f2 feat(themes): backend model, API, and registry pipeline (plan 60 Phase 2-3)
Themes are data, not code — so the backend is a simple validated-JSON store,
no zips/checksums/permissions.

- Theme model + migration 078_themes
- theme_tokens.py: server-side mirror of the token whitelist + validators
  (the gate: a malicious/malformed theme never reaches the DB)
- theme_service: bundled-seed loading, import/list/delete, panel default,
  pre-auth public/active
- /api/v1/themes: /installed, /import (admin), DELETE (admin), /default
  get+set (admin), unauthenticated /public/active for login/setup, plus
  /registry + /registry/<slug>/install
- theme_registry_service: offline-tolerant registry fetch (TTL + last-good +
  bundled fallback), mirrors the extension registry pattern
- bundled seed themes synced to app/data/themes + themes_index.json
- 18 proving tests (server-side validation sanitizes url()/;/} smuggling,
  admin gate, panel-default → public/active, offline fallback, install flow)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 00:24:00 -04:00
Juan DenisandClaude Opus 4.8 0016b1ff22 feat(themes): theme gallery + runtime skins (plan 60 Phase 1)
A ServerKit theme is data, not code: a validated map of CSS custom-property
tokens. This lands the client-side foundation.

- themeTokens.js: canonical token whitelist, legacy-alias table, and strict
  value validators (reject url()/@/;/}/expression, type-check per group)
- applySkin.js: runtime skin applier via setProperty (injection-safe); dark/
  light resolution with stock-light fallback for dark-only themes
- ThemeContext: per-user skin selection (localStorage), live hover preview,
  and accent precedence workspace > user > skin > default
- 6 bundled seed themes (default/paper/nord-deep/gruvbox/phosphor/high-contrast)
- Theme Gallery in Settings > Appearance (instant apply, 4-swatch cards) +
  command-palette index entry
- hardcoded-hex audit: 3 exact token-value leaks fixed to var(--token)
- check-theme-tokens.mjs proving guard wired into the lint chain

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 23:55:19 -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
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
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 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