feat: implement and deploy blind_chess MVP
- pnpm workspace: shared/server/client packages - Server: Fastify+ws, chess.js, FSM (touch-move + hierarchy), per-player view filter, zod validation, rate limiting, grace-window disconnect handling - Client: Svelte 5 + Vite, click-to-move board, moderator panel, promotion/draw dialogs - Shared: protocol types, ModeratorText enum, geometricMoves helper (provably zero opponent-info leak) - 43 tests pass (21 shared, 22 server incl. 4 real-WS integration) - Deploy: CT 690 on node-241 (192.168.0.245), systemd-managed, Caddy block for chess.sethpc.xyz - Live at https://chess.sethpc.xyz Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import type { Chess } from 'chess.js';
|
||||
import type { WebSocket } from 'ws';
|
||||
import type {
|
||||
Announcement,
|
||||
Color,
|
||||
EndReason,
|
||||
GameId,
|
||||
GameStatus,
|
||||
Mode,
|
||||
PieceType,
|
||||
PlayerToken,
|
||||
PromotionType,
|
||||
Square,
|
||||
} from '@blind-chess/shared';
|
||||
|
||||
export interface MoveRecord {
|
||||
ply: number;
|
||||
by: Color;
|
||||
from: Square;
|
||||
to: Square;
|
||||
san: string;
|
||||
capturedPieceType?: PieceType;
|
||||
promotion?: PromotionType;
|
||||
flags: { castle?: 'k' | 'q'; enPassant?: boolean; check?: boolean; mate?: boolean };
|
||||
at: number;
|
||||
}
|
||||
|
||||
export interface PlayerSlot {
|
||||
token: PlayerToken;
|
||||
socket: WebSocket | null;
|
||||
joinedAt: number;
|
||||
rateBucket: { tokens: number; last: number };
|
||||
}
|
||||
|
||||
export interface Game {
|
||||
id: GameId;
|
||||
mode: Mode;
|
||||
highlightingEnabled: boolean;
|
||||
status: GameStatus;
|
||||
createdAt: number;
|
||||
finishedAt?: number;
|
||||
endReason?: EndReason;
|
||||
winner?: Color | null;
|
||||
|
||||
chess: Chess;
|
||||
moveHistory: MoveRecord[];
|
||||
announcements: Announcement[];
|
||||
|
||||
players: { w: PlayerSlot | null; b: PlayerSlot | null };
|
||||
|
||||
armed: { color: Color; from: Square } | null;
|
||||
drawOffer: { from: Color; at: number } | null;
|
||||
disconnectAt: { w?: number; b?: number };
|
||||
}
|
||||
|
||||
export const RATE_LIMIT = { capacity: 20, refillPerSec: 10 };
|
||||
export const GRACE_MS = 5 * 60 * 1000;
|
||||
export const PRUNE_AFTER_FINISHED_MS = 30 * 60 * 1000;
|
||||
Reference in New Issue
Block a user