Validate card metadata types at parse time #516

Open
opened 2026-09-03 12:05:54 +01:00 by Smithy-bot · 1 comment
Member

Parent: #487 (2026 Code Clean Up). Spun out of the review note on PR #515.

Why

Card metadata is JSON.parsed with no schema/type validation. Fields such as type are declared numeric (CardRarity) in TypeScript, but a metadata file can still contain a string, e.g. "type": "1".

Under loose equality (==) that value matched numeric 1. After the strict-equality sweep in #515 (===), the same card would silently disappear from:

  • the drop pool (GetUnclaimedCardsHelper)
  • /inventory type filters (InventoryHelper)
  • /stats rarity counts

Strict equality is the right long-term behaviour; the real fix is to reject or coerce bad metadata when it is loaded, not to keep ==.

docs/cards.md (PR #514) already asks for parse-level validation — this ticket is that work.

Suggested approach

  1. Find where card JSON is loaded/parsed (card folder → in-memory card objects).
  2. Validate (or safely coerce) known numeric/enum fields (type / rarity, and any other number fields used in comparisons).
  3. On invalid metadata: log a clear error identifying the file/card id, and either skip that card or fail fast in non-production — pick one and document it.
  4. Add unit tests for: valid numeric type, string "1" (invalid or coerced per chosen policy), missing type, and non-numeric garbage.
  5. Smoke /drop, /inventory, and /stats against the real card folder after the change.

Acceptance criteria

  • Malformed type (string/null/missing) cannot silently pass into drop/inventory/stats comparison paths.
  • Invalid card files are visible in logs (file path or card id).
  • Tests cover valid + invalid metadata shapes.
  • Manual smoke of /drop, /inventory, /stats against real cards still looks right.
  • PR #515 — partial strict-equality sweep that surfaces this risk
  • PR #514 — docs note in docs/cards.md
  • Sibling #517 — finish the repo-wide eqeqeq sweep (prefer doing this validation first)
  • Parent #487
Parent: #487 (2026 Code Clean Up). Spun out of the review note on PR #515. ## Why Card metadata is `JSON.parse`d with no schema/type validation. Fields such as `type` are declared numeric (`CardRarity`) in TypeScript, but a metadata file can still contain a string, e.g. `"type": "1"`. Under loose equality (`==`) that value matched numeric `1`. After the strict-equality sweep in #515 (`===`), the same card would **silently disappear** from: - the drop pool (`GetUnclaimedCardsHelper`) - `/inventory` type filters (`InventoryHelper`) - `/stats` rarity counts Strict equality is the right long-term behaviour; the real fix is to reject or coerce bad metadata when it is loaded, not to keep `==`. `docs/cards.md` (PR #514) already asks for parse-level validation — this ticket is that work. ## Suggested approach 1. Find where card JSON is loaded/parsed (card folder → in-memory card objects). 2. Validate (or safely coerce) known numeric/enum fields (`type` / rarity, and any other number fields used in comparisons). 3. On invalid metadata: log a clear error identifying the file/card id, and either skip that card or fail fast in non-production — pick one and document it. 4. Add unit tests for: valid numeric `type`, string `"1"` (invalid or coerced per chosen policy), missing `type`, and non-numeric garbage. 5. Smoke `/drop`, `/inventory`, and `/stats` against the real card folder after the change. ## Acceptance criteria - [ ] Malformed `type` (string/null/missing) cannot silently pass into drop/inventory/stats comparison paths. - [ ] Invalid card files are visible in logs (file path or card id). - [ ] Tests cover valid + invalid metadata shapes. - [ ] Manual smoke of `/drop`, `/inventory`, `/stats` against real cards still looks right. ## Related - PR #515 — partial strict-equality sweep that surfaces this risk - PR #514 — docs note in `docs/cards.md` - Sibling #517 — finish the repo-wide `eqeqeq` sweep (prefer doing this validation first) - Parent #487
Smithy-bot added this to the 0.12.0 milestone 2026-09-03 12:05:54 +01:00
Vylpes stopped working 2026-09-06 09:30:55 +01:00
20 minutes 1 second
Author
Member

QA results (step/testing → step/uat)

Tested against merged PR #518 on release/0.12.0 (bd1cd3d).

Pipeline (yarn build / yarn test / yarn lint)

  • build (tsc): pass
  • test (jest): 17/17 suites, 118/118 tests, 8 snapshots — pass
  • lint (eslint .): pass

Feature suite (tests/Functions/CardMetadataValidator.test.ts)

28/28 cases pass, covering the acceptance criteria:

  • valid numeric type accepted
  • string "1", missing, null, non-numeric garbage, and out-of-range type rejected
  • error messages include the file path (and card/series id)
  • series id numeric-string coercion still works

Acceptance criteria check

  • Malformed type cannot silently reach drop/inventory/stats comparison paths (reject-not-coerce; load aborts → safe mode via existing CardMetadataFunction catch)
  • Invalid files are identifiable in logs (LogError with jsonPath + validation message)
  • Tests cover valid + invalid metadata shapes
  • Manual Discord smoke of /drop, /inventory, /stats against the real card folder — not run here (no DATA_DIR card pack in the repo / no live bot in this environment). Worth a quick human check in UAT.

Moving to step/uat.

## QA results (step/testing → step/uat) Tested against merged PR #518 on `release/0.12.0` (`bd1cd3d`). ### Pipeline (`yarn build` / `yarn test` / `yarn lint`) - **build** (`tsc`): pass - **test** (`jest`): **17/17** suites, **118/118** tests, 8 snapshots — pass - **lint** (`eslint .`): pass ### Feature suite (`tests/Functions/CardMetadataValidator.test.ts`) **28/28** cases pass, covering the acceptance criteria: - valid numeric `type` accepted - string `"1"`, missing, null, non-numeric garbage, and out-of-range `type` rejected - error messages include the file path (and card/series id) - series `id` numeric-string coercion still works ### Acceptance criteria check - [x] Malformed `type` cannot silently reach drop/inventory/stats comparison paths (reject-not-coerce; load aborts → safe mode via existing `CardMetadataFunction` catch) - [x] Invalid files are identifiable in logs (`LogError` with `jsonPath` + validation message) - [x] Tests cover valid + invalid metadata shapes - [ ] Manual Discord smoke of `/drop`, `/inventory`, `/stats` against the real card folder — **not run here** (no `DATA_DIR` card pack in the repo / no live bot in this environment). Worth a quick human check in UAT. Moving to `step/uat`.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Total time spent: 20 minutes 1 second
Vylpes
20 minutes 1 second
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
External/card-drop#516
No description provided.