.gitattributes CHANGED
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ explanationSS1.png filter=lfs diff=lfs merge=lfs -text
37
+ explanationSS2.png filter=lfs diff=lfs merge=lfs -text
38
+ explanationSS3.png filter=lfs diff=lfs merge=lfs -text
39
+ exampleRedactedStars.pdf filter=lfs diff=lfs merge=lfs -text
app.py CHANGED
@@ -3,10 +3,21 @@ Streamlit front end for the STARS report redactor (student-facing).
3
 
4
  Privacy design: the uploaded PDF is redacted entirely IN MEMORY via
5
  `engine.redact_bytes` and is never written to the server's disk. Only the
6
- redacted copy is offered back to the student for download; nothing is stored.
 
7
 
8
  Deployment: Hugging Face Space (Streamlit SDK). Set a Space secret named
9
  APP_PASSPHRASE to the access phrase before going live.
 
 
 
 
 
 
 
 
 
 
10
  """
11
  import os
12
  import uuid
@@ -23,6 +34,18 @@ DELETE_FORM_URL = ( # "delete my report" request
23
  "https://docs.google.com/forms/d/e/"
24
  "1FAIpQLScSpM1ov0dMEXhT3hHhsWmIByu-j1myQYnNvRv7C0FNUW81eg/viewform"
25
  )
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
  # --- submission storage (a private HF Dataset in the org) -------------------
28
  # In-app submission switches on automatically once these Space secrets are set:
@@ -68,10 +91,12 @@ st.markdown(
68
  html, body, [class*="css"], .stMarkdown, p, li { font-family: 'Inter', system-ui, sans-serif; }
69
  h1, h2, h3 { font-family: 'Newsreader', Georgia, serif !important; color: #990000; letter-spacing: .2px; }
70
  h1 { border-bottom: 3px solid #FFCC00; padding-bottom: .35rem; }
71
- .stButton > button, .stDownloadButton > button {
72
  background-color: #990000; color: #ffffff; border: 0; font-weight: 600; border-radius: 8px;
73
  }
74
- .stButton > button:hover, .stDownloadButton > button:hover { background-color: #7a0000; color: #FFCC00; }
 
 
75
  div[data-testid="stExpander"] { border: 1px solid #ece2cc; border-radius: 8px; }
76
  div[data-testid="stExpander"] summary { font-weight: 600; color: #990000; }
77
  </style>
@@ -95,22 +120,64 @@ st.markdown(
95
  unsafe_allow_html=True,
96
  )
97
 
98
- # ---------------------------------------------------------------- the ask ----
99
- st.title("Help us build better tools for USC students")
 
 
100
 
101
  st.markdown(
102
- "BBH (the **BUAI Builder Hub**) is hard at work building tools to make "
103
- "**degree planning, course registration, and picking classes** way less of "
104
- "a headache. One thing we all agree on: actually **making sense of your "
105
- "STARS report** is a pain.\n\n"
106
- "**You can help.** We're putting together a set of STARS reports to build "
107
- "against. Upload yours below β€” we'll strip out the sensitive "
108
- "stuff (**your name, address, student ID, and grades**) right here, and only "
109
- "ever keep the **redacted** version."
110
  )
111
 
112
- # ------------------------------------------------------------------- Q & A ----
113
- st.subheader("Quick questions you might have")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
 
115
  with st.expander("Wait β€” are my grades going in a database?"):
116
  st.markdown(
@@ -126,27 +193,22 @@ with st.expander("Who actually sees my report?"):
126
  "the USC student experience. Your redacted report is kept somewhere "
127
  "**private and access-controlled** (not public, never for sale), and used "
128
  "only to build and test those tools. Whoever works with it agrees not to "
129
- "try to figure out who anyone is. (See the consent box below for the "
130
- "honest caveat on why we still can't *totally* promise anonymity.)"
131
  )
132
 
133
- with st.expander("I changed my mind β€” can you delete my report?"):
134
- st.markdown(
135
- "Totally fine β€” we get it! When you submit, we give you a **report ID**. "
136
- f"Pop it into [this quick form]({DELETE_FORM_URL}) and we'll remove your "
137
- "report.\n\n"
138
- "⚠️ **Save that ID somewhere safe.** Your report is stored with **no name "
139
- "attached**, so the ID is the *only* way we can find it. If you lose it, we "
140
- "won't be able to delete your report."
141
- )
142
 
143
- with st.expander("Why should I bother?"):
144
- st.markdown(
145
- "You'd be helping build tools that make planning your degree and getting "
146
- "into the classes you need way less painful β€” for you *and* everyone after "
147
- "you. It takes about two minutes, and your personal info and grades get "
148
- "stripped out before anything is stored. That's it."
149
- )
150
 
151
  with st.expander("How do I even get my STARS report?"):
152
  st.markdown(
@@ -158,81 +220,20 @@ with st.expander("How do I even get my STARS report?"):
158
  "or scan won't work.)"
159
  )
160
 
161
- st.markdown("### Ready? Let's do it πŸ‘‡")
162
-
163
- # --------------------------------------------------------------- pass gate ----
164
- if not PASSPHRASE:
165
- st.error("This app isn't set up yet (no passphrase configured). Ping the team.")
166
- footer()
167
- st.stop()
168
-
169
- entered = st.text_input("Passphrase", type="password")
170
- st.caption("If you're a USC student using this, whoever referred you should've "
171
- "shared a passphrase.")
172
- if entered.strip() != PASSPHRASE:
173
- if entered:
174
- st.warning("Hmm, that's not it β€” double-check with whoever sent you here.")
175
- footer()
176
- st.stop()
177
-
178
- # ------------------------------------------------------- consent + upload ----
179
- with st.expander("πŸ“‹ Please read this before you upload β€” what you're agreeing to",
180
- expanded=True):
181
- st.markdown(
182
- "- **This is totally voluntary.** You don't have to do it, and you can "
183
- "close this page anytime. No penalty, no hard feelings.\n"
184
- "- **What we keep:** only the **redacted** version of your STARS report β€” "
185
- "the file this tool hands back after removing your personal info.\n"
186
- "- **What's removed before anything is stored:** your **name, USC ID, "
187
- "mailing address, sport/team**, every **letter grade** (each becomes a "
188
- "simple pass/fail marker), and your **GPA**.\n"
189
- "- **What stays in the file:** your **major/minor, the courses and terms "
190
- "on your record, and your degree-progress details** β€” that's the part "
191
- "we're actually building with.\n"
192
- "- **Can people tell it's you?** We want to be upfront: possibly. We "
193
- "remove your name, ID, grades, and GPA, but we **keep your major(s), "
194
- "minor, and the list of classes you've taken** β€” that's the part we build "
195
- "with. If your combination is unusual (say you're the only person at USC "
196
- "double-majoring in BUAI and Anthropology), someone who sees the file "
197
- "could figure out it's yours. They still **won't** see your grades, GPA, "
198
- "or student ID β€” but they might know the report belongs to you. Only share "
199
- "if you're okay with that.\n"
200
- "- **Your original file never sticks around.** It's handled right here in "
201
- "the page's memory, **never written to disk**, and **automatically "
202
- "discarded the moment you close this tab**. If you hit **Submit**, we save "
203
- "**only the redacted copy** to a **private BBH archive**, tagged with a "
204
- "random ID we show you (keep it β€” that's how you can ask us to delete your "
205
- "report later). We never keep your original.\n"
206
- "- **How we use it:** to build and test tools that help USC students plan "
207
- "degrees and register for classes, and β€” because it's de-identified β€” "
208
- "possibly for research about the student experience. We won't sell it or "
209
- "try to identify you.\n"
210
- f"- **Changed your mind later?** It's your record and your call β€” you can "
211
- f"ask us to delete your redacted report anytime via our "
212
- f"[deletion form]({DELETE_FORM_URL}), using the report ID we give you at "
213
- "submission. Because we store it with **no name attached**, that ID is the "
214
- "only way to find your file, so please keep it β€” if it's lost, we can't "
215
- "identify your report to delete it."
216
- )
217
-
218
- consent = st.checkbox(
219
- "I've read the above and I'm good with sharing my **redacted** STARS report.")
220
-
221
  uploaded = st.file_uploader(
222
  "Upload your STARS report (the PDF you saved from experience.usc.edu)",
223
  type=["pdf"], accept_multiple_files=False)
224
  st.caption("πŸ”’ Your upload is handled in memory only and is discarded the moment "
225
- "you close this tab.")
 
226
 
227
- if uploaded is not None and not consent:
228
- st.info("Check the consent box above and you're good to go.")
229
-
230
- if uploaded is not None and consent:
231
  # Redact ONCE per uploaded file and cache the exact result. Streamlit reruns
232
- # the whole script on every click, so without caching, clicking Submit would
233
- # re-run redaction and upload a freshly-recomputed file β€” not the same bytes
234
- # the student downloaded and reviewed. One redaction, one UID, reused for the
235
- # download filename and the database submission so they always match.
 
236
  file_key = getattr(uploaded, "file_id", None) or f"{uploaded.name}:{uploaded.size}"
237
  if st.session_state.get("uid_key") != file_key:
238
  with st.spinner("Scrubbing your info…"):
@@ -244,6 +245,7 @@ if uploaded is not None and consent:
244
  st.session_state["uid"] = uuid.uuid4().hex[:8].upper()
245
  st.session_state["res"] = res
246
  st.session_state["out"] = out
 
247
 
248
  res = st.session_state["res"]
249
  out = st.session_state["out"]
@@ -265,33 +267,9 @@ if uploaded is not None and consent:
265
  st.download_button("⬇️ Download my redacted report", data=out,
266
  file_name=f"REDACTED_{uid}.pdf",
267
  mime="application/pdf")
268
- st.caption(f"Saved as `REDACTED_{uid}.pdf` β€” that code is your report ID. "
269
- "Open it to check it looks right, then submit below.")
270
-
271
- st.divider()
272
- if _submissions_enabled():
273
- st.markdown("**Share it with BBH**")
274
- if st.button("πŸ“€ Submit my redacted report"):
275
- try:
276
- _upload_submission(out, uid)
277
- st.success("Submitted β€” thank you so much! πŸŽ‰")
278
- st.warning(
279
- f"**Your report ID is `{uid}`.**\n\n"
280
- "**Save this now** (screenshot it, write it down β€” whatever "
281
- "works). Your report is stored with **no name attached**, so "
282
- "this ID is the **only** way to delete it later. If you lose "
283
- "it, we can't find your report to remove it."
284
- )
285
- st.markdown(
286
- f"Changed your mind? Fill out our "
287
- f"[deletion form]({DELETE_FORM_URL}) with this ID.")
288
- except Exception:
289
- st.error("Submission didn't go through β€” sorry! Your redacted "
290
- "file is still available above; please try submitting "
291
- "again in a moment.")
292
- else:
293
- st.caption("Direct submission is unavailable right now β€” you can still "
294
- "download your redacted file above.")
295
 
296
  elif status == "SKIPPED":
297
  st.error("This looks like a **scan or photo** (no text in it), so it can't "
@@ -310,4 +288,101 @@ if uploaded is not None and consent:
310
  f"better safe than sorry. Please email {CONTACT_EMAIL}, and "
311
  "don't share the original in the meantime.")
312
 
313
- footer()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
  Privacy design: the uploaded PDF is redacted entirely IN MEMORY via
5
  `engine.redact_bytes` and is never written to the server's disk. Only the
6
+ redacted copy is offered back to the student for download; nothing is stored
7
+ unless the student explicitly chooses to submit it to BBH.
8
 
9
  Deployment: Hugging Face Space (Streamlit SDK). Set a Space secret named
10
  APP_PASSPHRASE to the access phrase before going live.
11
+
12
+ Page layout (top to bottom):
13
+ 1) What is BBH, and why are we doing this
14
+ 2) Access code
15
+ 3) Screenshots - what we keep / don't keep
16
+ 4) Link to a full sample redacted STARS report
17
+ 5) Try it yourself - upload & see
18
+ 6) Consent form check (only required to SHARE your redacted copy)
19
+ 7) Your code (shown after you submit)
20
+ 8) Removal link
21
  """
