Skip to content

feat(4shared): add 4shared mirror - #90

Open
sarendis56 wants to merge 2 commits into
aiming-lab:mainfrom
sarendis56:add-4shared-mirror
Open

feat(4shared): add 4shared mirror#90
sarendis56 wants to merge 2 commits into
aiming-lab:mainfrom
sarendis56:add-4shared-mirror

Conversation

@sarendis56

@sarendis56 sarendis56 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a deterministic 4shared mirror as WebHarbor site 24 on port 40023.

  • Implements public search, category browsing, file details/previews, downloads, authentication, account editing, folders, uploads, rename/move/trash/restore, favorites, Saved files, sharing, comments, activity, and plan checkout.
  • Adds 20 contributor-format WebVoyager tasks spanning research, comparison, authentication, and persistent multi-step actions.
  • Registers 4shared in the startup script, control server, Docker image, and project documentation.
  • Uses 122 public catalog records across seven categories plus four benchmark accounts and deterministic account state.

Review remediation

The final review pass replaces every reported placeholder/fidelity gap and fixes the adjacent workflows found during manual review:

  • All 16 image records now load real, locally served photographs with recorded provenance.
  • The homepage now uses the captured 4shared upload illustration, real mobile-app QR code/frame, and Google/Apple/Huawei logos.
  • 500GB and 1TB selections preserve their capacity, advertised annual price, account plan, and storage allowance through checkout.
  • Upload category defaults to extension detection, so PDF task uploads persist as Documents.
  • Authenticated search is explicitly labeled as public-file search; Saved files navigation and page naming agree.
  • Exact-name searches used by tasks 6 and 7 now return 6 and 8 plausible results; both targets appear at position 6.
  • Press Room, Blog, and file-converter footer links have distinct working destinations.
  • 320px result cards, related-file titles, and account navigation no longer clip or escape the viewport.

Final per-task and hardening audit

Screenshots

Desktop — 1440px Mobile — 390px
4shared homepage at 1440px 4shared homepage at 390px

Assets

Validation

  • Final image: sha256:82a343822f5c0622f1cdd92c4dd3f24e9658f889019396bb9394e2ede5054e0f (4,356,239,480 bytes).
  • 24/24 registered sites healthy; /reset-all returned 24/24 ready.
  • 20/20 tasks passed in the packaged image through 252 visible Playwright steps. Each task reset before and after execution.
  • 51/51 page/viewport checks passed at 1440, 390, and 320 px: zero overflow, broken images, stretched images, or out-of-bounds controls.
  • 7/7 supplementary flows passed: signed-out upload entry, registration/re-login, both adjacent premium plans, footer destinations, and authenticated search scope.
  • Seed functions are function-level idempotent: rerunning both leaves row counts unchanged.
  • Runtime and seed database remain byte-identical after boot/reset: MD5 b577adc216900a6f0e3974a80e51c04c.

Seeded state

  • Files: 146 total / 122 public
  • Users: 4
  • Folders: 16
  • Favorites: 16
  • Saved files: 12
  • Download logs: 8
  • Comments: 12
  • Share links: 4
  • Plan orders: 1

No GitHub or Hugging Face merge is performed by this contribution update.

@sarendis56

Copy link
Copy Markdown
Contributor Author

Final contributor-side review — 4shared

Reviewed code head: 83928fa1d5e8cebb4c5cccf0d4079f8f278e6f76
Reviewed HF asset head: f426447ee209071110a5de80026a72d049bbd97f

Result

  • 20/20 benchmark tasks pass through visible Playwright interactions from the designated homepage, with a reset before and after every task (252 recorded browser steps).
  • 51/51 responsive page checks pass across 1440, 390, and 320 px: no overflow, broken/stretched images, or out-of-bounds controls.
  • 7/7 supplementary flows pass, including registration/login, signed-out upload handling, 500 GB and 1 TB checkout selection, distinct footer destinations, and authenticated public-search labeling.
  • Reset is byte-identical: runtime and seed DB MD5 are both b577adc216900a6f0e3974a80e51c04c.
  • All 24 bundled sites pass startup and /reset-all checks.

Remediation covered

  • Replaced missing/fallback catalog figures with real, locally served photographs and documented provenance.
  • Replaced the fabricated app-download QR graphic with the genuine captured 4shared QR asset; also restored the genuine upload and mobile-store UI assets.
  • Corrected premium-plan persistence, upload type detection, saved-files/search wording, footer routing, mobile wrapping, and image/metadata consistency.
  • Added nontrivial Federalist and ArchivePeek distractors to prevent first-result and insufficient-distractor leakage.

Full evidence and screenshots: review-reports/PR-90-FINAL-AUDIT.md

Pending integration step only: merge HF assets PR #62, then update .assets-revision to the resulting merged asset commit and rerun CI. No GitHub or Hugging Face merge was performed here.

This comment records contributor-side audit evidence; maintainer approval remains separate.

@JeremyJC67

Copy link
Copy Markdown

