docs(website): one self-service surface — /auth/me/account
Companion to RunicGateway/website's collapse of /admin/account (6 routes) and
/player/account (8 routes) onto /auth/me/account, which was already a strict
superset of both.
- BACKEND_DESIGN.md: the two router-tree entries go; the /auth/me prose is
rewritten from "additive, the older routes stay for web back-compat" to the
single surface it now is, recording why /auth/me was the one to keep and
that gating was equivalent. account.controller.js moved to router/v1/auth/.
The /player-group paragraph loses account.router.js from its mount list.
- ENGAGEMENT.md: new Phase 1a records the collapse as built, and §0.6 finding 4
is corrected — it named router/v1/player/account.router.js, which is gone.
Phase 1b's change-and-verify flow now lands on /auth/me/account and nowhere
else, which was the reason to do this first: a self-service field would
otherwise have been written three times, in 1b and again in Phase 3.
- android/PLAN.md §6.4/§8: the "routes stay for web back-compat" note is now
false. The app needed no change — MeApi.kt was already 100% /auth/me/*.
- API_V2_PLAN.md: a forward pointer only. Its router inventories are a record
of the domain split as it landed and are deliberately left as written.
api-route-inventory.json is regenerated wholesale, not partially updated. It is
a generated mirror of server/routes.manifest.json with no CI gate, and it had
drifted on its own: 168 entries against the manifest's 203, missing every Teams
route and still listing the two Gmail connect routes Phase 1 deleted. It is now
byte-identical to the manifest. A gate for it is flagged in ENGAGEMENT.md
Phase 1a as later work — a mirror nothing checks will drift again.
PROJECT_TREE.md is deliberately untouched: it is auto-generated by the
sync-project-tree workflow in the website repo, which regenerates it from
tracked files on main.
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -659,7 +659,7 @@ not rank).
|
||||
| **Rules / Leaderboards / Market** | everyone, *if the shard publishes them* | `/public/shard/{ruleset,points,market}` (M11) |
|
||||
| **Atlas** (bestiary) | everyone, *if the shard publishes it* | `/public/atlas/*` (M11) |
|
||||
| Contact | everyone | `/public/contact` |
|
||||
| **My Account** | signed-in | `/player/account/*` (or `/admin/account/*` for staff — see §6.4) |
|
||||
| **My Account** | signed-in | `/auth/me/account/*` — one surface for every role (see §6.4) |
|
||||
| **My Characters / Vendors / Houses** | `player` (linked) | `/player/shard/*` |
|
||||
| Sign in / Sign out | toggles on session | `/auth/mobile/*` |
|
||||
|
||||
@@ -707,8 +707,10 @@ Guidelines:
|
||||
and `GET /public/atlas/*` are the new reads. Full contract and traps in §9 M11.
|
||||
|
||||
### 6.3 Player self-service & game data (bearer)
|
||||
- **Account** — `GET /player/account`; `PATCH /player/account/username`;
|
||||
`PATCH /player/account/password`; TOTP `setup`/`enable`/`disable`; identities `GET` / `DELETE`.
|
||||
- **Account** — `GET /auth/me/account`; `PATCH /auth/me/account/username`;
|
||||
`PATCH /auth/me/account/password`; TOTP `setup`/`enable`/`disable`; identities `GET` / `DELETE`.
|
||||
Role-agnostic — see §6.4. (These were `/player/account/*` when this section was written; that
|
||||
surface was deleted on 2026-08-29. The app was already calling `/auth/me/*` and needed no change.)
|
||||
- **Game account linking** — `POST /player/shard/link` (one-time `[link` code),
|
||||
`POST /player/shard/account` (hybrid signup, when enabled), `GET /player/shard/accounts`.
|
||||
- **My game data** — `GET /player/shard/roster/:account`, `/char/:serial`, `/vendors/:account`,
|
||||
@@ -724,13 +726,16 @@ Guidelines:
|
||||
art/asset work on the platform side) and is explicitly out of the first release.
|
||||
|
||||
### 6.4 Self-service is role-agnostic under `/auth/**` (decided)
|
||||
Player self-service is under `/player/account/*` (gated to `role='player'`) and staff use the *same*
|
||||
handlers under `/admin/account/*`. Rather than have the app branch by role (and touch `/admin`), we
|
||||
**add a role-agnostic self surface under `/auth/**`** — the canonical "me" endpoints for every role.
|
||||
The app calls these regardless of role. This is an **additive v1**
|
||||
change (see §8): the existing `/player/account/*` and `/admin/account/*` routes stay for web
|
||||
back-compat; `/auth/me/*` reuses the same `account.controller` handlers behind `requireAuth` (any
|
||||
authenticated role), so there's no logic duplication.
|
||||
Self-service account security lives under `/auth/me/account/*` — the canonical "me" endpoints for
|
||||
every role, behind `requireAuth` (any authenticated role). The app calls these regardless of role and
|
||||
never touches `/admin`.
|
||||
|
||||
> **Update (2026-08-29).** When this was decided it was an *additive* change: `/player/account/*`
|
||||
> (gated to `role='player'`) and `/admin/account/*` served the same `account.controller` handlers and
|
||||
> stayed for web back-compat. **Those 14 routes have since been deleted** — `/auth/me/account` was
|
||||
> already a strict superset of both, so the web client moved onto it and `/auth/me/*` is now the only
|
||||
> self-service surface. See `website/ENGAGEMENT.md` Phase 1a. **The app required no change**: `MeApi.kt`
|
||||
> was already 100% `/auth/me/account/*`.
|
||||
|
||||
> **M10 update (2026-07-21):** *self-service* stays role-agnostic under `/auth/me/*` as above. Separately,
|
||||
> the **operational** admin subset (§1, §10 — moderation, support queue, dashboard/site-mode, content)
|
||||
@@ -784,8 +789,9 @@ maintenance cost. Reserve v2 for a real breaking re-shape if one ever arises.
|
||||
1. **Role-agnostic self-service under `/auth/**` (§6.4, decided).**
|
||||
✅ **DONE (2026-07-19, RunicGateway/website#76 (+ this docs PR)).** A `me.routes.js`
|
||||
sub-router mounts the existing `account.controller` self handlers behind `requireAuth` (any role) at
|
||||
`/auth/me/*`, so the app has one self surface and never touches `/admin`. The old
|
||||
`/player/account/*` + `/admin/account/*` routes stay for web back-compat. Shipped routes:
|
||||
`/auth/me/*`, so the app has one self surface and never touches `/admin`. (The old
|
||||
`/player/account/*` + `/admin/account/*` routes stayed for web back-compat at the time; they were
|
||||
deleted on 2026-08-29 — see §6.4.) Shipped routes:
|
||||
- `GET /auth/me` — current `{ id, username, role }` (already existed; the app's role source).
|
||||
- `GET /auth/me/account` — full self account.
|
||||
- `PATCH /auth/me/account/username`, `PATCH /auth/me/account/password`.
|
||||
|
||||
@@ -14,6 +14,14 @@ Target repo: `website/` · Docs owner: this file + `BACKEND_DESIGN.md`
|
||||
> 2. **The domain split** — `admin.routes.js` (1552 lines, 110 routes) broken into one router file per
|
||||
> business capability, **in place, with every URL unchanged**. This is the actual driver.
|
||||
|
||||
> **Later change, recorded here so the tables below are not read as current (2026-08-29).** The router
|
||||
> inventories in this file are a **record of the split as it landed**, and are deliberately left as
|
||||
> written. Since then, `admin/account.router.js` (6 routes) and `player/account.router.js` (8 routes)
|
||||
> were **deleted**: `/auth/me/account/*` was already a strict superset of both, and is now the single
|
||||
> self-service surface. `account.controller.js` moved to `router/v1/auth/`. See
|
||||
> [ENGAGEMENT.md](./ENGAGEMENT.md) Phase 1a and [BACKEND_DESIGN.md](./BACKEND_DESIGN.md) §4. The
|
||||
> authoritative URL list is, as this file argues throughout, the generated manifest — never a table.
|
||||
|
||||
---
|
||||
|
||||
## Why the auth merge is out
|
||||
|
||||
@@ -87,7 +87,15 @@ server/
|
||||
/me sub-routers below also match the
|
||||
bare /me and supply its noindex header
|
||||
me.routes.js (23) /auth/me/account*, sessions, trusted
|
||||
devices — router-level requireAuth
|
||||
devices — router-level requireAuth.
|
||||
The ONLY self-service account surface
|
||||
(see below); account.controller.js
|
||||
sits beside it and is reached from
|
||||
nowhere else
|
||||
account.controller.js the self-service handlers: username,
|
||||
password, TOTP, identities, device
|
||||
sessions, trusted devices, recovery
|
||||
codes
|
||||
notifications.routes.js (3) /auth/me/devices*, notifications/*
|
||||
mobile.routes.js + /auth/mobile/* — native bearer login
|
||||
mobileSso.routes.js (5)
|
||||
@@ -121,9 +129,6 @@ server/
|
||||
player/ index.js owns the shared `noindex, requireAuth` gate
|
||||
(authenticated, ANY role — staff are a superset
|
||||
of players) and the mount table
|
||||
account.router.js (8) /player/account — credentials, TOTP,
|
||||
linked identities; handlers shared
|
||||
with /admin/account and /auth/me
|
||||
appeals.router.js (4) /player/appeals
|
||||
appeals.controller.js
|
||||
(/player/shard is module-uo's)
|
||||
@@ -145,7 +150,6 @@ server/
|
||||
own prefixes; owns the shared
|
||||
`noindex, isLoggedIn, staffOnly` gate and
|
||||
declares no routes itself
|
||||
account.router.js (6) /admin/account — self-service, no adminOnly
|
||||
users.router.js (9) /admin/users — adminOnly. The six
|
||||
/users/:id/shard/* routes are a
|
||||
MODULE's, reached through the
|
||||
@@ -786,21 +790,29 @@ their own router level, and `/sso/:provider/link` carries `requireAuth` per rout
|
||||
| GET · PUT | `/me/notifications/subscriptions` | cookie / bearer | `{streams:[id]}` on PUT | get / replace own opted-in streams (unknown ids dropped) |
|
||||
| GET · PUT | `/me/notifications/teams` | cookie / bearer | `{teams:[{teamId,muted,emailMode}]}` on PUT | get / replace own **per-Team** preferences (phase 6, [`TEAMS.md`](TEAMS.md) §6.3). One entry per Team the caller could be notified about — active membership or an active forum grant — plus any Team they already hold a preference for; server-side defaults applied. An entry naming a Team the caller has no access to is **dropped, not refused**: a Team left between loading the screen and saving it is a race, not a client bug. The array is required even when empty (`../android/PLAN.md` §11) |
|
||||
|
||||
**Role-agnostic self-service (`/auth/me/*`).** The canonical "me" surface for **every** authenticated
|
||||
role. It reuses the exact `account.controller` handlers as `/player/account/*` and `/admin/account/*`
|
||||
(no logic duplication) behind `requireAuth` **only** — any active account, never a specific role. This
|
||||
lets a client (the Android app) manage its own account through one surface without ever touching
|
||||
`/admin` (docs/android/PLAN.md §6.4). The older `/player/account/*` + `/admin/account/*` routes stay
|
||||
for web back-compat.
|
||||
**Role-agnostic self-service (`/auth/me/*`).** The **only** self-service account surface, for every
|
||||
authenticated role, behind `requireAuth` **only** — any active account, never a specific role. A
|
||||
client (the Android app) manages its own account through it without ever touching `/admin`
|
||||
(docs/android/PLAN.md §6.4).
|
||||
|
||||
It used to be the third of three URL surfaces onto `account.controller`, beside `/player/account/*`
|
||||
and `/admin/account/*`. **Those 14 routes were deleted.** Both were strictly *smaller* than this one —
|
||||
neither carried recovery codes, and `/admin/account` carried no username or password change — so the
|
||||
web client already reached in here for part of a single screen. Gating was equivalent where it
|
||||
overlapped (`/player` and `/auth/me` are byte-identical `noindex, requireAuth`; `staffOnly` on
|
||||
`/admin/account` was strictly narrower and bought nothing, since every handler is self-scoped to
|
||||
`req.user.id`). The controller moved to `router/v1/auth/account.controller.js` beside its one
|
||||
remaining router. **New self-service fields go here and only here.**
|
||||
|
||||
**The `/player/*` group is self-service, not player-only.** Staff are a **superset** of players — every
|
||||
player ability plus their staff tools on top — so the whole group (`account.router.js`,
|
||||
`appeals.router.js`, mounted by `player/index.js`, plus whatever a module mounts here) sits behind
|
||||
player ability plus their staff tools on top — so the whole group (`appeals.router.js`, mounted by
|
||||
`player/index.js`, plus whatever a module mounts here) sits behind
|
||||
the shared `noindex, requireAuth` gate **only**, never `requireRole('player')`. Every handler is self-scoped to the caller by `req.user.id`, so an admin/editor/
|
||||
moderator using it sees only their **own** linked accounts and characters (with the pre-existing
|
||||
`isAdmin` bypass still letting a genuine admin read *any* character). `module-uo` inherits the rule
|
||||
and relies on it: its `/player/shard/*` handlers are the identical self-scoped ones it also serves
|
||||
under `/admin/shard/*`, so the two are interchangeable. This is why a staff account with linked game characters gets its "My characters" and
|
||||
under `/admin/shard/*`, so the two are interchangeable. (Core no longer does this for account
|
||||
security — see `/auth/me/*` above — but the rule the module depends on is unchanged.) This is why a staff account with linked game characters gets its "My characters" and
|
||||
personal notification streams on the mobile client — the group no longer 403s a non-`player` role.
|
||||
|
||||
`teams.router.js` joins the group in Teams phase 2, and relies on exactly that rule: a moderator is in
|
||||
|
||||
@@ -182,10 +182,16 @@ duplicates Phase 1b must clean up, and it makes `email_verified` too weak a sign
|
||||
duplicate wins (which is why §7.1 Q1's answer is oldest-wins, not verified-wins).
|
||||
|
||||
**4. There is no self-serve email flow at all.** No route lets a user set or change their own address
|
||||
after signup — `router/v1/player/account.router.js` has none, and `users.model.js:72`'s `update()` is
|
||||
reached only by admin user management. An address is captured once, at registration or SSO provisioning,
|
||||
and is thereafter unchangeable by its owner. A verification gate presupposes a change-and-verify flow,
|
||||
so Phase 1b builds one; it is not an add-on to an existing screen.
|
||||
after signup — `router/v1/auth/me.routes.js`, the self-service surface, has none, and
|
||||
`users.model.js:72`'s `update()` is reached only by admin user management. An address is captured once,
|
||||
at registration or SSO provisioning, and is thereafter unchangeable by its owner. A verification gate
|
||||
presupposes a change-and-verify flow, so Phase 1b builds one; it is not an add-on to an existing
|
||||
screen.
|
||||
|
||||
> Read out of the tree on 2026-08-28, when self-service had *three* URL surfaces onto one controller
|
||||
> (`/auth/me/account/*`, `/player/account/*`, `/admin/account/*`), so a new field meant writing it
|
||||
> three times. **The two smaller ones were deleted on 2026-08-29** — see Phase 1a below. Phase 1b's
|
||||
> change-and-verify routes are written once, on `/auth/me/account`.
|
||||
|
||||
**One consequence for the error surface.** A unique constraint needs a user-facing failure, and the
|
||||
obvious wording (*"that email is already registered"*) makes account existence queryable — a step back
|
||||
@@ -1204,6 +1210,7 @@ change is not complete until `docs/` reflects it" — is the floor; this table i
|
||||
| Phase | `docs/` | Other repos |
|
||||
| --- | --- | --- |
|
||||
| **1** Remove Gmail OAuth2, SMTP | `website/BACKEND_DESIGN.md` §7 **rewritten** (not amended — it documents Gmail OAuth2 as *the* mechanism); route tables lose `/admin/email/connect/*` | `website/README.md` + `.env.example` wherever they point at Connect Gmail · **`runicgateway.com`**: `notifications-and-email.mdx` (its "There is no SMTP option" aside is now false), `configuration.mdx:62`, `troubleshooting.mdx:101`, `system-architecture.mdx:117` · a release note |
|
||||
| **1a** One self surface | `website/BACKEND_DESIGN.md` — the `/auth/me` prose and the `/player`+`/admin` router trees · `api-route-inventory.json` regenerated · `website/ENGAGEMENT.md` this phase | `android/PLAN.md` §6.4/§8 — the "routes stay for web back-compat" note is now false · `website/API_V2_PLAN.md` historical tables get a pointer |
|
||||
| **1b** Unique email | `website/BACKEND_DESIGN.md` — the `users` table (the "not unique" note is now false), the new change/verify routes, and the de-dupe migration as an operator-visible upgrade step | `website/README.md` upgrade notes · a release note naming the admin report and the verification-gate default |
|
||||
| **2** Trigger registry | `website/MODULE_API.md` §1.1 (**1.7.0** + correct the stale "1.6.0 has only ever been on `edge`" paragraph), §2.3 (`ctx.events`, `ctx.inbox`), §2.4 (`registerEventTriggers`), §7.3's dormant-rule note · `website/ENGAGEMENT.md` §4.3 kept true | `Integration-kit`: `ci/core-ref.json` re-pinned (the equality check goes red **on purpose**) + chapter 2 gains a "registering a trigger" section · **`runicgateway.com`**: `platform.json.moduleApi` → 1.7.0 |
|
||||
| **3** Channel preferences | `website/BACKEND_DESIGN.md` route table · `android/PLAN.md` §11 | — |
|
||||
@@ -1299,6 +1306,45 @@ of a 500 that takes the contact form with it.
|
||||
|
||||
---
|
||||
|
||||
### Phase 1a — One self-service surface: `/auth/me/account` ✅
|
||||
|
||||
**Not in the original plan.** It was added on 2026-08-29, ahead of Phase 1b, when mapping Phase 1b's
|
||||
ground truth turned up that self-service account security had **three URL surfaces onto one
|
||||
controller** — `/auth/me/account/*`, `/player/account/*` and `/admin/account/*`, all mounting the same
|
||||
`account.controller` handlers. Phase 1b adds a self-service field (email), Phase 3 adds another
|
||||
(channel preferences), and each would otherwise have been written three times.
|
||||
|
||||
**`/auth/me/account` was already a strict superset**, which is what settled which one to keep: it was
|
||||
the only surface carrying recovery codes, and `/admin/account` carried no username or password change
|
||||
at all. The web client already reached into `/auth/me` for two calls on a screen it otherwise served
|
||||
from `/admin/account` — the split was leaking before anyone touched it. Gating was equivalent where it
|
||||
overlapped: `/player` and `/auth/me` apply byte-identical `noindex, requireAuth`, and `staffOnly` on
|
||||
`/admin/account` was strictly narrower while buying nothing, since every handler is self-scoped to
|
||||
`req.user.id`.
|
||||
|
||||
**14 routes deleted, 0 added, no handler changed.** `account.controller.js` moved from
|
||||
`router/v1/admin/` to `router/v1/auth/`, beside the one router that still reaches it. The web client's
|
||||
14 call sites moved onto the root-level `api.myAccount` / `api.changeUsername` / … group. The Android
|
||||
app needed **nothing** — `MeApi.kt` was already 100% `/auth/me/account/*`.
|
||||
|
||||
It is a **breaking change to the published OpenAPI surface**, accepted deliberately: both consumers are
|
||||
in this org, and deprecating-then-deleting would have meant Phase 1b deciding whether to add its email
|
||||
routes to surfaces already marked for removal.
|
||||
|
||||
**As built:** `routes.manifest.json` shows exactly 14 deletions and 0 additions; the OpenAPI spec loses
|
||||
the same 14 paths with **zero surviving path definitions changed** and identical `components` (its large
|
||||
textual diff is pure reordering — removing the first-mounted router shifts every later path). Two
|
||||
swagger tags — `Admin · Account` and `Player` — were declared *only* by the deleted routes and went with
|
||||
them. 1203 server tests and 288 client tests green.
|
||||
|
||||
**One thing this phase did not fix, on purpose:** `docs/website/api-route-inventory.json`, the docs
|
||||
mirror of the route manifest, had drifted badly on its own (168 entries against the manifest's 203 —
|
||||
missing every Teams route, and still listing the two Gmail `connect` routes Phase 1 deleted). It is a
|
||||
generated mirror with no CI gate, so it was regenerated wholesale here rather than partially updated.
|
||||
**A mirror nothing checks will drift again** — a gate for it belongs in a later phase.
|
||||
|
||||
---
|
||||
|
||||
### Phase 1b — Unique, changeable, verifiable email addresses *(decision 6)*
|
||||
|
||||
**Lands alone, between 1 and 2, and before any engagement mail exists.** It touches registration, SSO
|
||||
@@ -1323,7 +1369,8 @@ uniqueness *after* a send log and a suppression list hold rows is strictly worse
|
||||
`foo@x.com` are one mailbox everywhere that matters, and folding must happen in the index rather than
|
||||
in application code that can be bypassed.
|
||||
3. **A self-serve change-and-verify flow**, which does not exist today (§0.6 finding 4). Set/change
|
||||
address, a signed time-boxed verification link, `email_verified` set only on link use. SSO's
|
||||
address, a signed time-boxed verification link, `email_verified` set only on link use. It lands on
|
||||
**`/auth/me/account` and nowhere else** — Phase 1a made that the single self-service surface. SSO's
|
||||
`emailVerified: Boolean(profile.email)` is corrected at the same time to honour the IdP's actual
|
||||
`email_verified` claim rather than the mere presence of an address.
|
||||
4. **The verification gate as an admin setting** — `on` for fresh installs, `off` for upgrades, so the
|
||||
|
||||
@@ -17,30 +17,6 @@
|
||||
"method": "GET",
|
||||
"path": "/api/health"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/admin/account"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/admin/account/identities"
|
||||
},
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "/api/v1/admin/account/identities/:provider"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/admin/account/totp/disable"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/admin/account/totp/enable"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/admin/account/totp/setup"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/admin/activity"
|
||||
@@ -89,14 +65,6 @@
|
||||
"method": "PUT",
|
||||
"path": "/api/v1/admin/email/config"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/admin/email/connect/callback"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/admin/email/connect/start"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/admin/email/disconnect"
|
||||
@@ -145,6 +113,14 @@
|
||||
"method": "GET",
|
||||
"path": "/api/v1/admin/moderation/recent"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/admin/moderation/reports"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/admin/moderation/reports/:id/handle"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/admin/moderation/search"
|
||||
@@ -293,6 +269,98 @@
|
||||
"method": "PUT",
|
||||
"path": "/api/v1/admin/site-mode"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/admin/teams"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/admin/teams/:id"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/admin/teams/:id/archive"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/admin/teams/:id/display-name"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/admin/teams/:id/forum/moderation"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/admin/teams/:id/grants"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/admin/teams/:id/hide"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/admin/teams/:id/leader-override"
|
||||
},
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "/api/v1/admin/teams/:id/leader-override/:memberKey"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/admin/teams/:id/unhide"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/admin/teams/forum/settings"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/admin/teams/forum/uploads"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/admin/teams/integrations"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "/api/v1/admin/teams/integrations"
|
||||
},
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "/api/v1/admin/teams/integrations/:teamId"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/admin/teams/requests"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/admin/teams/requests/:id/decide"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/admin/teams/resync"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/admin/teams/review"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/admin/teams/voice"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "/api/v1/admin/teams/voice"
|
||||
},
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "/api/v1/admin/teams/voice/:teamId"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/admin/teams/voice/sync"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/admin/uploads"
|
||||
@@ -477,6 +545,14 @@
|
||||
"method": "PUT",
|
||||
"path": "/api/v1/auth/me/notifications/subscriptions"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/auth/me/notifications/teams"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "/api/v1/auth/me/notifications/teams"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/auth/me/sessions"
|
||||
@@ -557,38 +633,6 @@
|
||||
"method": "POST",
|
||||
"path": "/api/v1/auth/sso/totp"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/player/account"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/player/account/identities"
|
||||
},
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "/api/v1/player/account/identities/:provider"
|
||||
},
|
||||
{
|
||||
"method": "PATCH",
|
||||
"path": "/api/v1/player/account/password"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/player/account/totp/disable"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/player/account/totp/enable"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/player/account/totp/setup"
|
||||
},
|
||||
{
|
||||
"method": "PATCH",
|
||||
"path": "/api/v1/player/account/username"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/player/appeals"
|
||||
@@ -605,6 +649,66 @@
|
||||
"method": "GET",
|
||||
"path": "/api/v1/player/appeals/eligible"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/player/teams"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/player/teams/:slug/access"
|
||||
},
|
||||
{
|
||||
"method": "PATCH",
|
||||
"path": "/api/v1/player/teams/:slug/forum/posts/:id"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/player/teams/:slug/forum/posts/:id/moderate"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/player/teams/:slug/forum/report"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/player/teams/:slug/forum/threads"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/player/teams/:slug/forum/threads"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/player/teams/:slug/forum/threads/:id"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/player/teams/:slug/forum/threads/:id/moderate"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/player/teams/:slug/forum/threads/:id/posts"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/player/teams/:slug/forum/uploads"
|
||||
},
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "/api/v1/player/teams/:slug/forum/uploads/:id"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/player/teams/:slug/grants"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/player/teams/:slug/grants"
|
||||
},
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "/api/v1/player/teams/:slug/grants/:userId"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/public/contact"
|
||||
@@ -637,6 +741,34 @@
|
||||
"method": "GET",
|
||||
"path": "/api/v1/public/status"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/public/teams"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/public/teams/:slug"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/public/teams/:slug/activity"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/public/teams/:slug/members"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/public/teams/by-external/:moduleId/:externalId"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/public/teams/unsubscribe/:token"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/public/teams/unsubscribe/:token"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/v1/public/version"
|
||||
@@ -674,6 +806,14 @@
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/internal/bot-config"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/internal/commands"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/internal/commands/dispatch"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user