@orakl/protocol 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -12,12 +12,13 @@ export * from "./pages/quiz.schema.ts";
12
12
  export type { PlayerSafeQuestion } from "./player-safe-question.ts";
13
13
  export { DifficultySchema, type ImageChoiceQuestion, type ImageMatchingQuestion, isHttpsUrl, type Media, MediaSchema, type MediaType, MediaTypeSchema, PostAnswerNoteSchema, type Question, QuestionSchema, type QuestionSource, QuestionSourceSchema, type QuestionType, QuestionTypeSchema, type Source, SourceSchema, type TextChoiceQuestion, type TrueFalseQuestion, } from "./question.schema.ts";
14
14
  export { hasMedia, isImageMatching, isTextChoice, isTrueFalse, } from "./question.ts";
15
+ export type { QuestionRating } from "./question-rating.ts";
15
16
  export { OptionalScoringModeSchema, ScoringModeSchema, } from "./scoring.schema.ts";
16
- export { type SoloAnswerChangeMessage, type SoloAnswerMessage, type SoloAuthMessage, type SoloClientMessage, type SoloErrorMessage, type SoloFinalMessage, type SoloGuestLimitMessage, type SoloLifeSpentMessage, type SoloNextMessage, type SoloPingMessage, type SoloPongMessage, type SoloQuestionMessage, type SoloReadyMessage, type SoloResumeMessage, type SoloRoundResultMessage, type SoloServerMessage, type SoloStartMessage, type SoloStreakBestMessage, type SoloStreakLostMessage, type SoloStreakMessage, type SoloStreakNearMissMessage, type SoloTabBlurMessage, type SoloTabFocusMessage, type SoloTickMessage, soloError, } from "./solo-ws.ts";
17
+ export { type SoloAnswerChangeMessage, type SoloAnswerMessage, type SoloAuthMessage, type SoloClientMessage, type SoloErrorMessage, type SoloFinalMessage, type SoloGuestLimitMessage, type SoloLifeSpentMessage, type SoloNextMessage, type SoloPingMessage, type SoloPongMessage, type SoloQuestionMessage, type SoloRateAckMessage, type SoloRateMessage, type SoloReadyMessage, type SoloResumeMessage, type SoloRoundResultMessage, type SoloServerMessage, type SoloStartMessage, type SoloStreakBestMessage, type SoloStreakLostMessage, type SoloStreakMessage, type SoloStreakNearMissMessage, type SoloTabBlurMessage, type SoloTabFocusMessage, type SoloTickMessage, soloError, } from "./solo-ws.ts";
17
18
  export type { StreakFlourish } from "./streak-flourish.ts";
18
19
  export type { LeaderboardBoard, LeaderboardDifficulty, LeaderboardScope, } from "./wire/leaderboard.ts";
19
20
  export type { OperatorQuestionRevision, PublishManyResult, QuestionRevision, } from "./wire/question-bank.ts";
20
21
  export type { FlagDetail, FlagReporter, FlagStatus, QuestionFlagAnswerSnapshot, QuestionSnapshot, } from "./wire/question-flags.ts";
21
- export type { ClientMessage, CuratorAdvanceMessage, CuratorIntermissionMessage, CuratorPlayerActionMessage, CuratorResetMessage, CuratorStartMessage, CuratorStartRoleSelectionMessage, CuratorStopMessage, GameErrorMessage, GameFinalScoresMessage, GameIntermissionMessage, GamePingMessage, GameQuestionMessage, GameResultsReadyMessage, GameResumeMessage, GameRoundResultMessage, GameStartMessage, GameTickMessage, JoinAcceptedMessage, JoinRejectedMessage, LobbyEndedMessage, LobbyResetMessage, LobbyUpdateMessage, PlayerAnsweredMessage, PlayerAnswerMessage, PlayerEmoteBroadcastMessage, PlayerEmoteMessage, PlayerLeaveMessage, PlayerNicknameChangedMessage, PlayerQuestionAnswer, PlayerRemovedMessage, PlayerRoleMessage, RoleSelectionLockedMessage, RoleSelectionStartMessage, RoleSelectionUpdateMessage, ServerMessage, WsAuthMessage, WsPongMessage, } from "./ws.ts";
22
+ export type { ClientMessage, CuratorAdvanceMessage, CuratorIntermissionMessage, CuratorPlayerActionMessage, CuratorResetMessage, CuratorStartMessage, CuratorStartRoleSelectionMessage, CuratorStopMessage, GameErrorMessage, GameFinalScoresMessage, GameIntermissionMessage, GamePingMessage, GameQuestionMessage, GameResultsReadyMessage, GameResumeMessage, GameRoundResultMessage, GameStartMessage, GameTickMessage, JoinAcceptedMessage, JoinRejectedMessage, LobbyEndedMessage, LobbyResetMessage, LobbyUpdateMessage, PlayerAnsweredMessage, PlayerAnswerMessage, PlayerEmoteBroadcastMessage, PlayerEmoteMessage, PlayerLeaveMessage, PlayerNicknameChangedMessage, PlayerQuestionAnswer, PlayerRateAckMessage, PlayerRateMessage, PlayerRemovedMessage, PlayerRoleMessage, RateAckReason, RoleSelectionLockedMessage, RoleSelectionStartMessage, RoleSelectionUpdateMessage, ServerMessage, WsAuthMessage, WsPongMessage, } from "./ws.ts";
22
23
  export { ClientMessageSchema } from "./ws-game.schema.ts";
