feat: Mailbox level + slug ids + curriculum restructure#10
Merged
Conversation
- New Level 9 "Mailbox" (mailbox + mailbox_relay) teaching Sui's transfer-to-object pattern via a trust-by-typed-value cross-module bug. - Removed "Object Chest" (was level 4); ids stay gapped for URL stability. - Renamed blackbook -> night_ledger / NightLedgerFlag so contract module names match level names everywhere. - Curriculum order auto-derived: easy -> medium -> hard, tiebreak by id. Display position (1..N) shown in sidebar/header/mobile picker while URLs continue to use the stable id; body H1 in instructions generated from position + name so chrome and body always agree. - Tightened all descriptions to goal + minimal structure cue (no analysis); removed the hints field across all levels. - Fixed LocaleSwitcher checkmark vertical alignment and RTL positioning (Tailwind rtl: variant via :lang(ar)/[dir=rtl] + explicit lang attribute on each SelectItem). - Full i18n updates across all 12 locales. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Level ids are now snake_case slugs (e.g. "artifact", "coin_collector",
"night_ledger", "mailbox") instead of integers. Used as the JSON key in
meta.config.json + every locale's content, and as the URL segment
(`/levels/artifact`, `/levels/mailbox`, etc.).
- `Level.id` typed as string; numeric tiebreak dropped from compareLevels
(stable sort preserves meta.config.json insertion order within a
difficulty).
- One-time localStorage migration (`progressStorage.ts`) rekeys solved set,
saved solutions, hint counter, and last-visited level from the old numeric
ids to slugs on first access. Idempotent via a sentinel key. Drops the
removed Object Chest's id 4. Slug entries win over numeric on collision.
- Route handlers updated to accept slug params (no more `Number(id)`);
redirect-on-not-found targets `levels[0].id` so it stays correct as the
curriculum changes.
- Hardcoded `/levels/0` removed from Landing, How-to-play, and Completion —
all now use `LEVEL_IDS[0]`.
- runConfig keyed by slug; per-level solution module name is `<slug>_solution`.
- sync-meta / create-level / delete-level scripts updated for slug ids
(create derives the slug from the module name; delete no longer reindexes).
- Old `/levels/{number}` URLs intentionally 404 (no redirect layer).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sweep of dead references left over from the older numeric-id + different level set. No functional changes; cleanups across content, i18n, code, docs, and a vestigial script. Content (per-locale en/es/pt/fr/ja/ko/ru/ar/tr/uk/zh-Hans/zh-Hant): - Strip the stale `# Level N: Name` H1 prefix from every level's instructions (the renderer prepends a fresh, position-based H1 at runtime; the source H1 went stale on every reorder). - Rewrite `artifact.explanation` to drop the "Level 0" self-reference. i18n (per-locale x 12): - `landing.cta` / `level.runNotSupported` / `howToPlay.startLevel0`: numeric "Level 0" / "Nivel 0" / "Уровень 0" / "レベル0" / etc. bumped to "Level 1" (position-based; durable across renames). - `landing.feedLine2`: `genesis, lockbox, fallout` → `artifact, coin_collector, sticky_treasure` (real modules). - `landing.recommendedBody`: Genesis/Lockbox/Fallout → Artifact/Sticky Treasure/Flash Vault. - `level.solutionPlaceholder`: `genesis::create(t)` → real Artifact API (`artifact::forge / charge / shatter`). Code: - `CompletionCard.tsx`: `level_8::solve(margin_note)` + `BlackbookFlag` → `night_ledger::solve(margin_note)` + `NightLedgerFlag`. - `contractCode.ts` doc-comment example: `genesis` → `artifact`. Vestigial cleanup: - Delete `scripts/sync-contracts.mjs` (synced from `move_over/sources/`, a directory that no longer exists in the repo). - Delete `public/contracts/_manifest.json` (auto-generated by the deleted script; listed `fallout.move`/`genesis.move`/`lockbox.move` and `level_N_solution.move` filenames that never existed in the current set). - Remove `npm run sync:contracts` from package.json and its README row. Docs: - ADD_LEVEL_README.md: rewrite the manual-add example using slug ids; drop the H1 from the example instructions. - DELETE_LEVEL_README.md: rewrite to reflect that deletion no longer reindexes higher ids (slugs are stable). - README.md: drop the "reindex ids" line; drop the sync:contracts row. CI: - Add `.github/workflows/codeql.yml` pinned to a working `github/codeql-action@v3` so the repo overrides GitHub's default code-scanning (the default was resolving `@v4` to a SHA that returns 404 from upstream). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 tasks
kosedogus
approved these changes
May 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replaces #9 with signed commits (the original branch's history was rewritten to add SSH signatures; force-push to update #9 was blocked locally, so this is a fresh branch with the same content).
Summary
mailbox) —mailbox+mailbox_relaymodules teaching Sui's transfer-to-object pattern via trust-by-typed-value cross-module exploitblackbook→night_ledger+BlackbookFlag→NightLedgerFlagso contract modules match level namesmeta.config.json, all locale JSONs,runConfig, URLs (/levels/artifact,/levels/mailbox, …); one-time localStorage migration rekeys user progresscompareLevelscomparator; display position (1..N) shown in sidebar/header while URLs use the stable slug# Level N:H1s from instructionsgenesis/lockbox/falloutmodules and bumped "Level 0" labels to "Level 1".github/workflows/codeql.yml) pinned to@v3to work around the org-default@v4SHA-404 issueNote on CodeQL checks
The new
codeql.ymlruns but the SARIF upload is rejected with "CodeQL analyses from advanced configurations cannot be processed when the default setup is enabled". Repo admin needs to disable the Default CodeQL setup at https://github.com/OpenZeppelin/move_over_ctf/settings/security_analysis — that lets our advanced workflow take over.Test plan
/en/levels/artifact,/en/levels/mailbox,/en/levels/night_ledgerrender correctly🤖 Generated with Claude Code