diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml index 10ec5df..25f11e5 100644 --- a/.github/workflows/deploy-pages.yml +++ b/.github/workflows/deploy-pages.yml @@ -39,6 +39,9 @@ jobs: - name: Configure GitHub Pages uses: actions/configure-pages@v5 + - name: Add SPA deep-link fallback + run: cp dist/index.html dist/404.html + - name: Upload production artifact uses: actions/upload-pages-artifact@v4 with: diff --git a/docs/OPERATOR_RUNBOOK.md b/docs/OPERATOR_RUNBOOK.md index eb124d9..4723f7b 100644 --- a/docs/OPERATOR_RUNBOOK.md +++ b/docs/OPERATOR_RUNBOOK.md @@ -7,8 +7,9 @@ This runbook is the release and recovery path for the Signum guest, Chain contra | Item | Canonical location | Current value | | ------------------------ | ------------------------- | ----------------------------------------------------------------------- | | Guest source | `main` in this repository | | -| Production guest | GitHub Pages | | -| Manifest | Same origin as guest | | +| Production guest | Vercel | | +| Manifest | Same origin as guest | | +| Static mirror | GitHub Pages | | | Local game address | Simulator-generated | `vendor/chain-casino-sdk/simulator/local-node/deployed.json` at runtime | | Production game address | Chain deployment | **Not deployed—record before enabling real wagering** | | Contract source | Repository | `contracts/SignumGame.sol` | @@ -44,8 +45,9 @@ Complete this table in the release PR; do not rely on chat history. | `SignumGame` address | Pending production deployment | | Deployment transaction | Pending production deployment | | Registered game ID | `signum` | -| Guest commit SHA | `e5a02d5f8fcef1efe69d262191933cfd5250257a` | -| Pages workflow run | `36082185638` | +| Guest commit SHA | `e2f19ac7e82b3659a75270a608923905639fed61` | +| Main CI workflow run | `36181869651` | +| Pages workflow run | `36181869582` | | Verified at (UTC) | 2026-09-25 | ## Fairness verification diff --git a/docs/QUALITY.md b/docs/QUALITY.md index f768344..131aa40 100644 --- a/docs/QUALITY.md +++ b/docs/QUALITY.md @@ -23,12 +23,12 @@ The production-browser suite covers a 390 × 844 viewport and rejects horizontal | Resource | Gzip limit | | ---------------- | ---------: | -| JavaScript | 100 kB | +| JavaScript | 116 kB | | CSS | 10 kB | -| JavaScript + CSS | 115 kB | +| JavaScript + CSS | 125 kB | These budgets cover first-party runtime assets. The Chain Jam widget is loaded asynchronously by the host integration and does not block Signum's initial render. ## Release checks -Run `npm run ci` for static checks and unit tests. Run `npm run test:e2e:simulator` for the real production build, Chain simulator, local contract, keyboard/mobile flow, axe scan, and browser error checks. +Run `npm run ci` for static checks and unit tests. Run `npm run test:e2e:routing` for every stable standalone route, navigation, metadata, mobile navigation, axe scans, and browser error checks. Run `npm run test:e2e:simulator` for the production build, Chain simulator, local contract, keyboard/mobile flow, and real VRF lifecycle. diff --git a/docs/RELEASE_AUDIT.md b/docs/RELEASE_AUDIT.md index b7697d6..6c534c6 100644 --- a/docs/RELEASE_AUDIT.md +++ b/docs/RELEASE_AUDIT.md @@ -1,90 +1,92 @@ -# Signum eligibility and product-readiness audit - -Audit package prepared: 2026-09-25 UTC -Application release candidate: [`e5a02d5f8fcef1efe69d262191933cfd5250257a`](https://github.com/EcstaceeLOR/Signum/commit/e5a02d5f8fcef1efe69d262191933cfd5250257a) -Deployed URL: -Official brief reviewed: -Status: **Blocked pending independent sign-off and production Chain registration** - -This report separates machine-backed findings from the independent review required by issue #33. It must not be marked final by a Signum implementer. - -## Release evidence - -| Evidence | Result | Record | -| ------------------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Main CI | Pass | [Run 36082185605](https://github.com/EcstaceeLOR/Signum/actions/runs/36082185605): lint, formatting, types, 69,888-case math/contract checks, unit/component tests, build, dependency audit, secret scan | -| Chain simulator | Pass | Same run: official simulator build plus real local VRF settlement and delayed-randomness cancellation through the iframe bridge | -| Pages deployment | Pass | [Run 36082185638](https://github.com/EcstaceeLOR/Signum/actions/runs/36082185638) deployed the tested `e5a02d5` artifact | -| Production smoke script | Pass | `npm run deployment:check -- https://ecstaceelor.github.io/Signum/` on 2026-09-25: page, manifest, Jam widget, and iframe policy | -| Asset and dependency provenance | Pass | `npm run assets:check`; see `docs/ASSET_PROVENANCE.md` and `THIRD_PARTY_NOTICES.md` | - -## Binary eligibility gates - -| Gate from the official brief | Result | Evidence | -| ------------------------------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | -| Casino game built with the Chain casino SDK | Pass | Guest imports `@chain/casino-sdk/guest`; the required SDK is pinned under `vendor/chain-casino-sdk`; CI exercises its simulator | -| Wager, random outcome, and payout | Pass in source and simulator | `contracts/SignumGame.sol`; simulator E2E opens, fulfills, settles, and verifies a session | -| Theoretical RTP between 93% and 98% | Pass | Pulse 96.25%; Carrier and Deepwave 96.09375%; `docs/PRODUCT_SPEC.md`; exhaustive cross-layer check | -| Local simulator game completes quickly | Pass | Automated E2E completes settlement without human/operator intervention | -| Playable standalone experience | Pass | Public HTTPS URL starts in a visibly labelled, no-money demo with secure browser randomness | -| Original concept rather than a clone | Pass with documented search | `docs/NOVELTY_DOSSIER.md`; no equivalent signal-composition casino mechanic found in the reviewed field | -| Chain Jam widget included | Pass | Deployed HTML loads `https://jam.chain.wtf/widget.js`; production smoke verifies it | -| Source can be shared with reviewers | Pass | Public repository: | -| Embeddable in the Chain host | Pass | Cross-origin iframe smoke and simulator lifecycle pass; deployed headers do not deny framing | -| Production Chain game address registered | **Blocked** | No production deployment signer, network, transaction, or registered address has been provided | - -## Cross-layer consistency - -| Area | Result | Evidence | -| -------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------ | -| Contract interface and lifecycle | Pass | Canonical `ICasinoGameV2`; no constructor arguments; malformed data and lifecycle paths covered | -| Bridge authority | Pass | Host owns wallet, token metadata, limits, signing, randomness, and settlement; guest fails closed on malformed snapshots | -| Manifest | Pass | Public `game.manifest.json` returns `gameId: signum`, API version 1, full-iframe presentation, and declared capabilities | -| RTP and payout cap | Pass | Contract, fixtures, UI, docs, and exhaustive report agree on all three paytables and the 40.00x Deepwave cap | -| Fairness claims | Pass | Demo and showcase are labelled; real Chain proof is not claimed in standalone mode; player patterns cannot change odds | -| Responsible play | Pass | Real mode is gated by age/jurisdiction acknowledgement and shows independence, limits, break, and support messaging | -| Accessibility and mobile | Pass in automation | Axe, keyboard path, focus handling, reduced motion, responsive layout, and compressed bundle budgets are covered | -| Privacy and diagnostics | Pass | Local-only bounded diagnostics; no analytics, wallet addresses, signals, wagers, or outcomes are collected | - -## Product-readiness review - -| Quality question | Current assessment | Evidence / limitation | -| ------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -| First-round simplicity | Strong automated evidence | Ten-second rule, one-screen guide, keyboard flow, and deterministic judge path; five independent first-time-player sessions are still outstanding | -| Ten-hour replay potential | Plausible, not proven | Three volatility modes, expressive signals, non-predictive journal, and varied audiovisual profiles avoid strategy misrepresentation | -| Visual and sound finish | Pass for release candidate | Responsive signal-room presentation, original CSS motion, mode-specific Web Audio, mute, and reduced-motion support | -| Judge path | Pass | `?showcase=1` offers an explicitly labelled deterministic walkthrough; normal demo and Chain wagering never use it | - -## Findings - -| ID | Severity | Finding | Owner | Release disposition | -| ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- | ---------------------------------------------------------------------------------------- | -| AUD-01 | High | Production Chain network, contract address, deployment transaction, and game registration are absent. | Release operator with a Chain-approved signer | **Block submission** until deployed, registered, and smoke-tested in the real host | -| AUD-02 | High | The required reviewer must be someone who did not implement Signum; implementer-generated evidence cannot satisfy independent sign-off. | Independent reviewer | **Block closure of issue #33** until the sign-off below is completed | -| AUD-03 | Medium | The five first-time-player sessions in issue #27 have not been conducted. Automated UX evidence is not a substitute for human comprehension and replay-intent data. | Product owner / five testers | Keep visible; complete the privacy-safe protocol before final product-readiness approval | - -No payout, RTP, bridge, manifest, standalone, widget, source-access, or iframe discrepancy was found in the tested candidate. +# Signum complete-product release audit -## Independent reviewer procedure +Audit refreshed: 2026-09-25 UTC + +Tested application commit: [`e2f19ac7e82b3659a75270a608923905639fed61`](https://github.com/EcstaceeLOR/Signum/commit/e2f19ac7e82b3659a75270a608923905639fed61) + +Release-fallback fix: [`db96dfea0ff7ef8f4b59f61498bac44f5b5de248`](https://github.com/EcstaceeLOR/Signum/commit/db96dfea0ff7ef8f4b59f61498bac44f5b5de248) + +Primary URL: + +Static mirror: + +Status: **Automated product gates pass; release remains blocked by three external acceptance gates.** + +This record distinguishes reproducible machine evidence from human validation. A Signum implementer cannot complete the five first-time-player sessions or independent sign-off on behalf of the required participants. + +## Complete-product delivery + +Issues [#79 through #91](https://github.com/EcstaceeLOR/Signum/milestone/1) are closed. They deliver the route/UX contract, application shell, persistence and recovery, Home, Play setup, active round, result receipts, history/detail, learning and fairness, settings, responsible play, support, failure states, and full-product E2E coverage. + +Issue #92 and epic #78 remain open until the human and production release gates below pass. + +## Reproducible release evidence -The reviewer should use a clean browser profile and must not rely only on this report: +| Evidence | Result | Record | +| -------------------------- | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Main CI | Pass | [Run 36181869651](https://github.com/EcstaceeLOR/Signum/actions/runs/36181869651): lint, formatting, types, exhaustive math/contract checks, tests, build, dependency audit, and secret scan | +| Standalone route matrix | Pass | Same run: every stable route, metadata, navigation, mobile menu, serious/critical axe scan, and browser error checks | +| Chain simulator | Pass | Same run: official simulator build, iframe bridge, real local VRF settlement, and delayed-randomness cancellation | +| Exact Pages artifact | Pass | [Run 36181869582](https://github.com/EcstaceeLOR/Signum/actions/runs/36181869582) deployed the tested application commit | +| Vercel production smoke | Pass | Root and all stable deep links return HTTP 200; page, manifest, Chain Jam widget, and iframe policy pass `npm run deployment:check` | +| Pages root smoke | Pass | Page, manifest, Chain Jam widget, HTTPS, and iframe policy pass | +| Pages child-route fallback | Fix prepared | `db96dfe` adds `dist/404.html`; re-test after this audit PR deploys | +| Public source | Pass | | + +## Route and state acceptance + +| Area | Result | Evidence | +| ---------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- | +| Product journey | Pass | Home -> setup -> active round -> immutable result -> history/detail is implemented and E2E-covered | +| Supporting pages | Pass | How It Works, Fairness, Settings, Responsible Play, and Support are directly navigable and functional | +| Failure recovery | Pass | Offline, runtime error, invalid route, missing receipt, corrupt storage, delayed randomness, and reconnect paths expose recovery actions | +| Responsive input | Pass in automation | Desktop and mobile navigation, keyboard play, focus transitions, reduced motion, and overflow checks pass | +| Accessibility | Pass in automation | Stable routes have no serious/critical axe findings; semantic controls and visible focus are tested | +| Data honesty | Pass | Demo/Chain receipts are separated; no fake account, server history, support chat, transaction, or VRF proof is shown | +| Canonical math | Pass | Pulse 96.25%; Carrier and Deepwave 96.09375%; UI, fixtures, TypeScript, Solidity, and docs agree | +| Privacy | Pass | Bounded local diagnostics; no analytics or collection of wallet addresses, signals, wagers, or outcomes | + +No placeholder, dead control, fake data, contract/RTP mismatch, or automated critical/high product finding was found in the tested candidate. + +## Eligibility gates + +| Gate | Result | Evidence / action | +| ---------------------------------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------- | +| Chain casino SDK guest and canonical interface | Pass | Pinned SDK, manifest, guest bridge, contract interface, and official simulator are exercised in CI | +| Wager, random outcome, and payout | Pass in simulator | Real local contract/VRF lifecycle settles and reconstructs a receipt | +| RTP between 93% and 98% | Pass | Exhaustive 69,888-case cross-layer check | +| Original concept | Pass with documented search | See `docs/NOVELTY_DOSSIER.md` | +| Standalone HTTPS and embeddability | Pass | Vercel deployment and iframe policy smoke pass | +| Chain Jam widget and public source | Pass | Production HTML and public repository verified | +| Production Chain deployment/registration | **Blocked** | Requires an authorized Chain deployment signer, network, transaction, contract address, registration, and real-host smoke | + +## Open release blockers + +| ID | Gate | Owner | Required evidence | +| ------ | --------------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | +| REL-01 | Five first-time-player sessions | Product owner plus five real testers | Complete `docs/PLAYTEST_PROTOCOL.md`; at least 4/5 comprehend the rule and median first play is under 30 seconds | +| REL-02 | Independent eligibility/readiness audit | Reviewer who did not implement Signum | Sign the exact commit and production URL below; no unresolved critical/high finding | +| REL-03 | Production Chain registration | Authorized release operator | Record network, address, deployment transaction, registration, and successful minimum-wager real-host settlement | + +These are release-process blockers, not hidden product defects. They must not be replaced with invented names, timings, addresses, or implementer self-approval. + +## Independent reviewer procedure -1. Open the deployed URL and play Pulse, Carrier, and Deepwave in standalone mode. -2. Explain the rule, whether pattern choice changes odds, and what `1.00x` means. -3. Confirm the demo and showcase labels cannot be mistaken for real wagering. -4. Run `npm ci`, `npm run ci`, and `npm run test:e2e:simulator` from the tested commit. -5. Inspect the official brief, manifest, widget, contract interface, paytables, public source access, and iframe behavior. -6. Recheck the production address and host settlement after AUD-01 is resolved. -7. Record every new finding with severity and owner. Do not approve with an unresolved critical/high finding. +1. Use a clean browser profile to complete standalone rounds in Pulse, Carrier, and Deepwave on the primary URL. +2. Explain the rule, pattern independence, receiver differences, demo disclosure, and `1.00x` meaning without implementer hints. +3. Run `npm ci`, `npm run ci`, `npm run test:e2e:routing`, and `npm run test:e2e:simulator` from the tested release commit. +4. Check the official brief, manifest, widget, contract interface, paytables, public source, direct links, and iframe behavior. +5. After REL-03, complete one minimum-wager production round and verify the receipt and proof state. +6. Record every finding with severity and owner. Do not approve with an unresolved critical/high finding. ## Independent sign-off -| Field | Value | -| --------------------------------------------------- | ----------------- | -| Reviewer name or GitHub handle | Pending | -| Confirmation that reviewer did not implement Signum | Pending | -| Commit tested | Pending | -| Production URL tested | Pending | -| Production contract/network tested | Pending | -| Critical/high findings remaining | AUD-01 and AUD-02 | -| Decision and UTC timestamp | **Not approved** | +| Field | Value | +| ---------------------------------------- | -------------------------- | +| Reviewer name or GitHub handle | Pending | +| Reviewer did not implement Signum | Pending | +| Exact commit tested | Pending | +| Production URL tested | Pending | +| Production Chain network/address tested | Pending | +| Critical/high product findings remaining | Pending independent review | +| Decision and UTC timestamp | **Not approved** | diff --git a/docs/SUBMISSION_CHECKLIST.md b/docs/SUBMISSION_CHECKLIST.md index 9c4937d..74098d2 100644 --- a/docs/SUBMISSION_CHECKLIST.md +++ b/docs/SUBMISSION_CHECKLIST.md @@ -18,14 +18,19 @@ ## Release proof -- [x] The GitHub Pages deployment for the intended application commit is green: run `36082185638`. -- [x] Record the deployed application commit in the submission notes: `e5a02d5f8fcef1efe69d262191933cfd5250257a`. -- [x] `npm run deployment:check -- https://ecstaceelor.github.io/Signum/` passes. +- [x] The complete-product CI run is green: [`36181869651`](https://github.com/EcstaceeLOR/Signum/actions/runs/36181869651). +- [x] The exact complete-product Pages artifact is deployed: [`36181869582`](https://github.com/EcstaceeLOR/Signum/actions/runs/36181869582). +- [x] Record the tested application commit in the submission notes: `e2f19ac7e82b3659a75270a608923905639fed61`. +- [x] `npm run deployment:check` passes against Vercel and the Pages root. +- [x] Vercel directly serves every stable product route and the product not-found route with HTTP 200. +- [ ] Re-run the Pages smoke after the SPA fallback in `db96dfea0ff7ef8f4b59f61498bac44f5b5de248` reaches `main`. - [x] The URL loads standalone over HTTPS. - [x] The URL renders inside a cross-origin iframe without a frame-policy error. - [x] `game.manifest.json` returns HTTP 200 and `gameId: signum`. - [x] The deployed HTML contains `https://jam.chain.wtf/widget.js`. - [x] The production UI and submission copy show the RTP and payout table above. +- [ ] Five privacy-safe first-time-player sessions pass `docs/PLAYTEST_PROTOCOL.md`. +- [ ] A reviewer who did not implement Signum signs `docs/RELEASE_AUDIT.md` against the release commit and URL. - [ ] The contract address and target Chain network are recorded after production deployment. GitHub Pages deploys the exact `dist` artifact built from `main`; it does not rebuild during the deploy job. This keeps the public release tied to the tested repository commit shown by the workflow run. diff --git a/docs/SUBMISSION_DRAFT.md b/docs/SUBMISSION_DRAFT.md index f34ceac..5c51a9f 100644 --- a/docs/SUBMISSION_DRAFT.md +++ b/docs/SUBMISSION_DRAFT.md @@ -8,7 +8,7 @@ Status: **Do not submit until the required values and release blockers below are | Field | Value | | ------------- | ------------------------------------------------------ | | Title | Signum: Resonance | -| Game URL | | +| Game URL | | | Declared RTP | Pulse: 96.25%; Carrier: 96.09375%; Deepwave: 96.09375% | | Source access | | | Discord | **REQUIRED FROM OWNER** | @@ -21,8 +21,8 @@ Signum turns one transparent mathematical rule into an expressive casino instrum Additional reviewer links: -- Judge showcase: -- Manifest: +- Judge showcase: +- Manifest: - Audit: - Demo video: @@ -32,10 +32,10 @@ The showcase and video are visibly labelled deterministic standalone fixtures an | Item | Record | | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------- | -| Application commit | [`e5a02d5f8fcef1efe69d262191933cfd5250257a`](https://github.com/EcstaceeLOR/Signum/commit/e5a02d5f8fcef1efe69d262191933cfd5250257a) | -| CI and simulator | [Run 36082185605](https://github.com/EcstaceeLOR/Signum/actions/runs/36082185605) — pass | -| Pages deployment | [Run 36082185638](https://github.com/EcstaceeLOR/Signum/actions/runs/36082185638) — pass | -| Production smoke | Page, manifest, widget, HTTPS, and iframe policy passed on 2026-09-25 | +| Application commit | [`e2f19ac7e82b3659a75270a608923905639fed61`](https://github.com/EcstaceeLOR/Signum/commit/e2f19ac7e82b3659a75270a608923905639fed61) | +| CI and simulator | [Run 36181869651](https://github.com/EcstaceeLOR/Signum/actions/runs/36181869651) — all three required jobs pass | +| Pages deployment | [Run 36181869582](https://github.com/EcstaceeLOR/Signum/actions/runs/36181869582) — exact artifact deployed | +| Production smoke | Vercel routes, deep links, manifest, widget, HTTPS, and iframe policy passed on 2026-09-25 | | Contract/network | **REQUIRED: production deployment and Chain registration** | | Independent review | **REQUIRED: issue #33 sign-off by a non-implementer** | | Human playtest | **REQUIRED: five anonymous first-time-player sessions for issue #27** | diff --git a/scripts/check-deployment.mjs b/scripts/check-deployment.mjs index 2abc597..6e17941 100644 --- a/scripts/check-deployment.mjs +++ b/scripts/check-deployment.mjs @@ -7,8 +7,9 @@ const pageUrl = new URL(input) assert.equal(pageUrl.protocol, 'https:', 'Deployment URL must use HTTPS.') if (!pageUrl.pathname.endsWith('/')) pageUrl.pathname += '/' -const [pageResponse, manifestResponse] = await Promise.all([ +const [pageResponse, deepLinkResponse, manifestResponse] = await Promise.all([ fetch(pageUrl), + fetch(new URL('play', pageUrl)), fetch(new URL('game.manifest.json', pageUrl)), ]) @@ -20,9 +21,24 @@ assert.equal( ) const html = await pageResponse.text() +const deepLinkHtml = await deepLinkResponse.text() const manifest = await manifestResponse.json() assert.match(html, /https:\/\/jam\.chain\.wtf\/widget\.js/) assert.match(html, /
<\/div>/) +assert.ok( + deepLinkResponse.status === 200 || deepLinkResponse.status === 404, + `Deep link returned ${deepLinkResponse.status}.`, +) +assert.match( + deepLinkHtml, + /
<\/div>/, + 'Deep link did not return the application shell.', +) +assert.match( + deepLinkHtml, + /https:\/\/jam\.chain\.wtf\/widget\.js/, + 'Deep link did not return the Chain Jam-enabled application shell.', +) assert.equal(manifest.gameId, 'signum') assert.equal(manifest.presentation?.mode, 'full-iframe') @@ -40,5 +56,5 @@ assert.doesNotMatch( ) console.log( - `Verified public page, manifest, Jam widget, and iframe policy at ${pageUrl}`, + `Verified public page, deep-link shell (${deepLinkResponse.status}), manifest, Jam widget, and iframe policy at ${pageUrl}`, )