openvibers/openvibe.casino Commits
AGENTS.md: the context an agent starts from (#121)
Changes
nnew file mode 100644@@@ -0,0 +1,143 @@++# AGENTS.md — OpenVibe.Casino++++## Project overview++++"Learn it, play it, never pay it." Every casino game with its insides showing: the rules, the exact++odds and what each bet costs, tables playable with chips worth nothing, and a simulator that runs a++million rounds in the browser. Node.js/Express, PostgreSQL (optional identity state), CommonJS, no++build step.++++- Origin `https://openvibe.casino`, port `5210`, service id `casino`, env prefix `CASINO`, unit++ `openvibe-casino.service`, release root `/opt/openvibe.casino`.++- **No real money, ever.** Play chips are free (1,000 a day), live in the player's browser, and cannot++ be bought, sold, won as anything or cashed out. No operator listings and no affiliate links until the++ owner's legal review. The tables sit behind a self-declared 18+ gate, remind a player every 30++ minutes, and every page carries one calm line pointing at free help (1-800-GAMBLER, BeGambleAware,++ Gamblers Anonymous).++++## What it owns++++- The pure, deterministic game engines in [engine/](engine/): `blackjack.js` (6 decks, S17, DAS, split++ to 4, split aces one card, peek, insurance, 3:2), `roulette.js` (European/American, every layout++ bet), `baccarat.js` (punto banco, third-card tableau, 5% commission), `craps.js` (pass/don't pass,++ 3-4-5x odds, place, field), `slots.js` (three 24-stop reels, a paytable). `engine/rng.js` is a seeded++ mulberry32; `engine/games.js` is the catalogue every page and the API read.++- Every edge/odds figure on the site and in the API, computed from the engines — no edge is typed in.++- The pages and API: `/`, `/play`, `/play/:game`, `/learn`, `/learn/:game`, `/simulate`, `/s/:id`++ (shared run, noindex), `/safe`, `/developers`, `GET /api/v1/*` (open, no key), `/engine/*` (the UMD++ files).++- The simulator ([server/sims.js](server/sims.js) for shared runs; `public/js/sim-worker.js` in the++ browser), the 18+ gate, contrast/`prefers-reduced-motion` behaviour and the safe-play copy.++- Account-data receipts and telemetry; a small PostgreSQL database for shared runs and receipts.++++Not owned: money, balances, purchases, cashouts (Billing owns money and this product must never touch++it), any gambling operator's listing, identity (Network).++++## Who calls it, and whom it calls++++- Callers: people in the browser; the open API and the shared-run pages; sites linking to `/learn`;++ OpenVibe's launcher/discovery.++- Depends on: **Network** for optional SSO (OAuth client `casino`, PKCE) and account export/deletion++ events; PostgreSQL and Valkey for shared runs/limits; `openvibe-shared` for the Frame, legal, SEO and++ `/shared/*`. It does **not** call Billing, Live, AI or any gaming provider.++- The API is open and keyless by design (the README says so); it serves probabilities and simulations,++ never a player's balance.++++## Repository map++++- **Entry:** [server/index.js](server/index.js) — `createApp()`, listen, key warm-up, graceful stop.++- **App:** [server/app.js](server/app.js) — helmet/CSP, `/auth`, `/internal/events`, `/shared`,++ `/engine`, `/api/v1`, pages, machine endpoints.++- **Config/db:** [server/config.js](server/config.js), [server/db.js](server/db.js).++- **Sims and storage:** [server/sims.js](server/sims.js), [server/db.js](server/db.js).++- **HTTP:** [server/http/api.js](server/http/api.js), `pages.js`, `principal.js`, `discovery.js`,++ `router.js`; views [server/views/index.js](server/views/index.js), `server/render/`.++- **Engines:** [engine/](engine/) — `rng.js`, `blackjack.js`, `roulette.js`, `baccarat.js`, `craps.js`,++ `slots.js`, `games.js`; UMD so the same file runs on the server, at the table and in the worker.++- **Browser:** [public/js/table.js](public/js/table.js), `casino.js` (the chips), `simulate.js`,++ `sim-worker.js`; [public/css/casino.css](public/css/casino.css).++- **Deploy:** [deploy/systemd/openvibe-casino.service](deploy/systemd/openvibe-casino.service),++ [deploy/nginx/openvibe.casino.conf](deploy/nginx/openvibe.casino.conf).++++## Commands++++```bash++npm install++npm run dev # NODE_ENV=development node server/index.js++npm start # node server/index.js, http://127.0.0.1:5210++npm test # test/run.js, PGlite, mock Network, fixture games++npm run test:pg # same on PostgreSQL (CASINO_TEST_STORE=pg)++npm test -- engines # filter by file name; --strict makes a skip fail++ov test # the harness's sharded run of what the change reaches++```++++## Database and migrations++++One migration ([migrations/0001_initial.sql](migrations/0001_initial.sql)) for shared simulations and++account-data receipts; PGlite in development/tests, PostgreSQL in production through++`openvibe-sdk/db`/`DATABASE_URL`. Play chips are **not** in the database — they live in the player's++browser. Never edit an applied migration; add a new number. No table stores a real balance.++++## Auth and the 18+ gate++++- The games and `/api/v1` are open and need no account; a signed-in person is only used for shared++ runs and account export/deletion. Network SSO is optional (OAuth client `casino`, PKCE).++- The 18+ gate is self-declared and stored in the browser; it is not an age verification. The 30-minute++ reminder and the help line are product requirements, not decoration.++- Service tokens, if added, need a `casino.*` capability from `openvibe-contracts`; today there is no++ money or account operation to authorize.++++## Frontend loading model++++Server-rendered pages plus plain browser modules: [public/js/table.js](public/js/table.js) plays,++[public/js/casino.js](public/js/casino.js) holds the chips, [public/js/simulate.js](public/js/simulate.js)++with `public/js/sim-worker.js` simulates in a Web Worker. The engines are UMD and shared by server,++page and worker, so a rule cannot drift between the demonstration and the simulator. No SPA, bundler++or transpiler; `openvibe-shared` supplies the Frame/legal/SEO and `/shared/*`.++++## Deploy++++Unit [deploy/systemd/openvibe-casino.service](deploy/systemd/openvibe-casino.service) runs++`/opt/openvibe.casino/server/index.js` on `127.0.0.1:5210`, env `/etc/openvibe/casino.env`; vhost++[deploy/nginx/openvibe.casino.conf](deploy/nginx/openvibe.casino.conf). The README records the deploy++files, not a live `ovhost` command; use the host's own installer. A change is frontend + server only;++there is no money migration to run.++++## Tests++++`npm test` runs each `test/*.test.js` in its own process with a temp PGlite and a mock Network.++`test/engines.test.js` checks **every published edge/RTP** against Wizard of Odds (basic-strategy++0.40%, roulette 2.70/5.26/7.89%, baccarat 1.06/1.24/14.36%, slots 93.63%); `test/contrast.test.js`++pins readable colours; `test/account-data.test.js` the export/deletion; `test/agent-*.test.js` the++agent descriptor/twins. `ov test` runs the same.++++## Conventions++++- CommonJS on the server, UMD in `engine/`; 4-space indent, single quotes, semicolons; factories with++ injectable config/clock/fetch/log.++- Numbers that a player might rely on are **computed by the engine** and tested against a published++ source; never hard-code an edge in a page or in `server/`.++- Copy is calm, short and honest: "Expiry unknown" style rules apply to odds too — an unstated number++ is not guessed.++- Accessibility: contrast, focus and reduced motion are part of the product; the 18+ gate must be++ reachable by keyboard.++++## Pitfalls++++- **No real money and no affiliate/operator links** until the owner's legal review; adding a purchase,++ balance, cashout or referral path is out of bounds and Billing is not a dependency.++- **Do not type an edge or RTP into a view.** It comes from `engine/games.js`/the engines and is++ checked by `test/engines.test.js`; a copied figure will drift.++- **Play chips never leave the browser.** Do not add a server balance, leaderboard prize or transfer.++- **The 18+ gate, the 30-minute reminder and the help line are required** on every play page; a new++ table that omits them is a bug.++- **Keep the engines deterministic from a seed** and free of browser/Node globals in their core; the++ same file must run in the worker and on the server.++- **Shared runs are noindex** (`/s/:id`) and contain no personal data.++- **Do not use a dark pattern** (fake urgency, "hot" streaks) — the product is a teaching tool.++++## Documentation++++- [README.md](README.md) — the engines and their edges, pages, API, data and deploy files.++- [STATUS.json](STATUS.json) — what works and what does not.++- The new-domains plan §5.14 is the product brief; `openvibe-contracts` holds any `casino.*` shapes.nnew file mode 100644@@@ -0,0 +1 @@
new file mode 100644
new file mode 100644
@@ -0,0 +1,143 @@
@@ -0,0 +1,143 @@
+# AGENTS.md — OpenVibe.Casino
+
+## Project overview
+
+"Learn it, play it, never pay it." Every casino game with its insides showing: the rules, the exact
+odds and what each bet costs, tables playable with chips worth nothing, and a simulator that runs a
+million rounds in the browser. Node.js/Express, PostgreSQL (optional identity state), CommonJS, no
+build step.
+
+- Origin `https://openvibe.casino`, port `5210`, service id `casino`, env prefix `CASINO`, unit
+ `openvibe-casino.service`, release root `/opt/openvibe.casino`.
+- **No real money, ever.** Play chips are free (1,000 a day), live in the player's browser, and cannot
+ be bought, sold, won as anything or cashed out. No operator listings and no affiliate links until the
+ owner's legal review. The tables sit behind a self-declared 18+ gate, remind a player every 30
+ minutes, and every page carries one calm line pointing at free help (1-800-GAMBLER, BeGambleAware,
+ Gamblers Anonymous).
+
+## What it owns
+
+- The pure, deterministic game engines in [engine/](engine/): `blackjack.js` (6 decks, S17, DAS, split
+ to 4, split aces one card, peek, insurance, 3:2), `roulette.js` (European/American, every layout
+ bet), `baccarat.js` (punto banco, third-card tableau, 5% commission), `craps.js` (pass/don't pass,
+ 3-4-5x odds, place, field), `slots.js` (three 24-stop reels, a paytable). `engine/rng.js` is a seeded
+ mulberry32; `engine/games.js` is the catalogue every page and the API read.
+- Every edge/odds figure on the site and in the API, computed from the engines — no edge is typed in.
+- The pages and API: `/`, `/play`, `/play/:game`, `/learn`, `/learn/:game`, `/simulate`, `/s/:id`
+ (shared run, noindex), `/safe`, `/developers`, `GET /api/v1/*` (open, no key), `/engine/*` (the UMD
+ files).
+- The simulator ([server/sims.js](server/sims.js) for shared runs; `public/js/sim-worker.js` in the
+ browser), the 18+ gate, contrast/`prefers-reduced-motion` behaviour and the safe-play copy.
+- Account-data receipts and telemetry; a small PostgreSQL database for shared runs and receipts.
+
+Not owned: money, balances, purchases, cashouts (Billing owns money and this product must never touch
+it), any gambling operator's listing, identity (Network).
+
+## Who calls it, and whom it calls
+
+- Callers: people in the browser; the open API and the shared-run pages; sites linking to `/learn`;
+ OpenVibe's launcher/discovery.
+- Depends on: **Network** for optional SSO (OAuth client `casino`, PKCE) and account export/deletion
+ events; PostgreSQL and Valkey for shared runs/limits; `openvibe-shared` for the Frame, legal, SEO and
+ `/shared/*`. It does **not** call Billing, Live, AI or any gaming provider.
+- The API is open and keyless by design (the README says so); it serves probabilities and simulations,
+ never a player's balance.
+
+## Repository map
+
+- **Entry:** [server/index.js](server/index.js) — `createApp()`, listen, key warm-up, graceful stop.
+- **App:** [server/app.js](server/app.js) — helmet/CSP, `/auth`, `/internal/events`, `/shared`,
+ `/engine`, `/api/v1`, pages, machine endpoints.
+- **Config/db:** [server/config.js](server/config.js), [server/db.js](server/db.js).
+- **Sims and storage:** [server/sims.js](server/sims.js), [server/db.js](server/db.js).
+- **HTTP:** [server/http/api.js](server/http/api.js), `pages.js`, `principal.js`, `discovery.js`,
+ `router.js`; views [server/views/index.js](server/views/index.js), `server/render/`.
+- **Engines:** [engine/](engine/) — `rng.js`, `blackjack.js`, `roulette.js`, `baccarat.js`, `craps.js`,
+ `slots.js`, `games.js`; UMD so the same file runs on the server, at the table and in the worker.
+- **Browser:** [public/js/table.js](public/js/table.js), `casino.js` (the chips), `simulate.js`,
+ `sim-worker.js`; [public/css/casino.css](public/css/casino.css).
+- **Deploy:** [deploy/systemd/openvibe-casino.service](deploy/systemd/openvibe-casino.service),
+ [deploy/nginx/openvibe.casino.conf](deploy/nginx/openvibe.casino.conf).
+
+## Commands
+
+```bash
+npm install
+npm run dev # NODE_ENV=development node server/index.js
+npm start # node server/index.js, http://127.0.0.1:5210
+npm test # test/run.js, PGlite, mock Network, fixture games
+npm run test:pg # same on PostgreSQL (CASINO_TEST_STORE=pg)
+npm test -- engines # filter by file name; --strict makes a skip fail
+ov test # the harness's sharded run of what the change reaches
+```
+
+## Database and migrations
+
+One migration ([migrations/0001_initial.sql](migrations/0001_initial.sql)) for shared simulations and
+account-data receipts; PGlite in development/tests, PostgreSQL in production through
+`openvibe-sdk/db`/`DATABASE_URL`. Play chips are **not** in the database — they live in the player's
+browser. Never edit an applied migration; add a new number. No table stores a real balance.
+
+## Auth and the 18+ gate
+
+- The games and `/api/v1` are open and need no account; a signed-in person is only used for shared
+ runs and account export/deletion. Network SSO is optional (OAuth client `casino`, PKCE).
+- The 18+ gate is self-declared and stored in the browser; it is not an age verification. The 30-minute
+ reminder and the help line are product requirements, not decoration.
+- Service tokens, if added, need a `casino.*` capability from `openvibe-contracts`; today there is no
+ money or account operation to authorize.
+
+## Frontend loading model
+
+Server-rendered pages plus plain browser modules: [public/js/table.js](public/js/table.js) plays,
+[public/js/casino.js](public/js/casino.js) holds the chips, [public/js/simulate.js](public/js/simulate.js)
+with `public/js/sim-worker.js` simulates in a Web Worker. The engines are UMD and shared by server,
+page and worker, so a rule cannot drift between the demonstration and the simulator. No SPA, bundler
+or transpiler; `openvibe-shared` supplies the Frame/legal/SEO and `/shared/*`.
+
+## Deploy
+
+Unit [deploy/systemd/openvibe-casino.service](deploy/systemd/openvibe-casino.service) runs
+`/opt/openvibe.casino/server/index.js` on `127.0.0.1:5210`, env `/etc/openvibe/casino.env`; vhost
+[deploy/nginx/openvibe.casino.conf](deploy/nginx/openvibe.casino.conf). The README records the deploy
+files, not a live `ovhost` command; use the host's own installer. A change is frontend + server only;
+there is no money migration to run.
+
+## Tests
+
+`npm test` runs each `test/*.test.js` in its own process with a temp PGlite and a mock Network.
+`test/engines.test.js` checks **every published edge/RTP** against Wizard of Odds (basic-strategy
+0.40%, roulette 2.70/5.26/7.89%, baccarat 1.06/1.24/14.36%, slots 93.63%); `test/contrast.test.js`
+pins readable colours; `test/account-data.test.js` the export/deletion; `test/agent-*.test.js` the
+agent descriptor/twins. `ov test` runs the same.
+
+## Conventions
+
+- CommonJS on the server, UMD in `engine/`; 4-space indent, single quotes, semicolons; factories with
+ injectable config/clock/fetch/log.
+- Numbers that a player might rely on are **computed by the engine** and tested against a published
+ source; never hard-code an edge in a page or in `server/`.
+- Copy is calm, short and honest: "Expiry unknown" style rules apply to odds too — an unstated number
+ is not guessed.
+- Accessibility: contrast, focus and reduced motion are part of the product; the 18+ gate must be
+ reachable by keyboard.
+
+## Pitfalls
+
+- **No real money and no affiliate/operator links** until the owner's legal review; adding a purchase,
+ balance, cashout or referral path is out of bounds and Billing is not a dependency.
+- **Do not type an edge or RTP into a view.** It comes from `engine/games.js`/the engines and is
+ checked by `test/engines.test.js`; a copied figure will drift.
+- **Play chips never leave the browser.** Do not add a server balance, leaderboard prize or transfer.
+- **The 18+ gate, the 30-minute reminder and the help line are required** on every play page; a new
+ table that omits them is a bug.
+- **Keep the engines deterministic from a seed** and free of browser/Node globals in their core; the
+ same file must run in the worker and on the server.
+- **Shared runs are noindex** (`/s/:id`) and contain no personal data.
+- **Do not use a dark pattern** (fake urgency, "hot" streaks) — the product is a teaching tool.
+
+## Documentation
+
+- [README.md](README.md) — the engines and their edges, pages, API, data and deploy files.
+- [STATUS.json](STATUS.json) — what works and what does not.
+- The new-domains plan §5.14 is the product brief; `openvibe-contracts` holds any `casino.*` shapes.
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@