diff --git a/lith/Caddyfile b/lith/Caddyfile index 9ac6cc1e2f..300239eec5 100644 --- a/lith/Caddyfile +++ b/lith/Caddyfile @@ -847,7 +847,24 @@ nopaint.art { handle_path /classic* { file_server } - file_server + handle /gallery* { + file_server + } + # A single archive id gets a human-readable record page. Existing files + # (runtime assets, icons, manifests) continue through the final handler. + @nopaint_archive_record { + not { + file + } + path_regexp archiveRecord ^/[^/]+/?$ + } + handle @nopaint_archive_record { + rewrite * /painting/index.html + file_server + } + handle { + file_server + } } www.nopaint.art { diff --git a/papers/nopaint-3-full-shape/nopaint-3-full-shape.tex b/papers/nopaint-3-full-shape/nopaint-3-full-shape.tex index 9e86e88113..f2723f0906 100644 --- a/papers/nopaint-3-full-shape/nopaint-3-full-shape.tex +++ b/papers/nopaint-3-full-shape/nopaint-3-full-shape.tex @@ -273,6 +273,28 @@ Existing AC contracts make this concrete: Saving therefore has four explicit levels: \textbf{local checkpoint}, \textbf{cloud session sync}, \textbf{published painting}, and \textbf{published Lisp organism}. Only the last two should emit public profile events. +\section{Archive records, ownership, privacy, and removal} + +The historical archive contains 32,184 anonymous paintings saved between 2021 and 2025. Each index slug should resolve to a stable human-readable record at \mono{nopaint.art/SLUG}, not directly to an uncontextualized PNG. The record presents the image, archive id, save date, machine-generated description and tags, privacy-review status, provenance limits, original file, and a prominent flag/removal route. Gallery thumbnails link to these records. + +\begin{tabularx}{\textwidth}{@{}L{1.35in}Y@{}} +\toprule +\textbf{Question} & \textbf{Current conclusion and product rule} \\ +\midrule +What AC owns & The No Paint software, brand, domain, storage infrastructure, archive compilation, metadata work, and aggregate curatorial presentation. \\ +Individual image rights & Anonymous saving and archive custody do not by themselves prove a complete copyright assignment for every individual painting. Do not present that uncertainty as settled ownership. \\ +Personal data & A camera-derived image, recognizable face, painted name, signature, location clue, or other identifying content can create a privacy interest even when the record has no account or handle. \\ +Removal standing & A person may flag privacy, personal safety, a minor, accidental capture, personal information, creator interest, or another rights concern without first proving copyright ownership. \\ +Data minimization & A removal request asks for archive id, reason, and only enough contact information to reply. Do not publish the request or require an account. Preserve a minimal private review/audit receipt. \\ +\bottomrule +\end{tabularx} + +\begin{plain} +\textbf{Audit finding, 2026-07-27:} the gallery contains a photo-face moderation interface, and its descriptions visibly include selfie/person records, but the published 32,184-item manifest currently marks \textbf{zero} records as \mono{unsafe}. Therefore the archive-wide face/privacy test is \textbf{not complete}. Until a documented detector plus human review has run, every unflagged record must say ``archive-wide face/privacy review pending,'' never ``cleared.'' +\end{plain} + +Recommended review states are \mono{pending}, \mono{machine-flagged}, \mono{human-review}, \mono{restricted}, \mono{removal-requested}, \mono{removed}, and \mono{cleared-with-date}. A face detector is a triage aid, not a privacy verdict: false negatives are expected, stylized or embedded photos may evade detection, and non-face personal data still matters. Default public behavior should blur/restrict strong photographic-person matches pending review; removed records retain only a non-public minimal tombstone sufficient to prevent accidental re-publication. + \section{Painting to code, without pretending} A raster cannot reveal one true source program. The product should call the result a \textbf{reading}, \textbf{response}, or \textbf{inferred score}. diff --git a/system/public/nopaint.art/gallery/index.html b/system/public/nopaint.art/gallery/index.html index 58d2d65ac6..f316d21ba0 100644 --- a/system/public/nopaint.art/gallery/index.html +++ b/system/public/nopaint.art/gallery/index.html @@ -101,7 +101,7 @@ for (; shown < end; shown++) { const p = view[shown]; const a = document.createElement("a"); - a.className = "cell"; a.href = CDN + p.id + ".png"; a.target = "_blank"; + a.className = "cell"; a.href = "/" + encodeURIComponent(p.id); const img = document.createElement("img"); img.loading = "lazy"; img.decoding = "async"; img.src = THUMB + p.id + ".webp"; diff --git a/system/public/nopaint.art/painting/index.html b/system/public/nopaint.art/painting/index.html new file mode 100644 index 0000000000..ac82274ef8 --- /dev/null +++ b/system/public/nopaint.art/painting/index.html @@ -0,0 +1,84 @@ + + + + + +No Paint — archive record + + + + + +
+ + +
This archive record was not found. Browse the gallery.
+
+ + +