# What a “contract” is (Neon Sprawl)

Decomposition modules and the [dependency register](module_dependency_register.md) use **contract** as the name for a **stable boundary**: something two systems (client and server, two server subsystems, or server and content pipeline) can depend on without sharing an undocumented struct.

This doc fixes **artifact types**, **ownership**, and **versioning** so “Contract needed” in the register is actionable.

**Baseline stack alignment:** [tech stack](../../architecture/tech_stack.md) — authoritative server in C#; client in Godot/GDScript; **Protobuf** for versioned client–server messages (JSON acceptable only for the earliest spike); **JSON/YAML + JSON Schema** for content tables. **Who owns truth** for movement, camera, and combat: [client vs server authority](client_server_authority.md).

---

## Contract kinds


| Kind                | Use for                                                                                        | Authoritative form                                                                                                           | Typical consumers                           |
| ------------------- | ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
| **Wire**            | Player intents, state snapshots, RPC payloads crossing the network                             | **Protocol Buffer** `.proto` definitions; generated C# on server; mirrored types or codegen path in GDScript client          | Client runtime, server host                 |
| **Server-internal** | Shapes used only inside the ASP.NET process (persistence DTOs, internal queues) until promoted | **C#** records/types in the server solution; behavior covered by tests                                                       | Server modules only                         |
| **Content**         | Data-driven defs (`SkillDef`, `RecipeDef`, `QuestDef`, …)                                      | **JSON or YAML** files + **JSON Schema** (or **CUE** later) validated in CI                                                  | Server load; tools; optional client bundles |
| **Telemetry**       | Analytics and ops events ([E9.M1](E9_M1_TelemetryEventSchema.md))                              | Versioned **event catalog** (JSON Schema or equivalent) + transport envelope; align names with OpenTelemetry where practical | Client emitters, ingest, dashboards         |
| **HTTP (optional)** | Health, admin, or tooling — not the primary game sim path                                      | **OpenAPI** if exposed; keep game loop on Protobuf per tech stack                                                            | Ops, CI, external tools                     |


A single logical name (e.g. `MoveCommand`) might appear as a **protobuf message** on the wire and a **different** internal server type that maps to/from it; the **wire schema** is what client and server must agree on. Until Protobuf exists for a message, a spike may use JSON with an explicit **throwaway** note in PRs and a tracked issue to migrate.

---

## Mapping module “Key contracts” to kinds

Rough default (exceptions per module):

- **Intents and state sync** (`MoveCommand`, `PositionState`, `CombatAction`, `CombatResolution`, …) → **Wire** (protobuf).
- **Catalog / defs** (`RecipeDef`, `QuestDef`, `ItemDef`, `SkillDef`, …) → **Content** (files + JSON Schema).
- **Pure server resolution** (e.g. internal threat tables, idempotency keys not sent to client) → **Server-internal** until a client or tool needs them; then promote to wire or document as admin-only HTTP.

When unsure, default to **wire protobuf** for anything the **Godot client** must send or interpret; default to **content + schema** for anything authored as **bulk data**.

---

## Repository layout (convention)

Paths are **conventions** until the first codegen lands; adjust in one doc PR when you add the first artifact.


| Artifact                | Planned location                                                        | Notes                                                                                                                                      |
| ----------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `.proto` files          | `contracts/proto/` (repo root)                                          | Keeps schemas visible to both server and client tooling; generate C# into `server/` and client bindings per chosen Godot/protobuf workflow |
| JSON Schema for content | `contracts/schemas/content/` (or co-located `schema.json` next to data) | Validate in CI before server boot in strict modes                                                                                          |
| Telemetry catalog       | `contracts/schemas/telemetry/` or under `docs/` until ingest exists     | Must carry **schema / semver** for [E9.M1](E9_M1_TelemetryEventSchema.md)                                                                  |


Server-only helpers stay next to features (e.g. `NeonSprawl.Server/Game/...`) until extracted to a shared assembly if multiple hosts need them.

---

## Naming

- Register and epics use **PascalCase** names (`CraftRequest`, `LevelUpEvent`). **Protobuf messages** use the same PascalCase style; **protobuf field names** follow `snake_case` in `.proto` if you adopt common style guides (generated C# still maps to idiomatic names).
- **JSON Schema** `$id` and file names should include a **version** or folder (`v1/`) when breaking changes ship.

---

## Versioning and “Ready”

- **Wire:** additive changes via new fields and reserved numbers; breaking changes require a **new message** or a negotiated major bump and client rollout strategy.
- **Content:** schema version in CI; server rejects or migrates unknown versions per policy.
- **Telemetry:** bump **EventSchemaVersion** (E9.M1); document in changelog for dashboards.

A module’s register **Status** can move to **Ready** when the contracts it **exports** are published in the agreed form (proto checked in, or schema in CI, plus a minimal consumer test or stub).

---

## What this doc does not decide

- **Exact** Protobuf package layout and service vs unary choices — decide when the first real RPC is added.
- **Godot** protobuf library choice — tooling decision; still must consume the same `.proto` truth as the server.

---

## Related docs

- [tech stack](../../architecture/tech_stack.md) — Protobuf vs JSON spike, content validation, client/server split
- [Client vs server authority](client_server_authority.md) — intents vs state, E1/E5 defaults, deferred networking choices
- [PvP and the combat engine](pvp_combat_integration.md) — E5.M1 gating with E6.M1, deny reasons
- [Quest scope and party rules](quest_scope_and_party.md) — per-character quest state, party credit, turn-in
- [Data reload and telemetry operations policy](data_and_ops_policy.md) — content reload, PII, sampling, retention, baseline events
- [Documentation and implementation alignment](documentation_and_implementation_alignment.md) — register Status vs repo, tracking table
- [Module dependency register](module_dependency_register.md)
- [Decomposition README](../README.md)