22
  import os
23
  import uuid
 
34
  "https://docs.google.com/forms/d/e/"
35
  "1FAIpQLScSpM1ov0dMEXhT3hHhsWmIByu-j1myQYnNvRv7C0FNUW81eg/viewform"
36
  )
37
+ # TODO: swap in the real link once you have a sample redacted STARS report to
38
+ # point to. Leaving this as a placeholder for now β€” st.link_button below opens
39
+ # it in a new tab automatically, no extra wiring needed once the URL is real.
40
+ SAMPLE_REPORT_URL = "https://example.com/TODO-sample-redacted-stars-report"
41
+
42
+ # TODO: drop your screenshot files into an `images/` folder in this Space repo
43
+ # (next to app.py) and update the filenames/captions below. Add or remove rows
44
+ # as needed β€” the layout adapts to however many images are listed here.
45
+ KEEP_DONT_KEEP_IMAGES = [
46
+ ("images/what_we_keep.png", "What stays in your redacted report"),
47
+ ("images/what_we_dont_keep.png", "What gets stripped out before anything is stored"),
48
+ ]
49
 
50
  # --- submission storage (a private HF Dataset in the org) -------------------
51
  # In-app submission switches on automatically once these Space secrets are set:
 
91
  html, body, [class*="css"], .stMarkdown, p, li { font-family: 'Inter', system-ui, sans-serif; }
