14 Commits
Author SHA1 Message Date
Juan DenisandClaude Opus 5 e181ae7f44 fix(authz census): count extension routes from a source git tracks
a31cc5d3 widened the jwt-only census to app/plugins and shipped a ceiling
of 611 measured on a dev box. CI measured 591 and went red: most
app/plugins/ live copies are GITIGNORED, so the count depended on which
extensions a machine happened to have installed. That is the same
machine-dependence the builtin-copy drift census exists to prevent, and
this walked straight into it.

Count builtin-extensions/ instead -- the source, pinned equal to the live
copy by test_builtin_extension_drift.py, and tracked. Filter to
git-tracked files as well, because extractions leave stale ignored
directories behind (cloudflare-ops, git, localkit after plan 52) that
would otherwise be counted on some working copies but not others.

Stable population: 608 (35 of them extension routes across
cloud-provision, remote-access and status). Also regenerates
docs/MIGRATION_INVENTORY.md, whose row is derived from this ceiling, and
points the CLAUDE.md / AGENTS.md notes at the scope actually scanned.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 00:53:15 -04:00
Juan DenisandClaude Opus 5 a31cc5d3a8 test(authz): ratchet plugin routes too, and write down why not to sweep them
PR #122 review suggested converting the serverkit-status routes from
@jwt_required() + an inline is_admin check to rbac decorators. Declined:
plan 76's recorded decision (2026-08-19) is that JWT-only is the
deliberate default, because every rbac decorator authenticates through
auth_required() and therefore GRANTS API-key callers access -- an
expansion of the authenticated surface, never a mechanical sweep.

Two gaps let that suggestion look uncontroversial:

1. jwt_only_census.py scanned only app/api, so the extension's 15 bare
   @jwt_required() routes were invisible to the ratchet. It now scans
   app/plugins as well; ceiling 577 -> 611 for the newly visible
   population (a scope widening, not a regression). Only the live copy
   is counted -- builtin-extensions/ is the same code twice and the
   drift guard pins them equal.

2. Neither CLAUDE.md nor AGENTS.md said the inline shape is already a
   valid explicit decision (test_route_authz_static counts .is_admin via
   ATTRIBUTE_GATES), or that ~91 routes across 21 files use it. Both now
   do, with the plan 76 quote and a note that automated reviewers raise
   this routinely.

Audited 2026-08-31 by AST over app/api + app/plugins + builtin-extensions.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 00:41:54 -04:00
Juan DenisandClaude Opus 5 9e18e35494 docs(authz): write down the default-deny and one-boundary rules
Both are now enforced by tests that fail the build, so they belong where the
"adding a feature" checklist is rather than in a commit message nobody
re-reads. The one-boundary rule is the trap this round fell into: stacking
`@jwt_required()` outside a policy decorator looks like belt-and-braces and
is actually a regression, because it rejects API-key callers before the
policy can authorize them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 21:44:56 -04:00
Juan DenisandClaude Opus 5 2624816680 docs: how to run the panel behind your own reverse proxy
Issue #96: an operator fronting the panel with Caddy and a smallstep private CA
hit a redirect loop, and there was no documented path to follow. The
architecture already tolerated this deployment -- the fix was a config file we
already ship -- but nothing said so anywhere.

