Skip to content

fix(api): user update wiping profiles, unusable app names, silent endpoint loss, validate-compose gaps - #123

Merged
vazra merged 5 commits into
mainfrom
fix/api-validation-gaps
Oct 11, 2026
Merged

vazra merged 5 commits into
mainfrom
fix/api-validation-gaps

Conversation

@vazra

@vazra vazra commented Oct 11, 2026

Copy link
Copy Markdown
Owner

Found by the E2E audit (tests were masking these with loose or conditional assertions).

  • PUT /api/users/:id wiped profiles. It wrote display_name/email before validating, so a rejected own-role change still changed the profile, and a role-only update blanked display name and email. Everything is now validated first; omitted fields are kept. Also: an unchanged role no longer bumps the token version, so saving the edit modal no longer signs the user out. Unknown id returns 404.
  • Setup accepted an empty username (only HTML required stopped it). Now 400; user create also rejects whitespace-only names.
  • App names compose cannot use. Names with . or uppercase passed validation but docker compose -p simpledeploy-<name> rejects them, so every such deploy failed. New apps (deploy, import) must now match compose's project rule (^[a-z0-9][a-z0-9_-]{0,62}$, checked against compose-go's normalizer) with a plain-language message; existing apps with legacy names stay viewable and removable. Wizard and import modal show the rule inline.
  • Endpoints with an unknown service returned 200 and silently dropped every endpoint label, leaving the app unreachable. Now 400 and the compose file is unchanged.
  • validate-compose only parsed. The wizard could say "Valid compose file" for a file deploy then refuses. It now applies deploy's rewrites and security rules with deploy's messages (still super admin only, as before).
  • Deploy audit summary said "version 0". The deployer cannot know the version at that point; the summary now omits it.

Docs: reference/api.md, security-hardening.md, apps-and-services.md, first-deploy, architecture/deployer.md.

Tests: Go tests for each (all failing before), vitests for slug/wizard/import modal. Full vitest (519) and affected Go packages pass.

vazra added 5 commits October 11, 2026 02:12
…riting

- POST /api/setup and POST /api/users reject empty/whitespace usernames
- PUT /api/users/:id validates role, self-guard, email, password before any
  write; omitted display_name/email are kept, unchanged role no longer bumps
  token_version; unknown id returns 404
Deploy and bundle import now require ^[a-z0-9][a-z0-9_-]{0,62}$ (compose
rejects uppercase and dots in -p simpledeploy-<name>), with a readable
message. Existing-slug paths keep the looser rule so legacy apps stay
viewable and removable. Wizard and import modal show inline errors.
Such endpoints were silently dropped when labels were rewritten, leaving
the app without its route. Return 400 naming the available services and
leave the compose untouched.
The wizard's check only parsed the file, so it could report a valid
compose that deploy then refused. It now applies the deploy rewrites,
parses as a new app folder inside apps_dir and returns deploy's
violation messages. Authorization unchanged (super_admin).
Deployer.Deploy is audited before the reconciler stores the compose
version, so every normal deploy read "Deploy succeeded (version 0)".
Omit version when unset; rollbacks keep theirs.
@vazra
vazra merged commit a0f1c9d into main Oct 11, 2026
8 checks passed
@vazra
vazra deleted the fix/api-validation-gaps branch October 11, 2026 09:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant