diff --git a/link/ADMIN_CONTROLS.md b/link/ADMIN_CONTROLS.md index 30af617..08345e0 100644 --- a/link/ADMIN_CONTROLS.md +++ b/link/ADMIN_CONTROLS.md @@ -140,7 +140,9 @@ It turns "a staff member must be logged into the game to see the queue" into "th > - *Docs*: `INTEGRATION.md` §6 documents the endpoints and the `admin.audit` event. > - *Bidirectional audit* (§5.5): **built and live-verified.** `patches/commandlogging-event.patch` (adds `CommandLogging.OnWrite`) + `patches/BridgeModerationAudit.cs` (the subscriber) forward in-game bans/kicks/broadcasts to the site as `admin.audit` (`origin:"in-game"`). A boot-time probe confirmed a genuine `[bcast` and resolved ban/kick lines produce the right frames with the target parsed, non-moderation lines ignored. > -> **Phase 1 + the bidirectional-audit slice are complete.** Remaining is downstream (website UI + moderation log) and the later Phase 2 (help-page queue) / Phase 3 work. +> **Phase 2 — help-page queue: built and live-verified.** `BridgePages.cs` polls the queue (`PageSweepSeconds`, default 5s) → `page.new`/`page.updated`/`page.closed`; inbound `pages.snapshot`/`page.respond`/`page.close`; sidecar `GET /pages` + `POST /pages/{id}/respond|close`; `INTEGRATION.md` §4/§6 documented. A live run (probe-seeded tickets) confirmed snapshot, both `page.new` emits, respond, close (→ page removed), `page.closed` emit, and 404 on an unknown page. +> +> **Phase 1 + bidirectional audit + Phase 2 are complete.** Remaining: downstream website UI (moderation log + support-queue view), then Phase 3 (mute/notes/teleport/save). **Wire in, in order:** diff --git a/link/INTEGRATION.md b/link/INTEGRATION.md index 17d46db..3a37309 100644 --- a/link/INTEGRATION.md +++ b/link/INTEGRATION.md @@ -185,6 +185,15 @@ Every event has `t` (epoch ms) and `kind`. A nested actor object looks like `{"s |------|--------|-------| | `link.request` | `code`, `account`, `char`, `ttlSec` | A player ran `[link` in game. Show them a prompt to enter `code` on the site; you then confirm it via `POST /link/confirm`. See §6. | +#### Help-page (support) queue +| kind | fields | notes | +|------|--------|-------| +| `page.new` | `pageId`, `sender`, `type`, `message`, `map`, `x`,`y`,`z`, `sentMs`, `handled`, `handler` | A player opened a help page (support ticket). `pageId` is the sender's serial (one page per player). `type` is `Bug`/`Stuck`/`Account`/`Question`/`Suggestion`/`Other`/`VerbalHarassment`/`PhysicalHarassment`. `sender` is the usual actor object (with `webId` if the account is linked). | +| `page.updated` | same as `page.new` | A page's handled state changed (a staffer claimed/released it in game). | +| `page.closed` | `pageId` | The page left the queue (resolved, cancelled, or the player logged out). | + +The queue has no in-game event, so it's polled (`PageSweepSeconds`, default 5s) — expect a few seconds' latency, and use `GET /pages` for the authoritative current queue on connect. See §6 to snapshot, respond, and close. + --- ## 5. REST — read queries @@ -351,6 +360,31 @@ Each applied action also emits an unsolicited **`admin.audit`** frame on the Web `origin:"web"`, so every connected dashboard — not just the caller — sees it. In-game moderation by staff in the game client surfaces the same way with `origin:"in-game"`. +### Help-page (support) queue + +Read the open queue, respond to a player, or close a page. Staff-facing — gate behind your own +roles, like the moderation endpoints above. + +``` +GET /pages # the open queue, newest state +POST /pages/{pageId}/respond { "message":"...", "close": false } +POST /pages/{pageId}/close +``` + +- **GET /pages** → `pages.list` with a `pages` array; each entry is the same shape as a `page.new` + event's fields (§4). This is the authoritative queue — use it on (re)connect, then keep it live + with the `page.new` / `page.updated` / `page.closed` events. +- **respond** delivers a message to the player exactly as an in-game staff reply does: a gump now if + they're online, otherwise queued for their next login. It shows as coming from "Staff". Pass + `"close": true` to resolve the page in the same call. → **200** `page.ok`. +- **close** removes the page from the queue. → **200** `page.ok`. +- Unknown `pageId` → **404** `page.error`; a respond with no `message` → **400**. + +```json +POST /pages/0x24C/respond { "message": "A GM is on the way.", "close": true } +→ { "kind":"page.ok", "action":"respond", "pageId":"0x24C", "closed":true } +``` + ### History (from the sidecar's database) ```