3 Commits
Author SHA1 Message Date
Juan Denis 55d8fb1e44 Read route bodies through json_object()
328 more routes used a JSON body as a dict straight from
request.get_json(), so a body of null, [] or a bare string crashed them
into a 500. Bare reads become json_object(); the
'get_json(silent=True) or {}' reads of action routes become
json_object(optional=True), which still treats a missing body as {}.
Routes that take arrays or pass the body through untouched are left
alone. The full backend suite shows no new failures.

Also carries three files' bare section citations (apps, backups,
notifications) and the extended citation guard, which needed them.
2026-10-10 20:53:43 -04:00
Juan DenisandClaude Opus 5 031142111d fix(authz): give every mutating route an explicit authorization decision
GHSA-r4q7-x795-vr4j was one forgotten check, but the audit behind it found
the same shape across the surface: `@jwt_required()` authenticates, it does
not authorize, and ServerKit has no default-deny to catch the difference.
This closes the routes that audit left open — fleet-monitor alert
acknowledge/resolve, recycle-bin restore, nginx test/diff, registrar
sync/test, server-template drift checks, uptime tracking on/off, server ping
and remote compose ps/logs, refresh-capabilities, template
test-db-connection, deploy branches, buildpack detect — plus three inline
gaps: a viewer could widen their own API key's scopes, the demo-deploy flag
was doing double duty as an authorization one, and tagging a shared resource
had no write check at all while attaching one did.

`_ensure_group_mutable` only ever blocked *system* queue groups, so every
queue_bus mutation now also calls `_ensure_group_accessible` (owner-or-admin)
— renaming, draining or deleting another user's group was open to any
authenticated caller.

The rbac policy decorators authenticate through `auth_required()`, so they
replace `@jwt_required()` rather than stack under it; stacking rejects
API-key callers before the policy can authorize them
(tests/test_auth_decorator_boundaries.py enforces this). Where a route then
needed the caller it reads `get_current_user()` — `get_jwt_identity()` raises
for an API-key request. The decorators also carry a `_sk_authz` marker so a
static test can see the decision from the source.

`migrations.get_migration_history` moves to `require_admin_user()` for the
same reason its siblings did: the inline `User.ROLE_ADMIN` check it kept was
already reading two names this module no longer imports, so the route raised
NameError for every caller, admin included.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 21:44:17 -04:00
Juan DenisandClaude Opus 4.8 a550f16baf feat: Phase 2 developer experience — build packs, config snapshots, catalog certification
- Build packs / zero-Dockerfile deploys (C1): new BuildpackService detects the
  stack from a cloned repo (Node/Python/Go/PHP/Ruby/Rust/static), produces a
  transparent build plan and a generated Dockerfile, and persists the plan +
  overrides on the Application. POST /api/v1/buildpacks/{detect,generate}; a
  BuildpackPreview shows the detected plan + editable overrides + Dockerfile in
  the create wizard and the app Build tab. Builds on the existing build_method
  plumbing instead of duplicating it.

- Deployment config snapshots + diff engine (C4): ConfigurationService captures
  an immutable, hashed snapshot of resolved config (env keys + masked values,
  domains, image/tag, build method, volumes) at every deploy and rollback; new
  DeploymentSnapshot model + /api/v1/apps/<id>/snapshots[/diff|/restore]. A
  DeploymentTimeline + ConfigDiffModal surface "what changed" and one-click
  restore in the app Deploy tab. Secret values are never serialized.

- Template catalog certification (C5 cont.): a whole-catalog validation test
  proves all 105 declarative templates conform to the documented schema; fixed
  the stale index.json (was 63/105 entries) to list every bundled template.

Migration 030 adds the buildpack columns + deployment_snapshots table. Full
backend suite: 820 passed, 14 skipped; frontend builds clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 18:49:04 -04:00