Full REST surface for /user/profile replaces upstream stub

Altien replaces upstream's single-method POST stub with four properly scoped endpoints: GET, PATCH, a credits increment, and DELETE /user/account with cascade. The whitelist-based PATCH and cascading account deletion are cleaner than anything upstream ships, regardless of whether you care about the Azure-specific pieces.

multi-tenantcompliance

Maintained by Allen Morgan · verified on MikeWatch

Commit ff992534 rewrites backend/src/routes/user.ts from roughly 10 lines to over 200. The old endpoint was a POST that upserted a blank profile row and returned { ok: true }. The new surface is four endpoints.

GET /user/profile returns the full profile row plus a global_api_keys map - booleans advertising which of Claude, Gemini, OpenAI, and Azure OpenAI have shared server-side keys configured. This lets the frontend show models as available without ever sending actual key values to the client. The GET also normalizes credits_reset_date: if the stored date has already elapsed, it resets the counter to zero and writes a new 30-day window before responding.

PATCH /user/profile uses an explicit allowlist of 11 fields (display_name, organisation, tabular_model, fast_model, and the four provider key/endpoint columns). Anything not on the list is silently ignored; an empty update body gets a 400. That's a meaningful improvement over the common pattern of passing req.body straight to the ORM.

DELETE /user/account cascades through every user-owned table and returns 403 in Entra mode, where account closure is the tenant admin's responsibility rather than the app's.

The auth.admin.deleteUser call that upstream used for deletion is gone. IdP teardown is deferred to the IdP, which is correct.

So what Worth pulling the PATCH whitelist pattern and the cascading DELETE on their own - both are better than upstream regardless of provider. The `global_api_keys` advertisement only makes sense if you're building the "shared server key with per-user override" feature that the rest of this fork targets.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

1 commit from Altien/mikeOssAzure, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
ff992534 feat(user): full /user/profile REST surface Allen Morgan 2026-05-08 ↗ GitHub
commit body
Replaces the upstream POST /user/profile stub + auth.admin.deleteUser
account-deletion path with:

  * GET    /user/profile               - returns the profile row plus
                                          a global_api_keys map telling
                                          the frontend which providers
                                          have shared keys configured
                                          server-side.
  * PATCH  /user/profile                - whitelist of editable fields
                                          (display_name, organisation,
                                          tabular_model, fast_model,
                                          claude/gemini/openai/aoai keys).
  * POST   /user/profile/credits/increment - used by chat to count
                                          billable messages.
  * DELETE /user/account                - cascades through every
                                          user-owned table; returns 403
                                          in entra mode (account closure
                                          for tenant-owned identities is
                                          handled out of band by the
                                          tenant admin).

GET /user/profile also normalises credits_reset_date so the 30-day
window self-refreshes when the previous one has passed. The auth-
admin-deleteUser path is gone - provider-specific identity teardown is
the IdP's responsibility, not the app's.

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-194.md from inside the repo you want the changes in.

⬇ Download capture-thread-194.md