4.7 KiB
Code review — NEO-55 player inventory GET/POST + Bruno
Date: 2026-05-23
Scope: Branch NEO-55-player-inventory-getpost-bruno · commit 69327f5 vs origin/main
Base: origin/main
Verdict
Approve with nits
Summary
NEO-55 adds versioned GET / POST /game/players/{id}/inventory with DTOs, position-gated reads, engine-backed add/remove mutations, and structured deny responses mirroring the NEO-37/38 skill-progression pattern. Implementation delegates all rules to PlayerInventoryOperations (NEO-54), maps HTTP status codes per plan (400 schema/mutationKind, 404 unknown player/store, 200 + applied/reasonCode for engine denies), and includes eight AAA integration tests plus three Bruno requests. Docs (plan, E3.M3 slice, alignment table, README) are updated and match the code. Risk is low for merge: thin HTTP adapter over a well-tested engine; remaining gaps are optional coverage and register footnote parity.
Documentation checked
| Document | Result |
|---|---|
docs/plans/NEO-55-implementation-plan.md |
Matches — single POST + mutationKind, fixed 24+1 slot arrays, applied/reasonCode/snapshot echo, status mapping, Bruno + README, no manual QA doc per kickoff; acceptance checklist complete. |
docs/decomposition/modules/E3_M3_ItemizationAndInventorySchema.md |
Matches — NEO-55 HTTP bullet under Related implementation slices. |
docs/decomposition/modules/documentation_and_implementation_alignment.md |
Matches — E3.M3 row notes NEO-55 landed with README + Bruno pointers; NEO-56 telemetry still planned. |
docs/decomposition/modules/module_dependency_register.md |
Matches — E3.M3 In Progress; footnote lists NEO-50–NEO-55. |
docs/decomposition/modules/client_server_authority.md |
Matches — inventory mutations remain server-authoritative; HTTP is read/apply surface only. |
server/README.md |
Matches — Player inventory section documents GET/POST shapes, curl examples, reason codes, persistence; NEO-54 deferral removed. |
Register/tracking: alignment table and dependency register footnote updated for NEO-55.
Blocking issues
None.
Suggestions
-
Dependency register footnote (optional) — Extend the E3.M3 note inDone.module_dependency_register.mdto mention NEO-55 (inventory HTTP) alongside NEO-50–NEO-54, matching the alignment table and prior NEO-54 review pattern. -
POST remove happy path (optional) — Integration tests cover add success and remove deny (Done. —insufficient_quantity) but not add-then-remove success. A short round-trip test would lock the full POST contract for bothmutationKindvalues.PostInventory_ShouldApplyRemove_AfterAdd_WithUpdatedSnapshotinPlayerInventoryApiTests.cs. -
Done. —invalid_quantityHTTP smoke (optional) — Engine returnsinvalid_quantityfor non-positive quantity; no HTTP test asserts 200 +applied: false+ that code. Low risk (engine tested in NEO-54) but would complete the documented reason-code surface at the API layer.PostInventory_ShouldDenyNonPositiveQuantity_WithInvalidQuantityinPlayerInventoryApiTests.cs.
Nits
-
Nit:Done. —Post inventory add.bruusesexpect(scrap.quantity).to.be.at.least(5)— correct for a cumulative dev server, but an exact=== 5assertion would fail if prior manual runs left stacks. Acceptable for prototype Bruno; document “fresh dev player” in folder docs if flakes appear.folder.brudocs note fresh-server baseline and cumulative stacks. -
Nit: Plan referenced a
BuildSnapshothelper name (NEO-37 mirror); implementation usesMapSnapshot— behavior is equivalent, naming only. -
Nit: No Bruno request forDone. —removehappy path — plan minimum (one deny) is met viainvalid_item; a remove-after-add Bruno would complement manual QA.Post inventory remove.bru(seq 4).
Verification
cd server
dotnet test NeonSprawl.Server.Tests/NeonSprawl.Server.Tests.csproj --filter "FullyQualifiedName~PlayerInventoryApiTests"
dotnet test NeonSprawl.Server.Tests/NeonSprawl.Server.Tests.csproj --filter "FullyQualifiedName~PlayerInventory"
Run Bruno folder bruno/neon-sprawl-server/inventory/ against a local dev server (dotnet run, player dev-local-1).