Skip to content

About

Web turn-based boardgame over battle of gettysburg

Resources

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

377 Commits

Folders and files

Repository files navigation

Gettysburg

Gettysburg is a browser-native, two-player adaptation of a turn-based hex-grid battle game. The project is intended to preserve the tabletop flow while adding modern multiplayer, saved games, server-authoritative state, and a clean user interface that can be self-hosted on the dedicated Gettysburg VPS.

The local project workspace contains supplied board, rules, and order-of-battle references that are deliberately ignored by Git. The repository contains only the approved implementation plan and rights-safe project work. The current application candidate enables mandatory Scenario Five for new games; complete phase/release acceptance remains tracked in ROADMAP.md and TASKS.md.

Current status

The latest reviewed deployment is d018e92 (2026-10-07). Road/rail movement and eligible reinforcement entry cost 1 for new games and the explicitly transitioned testing game. Earlier replay/costs and other saves are preserved. Game creation pauses at 90% host CPU or RAM; other abuse protections remain. Encrypted pre/post backups, exact-image scanning, transition verification, and public two-client smoke passed. See TASKS.md for evidence and rollback limits.

Reviewed PR #73 source 2990d8eb44f5b98b1fa96930234fb818382e7bc3 was deployed on 2026-10-06 after independent review, exact-head CI, vulnerability scanning, and verified encrypted backups. Per-game persistence replaces whole-service history rewriting. The owner-authorized purge removed 63 old development games; database volumes, credentials, audit history, and recovery backups were retained. Public desktop/tablet full 24-turn games now pass with unchanged bounds, reload, and exact replay. Move synchronization was observed at 248-260 ms instead of 5.36-5.87 seconds. Public readiness, two-client HTTPS/WebSocket checks, and restart/resume pass; gameplay is available for owner testing, not final release. Owner testing exposed a separate proxy source-attribution defect after the acceptance harness exhausted the creation budget. A controlled restart cleared that window without changing limits; proxy isolation remains an open repair. Phase 2 historical operational closeout remains complete. The deployed candidate uses gettysburg-mandatory-v5 / gettysburg-mandatory-board-v2 for new games, including weighted movement, continuous stack activation, reinforcement costs, connected terrain defense, retreat/advance, and mandatory night withdrawal. Saved versions are not silently reinterpreted. Dependency advisories were patched separately. Push remains disabled pending signing-key/provider setup. Retained-version replay, and Phase 4 release gates remain open. The owner accepted the board and rules on 2026-10-06; that approval does not close the remaining technical gates. See TASKS.md for dated evidence; this is a development deployment, not a claim of production readiness.

Project documents

  • PLAN.md - product direction, decisions, delivery strategy, and gates
  • SPEC.md - required behavior, architecture, security, and acceptance criteria
  • ROADMAP.md - ordered implementation phases and exit criteria
  • TASKS.md - current reviewable work and validation status
  • docs/operations/RELEASE_ACCEPTANCE.md - remaining owner/device/VPS checks
  • docs/references/SOURCE_ASSETS.md - local-only source inventory and missing inputs
  • docs/references/TERRAIN_ADJUSTMENTS.md - per-hex terrain/modifier owner-review worksheet
  • docs/operations/VPS.md - verified deployment target and operating model

Current technical direction

  • React, TypeScript, and Vite for the browser client
  • SVG for the first board renderer
  • Colyseus for authoritative multiplayer rooms
  • shared pure TypeScript rules and data packages
  • PostgreSQL for durable games and action logs
  • Caddy in front of rootless Podman Quadlet services on the VPS

The Phase 2 implementation provides the 82 available source-card counter fronts, 24 turns, reinforcement entry, automatic two-die combat results using verified unit factors, objective and casualty scoring, PostgreSQL state/actions/snapshots, restart-safe browser sessions, and a non-root production-shaped local container path. Reduced combat factors are owner-approved derived values: halve the full factor and round up, while a combat-one counter has one step and is eliminated by its first loss. All 253 owner-approved terrain records now feed rules and previews. Inferred movement/forest/hill connections and scenario adaptations are covered by the 2026-10-06 board/rules acceptance.

Development

Use Node.js 24 and pnpm 11.21.0, with Bash, coreutils/util-linux, and age (age plus age-keygen) available for local operations tests. These tests use temporary keys and controlled container/SSH boundaries, not the VPS. Install dependencies and run the terminating local gate with:

pnpm install --frozen-lockfile
pnpm format:check
pnpm lint
pnpm typecheck
pnpm test
pnpm build
pnpm smoke
pnpm exec playwright install --with-deps chromium
pnpm browser:acceptance
pnpm browser:movement
pnpm container:smoke

For interactive development, run pnpm dev. The web client listens on http://127.0.0.1:5173 and proxies health, readiness, and WebSocket traffic to the server on http://127.0.0.1:2567.