23
24
  export { SoloClientMessageSchema } from "./ws-solo.schema.ts";
@@ -171,6 +171,48 @@ export declare const ManageFlaggedQuestionsPageSchema: Schema.Struct<{
171
171
  statusFilter: Schema.Literal<["open", "resolved", "all"]>;
172
172
  page: typeof Schema.Number;
173
173
  }>;
174
+ declare const QuestionRatingRowSchema: Schema.Struct<{
175
+ id: typeof Schema.String;
176
+ excerpt: typeof Schema.String;
177
+ source: Schema.Literal<["built-in", "promoted"]>;
178
+ category: typeof Schema.String;
179
+ down: typeof Schema.Number;
180
+ up: typeof Schema.Number;
181
+ downAllTime: typeof Schema.Number;
182
+ upAllTime: typeof Schema.Number;
183
+ edited: typeof Schema.Boolean;
184
+ openFlags: typeof Schema.Number;
185
+ }>;
186
+ /** One rated question on the ratings page: counts since the last edit and all-time, no rater identity. */
187
+ export type QuestionRatingRow = typeof QuestionRatingRowSchema.Type;
188
+ /** Body of `GET /api/pages/manage/question-ratings`. */
189
+ export declare const ManageQuestionRatingsPageSchema: Schema.Struct<{
190
+ initial: Schema.mutable<Schema.Array$<Schema.Schema<{
191
+ readonly source: "built-in" | "promoted";
192
+ readonly id: string;
193
+ readonly up: number;
194
+ readonly category: string;
195
+ readonly excerpt: string;
196
+ readonly down: number;
197
+ readonly downAllTime: number;
198
+ readonly upAllTime: number;
199
+ readonly edited: boolean;
200
+ readonly openFlags: number;
201
+ }, {
202
+ readonly source: "built-in" | "promoted";
203
+ readonly id: string;
204
+ readonly up: number;
205
+ readonly category: string;
206
+ readonly excerpt: string;
207
+ readonly down: number;
208
+ readonly downAllTime: number;
209
+ readonly upAllTime: number;
210
+ readonly edited: boolean;
211
+ readonly openFlags: number;
212
+ }, never>>>;
213
+ initialHasMore: typeof Schema.Boolean;
214
+ page: typeof Schema.Number;
215
+ }>;
174
216
  declare const AuthoredQuestionRowSchema: Schema.Struct<{
175
217
  id: typeof Schema.String;
176
218
  category: typeof Schema.String;
@@ -469,11 +511,23 @@ export declare const CuratorQuestionsPageSchema: Schema.Struct<{
469
511
  readonly label: string;
470
512
  readonly category: string;
471
513
  readonly created_at: string;
514
+ readonly ratings?: {
515
+ readonly up: number;
516
+ readonly down: number;
517
+ readonly downAllTime: number;
518
+ readonly upAllTime: number;
519
+ } | undefined;
472
520
  }, {
473
521
  readonly id: string;
474
522
  readonly label: string;
475
523
  readonly category: string;
476
524
  readonly created_at: string;
525
+ readonly ratings?: {
526
+ readonly up: number;
527
+ readonly down: number;
528
+ readonly downAllTime: number;
529
+ readonly upAllTime: number;
530
+ } | undefined;
477
531
  }, never>>>;
478
532
  questionsCursor: Schema.NullOr<typeof Schema.String>;
479
533
  }>;
