Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/reports/qa-hardening/stage-07-closure.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ A post-run inventory comparison found the same 333 eligible names and one intent
| Post-remediation consolidated Gradle gate | `BUILD SUCCESSFUL` in 40m36s; 65 tasks, including parser, catalog, CLI, runtime, companion, and app unit suites. |
| Companion web gate | 32 Vitest files / 268 tests passed; TypeScript/Vite production build passed. |
| Release/governance gate at source stabilization | 80 tests passed. |
| Current release/governance gate after closure packaging | 83 Node tests passed. |
| Current release/governance gate after closure packaging and APK privacy correction | 85 Node tests passed. |
| Fresh corpus summarization | Streaming raw-report hash, source/generator lineage, canonical multiset, terminal outcomes, and persistence/reopen checks passed. |

The expensive parser and consolidated Gradle gates ran once after parser/catalog product-source stabilization. They were not repeated for downstream release packaging, acceptance-test stabilization, the later replacement of two Android API-33-only bounded reads with the shared API-30-compatible reader, repository-policy alignment with the established single-maintainer signing process, correction of GitHub policy reads to use public nonsecret endpoints instead of an integration token lacking administration scope, or binding the comparison range to the cache decision's prior parser schema. Focused checkpoint/save tests, the source-contract regression, Android test compilation, app lint, the PR managed-device suite, and all 83 release-governance tests passed after those corrections. `NONPARSER_REUSE` is explicit and does not permit parser, catalog, build, wrapper, or corpus-execution changes.
The expensive parser and consolidated Gradle gates ran once after parser/catalog product-source stabilization. They were not repeated for downstream release packaging, acceptance-test stabilization, the later replacement of two Android API-33-only bounded reads with the shared API-30-compatible reader, repository-policy alignment with the established single-maintainer signing process, correction of GitHub policy reads to use public nonsecret endpoints instead of an integration token lacking administration scope, binding the comparison range to the cache decision's prior parser schema, or tightening the Windows-path detector so arbitrary compressed APK bytes cannot be misclassified as a private path. Focused checkpoint/save tests, the source-contract regression, Android test compilation, app lint, the PR managed-device suite, the failed candidate's complete unsigned build and packaged Android gates, the reproduced APK privacy regression, and the release-governance tests passed after those corrections. `NONPARSER_REUSE` is explicit and does not permit parser, catalog, build, wrapper, or corpus-execution changes.

## Missing-feature classification

Expand Down
4 changes: 2 additions & 2 deletions docs/reports/qa-hardening/stage-08-closure.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,15 @@ The denominator correction does not waive an input. The audited physical invento
| Gate | Evidence | Verdict |
| --- | --- | --- |
| Post-remediation Gradle matrix | Parser core/CLI, catalog, RetroArch, mapper, battle, companion core/server/simulator, and app unit tests: `BUILD SUCCESSFUL` in 40m36s, 65 tasks | `PASS` |
| Release/governance matrix after closure packaging | 83 Node tests | `PASS` |
| Release/governance matrix after closure packaging and APK privacy correction | 85 Node tests | `PASS` |
| Companion browser unit/build matrix | 32 Vitest files / 268 tests; TypeScript/Vite build | `PASS` |
| Portable browser E2E after closure packaging | `npm run test:e2e:ci`: 3 tests in 15.4s | `PASS` |
| Packaged Android/WebView | Stage 3 source-bound GitHub managed-device run: 4/4 tests with immutable JUnit/screenshot evidence | `PASS` |
| PR packaged Android acceptance after final test stabilization | 7/7 managed-device tests passed, including canonical overlay picker delivery and production guide retry | `PASS` |
| Final corpus | 333/333 eligible inputs terminal; 0 parser/catalog/compatibility/persistence errors; 278/278 selected catalogs persisted and reopened | `PASS` |
| Downstream evidence hardening | Bounded 1.63 GB streaming summary, corrected denominator, duplicate-aware canonical contract, promotion/readiness/privacy regressions | `PASS` |