Adds an INSTALLATION.md section covering both topologies (external proxy ->
ServerKit nginx, full features, HOPS=2; external proxy -> the app directly,
panel-only, HOPS=1), why the loop happens, how to count TRUSTED_PROXY_HOPS,
Caddy (with acme_ca for a private CA), Traefik, Nginx Proxy Manager and plain
nginx snippets, what a private CA does and does not require (the panel never
sees it; a remote agent's host must trust the root), and a symptom-to-cause
table for the loop, stale HSTS, the rejected websocket and wrong client IPs.

Also corrects the Docker documentation, which had drifted badly:

- README (en/es/pt/zh-CN), INSTALLATION and DEPLOYMENT all told people to run
  `docker compose up -d` and reach the panel at http://localhost. It starts the
  all-in-one container on :5000, and a containerised panel cannot manage its own
  host -- now stated up front rather than discovered.
- DEPLOYMENT is a host-install guide that told operators to run
  `docker compose build && up` to fix a panel, which would build a second panel
  beside theirs, and carried a certbot cron copying certs and restarting a
  container that does not exist on a host install.
- CLAUDE.md, AGENTS.md, CONTRIBUTING.md and LOCAL_DEVELOPMENT.md (x3) pointed at
  a docker-compose.dev.yml that has never existed; the snippet offering to
  create it referenced a frontend/Dockerfile.dev that does not exist either.

Every anchor introduced here was checked to resolve.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-13 23:07:27 -04:00
Juan DenisandClaude Opus 4.8 adf70b4df0 docs: correct stale architecture facts in the agent instructions
File counts were roughly a third of reality (api 36 vs 90, services 48 vs 165,
models 15 vs 80, pages 29 vs 60), so both files understated the codebase enough
to mislead anyone sizing a change.

Two claims were wrong rather than stale. `db.create_all()` is never called —
schema is 74 Alembic migrations, and describing tables as auto-created invites a
model change that ships without one. And the Production Build section
recommended GeventWebSocket workers while the deployment note 25 lines above
warned against exactly that; the Dockerfile and systemd unit both use a plain
threaded worker.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 01:17:06 -04:00
Juan Denis 5fd04bbfb0 Add review rules and proxy/auth docs
Introduces a new `.coderabbit.yaml` with ServerKit-specific review guardrails, and expands env/security documentation for trusted proxy headers and per-IP login brute-force throttling. It also adds inline backend notes clarifying `request.remote_addr` behavior under ProxyFix for auth, cron, and pairing paths, and updates the frontend plugin manifest to remove the Tramo and K8s plugin entries.
2026-07-18 01:23:47 -04:00
Juan Denis 6e32519f7e restore: remaining reconstructed July 5-7 changes (clean recovered files not attributable to one plan) 2026-07-07 20:29:31 -04:00
Juan DenisandClaude Fable 5 751dde7a7d fix(deploy): threaded gunicorn worker — gevent-websocket class broke WebSocket
The app runs flask-socketio with async_mode='threading' (the backend
is real-thread based: jobs scheduler, queue bus, agent registry), where
engineio serves WebSocket via simple-websocket on the raw socket. The
systemd unit template and Dockerfile still launched gunicorn with the
GeventWebSocketWorker, which ALSO answers the upgrade — the client got
HTTP/1.1 101 twice and read the second one as a frame ('Invalid frame
header'), so every panel silently degraded to polling. Proven by
hexdump (double 101, first 'frame' byte 0x48 'H') and fixed live:
single 101 + 0x81 text frame, socket.io connects through Cloudflare.

- unit template + Dockerfile: gunicorn -w 1 --threads 100 (single
  PROCESS stays mandatory — in-memory agent gateway)
- requirements: pin simple-websocket explicitly (was transitive-only)
- CLAUDE.md / ARCHITECTURE.md / SECURITY.md single-worker notes updated

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 00:14:49 -04:00
Juan DenisandClaude Opus 4.8 eab1a35794 docs: sync docs with dev, add CHANGELOG/SECURITY, document Windows agent
dev was ~149 commits ahead of the last release with no changelog and several
stale docs. This brings the user-facing docs in line with what actually ships.

New:
- CHANGELOG.md — curates the unreleased panel work (agent fleet, plugins,
  status pages, cloud provisioning, RHEL support, installer hardening).
- agent/CHANGELOG.md — the agent release workflow links to this on every
  published release; it was a broken link. Now documents the agent's
  independent release line.
- SECURITY.md — vulnerability reporting policy + agent trust model
  (agent.key is host-equivalent; Features.Exec off by default; single-worker).

Fixes:
- Stale version stamps: docs/README.md and docs/API.md said 0.9.0 -> 1.6.7.
- Supported OS: README/INSTALLATION said Ubuntu/Debian only; installer also
  covers Fedora and RHEL/Rocky/AlmaLinux.
- Dead links/placeholders: API.md wiki link, INSTALLATION.md "yourusername".
- Windows agent + short-code pairing were undocumented; added to README,
  agent/README.md, and docs/pairing.md (incl. corrected host-stable
  credential-key derivation — USERNAME was dropped in agent 1.6.14).
- Documented the single gevent-websocket-worker deployment constraint in
  CLAUDE.md and docs/ARCHITECTURE.md.
- CONTRIBUTING.md: removed reference to a non-existent frontend test suite.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 14:38:15 -04:00
Juan Denis b4f5a466ce Add audit fallback, builtin extensions, and ports
Introduce fallback audit logging and enrich audit tooling; add builtin extension discovery/install; and update default launcher ports and related docs/config.

Key changes:
- New middleware app.middleware.audit registers an after-request fallback that records authenticated mutating API requests when routes don't emit explicit audit logs.
- Audit model/action constants extended and AuditService enhanced (request context handling, redaction for sensitive settings, optional commit flag, sets g.audit_logged, emits events).
- Routes/services updated to create explicit audit entries for marketplace and plugin operations (create/update/publish/install/uninstall/enable/disable) and SSO/settings flows switched to use AuditService.
- Added tests for audit logging behavior and redaction (backend/tests/test_audit_log.py).
- Plugin service: added BUILTIN_EXTENSIONS_DIR, list_builtin_extensions and install_builtin_extension; plugin API endpoints to list/install builtin extensions.
- Contribution system extended to support layouts and route layout metadata; frontend wiring updated to surface standalone/custom layouts and extension routes.
- Launcher port defaults changed (backend -> 47927, frontend -> 41921). Updated backend .env.example, config CORS defaults, Dockerfiles and docker-compose to use SERVERKIT_BACKEND_PORT, and many docs/README files and frontend envs to reflect new ports.
- Minor frontend cleanups and new builtin extension example (serverkit-git) plus associated manifest and frontend re-export.

These changes improve observability/security for mutating APIs, enable opt-in builtin plugins, and align local dev/run ports with the launcher defaults.
2026-05-03 15:57:02 -04:00
Juan Denis b4414aa5b8 Introduce unified dev launcher and SCSS migration
Add a unified, cross-platform development launcher and update docs/styles to SCSS.

- Add dev/dev.sh: comprehensive Bash dev launcher with stable non-default ports, port resolution/cleanup, WSL-aware behavior, ngrok support, and validation tooling.
- Rewrite Windows entrypoint (dev.ps1) to require WSL and delegate to dev/dev.sh; make top-level dev.sh a thin wrapper that execs dev/dev.sh.
- Add AGENTS.md with project overview, architecture, and development instructions for assistance tools.
- Update docs (CLAUDE.md, CONTRIBUTING.md) to reflect migration from LESS to SCSS and update style guidance.
- Update .gitignore to ignore backend/.venv-wsl, frontend.env.development.local, and /.agents.
- Frontend: add new pages and page-specific SCSS files, update main.scss, components, pages, client/socket services, and vite.config.js to support the SCSS-based frontend changes.

These changes unify local development workflows (especially via WSL), improve port stability, and complete the frontend styling migration from LESS to SCSS.
2026-05-03 04:20:14 -04:00
Juan Denis b992220f79 Add dev launcher; harden backups & storage
Add cross-platform development launchers (dev.sh, dev.ps1) and a frontend ESLint flat config; remove legacy scripts and update docs to use ./dev.sh. Harden backup and storage logic: require admin for backup endpoints, use realpath checks to ensure backup paths stay inside the backup dir, prevent path traversal during archive extraction, and generate schedule IDs with UUIDs. Improve StorageProviderService with masked-secret handling, set restrictive file perms on config, validate S3/B2 endpoint URLs to mitigate SSRF (urlparse + ipaddress), avoid following symlinks during uploads, and adjust MD5 usage. Update Bandit config to skip expected noisy checks and tweak .gitignore entries and contributing docs to target the dev branch and the new dev scripts.
2026-03-02 22:48:29 -05:00
Piya f0e640237a feature: add backups storage provider
Align backups API, services, frontend, and dev scripts for new backup storage functionality.

Made-with: Cursor
2026-03-03 02:56:51 +07:00
Juan Denis a706829a50 Add onboarding wizard and developer mode features
Introduces a multi-step onboarding wizard for initial server setup, including admin account creation, use case selection, resource tier display, and summary. Adds backend support for onboarding completion and use case storage. Implements developer mode toggle in settings, exposing an icon reference panel. Updates styles and refactors related frontend logic for setup and settings pages.
2026-01-27 21:25:15 -05:00