Taking ownership of the review for this PR (Track B). Plan: build and drive the mirror per the review-env pipeline, post a structured review here (mechanical / visual / functional / task-quality, with evidence), and open a separate Review: PR that keeps @sarendis56's commits intact and adds the grading contract (deterministic verifiers + judge rubrics for every accepted task, validated with no-op / pass / shortcut / wrong-answer / state-mismatch runs). Expect the review within the next day or two.

JeremyJC67 added a commit to JeremyJC67/WebHarbor that referenced this pull request Sep 11, 2026
@JeremyJC67

Copy link
Copy Markdown

Review: 4shared (PR #90) — site by @sarendis56, verifiers by reviewer

Verdict: APPROVE, conditional on one release-mechanics item (HF #62 merge + .assets-revision repin). The mirror is mechanically sound (byte-identical seed across four boots and a full read-only sweep), functionally complete (every write path drives end to end), and all 20 tasks are accepted — two reworded by me (task 2 was solvable from the first search result; task 16 named a plan that exists three times). The grading contract (20 deterministic verifiers + judge rubrics) is in the companion Review: PR and passes its full validation matrix (100/100 cells, no LLM).

Reviewed standalone on the review server (Flask app booted exactly as websyn_start.sh + site_runner.py do, port 45004) and driven with a real Chromium via Playwright; assets fetched from HF discussion #62 (refs/pr/62 = f426447e…). The PR was CONFLICTING and 28 commits behind main, so I rebased it: main already has 24 sites with walmart_careers on 40023 — the port this PR claimed — so 4shared becomes site 25 → port 40024 (provisional). The full 25-site Docker environment was then built from the review branch on the same host and passed every control-plane check (row at the end of §1).

1. Mechanical checks — PASS (standalone + full Docker environment)

Check Result Evidence
Syntax (py_compile app.py / seed_data.py / _health.py / control_server.py / site_runner.py) ok PYCOMPILE_OK
bash -n websyn_start.sh, git diff --check ok both clean on the review branch
Asset archive (scripts/validate_asset_archive.py) ok validated 30 managed members for 4shared; no ._* / .DS_Store members; instance_seed/4shared.db + 16 photos + 6 UI SVGs (static/images/, 14 MB); external_cache/ empty
Tarball integrity ok sha256 f50985a7ba74ba778b22583d1e64a228a9d650b9376509db29b87339e065ff0a = the PR body's value
Seed DB md5 ok b577adc216900a6f0e3974a80e51c04c (= contributor's claim)
Byte-identical instance vs seed ok ×4 after first boot; after the full read-only Playwright sweep; after 2nd and 3rd boots from seed — all b577adc2…. After the write-path pass the runtime DB was 4c7f3376… (expected) and a reboot restored b577adc2…
/_health ok {"files":122,"ok":true,"site":"4shared"}
Idempotent seeding ok seed_database() gated on FileItem.query.filter_by(public=True).count(), seed_benchmark_users() gated on alice's row (seed_data.py:221-224, 275-278)
Registration (after rebase) ok SITES shell == control_server (25 entries), 4shared index 24 → 40024; Dockerfile EXPOSE 8101 40000-40024, "25 Flask mirror sites"; docs swept (README / AGENTS / CONTRIBUTING / CLAUDE / agent_demo README)
Registry tests (this branch) ok walmart_careers test_exact_25_site_registry_and_port, test_docker_preserves…, test_shared_documentation_uses_25_site_range, test_assets_pin_is_immutable_merged_revision, test_no_merge_conflict_markers…; rotten_tomatoes test_task_manifest_and_registry7 passed
tasks.jsonl ok 20 rows, one JSON per line, ids 4shared--0..19, contributor keys exactly web_name,id,ques,web,upstream_url; web = http://localhost:40024/ on all rows (was 40023)
Cross-site imports ok grep -rn "from sites\.|import sites" sites/4shared → none
.assets-revision needs repin PR left it at 070123d7… (26 files on HF, no 4shared.tar.gz); after rebase it is main's 65c479f8… (27 files, still no 4shared.tar.gz). refs/pr/62 has it (14,209,943 bytes); HF discussion #62 is still open
Docker (from review/pr-90-4shared, assets refs/pr/62) ok docker build ok (4.72 GB); alt ports 44000-44024: 25/25 return 200; /health ok, 25/25 alive+ready, 4shared on internal 40024; POST /reset/4shared → md5 b577adc2… == seed; GET+POST /login then reset → still b577adc2…; docker restart → still b577adc2…; POST /reset-all ok, 25/25 ready in 1.76 s; verifier no-op matrix in the container (--container, DBs via docker cp): 20/20 FAIL, 0 errors; registry tests 4 passed

2. Visual fidelity — PASS

  • Homepage reproduces 4shared's public landing structure: search hero ("Search, store and share easily"), the drop-zone with the captured upload-image-initial.svg, category chips Music / Video / Apps / Images / Books / All Files, the "Get 4shared App" band with the real QR frame + deep-link QR and Google / Apple / Huawei badges, and the five-column footer (Site Links / Help / About / Convert to PDF / Legal). Signed-in homepage swaps the drop-zone target to /upload and shows the header search ("Search public files").
  • Images: all 16 image records render real photographs (naturalWidth > 0 for 16/16 cards on /category/images; zero broken <img> on any surveyed page). Provenance is in ASSET_SOURCES.md (3 reused WebHarbor photos, 13 Wikimedia Commons, 6 captured 4shared UI SVGs).
  • Detail pages (opened 15): uploader / date / tag line (ext · size · category · license) / actions (Open in…, To library, Download, Share) / "About this file" + notes / comments / "You might also like" — populated everywhere.
  • Responsive: document.documentElement.scrollWidth = 768 at 768 px (home and search) and 390 at 390 px — no horizontal overflow.
  • Not done: a live side-by-side against 4shared.com (no outbound browsing from the review host). Judgement is against 4shared's public layout and the contributor's captured UI assets; the contributor's own 1440/390 screenshots in review-reports/assets/ match what I rendered.

Screenshots: page_home.png, page_home_768.png, page_home_390.png, page_premium.png, category_images.png, category_books.png, detail_t0_target.png, detail_t1_target.png, detail_t4_target.png, detail_t6_target.png.

3. Functional depth — PASS (every path below driven with Playwright; DB writes confirmed)

Flow Result
Login alice.j@test.com / TestPass123! /account, header shows "Alice Johnson", stats "5 files / 4 favorites / Free"
Wrong password flash "The email or password is incorrect.", stays on /login
Register (+ re-login, duplicate email) short password blocked client-side (minlength 8) and server-side (app.py:365); "Welcome to 4shared…" → /account; re-login works; duplicate → "An account with that email already exists."
Search OR-scored, multi-word works ("garden bird guide" → 17, "field recording notes" → 28, "Boston Celtic" → 0 with a proper empty state); category tabs + sort (relevance / downloads / newest / size) work; q= empty → all 122
Browse 7 category pages populated: Music 16, Video 16, Apps 21, Images 16, Books 21, Documents 16, Archives 16; unknown category → 404
Favorite add / remove heart toggles ("Add to favorites" → "Remove from favorites" after reload), /favorites count 4 → 5 → 4
Save to My 4shared flash "Saved to My 4shared.", /saved (titled "Saved files") lists it
Account edit location / bio persist after reload; display name < 2 chars rejected
Folder create card appears with "0 files"; duplicate name → "A folder with that name already exists here."
Upload (simulated record) accessibility-session-notes.pdf 640 KB → Work, auto-classified Documents, Private; no-extension name rejected; public upload becomes searchable
Rename / move in-row forms; redirect follows the file's folder; no-extension rename rejected
Trash / restore data-confirm dialog honoured; file listed in Trash with "Deleted "; Restore returns it to its folder
Share link label + permission persist; public /shared/<token> page shows file, owner, access, size
Comment count 0 → 1, rendered with author/date; body < 2 chars rejected
Download POST → "Your download is ready" page; appears under /activity "Recent downloads"
Premium checkout 100 GB ($77.88/yr) / 500 GB ($29.99/yr) / 1 TB ($39.99/yr) checkout pages carry the right plan; confirmation "Premium 100 GB activated … 100 GB of storage"; /account shows "Premium" + "… of 100.0 GB used"; bad card → validation flash
Access control signed-out /account, /upload → login redirect; signed-out or other-user access to a private file / its share page → 404; owner → 200
Footer / misc /press-room, /blog, /help, /about, /convert/<fmt>-to-pdf (form works) all 200; unknown path → styled 404

Screenshots: fn_account_alice.png, fn_favorites_after_add.png, fn_saved_after_save.png, fn_my_files_work_after_move.png, fn_trash_after_delete.png, fn_share_after_create.png, fn_shared_page.png, fn_upload_result.png, fn_comment_after_post.png, fn_premium_confirmed.png, fn_account_bob_after_upgrade.png, fn_register_done.png.

4. Task quality — PASS (20/20 accepted; 2 reworded)

All catalog facts are synthetic (fictional uploaders "Open Culture Shelf", "Atlas Media Lab", …; invented durations / page counts / versions), so no task is answerable from prior knowledge; answers are stable (fixed SEED_TIME, no "today" values). None of the decisive detail facts (durations, kHz, LUFS, ISO, chapter counts, page numbers, versions, runtimes) appear on search cards or category cards — I grep'd every results page for them: zero leaks. Steps = actions my harness needed (incl. done).

id solvable leak distractors (results / target position / near-misses) steps verdict note
0 yes none Music + "nature ambience": 7 results, target #5; Morning Meadow (48 kHz but 12:08), Rain on Library Windows, Ocean Pier 7 ok
1 yes none 16 images, target #11 by download order; London Skyline is the same 3840 × 2160 (20:14 / 24 mm) 5 ok
2 yes none "classic fiction" in Books: 10 results; original target Pride and Prejudice was #1 → re-anchored to The Time Machine (#4; Pride and Prejudice / Tom Sawyer / Anne ahead of it) 7 ok (reworded) see fix 3
3 yes none 11 results, target #6; Community Garden Crop Calendar, Garden Planning Grid Pack, GardenPlot Planner, Community Garden Summer Tour 6 ok
4 yes none 9 results, target #2 (Open Icon Accessibility Set is #1); Accessible Presentation Templates, CaptionCraft, FontLedger 6 ok license shown twice on the page (tag "Open-source package", notes "GPL-3.0"); verifier accepts either — nit 6
5 yes none (runtimes only on detail pages) by name; both pages required; 16 videos 5 ok comparison task
6 yes none 6 results, target #6 behind 5 "Federalist Papers …" titles (confirms the contributor's claim) 6 ok stateful (download row)
7 yes none 8 results, target #6 behind 5 "ArchivePeek File Inspector …" variants (confirms the claim) 11 ok stateful
8 yes n/a (by name) 19 results for the exact name, target #1 — acceptable for a by-name action task 11 ok stateful
9 yes n/a account form 9 ok stateful
10 yes n/a root vs 4 existing folders 8 ok stateful
11 yes n/a 4 folder choices; category auto-detect 11 ok stateful
12 yes n/a file lives in Work; 4 destinations 11 ok stateful (rename + move)
13 yes n/a Trash holds exactly one file per account 7 ok stateful
14 yes n/a file in Shared Projects; 2 permission options 11 ok stateful
15 yes n/a (by name) 19 results, #1 10 ok stateful
16 yes n/a three annual Premium plans → reworded to name the 100 GB plan 11 ok (reworded) see fix 4
17 yes n/a 4 chained mutations (folder → upload → rename → share) 20 ok hardest task; stateful
18 yes none (counts only on detail pages) 21 books, 3 named; compare + login + save 13 ok comparison + stateful
19 yes none 40 results, target #2; Field Recording Metadata Forms (#1), Library Digitization Workflow, Open Photography Metadata Handbook 12 ok favorite + download + report

Difficulty: all 20 need ≥ 5 actions; 5 / 17 / 18 / 19 need multi-page comparison or chained actions; 17 (four dependent mutations) and 18 (three pages + login + save) would challenge a frontier agent. After the task-2 re-anchor no task is solvable by clicking the first result.

5. Required fixes before approval

  1. Release mechanics (blocking, maintainer): merge HF discussion feat(webmd): add WebMD mirror site (20 tasks, hardened) #62 (4shared.tar.gz, commit f426447ee209071110a5de80026a72d049bbd97f), then repin .assets-revision to the merge sha. Neither 070123d7… (the PR's pin) nor 65c479f8… (current main) contains the tarball; the image will fail to build until then.
  2. Rebase / port (done in the Review PR): the PR registered 4shared at index 23 / 40023, which main now assigns to walmart_careers. I rebased onto main, dropped the conflicting registration/docs hunks from the contributor's first commit and redid them in ff47ef7 as site 25 / 40024 (websyn_start.sh:8, control_server.py:29, Dockerfile:2,75, docs, both registry tests, sites/4shared/tasks.jsonl web, sites/4shared/app.py:23 SITE_PORT). Port is provisional.
  3. Task 2 (done, f50aec3): sites/4shared/tasks.jsonl row 3 — the original target (Pride and Prejudice, seed_data.py:141) is the first result for "classic fiction" in Books because scored_search ranks by score then download_count (app.py:261) and it has the highest count of the score-2 group; the contributor's audit claims "no first-item target", which is false here. Re-anchored to The Time Machine (seed_data.py:136; position 4). Contributor: please confirm or propose another non-first target.
  4. Task 16 (done, f50aec3): "the annual Premium plan" is ambiguous — premium.html:8-10 offers three annual plans. Reworded to "annual Premium 100 GB plan" and to ask for plan name + allowance "shown on My 4shared".
  5. Docker checks — done, all green (see §1): 25/25 sites 200, /reset/4shared byte-identical (b577adc216900a6f0e3974a80e51c04c) before and after a dirty request and after docker restart, /reset-all 25/25 in 1.76 s.
  6. Nits (non-blocking, contributor's call): (a) templates/search.html:7 — the category tab row omits Documents while the filter <select> and nav include it; (b) app.py:32-36 / premium.html:8-10 — pricing is non-monotonic (100 GB $77.88/yr vs 500 GB $29.99/yr vs 1 TB $39.99/yr); (c) seed_data.py:85 vs :98 — ColorScope's catalog license is "Open-source package" while its notes say "GPL-3.0" (pitfall 7, inconsistent fields; the verifier accepts either); (d) app.py:380/logout is a GET; (e) app.py:283-285 computes featured/popular/recent lists that index.html never renders.

6. Grading contract (reviewer deliverable, sites/4shared/verify/)

Deterministic-first, no LLM in the verdict path (the llm_* helpers exist for parity with merriam_webster and are never consulted; every verifier decides with --no_llm True). Ground truth is hardcoded in verify_N.py; tasks.jsonl carries only verifier_path + an English judge_rubric of rules (no answers; there is no answer key).

Every verifier enforces: (1) run-package identity — exact task id, agent_done, non-empty answer, every recorded URL on the same loopback host and port as start_url, every referenced screenshot present and PNG-framed; (2) navigation gates — exact /file/<slug> detail pages, an on-site /search (query tokens) or /category/<c> visit where the task says search/browse, /login + the typed account email for login tasks, and ordering (login → action, detail → download, checkout → account); (3) answer matchers — exact filename incl. extension, uploader, standalone numbers (never part of a time / ratio / version), runtimes, displayed sizes, resolutions, and a comparison-claim reader for tasks 5 / 18; (4) SQLite after-state — snapshot contract validated (9 tables, seed counts, schema equality, benchmark users), read-only tasks require all 9 tables row-identical, stateful tasks the exact delta and nothing else:

task exact persisted delta required
6 +1 downloads (file 81), download_count +1 on 81 only
7 / 8 +1 favorites (alice, 38) / +1 saved_files (alice, 97); not pre-existing
9 alice users row: location, bio only, exact values; other users untouched
10 +1 folders (bob, parent NULL, "Survey Exports")
11 +1 files (carol, folder 9 Work, exact name, 655360 B, exact description, private, Documents)
12 file 123: filename/extension/folder_id(3)/modified_at only
13 file 146: deleted 1 → 0 only
14 +1 shared_links (alice, 125, download, "Audio volunteers")
15 +1 comments (bob, 93, exact body)
16 +1 plan_orders (bob, Premium 100 GB, annual, 77.88, 4242); bob plan/storage_limit_mb only
17 +1 folder, +1 file (final name, in it, 393216 B, private), +1 view link on it; folder ≤ upload ≤ rename ≤ link timestamps
18 +1 saved_files (david, 90) after all three detail pages
19 +1 favorites + 1 downloads (alice, 96), download_count +1 on 96 only

7. Validation matrix (CONTRIBUTING §C; verify/tests/)

drive_tasks.py boots the site from instance_seed/ for each task, drives it with Chromium and writes agent.py-shaped run dirs (trajectory + screenshots + initial.db/after.db); run_matrix.py derives the negative variants and runs every verifier with --no_llm True:

variant expected result first failing check (typical)
no-op — homepage only, empty answer, clean DB FAIL ×20 20/20 FAIL final_answer_nonempty
genuine Playwright run PASS ×20 20/20 PASS
shortcut — correct answer + correct DB, every URL rewritten to the homepage FAIL ×20 20/20 FAIL searched_* / visited_detail_* / visited_login_page
wrong — wrong answer (0-5, 16, 18, 19) or wrong persisted row (6-15, 17) FAIL ×20 20/20 FAIL answer_has_*, download_row_added, target_favorited_for_alice, upload_private_documents, link_permission_download, …
state-mismatch — genuine trajectory, after.db = seed FAIL ×14 (tasks 6-19) 14/14 FAIL *_exact_delta / target_* / file_restored

agent_demo/eval_judge.py --run_dir <genuine run 7> --verifier Truepass: True success: True reason: all checks passed, exit 0; on the no-op → pass: False … reason: final_answer_nonempty. One verifier bug was found and fixed by this matrix: the comparison-claim reader split sentences on the "." inside …Seas.epub, failing the genuine task-18 run; now only sentence punctuation followed by whitespace splits.

8. Evidence (commands and outputs, condensed)

$ hf download ChilleD/WebHarbor 4shared.tar.gz --repo-type dataset --revision refs/pr/62
f50985a7ba74ba778b22583d1e64a228a9d650b9376509db29b87339e065ff0a  tarball/4shared.tar.gz   (commit f426447ee209071110a5de80026a72d049bbd97f)
$ python3 scripts/validate_asset_archive.py ../tarball/4shared.tar.gz 4shared
[fetch] validated 30 managed members for 4shared          # junk members: none
$ python3 scripts/extract_asset_archive.py ../tarball/4shared.tar.gz sites 4shared
[fetch] installed managed roots for 4shared
$ md5sum instance_seed/4shared.db ; find static/images -type f | wc -l
b577adc216900a6f0e3974a80e51c04c   /  23 (16 jpg + 6 ui svg + .gitkeep)
$ python3 -m py_compile sites/4shared/*.py && echo PYCOMPILE_OK                     -> PYCOMPILE_OK
$ rm -rf instance && cp -a instance_seed instance && python -c "from app import app; app.run(host='127.0.0.1', port=45004, ...)"
GET / -> 200 ; /_health -> {"files":122,"ok":true,"site":"4shared"}
$ md5sum instance/4shared.db instance_seed/4shared.db        # boot 1, after read-only sweep, boot 2, boot 3
b577adc216900a6f0e3974a80e51c04c  instance/4shared.db
b577adc216900a6f0e3974a80e51c04c  instance_seed/4shared.db
$ md5sum instance/4shared.db   # after the write-path pass (expected to differ)
4c7f337653bdb6e302508247d02d6c1a
$ sqlite3 seed: users 4 | folders 16 | files 146 (122 public) | favorites 16 | saved_files 12 | downloads 8 | shared_links 4 | comments 12 | plan_orders 1
$ uv run python survey_ro.py   (Playwright, read-only)
category music 16 | video 16 | apps 21 | images 16 (16 imgs load, 0 broken) | books 21 | documents 16 | archives 16 | nope 404
search t0 Music  n=7  target_pos=5  leaks=[]      search t2 Books n=10 target_pos=1 (Pride and Prejudice)  leaks=[]
search t3 n=11 pos=6 | t4 n=9 pos=2 | t6 n=6 pos=6 | t7 n=8 pos=6 | t19 n=40 pos=2 | "Boston Celtic" n=0 empty-state | leaks=[] on all
detail t0 id=13 'Atlas Media Lab' 'Duration 10:45 · 48 kHz WAV source · normalized to -16 LUFS.'
detail t1 id=55 'Open Culture Shelf' 'Resolution 3840 × 2160 · ISO 200 · exposure 1/80 s.'
detail t4 id=44 tags=['ZIP','5.8 MB','Apps','Open-source package'] 'Version 5.0.0 · WCAG contrast preview · GPL-3.0.'
detail t5 22 '27:03' / 29 '19:05' ; t6 81 '672 pages · 85 essays · searchable topic index.' ; t18 77 432/61, 73 412/38, 90 512/47 ; t19 96 '46 pages · 12-week … risk register on page 39.'
scrollWidth home_768=768 search_768=768 home_390=390
$ uv run python survey_rw.py   (Playwright, write paths)   -> every row in §3; bob on alice's private file/share: 404/404, own file 200
$ SITES consistency: shell==control: True | n = 25 | 4shared index 24 -> port 40024 ; EXPOSE 8101 40000-40024 ; # 25 Flask mirror sites
$ pytest -k "registry or docker or documentation or conflict or assets_pin" walmart_careers/tests rotten_tomatoes/tests  -> 7 passed
$ uv run python sites/4shared/verify/tests/drive_tasks.py --python <venv> --port 45004   -> 20/20 tasks driven (5-20 steps)
$ uv run python sites/4shared/verify/tests/run_matrix.py   -> table in §7 ; ALL EXPECTATIONS MET
$ curl https://huggingface.co/api/datasets/ChilleD/WebHarbor/tree/65c479f8…  -> 27 files, 4shared.tar.gz: False (070123d7…: 26 files, False; refs/pr/62: present, 14209943 B; discussion 62: open)

9. Contributor self-audit (review-reports/PR-90-FINAL-AUDIT.md) — claims checked

Confirmed: 20/20 tasks drivable through the UI (my harness reproduces all 20); seed md5 b577adc2…; 122 public records across 7 categories; 16/16 real photographs; tasks 6/7 return 6/8 results with the target at position 6; all footer routes distinct and working; no overflow at 768/390. Not confirmed: "no first-item target" — the original task 2 target was result #1 (fixed by re-anchoring). The audit's screenshots are homepage-only by design; the task-level evidence lives outside the repo, so it was re-derived here rather than trusted.

10. Screenshots

All cited screenshots: https://github.com/JeremyJC67/WebHarbor/tree/pr-screenshots/reviews/4shared

homepage 1440 px Premium plans (task 16 ambiguity)
home premium
search "classic fiction" in Books — original task-2 target was result #1 premium checkout confirmed (write path)
t2 premium confirmed

Full index:

page_home.png, page_home_768.png, page_home_390.png, page_premium.png, category_images.png, category_books.png, search_t0_music_nature_ambience.png, search_t2_books_classic_fiction.png, search_t3_garden_planning.png, search_t6_federalist.png, search_t7_archivepeek.png, search_multiword_boston_celtic.png, detail_t0_target.png, detail_t1_target.png, detail_t4_target.png, detail_t6_target.png, fn_account_alice.png, fn_favorites_after_add.png, fn_saved_after_save.png, fn_my_files_work_after_move.png, fn_trash_after_delete.png, fn_share_after_create.png, fn_shared_page.png, fn_upload_result.png, fn_comment_after_post.png, fn_premium_confirmed.png, fn_account_bob_after_upgrade.png, fn_register_done.png.

@JeremyJC67

Copy link
Copy Markdown

Follow-up review — 4shared (PR #90) — merge-blocker pass

Reviewer: JeremyJC67 · Site author: @sarendis56 · Date: 2026-09-11
Reviewed: review/pr-90-4shared, audited from ce13111, head now 7bd9c80.

Verdict: the site hardening is APPROVE; the merge stays blocked only on the one release-mechanics item
we cannot perform for you.
A second pass against the maintainer's merge-blocker checklist found 15
defects — 2 blocker, 5 major, 8 minor and nits. 14 are fixed on the review branch; the remaining one is
the Hugging Face upload. Everything below was reproduced against a standalone boot before the change and
re-probed after it, and the 20 task drives plus the full negative matrix were re-run at the end.

Because you are the site author, §3 lists every change we made to your code on your behalf.


1. The remaining blocker (yours to clear)

4shared.tar.gz is still absent from asset main (30 files) and from the pinned revision 65c479f8…
(27 files); it exists only at refs/pr/62. Merge HF discussion #62, then repin .assets-revision to the
merge sha. Until then scripts/fetch_assets.sh cannot fetch the site.

2. What this pass found

The checkout handed task 16 its answer (blocker, fixed)

plan_key = request.values.get("plan", "100")
if plan_key not in PREMIUM_PLANS:
    plan_key = "100"

Task 16 asks the agent to choose the annual Premium 100 GB plan. /premium/checkout with no plan, or
with ?plan=999, ?plan=abc, ?plan=, all rendered "Premium 100 GB / $77.88", and POSTing created the
correct order — the agent could satisfy the task without ever selecting anything. Now 404 on a missing or
unknown plan. Mutation proof: restoring those two lines reproduces 200 / "Premium 100 GB".

Cross-account disclosure of private files (major, fixed)

toggle_favorite and add_comment used db.get_or_404 and checked only deleted, so the write
succeeded
— the 404 the caller sees comes from the redirect target, which is exactly why it looked safe.
DB forensics after the probe:

favorites  id=17  actor=2  file_id=125  'Alice Field recording notes.docx'  public=0  owner_id=1
comments   on that same private file, and on David's trashed file

Bob's /favorites page then rendered Alice's private filename. Fixed with a shared
viewable_file_or_404(); after the fix all three routes are 404 and zero rows are written. Mutation
proof: restoring the old lookup gives back nonowner_private_favorite_rows: 1 and
private_name_on_favorites_page: true.

Two more forms typed the answer (major, fixed)

  • The share-permission <select> led with view, and the backend defaulted to view — exactly the
    preview-only link task 17 requires. Task 14 wants download, so the leak is task-specific rather than
    cosmetic.
  • The upload form shipped value="128" for the size and an unchecked public box, so an untouched form
    already submitted the private visibility that tasks 11 and 17 require.
  • Both also accepted empty or invalid input silently (share_empty_submit → 200, link created).

Now: empty first options, required fields, and 400 on absent or invalid input.

Create-after-delete returned 500 forever (major, fixed)

Slugs were <slug>-<user>-<unix seconds>, so a second upload of the same filename inside one second hit
sqlalchemy.exc.IntegrityError: UNIQUE constraint failed: files.slug → HTTP 500, no rollback, and no 500
template (15 of 25 merged sites ship one; this site did not). Now the slug is derived from the row,
IntegrityError rolls back to a 409, and 400/500 pages exist. Three same-name uploads yield
collision-probe-pdf-3, -3-2, -3-3; upload-after-trash works; zero tracebacks.

Invisible text, caught only by pixel sampling (major, fixed)

.file-icon was color:#fff unconditionally, and on /preview/<id> and /shared/<token> it sits in a
white panel. An element screenshot contained 1 distinct colour, 100 % #ffffff, zero glyph pixels;
the control on /file/…, where the same icon sits on a blue media block, has 217 colours. This is the
class of defect a stylesheet-reading contrast audit cannot see.

Accessibility and layout (fixed)

51 distinct failing contrast pairs → 0, using an --action / --action-dark token for interactive
fills and links while the brand blue stays decorative, plus a retuned --muted. /my-files overflowed at
320 px (scrollWidth 332 vs 320, from min-width:auto on grid and flex children) → 0 overflow at
1440 / 768 / 390 / 320
.

Two findings we did not report, because falsification killed them

Six apparent contrast failures on a.file-thumb / a.result-visual were our own tool's false positives:
those anchors have no text node of their own, and sampling found 0 pixels painted in the anchor's
colour. label.sr-only likewise (1×1, clip:rect(0,0,0,0)). The audit script now scores only elements
that paint their own text. This is the same instrument bug the checklist warns about, so it is recorded
rather than quietly dropped.

3. Every change we made to your code

Five reviewer commits, none of them amending yours (90590b0, 067fc00 are untouched):

commit what changed and why
27c68e8 /premium/checkout 404s on a missing or unknown plan instead of defaulting to 100 GB; share permission and upload visibility/size are explicit and required, invalid input is 400; favourite / comment / share go through viewable_file_or_404; collision-safe upload slugs plus IntegrityError rollback and 400/500 pages; POST-only logout; monotonic Premium pricing (100 GB unchanged); dead homepage queries removed; id tiebreaker on category and related ordering
964f282 the search category tabs render nav_categories, so Documents is reachable by tab
74ce864 .dockerignore excludes review-reports/ — repo-level; 340 KB of review evidence was being COPYd into the image
be21d83 the drive harness selects the now-required visibility field
7bd9c80 .file-icon no longer renders white-on-white on /preview/<id> and /shared/<token>; the 320 px /my-files overflow; WCAG contrast 51 failing pairs → 0

Nothing in seed_data.py, tasks.jsonl or instance_seed/ was touched by this pass, so the seed md5 is
unchanged and the task set is the one you and the first review already agreed on.

4. Checks that came back clean, each with the mutation that turns it red

check result mutation proof
MAX_CONTENT_LENGTH a real 60 MB multipart → 413 raise the cap to 256 MB → 200
static-text leaks on list surfaces none across 20 surfaces render preview_text on cards → 10:45, 48 kHz, -16 LUFS appear
read-only routes do not write md5 b577adc2… unchanged after three full sweeps make /search insert a row → md5 changes
cross-user authorization 0 illegal rows restore the old guard → 1 row, and the private name leaks
ordering is a total order all 7 categories tie-free, order stable force a download_count tie → the detector fires
upload form has no answer prefill none put value="640" back → it equals task 11's answer
grading matrix 20 tasks × 5 variants, all expectations met the matrix is itself the negative-sample suite
verifier ↔ recorder contract no drift (ast-extracted: steps carry url; no url_after / final_url, already optional)
answer-identifier grading no ground_truth − question subtraction anywhere
all 122 public files reachable by name search no field-set mismatch between the two search routes
console / network at four widths 0 broken images, 0 failed requests, 0 external requests, 0 dangling aria references
registry control_serverwebsyn_start (25 entries, index 24 → 40024), EXPOSE 40000-40024, 20 task rows on :40024, no answer key

5. Left for you to decide

  • The ColorScope licence is stated twice and inconsistently — the catalog tag says "Open-source package"
    while the notes say "GPL-3.0". A content call, so we left it.
  • Whether a user should be able to create a share link for a public catalog file they do not own. Plausibly
    intended; unchanged.
  • The fixed SECRET_KEY lets a forged cookie read /account. We did not change it here, because all
    25 sites do the same thing — it is a maintainer-level decision, not yours.

6. Container re-verification of this branch (7bd9c80, full 25-site image)

Docker was unavailable to the audit pass itself; it has now been run. Assets from HF refs/pr/62.

check result
docker build ok, 4.71 GB
HTTP sweep, alt ports 44000-44024 25/25 return 200
GET /health ok, 25/25 alive and ready, 4shared on internal 40024
POST /reset/4shared -> md5 instance vs instance_seed b577adc216900a6f0e3974a80e51c04c both
dirty request then reset still b577adc2...
docker restart then md5 still b577adc2...
POST /reset-all ok, 25/25 ready, 1.46 s
verifier no-op matrix, in-container DBs via docker cp 20/20 FAIL, 0 errors
walmart_careers / rotten_tomatoes registry + docs tests 4 passed, 3,343 subtests
review-reports/ inside the image confirmed absent from the image

The fixes behave in the image as they did standalone:

GET  /logout                                  405
POST /upload without a session or token       400
GET  /no-such-page                            404, 3029-byte branded page   (was a bare Werkzeug page)
GET  /login?next=https://evil.example/pwn     redirect_url empty (not followed)
GET  /account anonymous                       302
search category tabs                          Documents present (3 matches on /search)
md5 before / after 6 read-only GETs (/, /search, 3 category pages, /premium)
  b577adc216900a6f0e3974a80e51c04c / b577adc216900a6f0e3974a80e51c04c   -> byte-identical

Two readings to be precise about rather than let them be carried forward as something they are not.
A 300 KB url-encoded body to /register returns 400, not 413: the new field validation rejects the
malformed body before any size limit is reached. The size cap itself is the separate measurement from the
audit, a real 60 MB multipart returning 413. And pytest sites/4shared inside the image collects nothing,
which is expected: this site's harness lives under verify/tests/, which .dockerignore keeps out of the
image on purpose. It runs from a checkout, where it is green.

Raw output of the in-image check:

ls: cannot access '/opt/review-reports': No such file or directory
ls: cannot access '/opt/WebSyn/4shared/verify/tests': No such file or directory
---
15M	/opt/WebSyn/4shared

@JeremyJC67

Copy link
Copy Markdown

Tooling disclosure

Added after the fact, because it belongs in the public record and not only in our internal notes.

The second-pass audit had a general-purpose LLM available to it as a judgment aid — used for
adjudication calls (does this string leak an answer, is this task wording ambiguous) and as a second
opinion on our own checks. It produced no verdicts: every finding in the comment above is backed by a
command and its output, and the shipped verifiers decide with --no_llm, so nothing in the grading
contract depends on a model.

For this site I have no record of it changing any conclusion; the findings above came from the probes and
their outputs.

No call log was kept, so I cannot enumerate every consultation — that is the honest limit of this
disclosure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants