Canonical requirements: NIGHTCELL 7: FALSE DAWN — PRD V1.3 (25 July 2026).
This file records the locked decisions and maps each PRD section to the code that implements it. When a decision changes, update this file in the same commit as the code (CLAUDE.md).
Not yet in the repo: the full narrative PRD text (story bible, mission scripts, art-direction prose, asset inventory). Commit it as
docs/prd-v1.3.mdso the document CLAUDE.md points at is actually here. This file is the engineering-facing extract and index, not a replacement.
Steam: readiness, requirements and the open payment-rule decision are in
docs/prd-steam.md(assessment dated 2026-09-22, not a locked decision).
| Area | Decision |
|---|---|
| Working title | NIGHTCELL 7 |
| Episode 1 | FALSE DAWN |
| Genre | First-person tactical action shooter, single-player + online multiplayer |
| Camera | First person |
| Story structure | Two playable opposing perspectives |
| First theater | Fictional near-future Iran crisis |
| Free product | Launcher, benchmark, training, dual-side demo, Multiplayer Alpha |
| Episode price | $9.99 USD |
| Purchase includes | Both sides, Complete Truth epilogue, all platforms |
| Subscription / microtransactions | None |
| Multiplayer | P0 V1 requirement, server-authoritative |
| V1 multiplayer mode | 6v6 Team Deathmatch, private matches, optional bot fill |
| V1 multiplayer map | Ardavan Yard (derived from Episode 1 architecture) |
| V1 throwable | Frag grenade only — 2 per life, no resupply, no other gadget |
| Multiplayer access | Free to verified accounts, no pay-to-win |
| Runtime target | 60–90 minutes per campaign side |
| Engine / build | Babylon.js / Vite |
| Physics | Havok client-side; simplified authoritative server simulation |
| UI | Preact for menus and HUD only |
| Marketing site | Next.js App Router, custom art-directed design system |
| Repository | One Git repository and pnpm workspace |
| Separate repositories | Prohibited for V1 |
| Deployment | Railway for every deployable application service |
| Public domain | nightcell7.com |
| API base | https://nightcell7.com/api/v1 |
| Realtime endpoint | wss://nightcell7.com/api/v1/multiplayer/sync/... |
| Multiplayer framework | Colyseus on Node.js |
| Ephemeral realtime state | Railway Redis |
| Durable database | Postgres + Drizzle |
| Authentication | Better Auth, verified email |
| Payments | CoinPayPortal only — direct Stripe integration prohibited |
| Resend | |
| Asset/content storage | Cloudflare R2 |
| Mobile touch play | Out of scope |
| DRM | Low-friction entitlement, no invasive DRM |
The Ardavan runtime uses original modern military industrial scenery: pale concrete, slate-blue equipment, orange utility markings, dark asphalt and cool daylight. This replaces the earlier night/sodium presentation. All 27 scenery, vehicle, prop, world-weapon and operator models are rebuilt; the approved first-person C7 and its coating/normal maps remain unchanged. Two original animated operators, new environmental surfaces, lighting, effects, deployment menu and field HUD ship as one runtime set. Obsolete model and texture files are removed.
The episode title remains FALSE DAWN. The map collision layout, combat rules and
budgets remain unchanged. Reproduction and verification are documented in
tools/art/iron-rain/README.md; every website capture identifies its source commit
in apps/site/public/media/yard/manifest.json.
| PRD § | Requirement | Implementation |
|---|---|---|
| §5.2 | $9.99 episode, one purchase covers both sides | packages/entitlements/src/catalog.ts |
| §5.4 | No pay-to-win in multiplayer | packages/game-core/src/weapons.ts (multiplayer flag), multiplayer-sim loadout filter |
| §5.6 | Refund revokes entitlement, free multiplayer unaffected | packages/entitlements/src/entitlements.ts |
| §8 | Six mission variants over three shared locations | packages/game-core/src/campaign.ts |
| §8.1–8.2 | Shared timeline and cross-campaign events | campaign.ts (SHARED_TIMELINE) |
| §9 | Free demo, either side first, no account required | game-core/src/ids.ts (DEMO_MISSIONS), progress.ts (canStartMission) |
| §10.7 | Complete Truth unlocks only after both sides | progress.ts (shouldUnlockCompleteTruth) |
| §12.1 | Movement set and feel | packages/multiplayer-sim/src/movement.ts |
| §23.1 | Free sandbox scenes need no account | apps/game/src/modes.ts, access.ts (PLAY_MODE.SANDBOX) |
| §12.4 | Health/armour, regen ceiling, no bullet sponges | packages/game-core/src/damage.ts |
| §12.6 | Difficulty changes tactics, not enemy health | packages/game-core/src/difficulty.ts |
| §13.1 | Five hero weapons, fictional (see §13.1 note) | packages/game-core/src/weapons.ts |
| §13.2 | One throwable: the frag grenade | packages/game-core/src/grenades.ts, multiplayer-sim/src/grenades.ts |
| §13.3 | Friendly-fire and identification rules | multiplayer-sim/src/hitscan.ts (team filter), grenades.ts (resolveBlast) |
| §17.2 | Single-repository mandate | pnpm-workspace.yaml, CLAUDE.md |
| §17.3 | Monorepo layout | repository root |
| §17.5 | Railway topology and public routing | infra/railway/, services/gateway/src/routes.ts |
| §17.6 | Health checks, structured logs, env validation, SIGTERM | packages/observability/src/index.ts |
| §17.7 | Local development mirrors production paths | tools/release/dev.mjs |
| §18.1 | Multiplayer Alpha scope | packages/game-core/src/match-rules.ts |
| §18.2 | Ardavan Yard, headless collision map, checksum | multiplayer-sim/src/map.ts |
| §18.3 | Authority model — what the server owns | multiplayer-sim/src/simulation.ts |
| §18.4 | Prediction, reconciliation, interpolation | apps/game/src/net/prediction.ts |
| §18.5 | Handshake and machine-readable rejections | multiplayer-protocol/src/{version,codes}.ts |
| §18.6 | Canonical endpoints, one-time tickets | multiplayer-protocol/src/ticket.ts, services/api |
| §18.7 | Gateway/API/multiplayer/worker/cron daemons | services/* |
| §18.8 | Sharding, regions, drain | services/multiplayer/src/index.ts |
| §18.10 | Reconnect grace, aborted matches not counted | simulation.ts (expiredSeats), codes.ts (isRankableTermination) |
| §18.11 | Bots use the same rules, labelled, never counted as players | multiplayer-sim/src/bots.ts |
| §18.12 | Moderation: reports, blocks, bounded quick chat | services/api/src/app.ts, multiplayer-protocol/src/messages.ts |
| §19 | Local save schema and migration | packages/save-data/src/index.ts |
| §20 | Marketing site product requirements | apps/site/ |
| §21 | DIVIDED SIGNAL art direction | apps/site/app/globals.css, packages/ui/src/index.ts |
| §22.5 | Performance budgets, API never cached | apps/game/vite.config.ts, gateway/API cache-control |
| §23 | Access model, display names, guest claim, sessions | packages/auth/src/index.ts |
| §24 | CoinPayPortal only: checkout, states, webhooks, reconciliation | packages/coinpay/, packages/entitlements/src/orders.ts, services/worker, services/cron |
| §25 | Data model | packages/database/src/schema.ts |
| §26 | Entitlements and content delivery | packages/entitlements/, packages/content-schema/ |
| §27 | PWA caching rules | apps/game/vite.config.ts |
| §28 | Electron security, purchase flow, cross-play | apps/desktop/src/{main,preload}.ts |
| §29 | Centralised API surface | services/api/src/app.ts |
| §30.4 | Tick rate, snapshot rate, rewind cap, budgets | multiplayer-sim/src/constants.ts |
| §33.1 | Gateway security headers, forwarding trust | services/gateway/src/routes.ts |
| §33.3 | Multiplayer integrity and anti-cheat posture | simulation.ts, input.ts |
| §34 | QA — unit, integration, load/soak | *.test.ts, tools/multiplayer-loadtest/ |
| §36 | Scope priorities | this file + README.md status |
§13.1 said four hero weapons, on the principle that "four excellent weapons have more value than twenty weak weapons". The M9 Hammerfall is a fifth, and the principle is intact.
That line is an argument against power creep and filler: a fifth assault rifle with slightly different numbers would be exactly what it warns about. The M9 is not that. Every other weapon in the game is hitscan, and this one puts a projectile in the air with a blast at the end of it. It adds a verb, not a variant, and it is the only weapon whose shots can be dodged, led, or taken cover from after they are fired.
It stays inside the locked rules:
- Not pay-to-win. Bought with credits earned in play at 800, roughly eight
kills. Credits are never purchasable with money (
docs/prd.md, "Prohibited in V1"), so this adds nothing to the storefront. - Not power creep. One tube, a 3.4 s reload and five in reserve. A miss costs more than a miss with anything else in the yard, and the self-damage fraction is 0.75, so firing it at your own feet kills you.
- Fictional, like the rest of the family. Original geometry, built by
tools/art/iron-rain/generate.py(launcher()androcket()).
If a sixth is ever proposed, it has to clear the same bar: a new verb, not a new stat line.
Cast. The supporting cast (Jonas Vale, Director Mara Vey, Colonel Arman
Daryan, Silas Kade), the four factions and MIRAGE now live as data in
packages/game-core/src/cast.ts, taken from the story bible (PRD §7.5 to
§7.7). The site's /characters page and both dossiers render it, and so does
the game's first-run briefing, so no surface can describe a person differently.
It is public copy under the home-page timeline's rule: who these people are and
what the player sees of them early, never what the campaigns reveal. Tests in
cast.test.ts refuse the reveals (who authorised the cleanup, what Nightcell 7
designates), any Arabic-script text while Farsi awaits native review, and a
Daryan written as a villain. Both protagonists get a circle of the same size
(§14.3).
Onboarding. A first-time player gets a briefing on the deploy gate (their
side's institution and whose story it is, from the same cast data) and then a
coach in the yard that teaches one control at a time in §10.1's order and
advances only when the player does the thing. Skippable from the gate (Esc);
remembered in nc7.onboarded. Logic is pure in apps/game/src/onboarding.ts.
Changing any of these is a product decision, not a tuning tweak.
| Budget | Value | Source of truth |
|---|---|---|
| Authoritative tick | 30 Hz (33.3 ms) | multiplayer-sim/src/constants.ts |
| Snapshot cadence | ~20 Hz | same |
| Accepted client input | ≤60 Hz | multiplayer-protocol/src/input.ts |
| Movement time per player per tick | 1.25 × tick | simulation.ts (DT_BUDGET_PER_TICK_MS) |
| Lag-compensation rewind cap | 200 ms | constants.ts (MAX_REWIND_MS) |
| Remote interpolation delay | ~100 ms | apps/game/src/net/prediction.ts |
| Reconnect seat hold | 20 s | game-core/src/match-rules.ts |
| p95 server simulation | < 20 ms at certified capacity | tools/multiplayer-loadtest |
| Ticket TTL | 30–60 s, single use | services/api/src/env.ts |
| Shell download | ≤ 15 MB | content-schema (DOWNLOAD_BUDGET_BYTES) |
| Demo route download | ≤ 150 MB | same |
| Paid episode | ≤ 1.2 GB preferred, 1.5 GB hard gate | same |
| Multiplayer incremental | ≤ 250 MB | same |
Encoded in CLAUDE.md and enforced by review:
- A second payment processor, or any direct Stripe code, keys, webhooks or docs
- Subscriptions, battle passes, loot boxes, paid weapons, paid matchmaking priority
- Ranked play, skill rating, clans, tournaments, voice chat, free-form text chat
- Spectator mode, replays, co-op campaign, player-hosted authoritative servers
- Peer-to-peer or host-migrated multiplayer authority
- Kernel-level anti-cheat
- Native mobile play
- Throwables beyond the frag grenade — the other five entries in
GADGETare campaign fiction, not multiplayer content, and stay that way for V1 - Separate repositories for the site, game, backend, multiplayer or infrastructure
- Direct client connections to internal Railway service domains
- Selling the second campaign or the true ending separately
| Gate | Owner | Status |
|---|---|---|
| Title and domain clearance (registrar checkout + lock) | Product | Not started |
| Trademark screening (USPTO/WIPO/EUIPO/UKIPO + common law) | Legal | Not started |
| CoinPayPortal production approval | Product | Not started |
| Digital tax classification and jurisdiction review | Finance | Not started |
| Iranian/Iranian-diaspora cultural consultant | Product | Not started |
| Native Farsi dialogue, subtitle and signage review | Product | Not started |
| Asset provenance and license audit | Tech art | Not started |
| Multiplayer network load certification on a deployed shard | Engineering | Simulation gate only |
| Railway production readiness checklist | Engineering | See infra/railway/README.md |
| Security review | Engineering | Not started |
| Visual QA against signed-off design | Design | Design not signed off |
All 31 runtime models receive the full tactical art pass documented in
docs/art/full-tactical-overhaul.md. Original C7 weapons replace the legacy
weapon geometry. Licensed character rigs/animation and scenery base meshes
remain licensed inputs; the provenance manifest distinguishes them from original
work. Shared surface textures are regenerated and the three palette atlases are
removed from runtime loading. The 9 MiB asset guard remains in force.
Four mirrored low-cover volumes at x ±10, z ±31 match the new concrete cover. They are part of the authoritative map, so content compatibility advances to 1.1.0 while the wire protocol remains 2. Both game and multiplayer service must ship this content revision together. Placement preserves the imported glTF coordinate transforms, including quarter-turn cover orientation and weapon muzzle direction. The website gallery is recaptured from the integrated game.
M2 retires every legacy runtime model/texture filename and consolidates 31 former
model entries into 28 original tactical GLBs. No licensed legacy meshes, rigs or
animation clips remain in the active art build. The approved C7 rifle, field case
and low cover stay in the unified inventory. Content revision advances to 1.2.0;
wire protocol 2 and collision volumes stay unchanged. The public demo link always
opens Team Deathmatch, combat pauses behind the menu, and a single simulation
clock owns bot respawn. New character rigs, faction-safe roster construction,
visibility-aware navigation and corrected aim restore visible opponents and
return fire. Competitive server TDM limits remain unchanged. Details and full
coverage are in docs/art/modern-assets-and-demo.md.
The free-play deploy gate offers Ardavan Yard, Saffron Freight and Nacre Relay.
Saffron Freight uses staggered amber freight stacks and connected outer flanks;
Nacre Relay uses ivory relay houses surrounding an open cross-shaped plaza.
Each has original architectural art generated from shared collision volumes.
The chosen yard persists across mode, difficulty, operator and time-of-day
changes, and is directly addressable with ?yard=saffron_freight or
?yard=nacre_relay. Bot combat, movement, projectiles and respawns use that same
map. The competitive online map remains Ardavan Yard.
All three yards include parked utility helicopters and patrol jeeps as static cover, and four walkable stair flights each. Saffron Freight mixes cargo loading roofs, a tank farm, convoy cover and an aircraft service bay. Nacre Relay mixes two relay rooftops with field shelters, a bunker and an aircraft plaza. Both use the existing environment asset kit, with the largest industrial structures as perimeter landmarks. Vehicle driving and flight controls are outside this change. Shared collision is authoritative for vehicles, aircraft tails, steps and decks.