docs: add ownership protection to inventory spec

Viewing another user's inventory is read-only — Use and Discard
buttons only render when viewer is the inventory owner, with a
server-side guard in the interaction handler.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
syntaxbullet
2026-03-28 16:58:08 +01:00
parent 289044e26f
commit 8ef1873410

View File

@@ -48,12 +48,18 @@ Shown when a user selects an item from the dropdown or uses `/inventory view <it
4. **Separator** 4. **Separator**
5. **Stats row**`TextDisplayBuilder`: `Owned: **×{quantity}**` and `Value: **{price} 🪙**` (or "Not tradeable" if price is null) 5. **Stats row**`TextDisplayBuilder`: `Owned: **×{quantity}**` and `Value: **{price} 🪙**` (or "Not tradeable" if price is null)
6. **Action buttons**`ActionRowBuilder`: 6. **Action buttons**`ActionRowBuilder`:
- `◀ Back` (primary) — returns to list view at the same page - `◀ Back` (primary) — always shown, returns to list view at the same page
- `🧪 Use` (success) — only shown if item type is CONSUMABLE with effects defined - `🧪 Use` (success) — only shown if **viewer is the owner** AND item type is CONSUMABLE with effects defined
- `🗑 Discard` (danger) — drops one unit of the item - `🗑 Discard` (danger) — only shown if **viewer is the owner**
**Container:** `ContainerBuilder` with accent color matching the item's rarity color. **Container:** `ContainerBuilder` with accent color matching the item's rarity color.
### Ownership Protection
The command tracks two IDs: `viewerId` (who ran the command) and `ownerId` (whose inventory is displayed). When `viewerId !== ownerId`, the inventory is **read-only**:
- The detail view only shows the Back button (no Use or Discard).
- The interaction handler validates `viewerId === ownerId` before executing `useItem` or `removeItem`, as a server-side guard even if the buttons were somehow rendered.
### Use Button Flow ### Use Button Flow
Calls `inventoryService.useItem()` and shows the result inline. Then returns to the detail view with updated quantity. If quantity reaches 0, returns to the list view. Calls `inventoryService.useItem()` and shows the result inline. Then returns to the detail view with updated quantity. If quantity reaches 0, returns to the list view.