## Context The SCUM plugin already declares `reward.deliver`, and the prior game-player and player-state work owns server-local identity plus a durable approval/audit pattern. Neither establishes a platform-owned item catalog, immutable gift definition, or a reliable distinction between game delivery and player notification. This change adds those controls without extending browser access to raw game commands or connection material. ## Goals / Non-Goals **Goals:** - Persist server-version-fenced gift catalogs, revisions, and grants in model-first storage with memory/file/MySQL implementations. - Permit only validated item catalog references in a gift revision; freeze the revision contents and game-player identity at grant creation. - Require a platform administrator to approve delivery, dispatch only typed `reward.deliver`, and record delivery and notification outcomes separately. - Give the Chinese SCUM console shared-theme workflows for draft editing, preview, player selection, confirmation, approval, and readable histories. **Non-Goals:** - Commerce, shops, payment, offline inventory/database editing, raw item codes or generator syntax in browser requests, arbitrary RCON text, bulk grants, map trails, auto-retry of unknown delivery, or auto-redelivery after notification failure. ## Decisions 1. **Catalog ownership and version fencing.** Platform defines a small verified SCUM item catalog keyed by exact game version. A revision stores item-catalog keys, labels, quantities, and an item-catalog version; service validation rejects unknown versions, absent items, duplicate lines, and quantities beyond catalog bounds. This is safer than exposing game item IDs in page forms or accepting a client-provided command payload. 2. **Draft then immutable revision.** A `gift_catalog` carries editable metadata and a draft revision; publishing creates an immutable `gift_revision` with a monotonic revision number. A `gift_grant` copies the selected revision ID plus a deep-frozen item snapshot and game-player record/ID/display-name snapshot. Editing or publishing later revisions therefore cannot change a queued grant. 3. **Explicit approval and idempotency.** Any server-authorized operator creates a `pending-approval` grant with a required idempotency key. A platform administrator with the same server access revalidates target, revision, version catalog, and online eligibility before dispatch. The grant ID is the bridge idempotency key, and a duplicate create request returns the original grant rather than producing another command. 4. **Delivery and notification are separate terminal facts.** `reward.deliver` success becomes `delivered`; command failure becomes `failed`; expiry/cancellation/missing result becomes `unknown`. Only after a confirmed delivery does Platform queue the declared targeted notification command. A notification error produces `notification_failed` while preserving the delivery result. No terminal grant, especially `unknown` or `notification_failed`, is automatically retried or redelivered. 5. **No raw command or secret boundary crossing.** The frontend posts catalog keys, revision IDs, player record IDs, a bounded notice template, and idempotency key only. Platform composes typed bridge payloads from durable records, and browser/API projections omit run credentials, RCON strings, item codes, raw bridge payloads, and host paths. ## Risks / Trade-offs - [A server version has no verified item catalog] → Editing, publication, and grant approval are rejected with an explicit unsupported-version result. - [A selected player is offline] → Grant approval is denied before delivery; the pending record remains auditable and does not dispatch. - [The bridge reports delivery success but notification fails] → Preserve `notification_failed` and do not attempt another item delivery. - [The bridge result is lost] → Persist terminal `unknown`, do not infer success, and require a deliberate later operator workflow rather than automatic retry. - [Two callers repeat a request] → Enforce a server/requester/idempotency-key uniqueness check and reuse the prior grant. ## Migration Plan 1. Add model-first records and repositories, then wire file/MySQL snapshots with no existing data migration required. 2. Deploy typed plugin catalog/delivery/notification schemas and Platform service/API support together; versions without a verified item catalog stay unsupported. 3. Deploy the console after APIs are available; hide all raw command details behind the API contracts. 4. Roll back by disabling the console/command declarations; immutable revision and grant history remains readable and no automatic replay is performed. ## Open Questions None. The initial SCUM version and item list are deliberately small and can be extended through a future reviewed catalog revision.