The consolidated Gradle and hours-long parser gates ran once after parser/catalog product-source stabilization. They were not repeated for downstream release packaging, deterministic acceptance-test corrections, the replacement of two Android API-33-only read calls with the already-tested API-30-compatible bounded reader, repository-policy alignment with the established single-maintainer signing process, correction of GitHub policy reads to public nonsecret endpoints, or binding the release comparison range to the cache decision's prior parser schema. Focused checkpoint/save tests, source contracts, Android test compilation, app lint, the 7/7 PR managed-device suite, and the complete release-governance suite passed afterward. The evidence validator rejects reuse if parser/catalog sources, build logic, wrapper, or corpus-execution tooling changes.
The consolidated Gradle and hours-long parser gates ran once after parser/catalog product-source stabilization. They were not repeated for downstream release packaging, deterministic acceptance-test corrections, the replacement of two Android API-33-only read calls with the already-tested API-30-compatible bounded reader, repository-policy alignment with the established single-maintainer signing process, correction of GitHub policy reads to public nonsecret endpoints, binding the release comparison range to the cache decision's prior parser schema, or tightening the Windows-path detector so arbitrary compressed APK bytes cannot be misclassified as a private path. Focused checkpoint/save tests, source contracts, Android test compilation, app lint, the 7/7 PR managed-device suite, the failed candidate's complete unsigned build and packaged Android gates, the reproduced APK privacy regression, and the release-governance suite passed afterward. The evidence validator rejects reuse if parser/catalog sources, build logic, wrapper, or corpus-execution tooling changes.

No ad hoc emulator, ADB gesture, physical-device action, credential inspection, signing-material inspection, signing, tagging, or publication was performed for this closure.

Expand Down
53 changes: 53 additions & 0 deletions release/RELEASE_NOTES_1.1.0-rc.78-hotfix.3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# DualDex 1.1.0-rc.78-hotfix.3

RC78 hotfix 3 is the release candidate for the completed project-wide QA hardening program. It closes the remaining Android setup, parser/catalog, runtime authority, companion transport, privacy, and release-governance gaps, then binds them to the final source-bound compatibility corpus. The hotfix qualifier preserves the immutable failed RC78 tags while keeping cache validation bound to the correct prior parser-schema baseline and preventing arbitrary compressed APK bytes from being misclassified as private Windows paths.

## Android setup and recovery

- Recover cleanly when a guide cannot be loaded instead of crashing the app or leaving the guide surface in a stale state.
- Reconcile direct-storage and folder-picker access without discarding the last valid index during a failed rescan.
- Quarantine revoked folder grants, route package-specific settings safely, and explain protected `Android/data` and `Android/obb` limitations accurately.
- Deliver overlay picker results exactly once across cold starts, new intents, retries, and activity recreation.
- Keep Area Guide projection failures local to that optional module.

## Parser and catalog resilience

- Bound complete-ROM probes, archive extraction, catalog payloads, concurrent corpus work, and detached Gen I species discovery.
- Add cancellation checks to long parser passes and replenish ordered corpus work after any completion so one slow input cannot stall unrelated inputs.
- Verify catalog identity and canonical content digests before activation, quarantine invalid snapshots, and fail closed on malformed optional data.
- Invalidate pre-hardening parser catalogs through schema revision 46 and retain seeded rebuild coverage.

## Runtime authority and companion safety

- Require verified ROM identity and monotonic session epochs before live memory or SaveRAM state can become authoritative.
- Fence queued mapper, socket, command, delayed-reply, and checkpoint work against stale sessions.
- Recover RetroArch configuration and command sockets transactionally while bounding memory reads, UDP drains, and retained snapshots.
- Bound Android and desktop companion transport, fence navigation/state/media responses, preserve structured retries, and isolate optional feature failures.
- Remove private paths, reversible player-state fingerprints, raw failures, stacks, workspace identifiers, and device identifiers from normal diagnostics and public evidence.

## Source-bound QA closure

- Audit 334 supported-extension files while evaluating all 333 scanner-eligible mainline and hack inputs; one known spin-off remains intentionally excluded by scanner policy.
- Reach terminal parser outcomes for 333/333 inputs: 278 selected, 2 ambiguous, 53 without a family match, and 0 parser errors.
- Record 20 complete, 302 partial, and 11 unresolved data-compatibility outcomes with 0 compatibility errors.
- Materialize, persist, close, reopen, and decode all 278 selected catalogs with 0 catalog or persistence errors.
- Close QA Stages 7 and 8 with zero blockers and zero referrals.

## Measured validation

