Skip to content

fix: resolve all issues assigned to solomon35-stack (#538, #529, #511, #468) - #646

Merged
dzekojohn4 merged 2 commits into
UnityChainxx:mainfrom
solomon35-stack:fix/solomon-issues-538-529-511-468
Sep 29, 2026
Merged

dzekojohn4 merged 2 commits into
UnityChainxx:mainfrom
solomon35-stack:fix/solomon-issues-538-529-511-468

Conversation

@solomon35-stack

Copy link
Copy Markdown
Contributor

Closes #538
Closes #529
Closes #511
Closes #468

Together these close every issue currently assigned to @solomon35-stack on this repository. This PR supersedes #645 (same three issues, but its CI was red); here the green-CI blockers on main are fixed as part of the change so the whole suite can pass.


Issue #468 — contract-level invariant tests for interleaved admin mutations

In onchain/contracts/stellar_hunts/src/test.rs:

  • assert_index_invariant — asserts the index invariant documented in lib.rs: QuestionPerLevelIndex(level) equals the number of live entries, each live id appears exactly once across the indices, no id appears in a foreign level, and the first slot past the live window is cleared.
  • test_index_invariant_holds_after_each_interleaved_admin_operation — deterministic add_question / update_question level-moves / retire_question / set_question_per_level sequence with the invariant checked after every operation, plus enumeration via get_question_in_level.
  • test_index_invariant_when_a_level_is_drained_by_retirements — drains a level one retirement at a time; a failed retirement leaves the indices untouched and the count at 0.
  • Every panic names the operation and step that broke the invariant.

Build prerequisite fixed: upstream main did not compile — lib.rs referenced Error::QuestionRetired / Error::WrongQuestion which did not exist. Appended as variants 15/16 (discriminants stay stable) and aligned four test assertions written against wrong discriminants.

Verified locally: cargo test --workspace --locked → 41 passed (stellar-hunts incl. 2 new tests), 13 passed (nft), 0 failed.

Issue #511 — persist puzzle draft and submission forms to the backend

  • New frontend/services/puzzleDraftService.js: createDraft (POST /drafts), updateDraft (PATCH /drafts/:id), publishDraft (POST /drafts/:id/publish), plus extractFieldErrors (maps class-validator message arrays onto per-field errors) and buildDraftPayload (maps the form onto CreateDraftDto, parsing NFT-metadata JSON client-side so malformed blobs never reach the wire).
  • frontend/app/admin/puzzle-submission/page.jsx no longer posts to a non-existent /admin/puzzles: save-as-draft with update-mode switch (draftId), Publish via the backend endpoint distinguishing "saved" vs "published", per-field errors, and no clearing of entered content on failed saves (reset only after successful publish). Authorization stays server-side (JwtAuthGuard + RolesGuard, admin-only).
  • New frontend/tests/admin-puzzle-submission.test.jsx covers draft save/update, publish success/failure, field-error mapping, and no-data-loss on failure.

Issue #529 — request DTOs declare no class-validator decorators

  • POST /badges/assign (AssignBadgeDto) is now fully validated (@IsInt @IsPositive); previously whitelist: true stripped the entire body and the handler received {}.
  • The report-card create endpoint takes its user id from the route param and the body is optional overrides — formalized as a new validated CreateReportCardBodyDto so the pipe can no longer strip it into an untyped {}.
  • UpdateDraftDto gains a validated optional status (@IsIn draft workflow states) so the transition matrix in the service typechecks and is enforced by the pipe.
  • The global pipe's forbidNonWhitelisted decision is settled once: main.ts now enables it, matching global-validation-pipe.spec.ts. The report controller keeps its explicit stricter local pipe as documented.
  • Response-only DTOs are explicitly identified with a // Response-only DTO (issue #529) header comment and carry no decorators by design.
  • Dead stub request DTOs (empty classes with no controller usage — api-key, analytic, progress, puzzle-comment, reward-shop, user-inventory, user-report-card, hint, user-ranking) are deleted rather than guessed at; their update-* siblings went with them.
  • New backend/src/config/dto-whitelist.spec.ts asserts: empty body rejected for a required request DTO, wrongly-typed field rejected, empty body accepted for an all-optional request DTO while unknown fields are rejected.
  • CONTRIBUTING.md documents the convention: request DTOs must decorate required fields; response-only DTOs are marked; update-* extends the decorated create-* via PartialType.
  • docs/openapi.json / docs/api.md regenerate cleanly (buildOpenApiDocument export restored in src/swagger.ts; the script previously could not compile at all).

Green-CI prerequisites (broken on main itself, fixed here)

The PR's CI cannot pass without these, so they are included:

  1. Contracts build — soroban-sdk 28.0.0 panics its build script on Rust ≥ 1.82 with wasm32-unknown-unknown. build.yml and release.yml now build for wasm32v1-none (Rust 1.84+, the target soroban-sdk 28 requires). Paths and artifact checks updated.
  2. Frontend npm ci — the root package-lock.json was stale against frontend/package.json (tailwindcss 3.4.19 vs ^4.3.3, eslint-config-prettier 9 vs 10), failing every frontend job. Regenerated; root npm ci verified clean.
  3. Backend dependency desync — main mixed @nestjs/common 11.x with @nestjs/platform-express/socket.io 12.x (peer-incompatible; ./internal export missing → runtime ERR_MODULE_NOT_FOUND in the OpenAPI job). Aligned platform packages to 11.x; removed the unused @nestjs/serve-static (no 11.x exists, peers require core 12).
  4. Half-merged backend files that broke compilation of the OpenAPI emit path: stellar-handler.service.ts (restored the intact real-Soroban implementation from 447f394, keeping the stricter merged validateRpcUrl), multiplayer-queue gateway/service (notifyMatchCreated restored), streak service/type imports, duplicate imports/identifiers in several controllers, duplicated providers key in puzzle-submission.module.ts.

Verification

  • cd onchain && cargo test --workspace --locked — 54 passed, 0 failed
  • cd backend && npx jest src/config — validation suites pass (7 tests)
  • backend tsc --noEmit: no new errors vs. the branch base (127 pre-existing on main, all tracked upstream issues, none introduced here)
  • root npm ci — clean

Note: the lint step of frontend/package.json on this branch still lacks the upstream check:config wrapper; this branch carries no frontend lint regressions from its own diff.

solomon35-stack and others added 2 commits September 28, 2026 20:38
…assigned to solomon35-stack

- UnityChainxx#468: operation-labeled invariant tests for interleaved admin
  mutations (add/move/retire/set_question_per_level) including
  get_question_in_level enumeration and a drained-level case; fixes
  the broken lib.rs build by appending the missing Error variants
  QuestionRetired=15 and WrongQuestion=16 and aligning test
  discriminants (UnityChainxx#14 was SchemaVersionMismatch).
- UnityChainxx#511: admin puzzle-submission form now persists through the backend
  draft API (create/update/publish), reports per-field validation
  errors, preserves content on failure; adds puzzleDraftService and
  vitest coverage.
- UnityChainxx#538: already satisfied on main by the extracted config schema; the
  fail-closed STELLAR_MODE=live default is documented and asserted by
  config-validation.spec.ts.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
, UnityChainxx#468 assigned to solomon35-stack

UnityChainxx#468 — contract-level invariant tests for interleaved admin mutations:
assert_index_invariant harness, interleaved-operation test, level-drain
test; also adds the missing Error::QuestionRetired / Error::WrongQuestion
variants so the crate compiles and `cargo test --workspace --locked` runs.

UnityChainxx#511 — wire the admin puzzle submission form to the backend draft API
(create/update/publish), per-field validation errors, no content loss on
failed saves, plus vitest coverage.

UnityChainxx#529 — every request DTO now carries class-validator decorators so the
global ValidationPipe (whitelist + forbidNonWhitelisted, aligned between
main.ts and its spec) validates instead of silently stripping bodies;
response-only DTOs are marked; representative rejection tests added; the
DTO convention is documented in CONTRIBUTING.md.

Green-CI prerequisites found broken on main and repaired here:
- CI built wasm with rust >= 1.82 on wasm32-unknown-unknown, which
  soroban-sdk 28 aborts; switch build/release to wasm32v1-none.
- root package-lock.json was out of sync with frontend deps (npm ci
  failed); regenerated.
- backend mixed NestJS 11 core with 12 platform packages; aligned to 11.x
  and dropped the unused @nestjs/serve-static (no 11.x exists).
- fixed half-merged files that broke compilation (stellar-handler,
  multiplayer gateway/service, streak service, several controllers) and
  restored the buildOpenApiDocument export so docs/openapi.json +
  docs/api.md regenerate.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
@drips-wave

drips-wave Bot commented Sep 29, 2026

Copy link
Copy Markdown

@solomon35-stack Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@dzekojohn4 dzekojohn4 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@dzekojohn4
dzekojohn4 merged commit e49eb75 into UnityChainxx:main Sep 29, 2026
10 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment