Repository navigation
Add publisher-aware export and protected map content - #84
Draft
Italian-seasoning wants to merge 10 commits into
Draft
Italian-seasoning wants to merge 10 commits into
Italian-seasoning wants to merge 10 commits into
Conversation
Optional publisher packs for openMapper, built on the engine's omsi-pack and omsi-cfg. Ordinary maps and exports keep their current behaviour. - Hash original source bytes before conversion and recognise trusted signed provenance after renames, including retained PackIndex history. - Export restricted assets as exact dependency references in dependencies.json instead of copies, with ordinary warnings and an explicit redistribution-rights override. Protected content has no plaintext export path, including SCO outputs under invalid aliases. - Keep publisher-protected maps playback-only: no save, autosave, MCP exposure or collaboration hosting of protected sources. - Write ZIP, installed files and dependency manifests through unique same-directory temporaries that are removed on failure. - Publisher authoring: signed packs with optional AES-256-GCM content. - Optional bounded OBJ/P6 PPM fingerprint tool with documented limits. - Pin the engine crates to the content-protection engine revision.
Italian-seasoning
force-pushed
the
feat/publisher-content-protection-v2
branch
from
November 3, 2026 23:22
2a80497 to
0a4682d
Compare
tools/placement_watermark.py gives each buyer's copy of a map its own sub-millimetre object placements, derived from the creator's secret key and an opaque buyer ID, and inspects a suspect copy against the unmarked original with a stated false-match bound. - Only x and y of eligible [object] records in top-level tile files move, by 0.3 mm by default (0.1 to 0.5 mm allowed). Objects with paths, crossings or entry points, attached objects, splines, Chrono tiles and all other files are copied unchanged. - Follows each tile's [version] layout. The marked copy is written to a new folder that appears only when complete; inputs are never changed. - Tests cover exact, partial, reordered, rounded, averaged and mixed copies, 10,000 wrong IDs, the jitter limit and unsafe inputs. Both CI workflows run them.
openmapper --publish-licensed-packs builds one protected pack and one licence for each opaque licence ID in a list, using the engine's new signed licence_id (openOMSI f10c6d68). - Each pack has a fresh content key, and its signed manifest names the licence ID. Its licence repeats the ID, so one buyer's licence does not unlock another buyer's pack. - Licence IDs use the placement watermark buyer ID format, so one ID can name both. They hold no personal data. - The buyer receives <id>.oopp and <id>.licence.json. The publisher keeps <id>.key, for replacement licences, and licences.json, which records each ID with its pack, version, manifest digest, key ID and expiry. Both are written owner-only. - An unprotected specification, a repeated, malformed or case-only duplicate ID, a past expiry or any build failure leaves no output. - Original-file hashes are the same in every buyer's pack, so provenance recognition still works. - Repin openOMSI 6ac0681e -> f10c6d68.
5 of 7 tasks
Move the engine pins from f10c6d68 to 640f2ea1, which reports a missing Windows entitlement as KeyNotFound and moves entitlement code into its own module. No editor code changes.
Locale files keep both sides' new strings. The publisher-protected save guard now sits in save_with, so the background save is refused too, and the background copy of the document carries the publisher mounts and the protected flag. The openOMSI pin moves to the synced openOMSI branch.
Italian-seasoning
marked this pull request as ready for review
November 5, 2026 04:10
Italian-seasoning
marked this pull request as draft
November 5, 2026 07:39
Italian-seasoning
force-pushed
the
feat/publisher-content-protection-v2
branch
from
November 8, 2026 21:29
e731d78 to
774932f
Compare
The MCP server moved into src/mcp/: load_document and the refusal of a publisher-protected map now sit in mcp/mod.rs, and the test covers every tool the server lists.
…wgpu-hal and windows-core)
openOMSI no longer resolves a publisher alias through the global resolve_path (30fadba8): the game asks the map's DependencyMounts. The editor now does the same. Assets keeps the mounts with its map scope, Document::resolve_alias answers for the folder the map was read from, and the map check, the ground texture swatches and MCP use it. Without this the editor loaded no object from a pack and the check reported every one as missing.
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 #77, which conflicted with
main. The branch is the three feature commits plus engine repins, withmain(5ceca030) merged in; the latest commits repin the engine, lock its new dependencies and move alias lookups to the map's mounts.Adds optional publisher packs to openMapper: original-source hashes before conversion, trusted signed provenance, licence metadata and exact dependency references in export, an optional protected pack producer and playback extension, and a bounded opaque OBJ/PPM fingerprint inspector. A second commit adds optional per-buyer placement watermarks for whole maps, and a third builds per-sale packs and licences. Ordinary maps and exports keep their current behaviour and need no account or hosted service.
Engine dependency
Requires openOMSI-org/openOMSI#3593 at its head,
18567a01a17e24de9a2566c13801557ac7fc72a3. All 13 manifest pins and the 27 engine entries inCargo.lockselect that revision on the contributor fork;Cargo.lockalso gains the three dependencies that revision adds (windowsforomsi-pack,wgpu-hal,windows-core). After openOMSI-org/openOMSI#3593 merges, the pins and the format link indocs/PUBLISHER_PACKS.mdshould move to an openOMSI-org commit.Review corrections included
ec8002a), as the game has since Add optional signed publisher packs and protected playback openOMSI#3593 dropped the global alias lookup inresolve_path. Asset loading, the map check, the ground texture swatches and MCP use it; without it the editor loaded no object from a pack and the map check reported each one as missing.src/mcp/onmain; the refusal of publisher-protected maps moved with it (mcp/mod.rs), and its test now calls every tool the server lists.Optional placement watermarks (second commit)
tools/placement_watermark.pygives each buyer's copy of a map its own object placements: eligible[object]records in the tile files move horizontally by 0.3 mm (0.1 to 0.5 mm allowed), in directions derived from the creator's secret key and an opaque buyer ID. Objects that roads, rails or AI paths connect to, attached objects, splines, Chrono tiles and all other files stay unchanged.inspectcompares a suspect copy with the unmarked original and reports each candidate ID's score and an upper bound on the false-match probability. It contacts no service and stores no buyer data. Limits, including that deliberate millimetre jitter defeats it on small maps, are indocs/PLACEMENT_WATERMARKS.md. It is kept in its own commit so it can be reviewed or dropped separately.Per-sale packs and licences (third commit)
openmapper --publish-licensed-packs spec.json sales signing.pk8 licence-ids.txt <expiry-unix>builds one protected pack and one licence for each opaque licence ID in the list. Each pack has a fresh content key, and its signed manifest names the ID through the engine's newlicence_id; the licence repeats it, so one buyer's licence does not unlock another buyer's pack. Licence IDs use the placement watermark buyer ID format, so one ID can name both, and they hold no personal data. The buyer receives<id>.ooppand<id>.licence.json. The publisher keeps<id>.key, for replacement licences, andlicences.json, which records each ID's pack, version, manifest digest, key ID and expiry; both are written owner-only. An unprotected specification, a repeated, malformed or case-only duplicate ID, a past expiry or any build failure leaves no output. Original-file hashes are the same in every buyer's pack, so provenance recognition still works.Validation
ec8002awith the engine at18567a01:cargo test --release --locked620 passed, 2 failed, 7 ignored. The two failures,installed_maps_survive_a_saveandstock_depot_reads_back_the_same, read the add-on maps installed on that machine (Cayuga, Habana Oeste) and fail the same way onmain(5ceca030) there; this branch does not touch them.93e74abonly removes an unusedmuton Windows;cargo test --release --locked publisherpasses there (5).ec8002a, the repin alone failed four publisher tests on Windows (alias scope, signed aliases, both export round trips); they pass at the previous head (774932f, engineca01f9bb) and again now.cargo build --releaseon Windows passes. Translation check (2,736 texts, 26 languages), fingerprint tools and placement watermark tests pass (macOS).Contributor-fork CI: the Content protection run for
93e74abis queued. On the previous head its macOS job failed one test that is not part of this branch,a_set_of_pbr_pictures_becomes_one_material_with_openomsis_maps:import.rsonmaintreats a normal map as OpenGL-style when its whole path contains "gl", and the macOS temporary folder name is random. No gameplay, hardware or extraction-proof acceptance is claimed.Signatures identify trusted publishers, not ownership. A modified player can capture usable assets, and offline grants cannot guarantee immediate revocation.
🤖 Generated with Claude Code