@@ -137,6 +137,24 @@ export const ManageFlaggedQuestionsPageSchema = Schema.Struct({
137
137
  statusFilter: Schema.Literal("open", "resolved", "all"),
138
138
  page: Schema.Number,
139
139
  });
140
+ const QuestionRatingRowSchema = Schema.Struct({
141
+ id: Schema.String,
142
+ excerpt: Schema.String,
143
+ source: Schema.Literal("built-in", "promoted"),
144
+ category: Schema.String,
145
+ down: Schema.Number,
146
+ up: Schema.Number,
147
+ downAllTime: Schema.Number,
148
+ upAllTime: Schema.Number,
149
+ edited: Schema.Boolean,
150
+ openFlags: Schema.Number,
151
+ });
152
+ /** Body of `GET /api/pages/manage/question-ratings`. */
153
+ export const ManageQuestionRatingsPageSchema = Schema.Struct({
154
+ initial: Arr(QuestionRatingRowSchema),
155
+ initialHasMore: Schema.Boolean,
156
+ page: Schema.Number,
157
+ });
140
158
  const AuthoredQuestionRowSchema = Schema.Struct({
141
159
  id: Schema.String,
142
160
  category: Schema.String,
@@ -293,6 +311,13 @@ const OwnQuestionSchema = Schema.Struct({
293
311
  category: Schema.String,
294
312
  label: Schema.String,
295
313
  created_at: Schema.String,
314
+ /** Thumbs counts since the last edit and all-time; absent with the rating flag off. */
315
+ ratings: Schema.optional(Schema.Struct({
316
+ up: Schema.Number,
317
+ down: Schema.Number,
318
+ upAllTime: Schema.Number,
319
+ downAllTime: Schema.Number,
320
+ })),
296
321
  });
297
322
  /** Body of `GET /api/pages/curator/questions`. */
298
323
  export const CuratorQuestionsPageSchema = Schema.Struct({
@@ -41,6 +41,7 @@ export declare const LayoutPageSchema: Schema.Struct<{
41
41
  readonly IMAGE_QUIZ_CATEGORY?: boolean | undefined;
42
42
  readonly BADGE_DISPLAY?: boolean | undefined;
43
43
  readonly ROLE_SELECTION?: boolean | undefined;
44
+ readonly QUESTION_RATING?: boolean | undefined;
44
45
  }, {
45
46
  readonly FEEDBACK_WIDGET?: boolean | undefined;
46
47
  readonly ENABLE_IMPORTS?: boolean | undefined;
@@ -54,6 +55,7 @@ export declare const LayoutPageSchema: Schema.Struct<{
54
55
  readonly IMAGE_QUIZ_CATEGORY?: boolean | undefined;
55
56
  readonly BADGE_DISPLAY?: boolean | undefined;
56
57
  readonly ROLE_SELECTION?: boolean | undefined;
58
+ readonly QUESTION_RATING?: boolean | undefined;
57
59
  }, never>;
58
60
  }>;
59
61
  declare const PlayerJourneySchema: Schema.Struct<{
@@ -45,6 +45,7 @@ const UiFlagsSchema = Schema.partial(Schema.Struct({
45
45
  IMAGE_QUIZ_CATEGORY: Schema.Boolean,
46
46
  BADGE_DISPLAY: Schema.Boolean,
47
47
  ROLE_SELECTION: Schema.Boolean,
48
+ QUESTION_RATING: Schema.Boolean,
48
49
  }));
49
50
  /** Body of `GET /api/layout`. */
50
51
  export const LayoutPageSchema = Schema.Struct({
@@ -0,0 +1,2 @@
1
+ /** A Question rating's thumb: `"up"` is "Good question", `"down"` is "Bad question". */
2
+ export type QuestionRating = "up" | "down";
@@ -0,0 +1 @@
1
+ export {};
package/dist/solo-ws.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import type { BadgeAward } from "./badges.ts";
2
2
  import type { PlayerSafeQuestion } from "./player-safe-question.ts";
3
3
  import type { MediaType, QuestionSource } from "./question.ts";
4
+ import type { QuestionRating } from "./question-rating.ts";
5
+ import type { RateAckReason } from "./ws.ts";
4
6
  export type SoloAuthMessage = {
5
7
  type: "auth";
6
8
  token: string;
@@ -47,7 +49,16 @@ export type SoloResumeMessage = {
47
49
  /** Secret issued in solo:ready; required to resume a guest session (anti-hijack). */
48
50
  resumeToken?: string;
49
51
  };
50
- export type SoloClientMessage = SoloAuthMessage | SoloStartMessage | SoloAnswerMessage | SoloAnswerChangeMessage | SoloNextMessage | SoloTabBlurMessage | SoloTabFocusMessage | SoloPongMessage | SoloResumeMessage;
52
+ /** Rate a question revealed in this run (signed-in runs only). The server
53
+ * answers with `solo:rate-ack` echoing `questionId`; `reason: "disabled"`
54
+ * when the rating flag is off. */
55
+ export type SoloRateMessage = {
56
+ type: "solo:rate";
57
+ /** Bank question id, as on `solo:question`. */
58
+ questionId: string;
59
+ rating: QuestionRating;
60
+ };
61
+ export type SoloClientMessage = SoloAuthMessage | SoloStartMessage | SoloAnswerMessage | SoloAnswerChangeMessage | SoloNextMessage | SoloTabBlurMessage | SoloTabFocusMessage | SoloPongMessage | SoloResumeMessage | SoloRateMessage;
51
62
  export type SoloReadyMessage = {
52
63
  type: "solo:ready";
53
64
  isGuest: boolean;
@@ -199,4 +210,13 @@ export type SoloGuestLimitMessage = {
199
210
  reason: string;
200
211
  upgradeHint: string;
201
212
  };
202
- export type SoloServerMessage = SoloReadyMessage | SoloQuestionMessage | SoloTickMessage | SoloRoundResultMessage | SoloStreakMessage | SoloStreakLostMessage | SoloStreakNearMissMessage | SoloStreakBestMessage | SoloLifeSpentMessage | SoloFinalMessage | SoloPingMessage | SoloErrorMessage | SoloGuestLimitMessage;
213
+ /** Outcome of one `solo:rate`: `ok` is false when the rating was refused or
214
+ * not stored. Failures ride here, never on `solo:error`. */
215
+ export type SoloRateAckMessage = {
216
+ type: "solo:rate-ack";
217
+ questionId: string;
218
+ ok: boolean;
219
+ /** Set when the server refuses every rating because the flag is off. */
220
+ reason?: RateAckReason;
221
+ };
222
+ export type SoloServerMessage = SoloReadyMessage | SoloQuestionMessage | SoloTickMessage | SoloRoundResultMessage | SoloStreakMessage | SoloStreakLostMessage | SoloStreakNearMissMessage | SoloStreakBestMessage | SoloLifeSpentMessage | SoloFinalMessage | SoloPingMessage | SoloErrorMessage | SoloGuestLimitMessage | SoloRateAckMessage;
@@ -16,6 +16,10 @@ export declare const ClientMessageSchema: Schema.Union<[Schema.Struct<{
16
16
  role: Schema.Literal<["player", "observer"]>;
17
17
  }>, Schema.Struct<{
18
18
  type: Schema.Literal<["player:leave"]>;
19
+ }>, Schema.Struct<{
20
+ type: Schema.Literal<["player:rate"]>;
21
+ questionId: Schema.filter<typeof Schema.NonEmptyString>;
22
+ rating: Schema.Literal<["up", "down"]>;
19
23
  }>, Schema.Struct<{
20
24
  type: Schema.Literal<["curator:start"]>;
21
25
  categoryIds: Schema.optional<Schema.filter<Schema.Array$<typeof Schema.NonEmptyString>>>;
@@ -45,6 +45,11 @@ const PlayerRoleMessageSchema = Schema.Struct({
45
45
  const PlayerLeaveMessageSchema = Schema.Struct({
46
46
  type: Schema.Literal("player:leave"),
47
47
  });
48
+ const PlayerRateMessageSchema = Schema.Struct({
49
+ type: Schema.Literal("player:rate"),
50
+ questionId: BoundedIdSchema,
51
+ rating: Schema.Literal("up", "down"),
52
+ });
48
53
  // ─── curator:* ──────────────────────────────────────────────────────────────
49
54
  // QuestionType minus "image_matching" (mirrors StandardQuizQuestion).
50
55
  const StandardQuizQuestionTypeSchema = Schema.Literal("text_choice", "image_choice", "true_false", "finish_line", "audio_identify", "sequence_order", "estimate_range", "fill_blank", "matching_pairs", "progressive_reveal");
@@ -127,5 +132,5 @@ const WsPongMessageSchema = Schema.Struct({
127
132
  });
128
133
  // Discriminant: Effect Schema detects the shared `type: Schema.Literal(...)`
129
134
  // field and short-circuits matching — every member needs a unique `type`.
130
- export const ClientMessageSchema = Schema.Union(WsAuthMessageSchema, PlayerAnswerMessageSchema, PlayerEmoteMessageSchema, PlayerRoleMessageSchema, PlayerLeaveMessageSchema, CuratorStartMessageSchema, CuratorAdvanceMessageSchema, CuratorStartRoleSelectionMessageSchema, CuratorIntermissionMessageSchema, CuratorPlayerActionMessageSchema, CuratorStopMessageSchema, CuratorResetMessageSchema, WsPongMessageSchema);
135
+ export const ClientMessageSchema = Schema.Union(WsAuthMessageSchema, PlayerAnswerMessageSchema, PlayerEmoteMessageSchema, PlayerRoleMessageSchema, PlayerLeaveMessageSchema, PlayerRateMessageSchema, CuratorStartMessageSchema, CuratorAdvanceMessageSchema, CuratorStartRoleSelectionMessageSchema, CuratorIntermissionMessageSchema, CuratorPlayerActionMessageSchema, CuratorStopMessageSchema, CuratorResetMessageSchema, WsPongMessageSchema);
131
136
  const _assertNoClientMessageDrift = null;
@@ -28,4 +28,8 @@ export declare const SoloClientMessageSchema: Schema.Union<[Schema.Struct<{
28
28
  type: Schema.Literal<["solo:resume"]>;
29
29
  sessionId: Schema.filter<typeof Schema.NonEmptyString>;
30
30
  resumeToken: Schema.optional<Schema.filter<typeof Schema.NonEmptyString>>;
31
+ }>, Schema.Struct<{
32
+ type: Schema.Literal<["solo:rate"]>;
33
+ questionId: Schema.filter<typeof Schema.NonEmptyString>;
34
+ rating: Schema.Literal<["up", "down"]>;
31
35
  }>]>;
@@ -51,7 +51,12 @@ const SoloResumeMessageSchema = Schema.Struct({
51
51
  sessionId: BoundedIdSchema,
52
52
  resumeToken: Schema.optional(BoundedIdSchema),
53
53
  });
54
+ const SoloRateMessageSchema = Schema.Struct({
55
+ type: Schema.Literal("solo:rate"),
56
+ questionId: BoundedIdSchema,
57
+ rating: Schema.Literal("up", "down"),
58
+ });
54
59
  // Discriminant: Effect Schema detects the shared `type: Schema.Literal(...)`
55
60
  // field and short-circuits matching — every member needs a unique `type`.
56
- export const SoloClientMessageSchema = Schema.Union(SoloAuthMessageSchema, SoloStartMessageSchema, SoloAnswerMessageSchema, SoloAnswerChangeMessageSchema, SoloNextMessageSchema, SoloTabBlurMessageSchema, SoloTabFocusMessageSchema, SoloPongMessageSchema, SoloResumeMessageSchema);
61
+ export const SoloClientMessageSchema = Schema.Union(SoloAuthMessageSchema, SoloStartMessageSchema, SoloAnswerMessageSchema, SoloAnswerChangeMessageSchema, SoloNextMessageSchema, SoloTabBlurMessageSchema, SoloTabFocusMessageSchema, SoloPongMessageSchema, SoloResumeMessageSchema, SoloRateMessageSchema);
57
62
  const _assertNoSoloClientMessageDrift = null;
package/dist/ws.d.ts CHANGED
@@ -4,8 +4,9 @@ import type { AdvanceMode, Difficulty, DifficultyFilter, ScoringMode, TimerDurat
4
4
  import type { Player, PlayerRole, QuizQuestion } from "./game.ts";
5
5
  import type { GameAnswerRecord } from "./game-answer-record.ts";
6
6
  import type { MediaType, QuestionType } from "./question.schema.ts";
7
+ import type { QuestionRating } from "./question-rating.ts";
7
8
  import type { StreakFlourish } from "./streak-flourish.ts";
8
- export type ClientMessage = WsAuthMessage | PlayerAnswerMessage | PlayerEmoteMessage | PlayerRoleMessage | PlayerLeaveMessage | CuratorStartMessage | CuratorAdvanceMessage | CuratorStartRoleSelectionMessage | CuratorIntermissionMessage | CuratorPlayerActionMessage | CuratorStopMessage | CuratorResetMessage | WsPongMessage;
9
+ export type ClientMessage = WsAuthMessage | PlayerAnswerMessage | PlayerEmoteMessage | PlayerRoleMessage | PlayerLeaveMessage | PlayerRateMessage | CuratorStartMessage | CuratorAdvanceMessage | CuratorStartRoleSelectionMessage | CuratorIntermissionMessage | CuratorPlayerActionMessage | CuratorStopMessage | CuratorResetMessage | WsPongMessage;
9
10
  /** First frame for native/display (cross-origin, no cookie): authenticates the
10
11
  * socket with the bearer game token (ADR 0014). Web rides the cookie instead. */
11
12
  export interface WsAuthMessage {
@@ -34,6 +35,15 @@ export interface PlayerRoleMessage {
34
35
  export interface PlayerLeaveMessage {
35
36
  type: "player:leave";
36
37
  }
38
+ /** Rate a question revealed in this game — from a signed-in player who played
39
+ * its round, or the curator. The server answers with `player:rate-ack`
40
+ * echoing `questionId`; `reason: "disabled"` when the rating flag is off. */
41
+ export interface PlayerRateMessage {
42
+ type: "player:rate";
43
+ /** Bank question id, as on `game:question`. */
44
+ questionId: string;
45
+ rating: QuestionRating;
46
+ }
37
47
  /** Curator starts the game. Questions are drawn server-side from categories,
38
48
  * or taken from a curator-side import (preloadedQuestions). */
39
49
  export interface CuratorStartMessage {
@@ -76,7 +86,7 @@ export interface CuratorPlayerActionMessage {
76
86
  export interface WsPongMessage {
77
87
  type: "pong";
78
88
  }
79
- export type ServerMessage = JoinAcceptedMessage | JoinRejectedMessage | LobbyUpdateMessage | LobbyEndedMessage | LobbyResetMessage | PlayerNicknameChangedMessage | GameStartMessage | GameQuestionMessage | GameTickMessage | PlayerAnsweredMessage | GameRoundResultMessage | GameFinalScoresMessage | GameResultsReadyMessage | RoleSelectionStartMessage | RoleSelectionUpdateMessage | RoleSelectionLockedMessage | PlayerRemovedMessage | GameIntermissionMessage | GameResumeMessage | PlayerEmoteBroadcastMessage | GameErrorMessage | GamePingMessage;
89
+ export type ServerMessage = JoinAcceptedMessage | JoinRejectedMessage | LobbyUpdateMessage | LobbyEndedMessage | LobbyResetMessage | PlayerNicknameChangedMessage | GameStartMessage | GameQuestionMessage | GameTickMessage | PlayerAnsweredMessage | GameRoundResultMessage | GameFinalScoresMessage | GameResultsReadyMessage | RoleSelectionStartMessage | RoleSelectionUpdateMessage | RoleSelectionLockedMessage | PlayerRemovedMessage | GameIntermissionMessage | GameResumeMessage | PlayerEmoteBroadcastMessage | GameErrorMessage | GamePingMessage | PlayerRateAckMessage;
80
90
  export interface JoinAcceptedMessage {
81
91
  type: "join:accepted";
82
92
  playerId: string;
@@ -279,3 +289,15 @@ export interface GameErrorMessage {
279
289
  /** Human-readable fallback when the UI has no copy for `code`. */
280
290
  message: string;
281
291
  }
292
+ /** Why a rate ack failed for every rating alike: the flag is off. */
293
+ export type RateAckReason = "disabled";
294
+ /** Outcome of one `player:rate`, to the rater only: `ok` is false when the
295
+ * rating was refused or not stored. Failures ride here, never on
296
+ * `game:error`, which carries no request id. */
297
+ export interface PlayerRateAckMessage {
298
+ type: "player:rate-ack";
299
+ questionId: string;
300
+ ok: boolean;
301
+ /** Set when the server refuses every rating because the flag is off. */
302
+ reason?: RateAckReason;
303
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orakl/protocol",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Orakl wire contract: WebSocket frames and API response schemas.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {