the tool should inform the user that the metadata is saved in the usernamespace and that it is by definition CC0. using this tool means the user agrees to this. there should be a button "agree, remind me next time" "agree and don't remind me anymore"Show a one-time, dismissable CC0 acknowledgment modal informing the user that the workbench persists their drafts/preferences to a public Commons user-subpage, and that this content is therefore licensed CC0 by Commons policy.
== Why ==
The Upload Workbench writes user state to two public JSON pages on Commons:
- `User:<self>/UploadWorkbench/Preferences.json` — UI prefs, required-field config, custom column defs
- `User:<self>/UploadWorkbench/Metadata.json` — drafts (per-file edits), filename cache, hidden-file list, history cache, manual photo groups
Both pages are written under the user's own user namespace and are publicly visible / mirrored / archivable like any other Commons page. By Commons convention all wiki contributions are CC BY-SA 4.0 + GFDL by default, but per [Commons:Licensing#Material_in_the_public_domain](https://commons.wikimedia.org/wiki/Commons:Licensing) factual data has no copyrightable expression — the maintainer's intent is that this data is treated as effectively CC0 (public-domain dedication). The user should be informed of this once, with an explicit acknowledgment, before the tool starts persisting their data to public pages.
== What ==
Add a small modal that appears the first time a logged-in user lands on the workbench. The modal:
- Explains briefly that drafts and preferences are saved to a public page in the user's user namespace.
- States clearly that this content is, by intent of the maintainer, dedicated as CC0.
- Provides a link to the user's own `User:<self>/UploadWorkbench/` so they can inspect what's stored.
- Has two buttons:
- **"I agree — remind me next session"** → records the acknowledgment but reprompts on next session.
- **"I agree — don't remind me again"** → records the acknowledgment permanently; modal never appears again.
- The modal blocks no functionality (the user can dismiss with either button or Esc), but it appears before any user-store write happens for a fresh user.
- Pressing Esc / backdrop click is treated as **no acknowledgment** (modal will reappear on the next session) — explicit choice required to suppress.
== Where ==
- Persistence: extend `Preferences.json` with a single new key:
```
cc0Acknowledgment: { acknowledgedAt: <ISO>, suppressFurther: <bool>, version: 1 } | null
```
Read/write via the existing `getPref` / `setPref` API in `src/api/user-store.js:766-779` (just-add-a-key — no schema migration).
- Trigger: mounted in `<App>` (`src/app.jsx:1932-1977`) alongside the existing `<InfoModal>`. Decision logic:
- If `cc0Acknowledgment` is missing or null → show modal on mount.
- If `cc0Acknowledgment.suppressFurther === true` → never show.
- Otherwise (acknowledged but not suppressed) → show on every fresh page load (per-tab is fine; the wiki write happens on click, the in-memory render decision is per-tab).
- New UI file: `src/ui/cc0-modal.jsx` (regular ESM import, follows the `wikitext-preview-modal.jsx` pattern — small, self-contained, uses existing `.modal-backdrop` / `.modal` styles from `src/app.css:3631-3682`).
== Acceptance ==
- Fresh login (no `cc0Acknowledgment` pref) → modal appears on first paint.
- Click "remind me next session" → modal disappears; reload page → modal reappears.
- Click "don't remind me again" → modal disappears; reload page → modal does **not** reappear.
- Esc / backdrop click → modal disappears; reload page → modal reappears.
- DEMO_MODE → modal does not appear (no auth, no wiki writes).
- Modal copy is in English (the rest of the UI is too) and the rendered Preferences.json contains the new field after either click.
- `npm run build` (incl. `scripts/check-undefined-refs.mjs`) passes.
== Notes ==
- Pre-existing users (anyone who has used the tool before this MR lands) will see the modal once — this is intentional. They retroactively get the chance to acknowledge.
- Storage shape includes a `version` field so a future copy/scope change can re-prompt by bumping the version number (the check becomes `ack.version === 1 && ack.suppressFurther` — out-of-date version reprompts).