Remove required imports RFC

This commit is contained in:
anxiousintrovert
2026-08-14 14:30:45 -05:00
parent 542856c83d
commit dfc216f974
-105
View File
@@ -1,105 +0,0 @@
# RFC 0010 — Manifest-declared user imports for mods
## Status
Proposed. Engine: `Manifest.lua`, `RequiredImports.lua`, `Loader.lua`,
`LauncherMods.lua`. Launcher: `RomImporter.lua`, `LauncherView.lua`. Native
picker bridges: Android and iOS.
## Motivation
Some mods derive presentation data from another cartridge the player owns.
Shipping those bytes in a mod is not acceptable, while asking each mod to
escape the sandbox, implement native pickers, and maintain platform-specific
paths defeats the sandbox's purpose. Pokemon Stadium and Pokemon Stadium 2 are
the first concrete consumers, but the ownership/import problem is generic.
## The decision it extends
This extends the manifest as the engine-owned declaration of mod dependencies
and preserves the sandbox rule in `src/mods/Sandbox.lua`: mods do not receive
raw host filesystem access. It also extends the launcher's established ROM,
save, and mod archive picker/inbox flows instead of introducing a second host
integration.
## Exact manifest delta
Additive `required_imports` and `optional_imports` arrays are accepted:
```json
{
"required_imports": [{
"id": "stadium2",
"name": "Pokemon Stadium 2 ROM",
"file": "stadium2.z64",
"format": "n64",
"md5": ["00000000000000000000000000000000"]
}]
}
```
Both arrays use the same object schema. A missing `required_imports` entry
blocks the mod; a missing `optional_imports` entry only leaves that bonus
functionality unavailable.
- `id` is unique within the manifest and uses the mod-id vocabulary.
- `name` is launcher-facing text.
- `file` is one safe filename below the mod's `baseroms/` directory.
- `md5` is one 32-digit hexadecimal digest or a non-empty array of accepted
digests. MD5 is a known-dump identity convention, not a trust primitive.
- `format` is `raw` by default. `n64` recognizes a canonical big-endian dump,
pair-byte-swapped and little-endian-word dumps, with or without a recognized
512-byte copier header. Validation and stored output use canonical big-endian
bytes.
The launcher copies a validated file to
`mods/<manifest.id>/baseroms/<file>`. Missing required imports make the launcher
row need attention and make the loader refuse that enabled mod before its entry
chunk runs. Missing optional imports remain selectable without changing load
status. A matching validated import owned by another installed mod is
copied automatically. Replace and remove remain explicit per-mod actions.
Desktop and UWP use their existing native/host picker routes. Android and iOS
add a `required_import` picker kind which stages
`picked_required_import.bin`. NX scans the engine-owned
`imports/baseroms/` MTP inbox. All writes continue through `CacheFs`, preserving
portable-mode placement.
`modkit validate` and `modkit pack` report MK307 for every file beneath a
source mod's `baseroms/` directory, so the packaging path cannot accidentally
distribute a file the launcher placed there. The installer also rejects a mod
archive containing `baseroms/` files, covering packages built without modkit.
## Mod-facing API and sandbox statement
There is no new runtime API and no new permission. A mod reads its own copied
file through the existing `mod:read("baseroms/<file>")` capability. It never
learns the selected host path, cannot browse another mod's tree, and receives
no raw `io`, `love.filesystem`, or platform-picker access.
## Migration and compatibility
Existing manifests omit both import arrays and behave exactly as before. The
fields are additive for both manifest API levels. Mods currently maintaining
their own cross-platform picker can declare the source file and remove that
host integration; their processing code changes only to read the declared
`baseroms/<file>` path.
## Parity tests
- Empty/absent `required_imports` leaves existing manifests and loader behavior
unchanged.
- Manifest validation refuses path traversal, duplicate ids/files, malformed
MD5 values, and unknown normalization formats.
- N64 byte orders and the recognized copier-header form produce identical
canonical bytes before MD5 validation.
- A mismatched selection is never written.
- An enabled mod with a missing declared file never executes its entry chunk.
- A matching import in another installed mod is copied into the requesting
mod's own `baseroms/` directory.
- The packaging gate refuses every `baseroms/` file.
- The launcher refuses an archive that contains `baseroms/` files.
## Deprecation etiquette
Nothing deprecated or removed.