Repository navigation
EN Create Asset Provenance
Français · Type: how-to + reference · Audience: author · Context: engine repository, created project · Status: ready · Applies from: 4.2.5
A release says where every image, sound, voice and video it ships comes from, under which licence, and proves that the
files are the ones someone reviewed. This page shows how to write provenance.json, lock it after a review, and pass a
release or a commercial release.
A provenance.json that covers every shipped asset exactly once, a provenance.lock.json holding each file's SHA-256
and size with the claims it was reviewed under, and a release check that fails as soon as a file or a claim changes
without a new review.
The engine repository (games/<id>/provenance.json) and the created project (game/provenance.json). True from 4.2.5
(the quest-n-click command name). The lock dates from 3.3.0, the commercial check from 3.3.1, the shipped archive's
licence files from 3.7.1.
- The assets prepared:
npm run assetshas run, soassets.gen.jsonandpublic/assets/exist. The checks read the files underpublic/assets(ASSETS_DIRpoints elsewhere, for a test fixture). - For each asset, you know its source, its licence and its author.
On your machine, at the root of the engine repository (npm run …) or of the created project
(npx quest-n-click …, npm run release).
-
Write an entry per source in
provenance.json. A created project starts with one: its template art is a placeholder drawn from shapes, markedplaceholder.{ "licences": { "allow": ["CC BY 4.0", "own work"] }, "assets": [ { "match": "img:*", "source": "Drawn for the game from the prompts in prompts.md", "author": "Wano", "licence": "CC BY 4.0", "status": "final" }, { "match": "sfx:door_*.mp3", "source": "Recorded at home", "author": "Wano", "licence": "own work", "status": "final" } ] }The fields are in the reference below. Each asset must match exactly one entry.
-
Check the coverage.
# in the engine repository npm run provenance # assets by licence, and what changed since the lock (exit 1: something to review) npm run validate # a game with provenance.json: every asset covered once, every entry complete
# in the created project npx quest-n-click provenance npx quest-n-click validate
-
Review, then lock. Look at every file and its entry. Then:
# in the engine repository npm run provenance -- --lock# in the created project npx quest-n-click provenance --lockIt refuses to lock while an asset is uncovered, ambiguous, its entry incomplete, or its file missing (
✖ … not locked: fix the provenance first).
-
Pass the release gates.
# in the engine repository npm run verify:release # validate --release, weight --release, i18n status, voices check --release, strict playtests npm run verify:commercial # verify:release, then validate --commercial, then verify:dist
# in the created project npm run release # includes validate --release npm run release -- --commercial # also validate --commercial
Guarantee ·
provenance-lock-detects-change· referenced · scope self-checked by the author (AI), not reviewed After--lock, a file whose bytes changed, an asset shipped since, a file missing or an entry whose licence was edited is reported.
validate --release fails on each of these, a plain validate only warns. An edited pattern or status is reported
like an edited licence.
Limit ·
claims-not-truthThe checks say the claims are complete and allow the release (or the sale), not that they are true. A wrong licence written in good faith passes. The review before--lockis a person's job.
npm run provenance ends with ✔ [<game>] provenance clean: every file is the one reviewed, and verify:release
(created project: npm run release) passes. What an exception lets through is printed as ℹ accepted: …, by name, not
as a warning to fix.
| Message | Cause | Fix |
|---|---|---|
✖ [<game>] no provenance.json: say where every asset comes from first (provenance), provenance.json › missing: a release says where every asset comes from (validate --release) |
No file | Write it (step 1) |
<key>: no entry says where it comes from (provenance), provenance.json › <key>: no entry says where this asset comes from (validate) |
No match covers the asset |
Add an entry, or widen a pattern |
<key>: more than one entry matches (provenance), … more than one entry matches this asset; make the patterns disjoint (validate) |
Two entries cover the asset, whatever their order | Narrow one pattern |
<match>: an entry needs match, source, licence and status |
An incomplete entry | Fill the four fields |
provenance.lock.json › missing: … |
Never locked | Review, then step 3 |
provenance.json › <key>: a placeholder would ship; replace it, or add a releaseExceptions entry that names it and says why |
A placeholder in a release |
Replace the file and mark it final, or add a releaseExceptions entry |
provenance.json › <licence>: not in licences.allow (…), used by n asset(s): … |
A licence outside the policy | Allow it, replace the asset, or except it by name |
provenance.json › releaseExceptions › …: a commercial release ships no exception |
verify:commercial refuses every exception |
Replace the asset |
provenance.json › …: <licence> does not allow commercial use (or changes) |
An NC or ND licence in a commercial release |
Replace the asset |
-
provenance.json(you write it),provenance.lock.json(--lockwrites it). - The build writes, into
dist/licenses/:LICENSE,LICENSE-ASSETS,CREDITS.md,THIRD_PARTY_NOTICES.txtandassets-manifest.json(see the reference).
A lock is a file: under git, git checkout -- provenance.lock.json brings the previous one back. Changing a file after
a lock is not a mistake to undo: review it again, then lock again.
assets: [{ match, source, licence, author?, url?, prompt?, status, note? }]
| Field | Form | Meaning |
|---|---|---|
match |
an asset key with *
|
img:<manifest image id>, sfx:<file>, music:<file>, voice:<file>, video:<file>
|
source |
text | Where it comes from: a tool, a shop, a repository file |
licence |
text |
CC BY 4.0, own work… |
author |
text, optional | Required by verify:commercial
|
url |
text, optional | Where the source can be checked (a shop page, a licence, a repository) |
prompt |
text, optional | The generation prompt |
status |
final or placeholder
|
A placeholder fails a release unless excepted |
note |
text, optional | Free |
The keys map to the built files: img:<id> → public/assets/img/<id>.webp, sfx:<file> → audio/sfx/<file>,
music:<file> → audio/music/<file>, voice:<file> → audio/voices/<file>, video:<file> → video/<file>.
-
licences: { allow: ['CC BY 4.0', 'own work'] }: a release needs it; any other licence fails unless an exception names the asset. -
releaseExceptions: [{ match, reason }]: lets a named placeholder or licence through a release, with its reason. An exception never covers a placeholder added later.
| Command | Checks |
|---|---|
npm run validate |
A game with the file: every asset covered by exactly one entry, every entry complete; a lock that disagrees only warns |
npm run validate -- --release |
Requires the file, the licence policy and the lock; fails on a placeholder or licence not excepted, and on any lock difference (changed file, asset shipped since, missing file, entry edited) |
npm run provenance |
Prints the assets by licence and what changed since the lock; exit 1 when something needs a review |
npm run provenance -- --lock |
Writes provenance.lock.json: each shipped file's SHA-256 and size with its entry's claims (pattern, licence, status) |
npm run verify:commercial |
verify:release, then validate --commercial: no releaseExceptions entry, no placeholder, no non-commercial or no-derivatives licence (NC, ND), every entry with an author and a source that can be checked (a url, or a repository file named in source) |
npm run new-game (engine repository) writes a provenance.json for the art it borrows from the sample game: all
placeholders, CC BY 4.0. The sample game's own file has no exception: every one of its assets is CC BY 4.0 since 3.7,
and it passes verify:commercial. tests/fixtures/release-game fails it on purpose.
The checks above read the game's asset graph; the archive is what Vite copies into dist/, and in the engine
repository public/ is shared by every game. So every build ends with tools/dist.ts seal (a Vite plugin): the assets
that are not this game's are removed, and dist/licenses/ is written: the engine's LICENSE, LICENSE-ASSETS (the
game's own if it has one), CREDITS.md from its provenance, THIRD_PARTY_NOTICES.txt (the licence of every package
the bundle took code from, Workbox's for the service worker, the fonts' OFL) and assets-manifest.json (each file:
path, author, source, licence, SHA-256, status). Then npm run verify:dist (a step of npm run build, so of the
release) classifies every file of dist/: code, a locked asset whose bytes are the ones reviewed, a data file the game
names (ending.file), a font, an icon, a notice. Anything else fails, and so does a locked file or a notice that is
missing. The release attaches the assets manifest beside the archive.
The weight budgets and translations checks that the same release gates run are in Images, Build and release and Translations.
Limit ·
audit-is-differentnpm run audit(engine repository) is a different check: it keeps names from a private project out of the public repository. It says nothing about licences.
-
tools/provenance.ts,tools/provenance-files.ts,src/engine/tools/provenance.ts,tools/dist.ts,tests/provenance.test.ts. - Build and release · Images · Sound effects · Voices · Licences and credits.
Generated publication · publication générée — current documentation · documentation courante: quest'n'click 4.4.0 r1, documentation revision · révision de la documentation 8dc717c69acb62c4742b69c54a7e7dfb620f75d8.
Earlier versions and permalinks · versions précédentes et liens permanents: https://wanoo.github.io/quest-n-click/docs/
An edit made in this wiki is overwritten at the next publication · une modification faite dans ce wiki est écrasée à la publication suivante.
Edit the source · Modifier la source · Report an error · Signaler une erreur
Index (6)
Start (6)
Play (9)
Install (17)
- Requirements
- Install from the release archive
- Install from npm, once published
- Install from the repository to work on the engine
- doctor: checking your machine
- Image toolchain
- Audio toolchain: ffmpeg, fluidsynth, Furnace, uv
- Upgrade
- Upgrade notes: 4.4
- Upgrade notes: 4.3
- Upgrade notes: 4.2
- Upgrade notes: 4.1
- Upgrade notes: v3
- Upgrade notes: v2 to v3
- Coming from web-scumm
- Package reference
- Install troubleshooting
Create a game (55)
- Your first game
- Layout of a created project and of the engine repository
- The working loop
- Content principles and the identity contract
- Rooms
- Geometry: placement, walk zones, masks, layers, camera
- Something is visible but unreachable
- Reactions
- Game commands
- Conditions
- Flags, variables and events: which to use
- Custom code
- Characters
- Items and inventory
- World map
- Dialogues
- Scripts and events
- Moving characters: patrols and walks
- Exits
- Chapters and objectives
- State and saves: persistent or temporary, renaming an id, migrations
- Staging: wide rooms and animations
- The stage: lights, particles, floors
- Skin and fonts
- Title and credits
- Heroes: several characters and hero choice
- Built-in minigames
- A custom minigame
- Translations
- Music in stems
- Sound effects
- Voices: per language and per hero
- Images: prompts, cutting sheets, transparency, scale
- Asset provenance
- The storyboard, source of truth
- Puzzle design
- Classic mechanics
- Review pages
- DSL reference
- Checking your game
- What the solver proves
- Solver options
- Playtests
- Remix
- Speedrun for authors
- The sealed ending
- Production template
- Example games
- Working with an AI
- Build and release a game
- Publish on GitHub Pages
- The static game on Clever Cloud
- Other static hosts
- Sub-path, cache and service worker, incomplete deploys, going back
- Testing on a phone over the LAN
Local Studio (24)
- The local Studio: overview and launch
- Edit a room
- Placement and stage
- Preview, apply, undo
- Storyboard
- Assets and cutting
- Check: validator, solver, critical path, heat, health, coverage
- Before and after captures
- Semantic diff
- Play and replay a session
- Rule explainer
- Language and objectives
- Voices and the heroes × languages matrix
- Map
- Notes
- Remix in the Studio
- Music
- The Assistant: bring your own key
- Demo mode and studio-apply
- Local and LAN security
- Studio API
- Local MCP: setting up each client
- MCP tools
- Studio troubleshooting
Team Studio (21)
- What runs where
- Concepts: revision, transaction, span, lease, preview, build
- Starting as an invited dev
- Working together day to day
- Roles and actions: the full matrix
- Invitations
- Managing members
- Write refused on the hosted Studio: stale base revision (409)
- Write refused on the hosted Studio: span locked (423)
- Recovering after a lost lease, a disconnection or a stale preview
- Comments
- Map and semantic diff
- Publishing builds
- Remote MCP
- The game in Git
- Upgrading the engine of a hosted game
- Hosted assets
- The server's command line
- Health and metrics routes
- Trying it locally with compose.yml
- Known limits
Clever Cloud (23)
- Clever Cloud: overview, cost and prerequisites
- Apps and add-ons
- Domains and TLS
- Keycloak
- Generic OIDC and GitLab
- Configuration
- First deployment
- Backups
- RPO and RTO
- Restore the Studio on a fresh installation
- Redeploys
- Upgrading the server and checking state after a migration
- Limits of going back
- Monitoring
- Security
- Rotating keys
- Recovering admin access
- Changing domain or OIDC provider
- Worker, PostgreSQL or Cellar down
- Exporting the game and leaving the installation
- Retention
- Clever Cloud troubleshooting
- Costs and teardown
Reality Bridge and connectors (16)
- The Reality Bridge: what it is
- Quick start
- Guarantees
- Install and run the Bridge
- Backup and restore
- Several tenants
- Signals and the manifest
- The Bridge's command line
- Connectors overview
- Email connector
- Telnet connector
- SSH connector
- Open Badges connector
- The connector SDK
- Security: Biscuit and signatures
- Bridge and connector troubleshooting
Contribute (25)
- Welcome
- Developer setup
- The dev loop
- Before a pull request
- Conventions
- Writing documentation
- Architecture
- Code tour
- Import boundaries
- Which tests run when
- Mutation testing
- The coverage ratchet
- The quality baseline
- CI explained
- Field passes
- Benchmarks
- Releasing
- npm packages
- Decisions and ADRs
- Governance
- Bot pull requests
- Contributing with AI agents
- Security policy
- Code of conduct
- Licences and credits