- Post-remediation Kotlin and Android gate: 65 tasks passed in 40m36s across parser, catalog, CLI, runtime, companion, and app unit suites.
- Companion web gate: 32 Vitest files and 268 tests passed; the TypeScript/Vite production build passed.
- Portable Chromium acceptance: 3/3 Playwright tests passed.
- Release and governance gate: 85/85 Node tests passed.
- Public QA evidence: 7/7 assets passed structural privacy validation.
- PR Android acceptance: 7/7 managed-device tests passed; min-SDK-30 app lint and focused bounded-read tests passed after the final compatibility correction.
- Public nonsecret repository-policy reads were verified against the live tag and environment configuration without querying signing material.
- Cache validation selects the latest prior tag whose parser schema matches the explicit cache decision, so failed immutable delivery tags cannot replace the evidence baseline.
- Public-asset validation still rejects complete private paths embedded in binary payloads while ignoring isolated drive-prefix byte sequences in compressed APK data.
- Protected release managed-device acceptance, signing, and Thor validation remain mandatory before candidate promotion.

## Delivery

- This candidate uses Android version code `1010081`.
- The candidate is built and signed only through the protected GitHub Actions environment; production signing material is never exposed to the repository or local workspace.
- DualDex remains read-only and sends no game commands or emulator-memory writes.
2 changes: 1 addition & 1 deletion release/compatibility-evidence.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
},
"scopeDecision": {
"type": "NONPARSER_REUSE",
"attestation": "Fresh raw parser evidence was generated at the named source commit; downstream release packaging, acceptance tests, API-30-compatible Android bounded reads, repository-policy alignment, public nonsecret GitHub policy access, and schema-bound comparison selection changed afterward without changing parser, catalog, build, wrapper, or corpus-execution source."
"attestation": "Fresh raw parser evidence was generated at the named source commit; downstream release packaging, acceptance tests, API-30-compatible Android bounded reads, repository-policy alignment, public nonsecret GitHub policy access, schema-bound comparison selection, and binary-safe public-asset privacy validation changed afterward without changing parser, catalog, build, wrapper, or corpus-execution source."
},
"cacheDecision": {
"type": "BUMP_REQUIRED",
Expand Down
22 changes: 22 additions & 0 deletions tools/release/release-privacy.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,28 @@ test("rejects Windows backslash and forward-slash absolute paths and Unix home p
}
});

test("ignores isolated drive-prefix bytes in binary APK payloads", () => {
for (const binaryFragment of [
Buffer.from([0xff, 0x0a, 0x0a, 0x59, 0x3a, 0x2f, 0x0e, 0x60, 0x0a]),
Buffer.from([0xff, 0x6f, 0x3a, 0x2f, 0x44, 0x5b, 0xff, 0x37]),
Buffer.from([0x47, 0xff, 0x6b, 0x3a, 0x2f, 0x7a, 0xff, 0x6d]),
]) {
validatePublicReleaseAsset({ name: "DualDex-candidate.apk", bytes: binaryFragment });
}
});

test("still rejects a complete private path embedded in a binary payload", () => {
const bytes = Buffer.concat([
Buffer.from([0xff, 0x00]),
Buffer.from("C:\\Users\\local-user\\project"),
Buffer.from([0x00, 0xff]),
]);
assert.throws(
() => validatePublicReleaseAsset({ name: "DualDex-candidate.apk", bytes }),
/private path/i,
);
});

test("rejects local device and workspace identifiers without returning their values", () => {
for (const privateText of [
"deploymentTarget=local-device",
Expand Down
2 changes: 1 addition & 1 deletion tools/release/validate-public-release-assets.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { basename, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";

const PRIVATE_PATH_PATTERNS = [
/\b[A-Za-z]:[\\/]/,
/\b[A-Za-z]:[\\/][\p{L}\p{N}._ -]{1,128}[\\/]/u,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Match valid punctuation in Windows path segments

When an asset contains a Windows path whose first segment uses valid filename punctuation鈥攆or example, C:\Program Files (x86)\vendor\file鈥攖his character class stops at (, so the private-path scan accepts the asset. The same regression affects other valid characters and drive-root files such as C:\secret.txt; because this validator is the final privacy gate before release creation, those host paths could be published. Detect segment boundaries without restricting valid segment contents to this narrow allowlist.

Useful? React with 馃憤聽/ 馃憥.

/\/(?:home|Users|private|tmp|var\/tmp)\/[A-Za-z0-9._-]+[\\/]/,
/\/(?:data\/user|storage\/emulated|sdcard)\//,
];
Expand Down
Loading