92
  h1, h2, h3 { font-family: 'Newsreader', Georgia, serif !important; color: #990000; letter-spacing: .2px; }
93
  h1 { border-bottom: 3px solid #FFCC00; padding-bottom: .35rem; }
94
+ .stButton > button, .stDownloadButton > button, .stLinkButton > a {
95
  background-color: #990000; color: #ffffff; border: 0; font-weight: 600; border-radius: 8px;
96
  }
97
+ .stButton > button:hover, .stDownloadButton > button:hover, .stLinkButton > a:hover {
98
+ background-color: #7a0000; color: #FFCC00;
99
+ }
100
  div[data-testid="stExpander"] { border: 1px solid #ece2cc; border-radius: 8px; }
101
  div[data-testid="stExpander"] summary { font-weight: 600; color: #990000; }
102
  </style>
 
120
  unsafe_allow_html=True,
121
  )
122
 
123
+ # ============================================================================
124
+ # 1) WHAT IS BBH, AND WHY ARE WE DOING THIS
125
+ # ============================================================================
126
+ st.title("Please Share Your STARS Report to Support Our Student Tool!")
127
 
128
  st.markdown(
129
+ "**BUAI Builder Hub** is working on creating tools to support students in "
130
+ "**degree planning, course registration, and picking classes**. We need your "
131
+ "help sourcing STARS reports to test against our tool!\n\n"
132
+ "It takes 2 minutes. Upload your STARS report and we'll strip out all "
133
+ "sensitive info."
 
 
 
134
  )
135
 
136
+ # A skimmable recap for anyone who won't read every section below.
137
+ with st.container(border=True):
138
+ st.markdown("**πŸ“Œ TL;DR**")
139
+ st.markdown(
140
+ "- Your **name, USC ID, address, grades, and GPA** are never stored β€” "
141
+ "only a de-identified copy, and only if you choose to share it.\n"
142
+ "- Only **BBH student developer teams** can ever access it. Private, "
143
+ "access-controlled, never sold or made public.\n"
144
+ "- You can **try the tool and see your redacted file first** β€” sharing "
145
+ "it with BBH is a separate, optional step.\n"
146
+ "- Changed your mind later? You can request that we **delete your report** "
147
+ "anytime using the code we give you.\n"
148
+ "- Takes about **two minutes**, start to finish."
149
+ )
150
+
151
+ # ============================================================================
152
+ # 2) ACCESS CODE
153
+ # ============================================================================
154
+ if not PASSPHRASE:
155
+ st.error("This app isn't set up yet (no passphrase configured). Ping the team.")
156
+ footer()
157
+ st.stop()
158
+
159
+ st.markdown("### Enter your access code")
160
+ entered = st.text_input("Passphrase", type="password")
161
+ st.caption("If you're a USC student using this, whoever referred you should've "
162
+ "shared a passphrase.")
163
+ if entered.strip() != PASSPHRASE:
164
+ if entered:
165
+ st.warning("Hmm, that's not it β€” double-check with whoever sent you here.")
166
+ footer()
167
+ st.stop()
168
+
169
+ # ============================================================================
170
+ # 3) SCREENSHOTS β€” WHAT WE KEEP & DON'T KEEP
171
+ # ============================================================================
172
+ st.markdown("### What we keep β€” and what we don't")
173
+
174
+ cols = st.columns(len(KEEP_DONT_KEEP_IMAGES))
175
+ for col, (path, caption) in zip(cols, KEEP_DONT_KEEP_IMAGES):
176
+ with col:
177
+ try:
178
+ st.image(path, caption=caption, use_container_width=True)
179
+ except Exception:
180
+ st.info(f"(Add `{path}` to the Space repo to show this screenshot.)")
181
 
182
  with st.expander("Wait β€” are my grades going in a database?"):
183
  st.markdown(
 
193
  "the USC student experience. Your redacted report is kept somewhere "
194
  "**private and access-controlled** (not public, never for sale), and used "
195
  "only to build and test those tools. Whoever works with it agrees not to "
196
+ "try to figure out who anyone is. (See the consent section further down "
197
+ "for the honest caveat on why we still can't *totally* promise anonymity.)"
198
  )
199
 
200
+ # ============================================================================
201
+ # 4) LINK TO A FULL SAMPLE REDACTED STARS REPORT
202
+ # ============================================================================
203
+ st.markdown("### See a full example")
204
+ st.markdown("Curious what a finished redacted report actually looks like end to end?")
205
+ st.link_button("πŸ“„ View a sample redacted STARS report", SAMPLE_REPORT_URL)
206
+ st.caption("Opens in a new tab.")
 
 
207
 
208
+ # ============================================================================
209
+ # 5) TRY IT YOURSELF β€” UPLOAD & SEE
210
+ # ============================================================================
211
+ st.markdown("### Try it yourself")
 
 
 
212
 
213
  with st.expander("How do I even get my STARS report?"):
214
  st.markdown(
 
220
  "or scan won't work.)"
221
  )
222
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  uploaded = st.file_uploader(
224
  "Upload your STARS report (the PDF you saved from experience.usc.edu)",
225
  type=["pdf"], accept_multiple_files=False)
226
  st.caption("πŸ”’ Your upload is handled in memory only and is discarded the moment "
227
+ "you close this tab. You can preview and download your redacted file "
228
+ "below β€” to share it, you must click submit further down the page.")
229
 
230
+ if uploaded is not None:
 
 
 
231
  # Redact ONCE per uploaded file and cache the exact result. Streamlit reruns
232
+ # the whole script on every click, so without caching, checking the consent
233
+ # box or clicking Submit would re-run redaction and upload a freshly
234
+ # -recomputed file β€” not the same bytes the student downloaded and reviewed.
235
+ # One redaction, one UID, reused for the download filename and the database
236
+ # submission so they always match.
237
  file_key = getattr(uploaded, "file_id", None) or f"{uploaded.name}:{uploaded.size}"
238
  if st.session_state.get("uid_key") != file_key:
239
  with st.spinner("Scrubbing your info…"):
 
245
  st.session_state["uid"] = uuid.uuid4().hex[:8].upper()
246
  st.session_state["res"] = res
247
  st.session_state["out"] = out
248
+ st.session_state["submitted"] = False
249
 
250
  res = st.session_state["res"]
251
  out = st.session_state["out"]
 
267
  st.download_button("⬇️ Download my redacted report", data=out,
268
  file_name=f"REDACTED_{uid}.pdf",
269
  mime="application/pdf")
270
+ st.caption(f"Saved as `REDACTED_{uid}.pdf` β€” take a look and make sure it "
271
+ "looks right. Sharing it with BBH is a separate, optional step "
272
+ "below.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
273
 
274
  elif status == "SKIPPED":
275
  st.error("This looks like a **scan or photo** (no text in it), so it can't "
 
288
  f"better safe than sorry. Please email {CONTACT_EMAIL}, and "
289
  "don't share the original in the meantime.")
290
 
291
+ # ============================================================================
292
+ # 6) CONSENT FORM CHECK β€” only needed to SHARE your redacted copy with BBH
293
+ # ============================================================================
294
+ have_valid_redaction = bool(
295
+ uploaded is not None
296
+ and st.session_state.get("out")
297
+ and st.session_state.get("res", {}).get("status") in ("REDACTED", "REVIEW")
298
+ )
299
+
300
+ if have_valid_redaction:
301
+ st.markdown("### Want to share it with BBH?")
302
+ st.caption("Totally optional β€” you've already got your redacted file above. "
303
+ "This part is only about whether you'd like to contribute a copy "
304
+ "to BBH's project.")
305
+
306
+ with st.expander("Sharing Consent Acknowledgement", expanded=True):
307
+ st.markdown(
308
+ "- **Submitting is voluntary.** You don't have to do it, and you can "
309
+ "close this page anytime.\n"
310
+ "- **What we'd keep:** only the **redacted** version of your STARS "
311
+ "report β€” the file this tool just handed you after removing your "
312
+ "personal info.\n"
313
+ "- **What's removed before anything is stored:** your **name, USC ID, "
314
+ "mailing address, sport/team**, every **letter grade** (each becomes a "
315
+ "simple pass/fail marker), and your **GPA**.\n"
316
+ "- **What stays in the file:** your **major/minor, the courses and "
317
+ "terms on your record, and your degree-progress details**.\n"
318
+ "- **Identifiability:** We remove your name, ID, grades, and GPA, but "
319
+ "we **keep your major(s), minor, and the list of classes you've "
320
+ "taken**. If your combination is unusual (e.g. the only USC student "
321
+ "double-majoring in BUAI and Anthropology), someone who sees the file "
322
+ "could figure out it's yours. They still **won't** see your grades, "
323
+ "GPA, or student ID.\n"
324
+ "- **Your original file is never saved.** It's handled right here in "
325
+ "the page's memory, **never written to disk**, and **automatically "
326
+ "discarded the moment you close this tab**. If you submit, we save "
327
+ "**only the redacted copy** to a **private BBH archive**, tagged with "
328
+ "a random code we show you. You can use this code to request that "
329
+ "your report be removed anytime.\n"
330
+ "- **How we use it:** to build and test tools that help USC students "
331
+ "plan degrees and register for classes, and β€” because it's "
332
+ "de-identified β€” possibly for research about the student experience. "
333
+ "We won't sell it or try to identify you.\n"
334
+ "- **Want to remove your report?** You can ask us to delete your "
335
+ "redacted report anytime, using the code we give you at submission."
336
+ )
337
+
338
+ consent = st.checkbox(
339
+ "I've read the above and I consent to sharing my **redacted** STARS "
340
+ "report with BBH.")
341
+
342
+ if not consent:
343
+ st.info("Check the box above if you'd like to submit your redacted copy.")
344
+ else:
345
+ st.markdown("**Share it with BBH**")
346
+ if _submissions_enabled():
347
+ if st.button("πŸ“€ Submit my redacted report"):
348
+ try:
349
+ _upload_submission(st.session_state["out"], st.session_state["uid"])
350
+ st.session_state["submitted"] = True
351
+ st.success("Submitted β€” thank you so much! πŸŽ‰")
352
+ except Exception:
353
+ st.error("Submission didn't go through β€” sorry! Your redacted "
354
+ "file is still available above; please try submitting "
355
+ "again in a moment.")
356
+ else:
357
+ st.caption("Direct submission is unavailable right now β€” you can still "
358
+ "download your redacted file above.")
359
+
360
+ # ============================================================================
361
+ # 7) YOUR CODE
362
+ # ============================================================================
363
+ if st.session_state.get("submitted"):
364
+ st.markdown("### Your code")
365
+ st.warning(
366
+ f"**Your report ID is `{st.session_state['uid']}`.**\n\n"
367
+ "**Save this code now** (screenshot it, write it down β€” whatever works). "
368
+ "Your report is stored with **no name attached**, so this ID is the "
369
+ "**only** way to delete it later. If you lose it, we can't find your "
370
+ "report to remove it."
371
+ )
372
+
373
+ # ============================================================================
374
+ # 8) REMOVAL LINK
375
+ # ============================================================================
376
+ st.markdown("### Requesting removal of your report?")
377
+ st.markdown(
378
+ "When you submit, we give you a **report ID code** (see above). Fill out the "
379
+ "form below with your code, and we'll remove your report."
380
+ )
381
+ st.link_button("πŸ—‘οΈ Request removal", DELETE_FORM_URL)
382
+ st.caption(
383
+ "⚠️ Save your report ID somewhere safe. Your report is stored with **no name "
384
+ "attached**, so the ID is the *only* way we can find it. If you lose it, we "
385
+ "won't be able to delete your report."
386
+ )
387
+
388
+ footer()
exampleRedactedStars.pdf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:98d2ee7ff5bcc0f26906776bba511aa88e630083daa817be01ffcff4fd528c59
3
+ size 278654
explanationSS1.png ADDED

Git LFS Details

  • SHA256: d71064d4760985a091547a79c5d81f4ef7b0c45b71e02e3f8700717dbf924e13
  • Pointer size: 131 Bytes
  • Size of remote file: 116 kB
explanationSS2.png ADDED

Git LFS Details

  • SHA256: 40fa2a1f31032c5a1b0979a7491cd4350818fe865b530ae9870b80e1c2e9a193
  • Pointer size: 131 Bytes
  • Size of remote file: 217 kB
explanationSS3.png ADDED

Git LFS Details

  • SHA256: c4a3077604adedc54116d06b6fb9531dfaed5381a1a30ffc0285d466a67bf397
  • Pointer size: 131 Bytes
  • Size of remote file: 362 kB