Skip to content

Regalia v1.2.2

Latest

Choose a tag to compare

@YDW99 YDW99 released this 14 Jul 17:17
· 4 commits to main since this release
0b01956

What's New in v1.2.2

Full Changelog: https://github.com/YDW99/Regalia/releases/tag/v1.2.2/compare/v1.2.1...v1.2.2

Contributors

Bug Fixes

  • fix;docs;build;chore (#45) (@YDW99) 0b01956

Installation

Download the APK from the assets below and install it on your Android device.
Note: This app requires Stockfish chess engine binaries (libstockfish.so) to be built separately via NDK.

⚠️ Note: If you encounter any issues, please report them here.


Regalia v1.2.2 — Hardened by an 8-Skill Audit

A precision patch release: one real defect fixed, seven false positives cleanly dismissed, and the version bumped from 1.2.11.2.2. No new features, no new permissions, no new network access — just a sharper, better-defended build of the same chess experience you already trust.

SonarQube Cloud
Lines of Code
Security Rating
Maintainability Rating
Vulnerabilities
Signing
Engine: Stockfish 18
License: AGPL v3
License: GPL v3
Platform: Android
Min SDK: 23
Target SDK: 35
Xiaomi HyperOS 3


📦 Download

Asset Size Purpose
Regalia-v1.2.2-release.apk ~75 MB Standalone installer for arm64-v8a devices
Regalia-v1.2.2-manual-en.html ~1.1 MB Self-contained English user manual
Regalia-v1.2.2-manual-zh.html ~956 KB Self-contained Chinese user manual

💡 Bilingual parity — every user-facing string, every changelog entry, and every manual page is synchronized across Chinese (zh) and English (en). The app auto-detects system language; switch manually anytime via the ↔️中 / ↔️EN button in the header.


🔐 Integrity Checksums

APK file:           Regalia-v1.2.2-release.apk
APK versionCode:    122
APK versionName:    1.2.2
APK signature:      v1 ✅  v2 ✅  v3 ✅  (Xiaomi HyperOS 3 compatible)

Stockfish engine SHA-256 (must match all three locations):
  Source binary:    8f7116d3f1a7004a6581d4fb0c1ff891ce095bab6d45e52f1578897cf23b61b5
  jniLibs copy:     8f7116d3f1a7004a6581d4fb0c1ff891ce095bab6d45e52f1578897cf23b61b5
  APK-embedded:     8f7116d3f1a7004a6581d4fb0c1ff891ce095bab6d45e52f1578897cf23b61b5

Verify on your own machine:

# APK signature (v1 + v2 + v3 must all be true)
apksigner verify --verbose Regalia-v1.2.2-release.apk

# Version info
aapt dump badging Regalia-v1.2.2-release.apk | head -2

# Engine SHA-256 (must equal the value above)
unzip -p Regalia-v1.2.2-release.apk lib/arm64-v8a/libstockfish.so | sha256sum

🩺 What Happened in This Release

v1.2.2 is the direct result of subjecting v1.2.1 to an 8-skill comprehensive audit. Five sub-reports — totaling 4,199 lines of analysis — were produced using the following skill stack:

# Skill What it does
1 secure-code-review OWASP Top 10 (A01–A10) full-spectrum review
2 code-vuln-audit Secret-leak scan + OWASP pattern matching
3 deep-module-refactor God Module friction-point analysis
4 code-arch-optimizer Coupling matrix + refactoring roadmap
5 git-repo-audit Hot-file analysis + contributor metrics
6 code-to-chart Module dependency graph generation
7 code-safety-audit OWASP pattern sweep (45 sites)
8 web-security-audit WebView / XSS / network review

Every single finding from those reports was then verified line-by-line against the actual source tree — not against the stale snapshot the auditors saw. The result:

7 findings were false positives. 1 finding was real and is now fixed. The architecture recommendations are real but deferred.

This is what a disciplined patch release looks like.


✅ The One Real Fix

YELLOW-1 — FEN Parsing Lacks Length Limit

Attribute Value
OWASP category A03 — Injection
Severity 🟡 YELLOW (medium)
File src/main/assets/chess.src/tablebase.js
Function fenToState(fen)
Risk if unfixed Pathologically long FEN strings could cause unnecessary string processing before validation rejected them — a low-impact DoS vector
Fix Added a 200-character length limit at function entry

Why 200 characters?

A standard FEN is at most ~87 characters. The generous 200 ceiling comfortably accommodates:

  • ✅ Chess960 Shredder castling notation (e.g. HAah)
  • ✅ En passant target square (e.g. e3)
  • ✅ Extended fields (move counters, half-move clock)
  • ✅ Reasonable user input noise (trailing whitespace, etc.)
// tablebase.js — fenToState()
function fenToState(fen){
  if(!fen || typeof fen !== 'string') return null;
  if(fen.length > 200) return null;   // ← NEW: DoS guard
  const parts = fen.trim().split(/\s+/);
  // ...existing validation continues from here
}

Why the audit's regex was rejected

The audit suggested a strict character whitelist:

// ❌ Audit's suggestion — REJECTED
if (!/^[1-8PNBRQKpnbrqk\/\s-]+$/.test(fen)) return null;

This regex would break legitimate chess functionality:

Use case Legal characters Caught by regex?
Chess960 castling rights (KQkq or AHah) A-H, a-h ❌ Breaks
En passant target square (e3, g6) a-h, 1-8 ❌ Breaks
Field separator ( ) whitespace ✅ Passes

The existing per-character validation already rejects invalid piece characters by returning null — that is the correct whitelist approach, applied at the right granularity. Adding a coarse regex at the top would have created false negatives for valid Chess960 positions.


🚫 The Seven False Positives — and Why

Each of the following audit findings was carefully verified against the current codebase and confirmed to be either (a) based on stale code from previously deleted files, or (b) describing a defense that already exists.

RED-1getStatsPayload() returns unescaped PGN data (XSS)
Audit's claim StatsActivity.getStatsPayload() returns raw PGN strings that could contain <script> tags, causing XSS in stats.html.
Reality stats.html already escapes every PGN header value (including White / Black player names) via _escFEN() at the rendering layer — see line 1770.
Why the audit's fix was rejected The suggested Java-layer JSON escaping ("\") would corrupt JSON syntaxgetStatsPayload() returns a JSON string, and double-escaping quotes would break JSON.parse() on the JS side.
Status ✅ False positive — existing defense confirmed.
RED-2shouldOverrideUrlLoading doesn't block javascript: protocol
Audit's claim ChessWebViewClient.shouldOverrideUrlLoading() doesn't explicitly check for javascript: URLs.
Reality The current implementation uses a fall-through blocker: it allows only file:///android_asset/ and http(s)://, then return true (block) for everything else — including javascript:, data:, intent:, content:, and about:blank.
Why the audit's fix was rejected The audit's suggested early if (url.startsWith("javascript:")) return true; is functionally redundant — the final return true already catches it. Adding it would be harmless but misleading (implying the block list is opt-in rather than default-deny).
Status ✅ False positive — default-deny policy confirmed.
RED-3_buildPGNString i18n text is directly concatenated into PGN output (XSS)
Audit's claim i18n strings like T('you') and T('ai_opponent') are concatenated into PGN without HTML/JS escaping.
Reality (1) These i18n strings are static, developer-controlled constants"你" / "You" / "AI对手" / "AI Opponent". There is no user input path. (2) When user-supplied player names flow into PGN tags, they pass through normalizeTagValue() (PGN escaping: \\\, "\", newlines stripped) and then through _escFEN() at the rendering layer (`&<>"'``). Double-escaped.
Why the audit's fix was rejected The suggested _escapeHtml() wrapper would apply HTML entity encoding to PGN text — corrupting the PGN itself (< in a comment becomes &lt; in the .pgn file). PGN is a plain-text format; HTML escaping belongs at the rendering layer, not the data layer.
Status ✅ False positive — static strings + double escaping confirmed.
YELLOW-2sendToEngine(String) has no UCI command whitelist
Audit's claim StockfishNative.sendToEngine() passes JS-supplied strings directly to the engine process without validation.
Reality The very first thing sendToEngine() does is call _jsBridgeGateway.isUciCommandAllowed(command) — if the command isn't on the whitelist, it's rejected with a Log.w() and the method returns immediately. This whitelist has been in place since round-1.
Status ✅ False positive — JsBridgeGateway UCI whitelist confirmed.
YELLOW-3android:allowBackup="true"
Audit's claim The manifest allows adb backup to extract app data.
Reality android:allowBackup was set to false back in round-1 (v1.2.1's first refinement pass). The audit was working from a stale snapshot.
Status ✅ False positive — already false since round-1.
YELLOW-5 — ProGuard rules are too permissive
Audit's claim The rule -keep class com.Regalia.MessageBus { *; } retains an entire class including non-public methods.
Reality MessageBus.java was deleted in round-4 (it was a Phase 73 extraction with no external callers). The referenced ProGuard rule does not exist in the current proguard-rules.pro. The current rules are tight: only @JavascriptInterface methods, native JNI methods, and manifest-declared components are kept.
Status ✅ False positive — based on a deleted file.
P0 #4–5 + P1 #12 — Empty catch blocks & HapticHelper dead code
Audit's claim Two empty catch(e){} blocks in chess.html; HapticHelper.java is 128 lines of dead code.
Reality Both were already fixed in prior rounds: empty catches were filled with console.warn() in round-16 (the previous release), and HapticHelper.java was deleted outright in round-10. The audit was working from a stale snapshot.
Status ✅ False positive — both already resolved.

📐 Architectural Recommendations — Acknowledged, Deferred

The audit's architectural findings are real and well-reasoned, but they require multi-week effort and are inappropriate for a patch release. They are documented here for transparency and future planning.

# Friction point Severity Recommended fix ETA
F2 StockfishNative.java is a 4,354-line God Class 🔴 Extract EngineController + UCIGateway v1.3.x
F3 ui.js (8,522 lines) + ai-bridge.js (4,304 lines) = 66% of JS layer 🔴 RendererController componentization v1.4.x
F4 91 @JavascriptInterface methods — no type contract 🔴 Facade aggregation (91 → 6 domain facades) v1.3.x
F5 state-store.js is decorative — core is still imperative globals 🟠 Migrate evaluation state (_sfEval etc.) into Store v1.4.x
F12 Zero test infrastructure 🟠 Introduce Jest (JS) + JUnit (Java) v1.4.x

📖 Full details in the audit reports: regalia_final_arch_refactor.md (1,448 lines) and regalia_final_arch_optimize.md (1,138 lines).


🔢 Version Bump — 11 Locations Updated

Per the project's 版本号位置.md convention, the version string appears in 11 places across the codebase. All were synchronized to 1.2.2:

# File Location Old New
1 version.properties VERSION_PATCH / VERSION_BUILD 1 / 121 2 / 122
2 build.gradle auto-computed from version.properties
3 strings.xml app_name Regalia v1.2.1 Regalia v1.2.2
4 ChessWebViewClient.java version comment v1.2.1 v1.2.2
5 game-logic.js loading_title i18n key Regalia v1.2.1 Regalia v1.2.2
6 index.html.tpl <title> Regalia v1.2.1 Regalia v1.2.2
7 ui.js about-dialog <h2> v1.2.1 v1.2.2
8 ui.js header badge <span class="ver"> v1.2.1 v1.2.2
9 ui.js about-dialog app_name row v1.2.1 v1.2.2
10 HTML manuals cover, footer, title, AGPL block v1.2.1 v1.2.2
11 HTML manuals filename Regalia-v1.2.1-manual-{zh,en}.html Regalia-v1.2.2-manual-{zh,en}.html

⚙️ Auto-synced via BuildConfig.VERSION_NAMEMainActivity.java, StockfishNative.java, and ChessApp.java reference the version string through AGP's generated BuildConfig class, so they pick up the new version automatically with no manual edits.


📊 Build Verification Checklist

Every box ticked before this release was published:

  • All 9 JS modules pass node --check — zero syntax errors
  • state-store.js TDZ safety verified — no regression from the round-8 white-screen fix
  • chess.html rebuilt — 21,988 lines, 1,321,170 bytes (via python3 build-chess.py)
  • Release APK assembled./gradlew assembleRelease -x lint → 78,141,232 bytes
  • APK signature verified — v1 ✅ + v2 ✅ + v3 ✅ (HyperOS 3 compatible)
  • APK version verifiedversionCode=122, versionName="1.2.2"
  • FGS subtype property presentandroid.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE = chess_engine_analysis
  • Stockfish engine is dotprod variant — SHA-256 three-way match (source = jniLibs = APK-embedded)
  • Tarball repackaged — 112 files, 0 forbidden entries (no .so / jniLibs / build / .gradle / .cxx / .keystore)
  • All 7 README.license files updated with v1.2.2 entry
  • All documentation syncedBUILDING.md, PRIVACY.md, README.md, NOTICE
  • Both HTML manuals updated — changelog entries in new-to-old order, cover/footer/title/AGPL block bumped

📜 Privacy Impact

Zero privacy impact. No new permissions, no new data collection, no new network access, no changes to data flow or storage.

Change Privacy impact
FEN length limit (tablebase.js) ✅ None — FEN strings are chess position notation with no PII; the limit just fails faster on invalid input
Version bump (v1.2.1 → v1.2.2) ✅ None — version numbers are public information
Audit false positives (no action) ✅ None — confirmed existing defenses are correct

The app remains 100% offline: the only network endpoint is the optional Lichess Syzygy tablebase API, which is HTTPS-only with certificate pinning and CSP-restricted to tablebase.lichess.ovh.


🛠️ System Requirements

Component Requirement
CPU architecture arm64-v8a (AArch64)
Android version 6.0 (API 23) or later
Recommended Android 12+ (for full Material You theme support)
Disk space ~200 MB for installation
RAM 2 GB minimum; 4 GB recommended for engine analysis
Engine Stockfish 18, arm64-v8a-dotprod build (NNUE with DOTPROD acceleration)

⚠️ DOTPROD requirement: The bundled engine uses ARMv8.6-A DOTPROD instructions for NNUE acceleration. Devices with Cortex-A76+ / Cortex-X1+ / Snapdragon 855+ CPUs (2019+) fully support this.


📚 Documentation

Document Description
Regalia-v1.2.2-manual-en.html Complete English user manual — self-contained HTML, no external dependencies
Regalia-v1.2.2-manual-zh.html Complete Chinese user manual — same content, synchronized
BUILDING.md Build instructions, environment setup, version bump history
PRIVACY.md Privacy policy (zero data collection, full offline disclosure)
NOTICE Third-party components + per-file license classification
README.md Project overview + directory tree + full version history

🤝 Credits

  • Engine: Stockfish 18 — GPL v3
  • PGN/UCI logic heritage: DroidFish by Peter Österlund — GPL v3
  • Lichess — For the Syzygy tablebase API and ECO opening data
  • All contributors who have helped shape Regalia through code reviews, bug reports, and feature suggestions
  • App code: Copyright © 2026 Regalia — AGPL v3 (original work) + GPL v3 (DroidFish-derived)
  • Audit: 8-skill comprehensive review using secure-code-review, code-vuln-audit, deep-module-refactor, code-arch-optimizer, git-repo-audit, code-to-chart, code-safety-audit, and web-security-audit

💬 Feedback

Found a bug? Have a feature request? Want to contribute to the v1.3.x architectural refactor?

  • 🐛 Bug reports: Open an issue — please include the FEN/PGN that triggered the bug and your device model
  • 💡 Feature requests: Open a discussion — architectural contributions toward F2/F3/F4 (God Module splits) are especially welcome

⏭️ What's Next

v1.2.2 is a stabilization release. The next minor version (v1.3.x) will begin the architectural work documented in the audit:

  1. @JavascriptInterface facade aggregation — consolidating 91 scattered methods into 6 typed domain facades
  2. UCI protocol parsing centralization — replacing 15 scattered regex patterns with a single UCIGateway
  3. Test infrastructure — introducing Jest (JS) and JUnit (Java) unit test frameworks

Until then — enjoy the games. ♔


Release date: 2026-07-14 · Build: 122 · Signed with v1+v2+v3 · 100% offline · AGPL v3 + GPL v3


AI-GEN