The browser acceptance command creates two isolated sessions at desktop and tablet widths and writes rights-safe board captures to test-results/browser-acceptance. pnpm browser:movement separately exercises mandatory-rule edge cases in clearly labelled development-only browser fixtures. Run GETTYSBURG_FULL_GAME=true pnpm browser:acceptance for the extended gate used in CI: two independent live combat games through turn 24, one using desktop keyboard controls and one using tablet touch. Both reload with server dice awaiting confirmation, resolve available combat choices, verify final and historical replay, and await durable cleanup. The games have an eight-minute per-game bound; commands are paced below the room's abuse limit even on fast runners. CI allows 25 minutes for these games plus the other required gates. These automated checks do not replace owner tabletop adjudication. Browser acceptance also records 20 click-to-confirmed-zoom/paint-opportunity samples at each layout in desktop-performance.json and tablet-performance.json. Strict mode (the default) fails the specified 100 ms feedback budget when exceeded. Shared CI explicitly sets GETTYSBURG_PERFORMANCE_MODE=report: misses retain their numeric evidence and warnings without failing otherwise complete interactions. Missing confirmation, input failure, and invalid configuration still fail in either mode. These are unthrottled test-machine measurements, not broadband-load, physical-device, cross-player-latency, or VPS-capacity claims. Release acceptance still requires GETTYSBURG_PERFORMANCE_MODE=strict on calibrated desktop hardware, recording hardware, OS/browser, workload, and evidence. A green report-mode CI run does not close that gate. Companion desktop-session-performance.json and tablet-session-performance.json record one initial-lobby, reload/reconnect, and input-to-both-player observation against the 3,000/5,000/500 ms targets. They include automation/render/network overhead and do not establish percentiles or isolate Internet latency.

GETTYSBURG_BROWSER=firefox GETTYSBURG_FULL_GAME=true pnpm browser:acceptance also passes locally at both widths with keyboard/mouse input. Chromium remains the default and supplies continuous tablet-touch and native notification-worker fixtures. The alternate-engine CI workflow additionally targets WebKit on Ubuntu; actual Safari/iPad and real push-provider behavior remain manual release gates. Locally managed WebKit runs use a task-owned HTTPS proxy (requires OpenSSL) so production Secure session cookies survive reload. Other engines can exercise that fixture with GETTYSBURG_BROWSER_HTTPS=true. Its self-signed certificate exception applies only to fixture browser contexts; explicitly configured remote origins retain certificate verification. No system trust store is changed. The private source scans and Battle Manual remain local and ignored.

On the board, drag any friendly counter to move its entire stack. Hold Ctrl before dragging to move only the grabbed counter, or Ctrl-click once to keep it in single-counter mode for a later drag. Use the group selector for other legal subsets. Repeated drags must retain the exact group until a different group moves; previous movers then cannot resume that phase. Roads/rails cost half a point outside enemy ZOC; other costs use the pinned terrain and connections.

Reinforcement controls select a single counter or common-entry group and show the actual entry cost and blocked-entry alternatives. Retreat controls offer legal next steps, undo, and confirmation, including trapped losses and permitted edge exits. Advance controls offer legal victorious groups and destinations or decline; normal movement spending does not restrict a free advance. Board shortcuts remain available. Night guidance names counters that must withdraw. All movement and combat choices are coordinate-entry-free.

Choose View replay to inspect verified mandatory-game history. Opening, previous/next, event-number, and latest controls reconstruct a historical board; you can inspect either side and pan/zoom, but cannot move counters or resolve combat there. Recorded dice are shown with each combat snapshot. Return to live game restores the current authoritative view. Closing replay cancels its pending request; a failed authorized read clears the displayed snapshot. Older tabletop rulesets currently fail closed for replay rather than use newer rules, and deleted games remain inaccessible.

Local container path

pnpm container:smoke builds the production-shaped image with Podman (or Docker when Podman is unavailable), proves the application runs with a nonzero UID/GID, checks PostgreSQL readiness and fail-closed mode, restarts the application, and proves the saved browser session resumes before clean shutdown.

For an interactive same-origin proxy path, run:

install -d -m 0700 .secrets
if [[ ! -s .secrets/postgres-password ]]; then
  umask 077
  openssl rand -hex 32 >.secrets/postgres-password
fi
chmod 0444 .secrets/postgres-password
podman compose up --build

The local Caddy endpoint is http://127.0.0.1:8080. The application container uses DATABASE_URL, a persistent GETTYSBURG_CREDENTIAL_PEPPER_FILE, GETTYSBURG_SERVER_HOST, GETTYSBURG_SERVER_PORT, the exact public origin in GETTYSBURG_TRUSTED_ORIGIN, and the readiness-test switch GETTYSBURG_REQUIRED_DEPENDENCY=unavailable. PostgreSQL and the credential pepper use private persistent volumes; no runtime secret is committed.

About

Web turn-based boardgame over battle of gettysburg

Resources

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Used by

Contributors

Languages