Phase 28 (Step 2): FBS schemas + message-type constants for mail
Tests · UI / test (push) Has been cancelled
Tests · Go / test (pull_request) Successful in 2m4s
Tests · Go / test (push) Successful in 2m5s
Tests · Integration / integration (pull_request) Successful in 1m54s
Tests · UI / test (pull_request) Successful in 2m50s
Tests · UI / test (push) Has been cancelled
Tests · Go / test (pull_request) Successful in 2m4s
Tests · Go / test (push) Successful in 2m5s
Tests · Integration / integration (pull_request) Successful in 1m54s
Tests · UI / test (pull_request) Successful in 2m50s
Adds the wire schema for the eight `user.games.mail.*` ConnectRPC commands together with the shared payload types (`MailMessage`, `MailRecipientState`, `MailBroadcastReceipt`). Send-request tables carry the optional `recipient_race_name` introduced in Step 1. Drops: - `pkg/schema/fbs/diplomail.fbs` — schema sources; - `pkg/schema/fbs/diplomail/*.go` — generated Go bindings (flatc `--go --go-module-name galaxy/schema/fbs`); - `pkg/model/diplomail/diplomail.go` — message-type catalog used by the gateway router; - `ui/frontend/src/proto/galaxy/fbs/diplomail/*.ts` — generated TS bindings consumed by the upcoming UI client wrapper; - `ui/Makefile` `FBS_INPUTS` extended to pick the new schema up on the next `make -C ui fbs-ts` run. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
// diplomail contains FlatBuffers payloads used by the authenticated
|
||||
// gateway boundary for the in-game diplomatic-mail subsystem. The
|
||||
// wire shapes here mirror the trusted internal
|
||||
// `/api/v1/user/games/{game_id}/mail/*` REST surface; gateway derives
|
||||
// the calling `user_id` from the verified session and forwards it as
|
||||
// `X-User-Id` to backend.
|
||||
|
||||
include "common.fbs";
|
||||
|
||||
namespace diplomail;
|
||||
|
||||
// MailMessage stores one inbox / sent-list / message-detail row. The
|
||||
// fields mirror `UserMailMessageDetail` in `backend/openapi.yaml`
|
||||
// with the following encoding rules:
|
||||
//
|
||||
// - `*_user_id` fields are RFC 4122 string UUIDs ("" means absent
|
||||
// for nullable fields such as `sender_user_id`).
|
||||
// - `*_at_ms` fields carry Unix milliseconds; `0` means the
|
||||
// timestamp is absent (e.g. an unread message has
|
||||
// `read_at_ms == 0`).
|
||||
// - `translated_*`, `translation_lang`, and `translator` are set
|
||||
// when the backend served a cached rendering into the caller's
|
||||
// preferred language; empty otherwise.
|
||||
// - `sender_race_name` is the snapshot of the sender's race name
|
||||
// in this game at send time. Present for `sender_kind="player"`
|
||||
// messages when the sender had an active membership; absent for
|
||||
// admin and system messages. The in-game UI keys per-race
|
||||
// threading on this field.
|
||||
table MailMessage {
|
||||
message_id:string;
|
||||
game_id:string;
|
||||
game_name:string;
|
||||
kind:string;
|
||||
sender_kind:string;
|
||||
sender_user_id:string;
|
||||
sender_username:string;
|
||||
sender_race_name:string;
|
||||
subject:string;
|
||||
body:string;
|
||||
body_lang:string;
|
||||
broadcast_scope:string;
|
||||
created_at_ms:int64;
|
||||
recipient_user_id:string;
|
||||
recipient_user_name:string;
|
||||
recipient_race_name:string;
|
||||
read_at_ms:int64;
|
||||
deleted_at_ms:int64;
|
||||
translated_subject:string;
|
||||
translated_body:string;
|
||||
translation_lang:string;
|
||||
translator:string;
|
||||
}
|
||||
|
||||
// MailRecipientState mirrors the `UserMailRecipientState` payload
|
||||
// returned from mark-read and soft-delete endpoints. Same timestamp
|
||||
// conventions as `MailMessage`.
|
||||
table MailRecipientState {
|
||||
message_id:string;
|
||||
read_at_ms:int64;
|
||||
deleted_at_ms:int64;
|
||||
}
|
||||
|
||||
// MailBroadcastReceipt mirrors `UserMailBroadcastReceipt`. Returned
|
||||
// from broadcast sends (paid-tier and admin); `recipient_count` is
|
||||
// the number of recipient rows the server materialised.
|
||||
table MailBroadcastReceipt {
|
||||
message_id:string;
|
||||
game_id:string;
|
||||
game_name:string;
|
||||
kind:string;
|
||||
sender_kind:string;
|
||||
subject:string;
|
||||
body:string;
|
||||
body_lang:string;
|
||||
broadcast_scope:string;
|
||||
created_at_ms:int64;
|
||||
recipient_count:int32;
|
||||
}
|
||||
|
||||
// InboxRequest stores the read-side request for the caller's inbox
|
||||
// in `game_id`. Backend filters to messages with `available_at` set
|
||||
// (translation completed when the recipient's preferred language
|
||||
// differs from the body language).
|
||||
table InboxRequest {
|
||||
game_id:common.UUID (required);
|
||||
}
|
||||
|
||||
// InboxResponse stores the resulting inbox list, newest first.
|
||||
// `items` is empty when the caller has no available messages in
|
||||
// this game.
|
||||
table InboxResponse {
|
||||
items:[MailMessage];
|
||||
}
|
||||
|
||||
// SentRequest stores the read-side request for the caller's sent
|
||||
// personal messages in `game_id`. Admin / system rows are not
|
||||
// included.
|
||||
table SentRequest {
|
||||
game_id:common.UUID (required);
|
||||
}
|
||||
|
||||
// SentResponse stores the caller's outgoing personal-message list.
|
||||
// Each `MailMessage` carries the original recipient snapshot.
|
||||
table SentResponse {
|
||||
items:[MailMessage];
|
||||
}
|
||||
|
||||
// MessageGetRequest stores the read-side request for a single
|
||||
// message detail. The caller must be a recipient of the message.
|
||||
table MessageGetRequest {
|
||||
game_id:common.UUID (required);
|
||||
message_id:common.UUID (required);
|
||||
}
|
||||
|
||||
// MessageGetResponse stores the fully decorated message detail
|
||||
// including any cached translation into the caller's preferred
|
||||
// language.
|
||||
table MessageGetResponse {
|
||||
message:MailMessage;
|
||||
}
|
||||
|
||||
// SendRequest stores the write-side request for a single-recipient
|
||||
// personal send. Exactly one of `recipient_user_id` /
|
||||
// `recipient_race_name` must be supplied; the empty string means
|
||||
// "use the other field".
|
||||
table SendRequest {
|
||||
game_id:common.UUID (required);
|
||||
recipient_user_id:string;
|
||||
recipient_race_name:string;
|
||||
subject:string;
|
||||
body:string;
|
||||
}
|
||||
|
||||
// SendResponse echoes the freshly inserted message detail.
|
||||
table SendResponse {
|
||||
message:MailMessage;
|
||||
}
|
||||
|
||||
// BroadcastRequest stores the paid-tier player broadcast. The
|
||||
// recipient set is always "every other active member of the game".
|
||||
table BroadcastRequest {
|
||||
game_id:common.UUID (required);
|
||||
subject:string;
|
||||
body:string;
|
||||
}
|
||||
|
||||
// BroadcastResponse stores the receipt returned by the server.
|
||||
table BroadcastResponse {
|
||||
receipt:MailBroadcastReceipt;
|
||||
}
|
||||
|
||||
// AdminRequest stores the owner-only admin send. `target="user"`
|
||||
// requires exactly one of `recipient_user_id` / `recipient_race_name`;
|
||||
// `target="all"` accepts the optional `recipients` scope (default
|
||||
// `active`).
|
||||
table AdminRequest {
|
||||
game_id:common.UUID (required);
|
||||
target:string;
|
||||
recipient_user_id:string;
|
||||
recipient_race_name:string;
|
||||
recipients:string;
|
||||
subject:string;
|
||||
body:string;
|
||||
}
|
||||
|
||||
// AdminResponse carries the result of an admin send. When the
|
||||
// request had `target="user"`, `message` is set; when `target="all"`,
|
||||
// `receipt` is set. Callers branch on which field is present.
|
||||
table AdminResponse {
|
||||
message:MailMessage;
|
||||
receipt:MailBroadcastReceipt;
|
||||
}
|
||||
|
||||
// ReadRequest stores the mark-read intent for a single message. The
|
||||
// caller must be a recipient. Idempotent.
|
||||
table ReadRequest {
|
||||
game_id:common.UUID (required);
|
||||
message_id:common.UUID (required);
|
||||
}
|
||||
|
||||
// ReadResponse echoes the recipient state after the operation.
|
||||
table ReadResponse {
|
||||
state:MailRecipientState;
|
||||
}
|
||||
|
||||
// DeleteRequest stores the soft-delete intent for a single message.
|
||||
// The message must already be marked read (HTTP 409 otherwise).
|
||||
table DeleteRequest {
|
||||
game_id:common.UUID (required);
|
||||
message_id:common.UUID (required);
|
||||
}
|
||||
|
||||
// DeleteResponse echoes the recipient state after the operation.
|
||||
table DeleteResponse {
|
||||
state:MailRecipientState;
|
||||
}
|
||||
Reference in New Issue
Block a user