The response is bound to the submitter's ORCID; the report PDFs read as print
Browse filesRecording a choice on the response page now requires an ORCID session
(verified by the site's proxy and signed into the body) whose iD matches the
one the paper was submitted with; test-tier records accept any whitelisted
test iD, since they store a tier token. The page view carries the submitter's
iD so the page can enable the buttons for the right person. The acceptance
email says so in one sentence. The panel report and RQC PDFs open every
reviewer block and no longer tell the reader to expand rows.
intake/author_approval.py
CHANGED
|
@@ -178,6 +178,9 @@ def public_view(sub_dir: Path, rec: dict) -> dict:
|
|
| 178 |
return {
|
| 179 |
"sub_id": Path(sub_dir).name,
|
| 180 |
"test_mode": is_test(Path(sub_dir).name),
|
|
|
|
|
|
|
|
|
|
| 181 |
"title": sub.get("title") or "",
|
| 182 |
"author_display": author,
|
| 183 |
"reserved_doi": st.get("crossref_doi") or "",
|
|
|
|
| 178 |
return {
|
| 179 |
"sub_id": Path(sub_dir).name,
|
| 180 |
"test_mode": is_test(Path(sub_dir).name),
|
| 181 |
+
# The page compares the signed-in ORCID with this before it enables the
|
| 182 |
+
# buttons; test records carry a tier token, not an ORCID, so they send "".
|
| 183 |
+
"submitter_orcid": "" if is_test(Path(sub_dir).name) else str((sub.get("form") or {}).get("orcid") or ""),
|
| 184 |
"title": sub.get("title") or "",
|
| 185 |
"author_display": author,
|
| 186 |
"reserved_doi": st.get("crossref_doi") or "",
|
intake/intake_server.py
CHANGED
|
@@ -1372,6 +1372,20 @@ async def api_approve_record(request: Request):
|
|
| 1372 |
except Exception:
|
| 1373 |
raise HTTPException(404, "no such approval link")
|
| 1374 |
test_mode = author_approval.is_test(sub_dir.name)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1375 |
try:
|
| 1376 |
excl = d.get("exclusions") or []
|
| 1377 |
if not isinstance(excl, list) or len(excl) > 20:
|
|
|
|
| 1372 |
except Exception:
|
| 1373 |
raise HTTPException(404, "no such approval link")
|
| 1374 |
test_mode = author_approval.is_test(sub_dir.name)
|
| 1375 |
+
# The link identifies the paper; the person is the ORCID session the site's
|
| 1376 |
+
# proxy verified and signed into the body (2026-09-28). Test records accept
|
| 1377 |
+
# any whitelisted test ORCID: their stored ORCID is a tier token.
|
| 1378 |
+
session_orcid = _normalize_orcid(str(d.get("orcid") or ""))
|
| 1379 |
+
if not session_orcid:
|
| 1380 |
+
raise HTTPException(401, "Sign in with the ORCID iD you submitted with, then respond again.")
|
| 1381 |
+
try:
|
| 1382 |
+
sub_rec = json.loads((sub_dir / "submission.json").read_text())
|
| 1383 |
+
except Exception:
|
| 1384 |
+
sub_rec = {}
|
| 1385 |
+
expected = _normalize_orcid(str((sub_rec.get("form") or {}).get("orcid") or ""))
|
| 1386 |
+
person_ok = is_test_submission(session_orcid) if test_mode else (bool(expected) and session_orcid == expected)
|
| 1387 |
+
if not person_ok:
|
| 1388 |
+
raise HTTPException(403, "This response must come from the ORCID iD the paper was submitted with.")
|
| 1389 |
try:
|
| 1390 |
excl = d.get("exclusions") or []
|
| 1391 |
if not isinstance(excl, list) or len(excl) > 20:
|
intake/notify_author.py
CHANGED
|
@@ -129,6 +129,13 @@ def _md_to_pdf_bytes(md_text: str, *, doc_title: str | None = None,
|
|
| 129 |
if end != -1:
|
| 130 |
body_md = body_md[end + 4:].lstrip("\n")
|
| 131 |
inner = _md_lib.markdown(body_md, extensions=["extra", "sane_lists", "tables"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
title_html = f"<title>{doc_title}</title>" if doc_title else ""
|
| 133 |
full = (
|
| 134 |
f"<!DOCTYPE html><html><head><meta charset='utf-8'>"
|
|
|
|
| 129 |
if end != -1:
|
| 130 |
body_md = body_md[end + 4:].lstrip("\n")
|
| 131 |
inner = _md_lib.markdown(body_md, extensions=["extra", "sane_lists", "tables"])
|
| 132 |
+
# Print has no rows to expand: open every reviewer block and say so
|
| 133 |
+
# (the web record keeps its collapsed rows).
|
| 134 |
+
inner = inner.replace("<details", "<details open")
|
| 135 |
+
inner = re.sub(r"Individual reviewer assessments are collapsed by default\.\s*Expand any row to read that "
|
| 136 |
+
r"reviewer.s summary\s*and per-dimension justification\.",
|
| 137 |
+
"Individual reviewer assessments follow, one per reviewer, each with its summary and "
|
| 138 |
+
"per-dimension justification.", inner)
|
| 139 |
title_html = f"<title>{doc_title}</title>" if doc_title else ""
|
| 140 |
full = (
|
| 141 |
f"<!DOCTYPE html><html><head><meta charset='utf-8'>"
|
intake/templates/submission_accept_upload_pending.md
CHANGED
|
@@ -31,7 +31,7 @@ These are the terms you accepted at submission (icsacinstitute.org/terms, revise
|
|
| 31 |
|
| 32 |
## Your response
|
| 33 |
|
| 34 |
-
Open your personal link to approve publication. There you can also tick anything you would rather we did not do — social media, print or broadcast advertising, newsletters, website features, or the annual print and ebook edition of *Persistence* — each all-or-nothing; leave a note for the curation team; ask us to hold and correct something; or withdraw:
|
| 35 |
|
| 36 |
**{{approval_url}}**
|
| 37 |
|
|
|
|
| 31 |
|
| 32 |
## Your response
|
| 33 |
|
| 34 |
+
Open your personal link to approve publication. The page asks you to sign in with the ORCID iD you submitted with; the link and that sign-in together are your signature. There you can also tick anything you would rather we did not do — social media, print or broadcast advertising, newsletters, website features, or the annual print and ebook edition of *Persistence* — each all-or-nothing; leave a note for the curation team; ask us to hold and correct something; or withdraw:
|
| 35 |
|
| 36 |
**{{approval_url}}**
|
| 37 |
|