Builder Showcase Phase 3 Validation + Anti-Spam Test Checklist
Working context: DataInsideData™ Builder Showcase / ProofMe intake pipeline.
Goal: confirm the new frontend preview flow, backend validation, duplicate detection, honeypot, metadata logging, and deployment path all work before moving deeper into Phase 3 hardening.
0. Pre-Test Setup
Local repo / branch
- [✔️] Confirm you are on the correct branch.
git branch --show-current
git status
- [✔️] Confirm there are no unexpected old submit pages or duplicate routes.
Get-ChildItem -Recurse -File | Select-String "submit-a-builder-project"
Get-ChildItem -Recurse -File | Select-String "Test payload created successfully"
- Confirm the canonical submit page is:
/projects/builder-showcase/submit/
1. Backend Database Prep
Required metadata columns
Run in pgAdmin or the SQL runner:
alter table public.builder_project_submissions
add column if not exists user_agent text,
add column if not exists request_origin text,
add column if not exists request_referer text,
add column if not exists client_ip_hash text;
Helpful indexes
create index if not exists idx_builder_project_submissions_readme_url
on public.builder_project_submissions(readme_url);
create index if not exists idx_builder_project_submissions_email_repo_title_created_at
on public.builder_project_submissions(
submitter_email,
repo_url,
project_title,
created_at desc
);
create index if not exists idx_builder_project_submissions_client_ip_hash
on public.builder_project_submissions(client_ip_hash);
2. Supabase Secrets
Confirm required Edge Function secrets
SUPABASE_URLDID_SUPABASE_WRITE_KEYDID_PUBLIC_FORM_KEYDID_IP_HASH_SALT
Check secrets:
npx supabase secrets list
Set IP salt if needed:
python -c "import secrets; print(secrets.token_hex(32))"
Then:
npx supabase secrets set DID_IP_HASH_SALT="PASTE_RANDOM_HEX_STRING_HERE"
3. Deno + Function Validation
From the function folder:
cd supabase/functions/submit-builder-project
deno check index.ts
Expected:
- No TypeScript errors.
- No
"public" is not assignable to type "never"error. - No missing import errors.
Deploy:
npx supabase functions deploy submit-builder-project
Expected:
- Function deploys successfully.
- Supabase CLI is logged in.
- Correct Supabase project is linked/selected.
4. Frontend Preview Flow
Start Jekyll cleanly:
bundle exec jekyll clean
bundle exec jekyll serve --livereload --trace
Open:
http://localhost:4000/projects/builder-showcase/submit/
Preview behavior
- [✔️] Fill a valid form.
- [✔️] Click
Preview Submission. - [✔️] Confirm preview panel appears.
- [✔️] Confirm cleaned email is lowercased.
- [✔️] Confirm tags are trimmed and comma-split.
- [✔️] Confirm long README URL wraps inside the preview box.
- [✔️] Confirm
Confirm & Submitis visible and left-aligned. - [✔️] Confirm
Make Editsis visible and not white-on-white. - [✔️] Click
Make Edits. - [✔️] Confirm page scrolls/focuses back to the first form field.
- [✔️] Confirm form values remain editable.
5. Frontend Required Field Tests
Try submitting with each missing field:
- [✔️] Missing first name fails.
- [✔️] Missing last name fails.
- [✔️] Missing email fails.
- [✔️] Missing repo URL fails.
- [✔️] Missing project title fails.
- [✔️] Blank category fails.
- [✔️] Missing description fails.
- [✔️] Blank tags/tools fails.
- [✔️] Unchecked ownership/permission checkbox fails.
- [✔️] Unchecked public showcase acknowledgement fails.
Expected:
Browser validation or preview validation blocks submission before database insert.
6. Backend Validation Tests
These should fail even if someone bypasses browser validation.
Bad repo URL
Use:
https://google.com/test
Expected:
- Backend returns
400. - Message says repository URL must be a valid GitHub repository URL.
- No row inserted.
Bad README URL
Use a normal GitHub page URL instead of raw URL:
https://github.com/user/repo/blob/main/README.md
Expected:
- Backend returns
400. - Message says README URL must be raw.githubusercontent.com and end in README.md.
- No row inserted.
Valid GitHub repo URL
Use:
https://github.com/user/repo
Expected:
- Backend accepts if all other fields are valid.
- Row inserted.
Valid raw README URL
Use:
https://raw.githubusercontent.com/user/repo/main/README.md
Expected:
- Backend accepts if all other fields are valid.
7. Honeypot Test
Use DevTools or temporarily unhide the honeypot field and enter a value for:
website
Expected:
- Backend returns
400. - Message says invalid submission.
- No row inserted.
8. Duplicate Submission Tests
Same README URL already active
Submit a project using a README URL that already exists in an active workflow status:
submitted
reviewing
approved
published
needs_changes
Expected:
- Backend returns
409. - Message says a submission using this README URL is already in the review/publishing workflow.
- No duplicate row inserted.
Same email + repo URL + project title within 10 minutes
Submit the same exact:
- repo URL
- project title
within 10 minutes.
Expected:
- Backend returns
409. - Message says similar submission was received recently.
- No duplicate row inserted.
Same email + same repo + different project title
Submit:
- same email
- same repo URL
- different project title
Expected:
- Submission is allowed.
- Row inserted.
Same email + same monorepo + different README URL
Submit:
- same email
- same repo URL
- different raw README URL
Expected:
- Submission is allowed.
- Row inserted.
9. Metadata Logging Tests
After successful submission, query:
select
id,
project_title,
submitter_email,
user_agent,
request_origin,
request_referer,
client_ip_hash,
created_at
from public.builder_project_submissions
order by created_at desc
limit 5;
Expected:
user_agentis populated.request_originis populated when submitted from browser.request_referermay be populated depending on browser/request context.client_ip_hashis populated if the Edge Function sees an IP header andDID_IP_HASH_SALTis set.- Raw IP address is not stored.
10. Frontend Browser Cooldown
After one successful submission:
- Try submitting again immediately from the same browser.
Expected:
- Frontend blocks rapid resubmission for around 60 seconds.
- User sees a friendly message.
- Backend duplicate rules still protect the database if frontend is bypassed.
11. Admin Workflow Retest
After a successful valid submission:
View submissions
python scripts/view_submissions.py
python scripts/view_submissions.py --status submitted
python scripts/view_submissions.py --submission-id YOUR_SUBMISSION_UUID
Expected:
- New row appears.
- Exact lookup works.
- Status count/reporting still works.
Update status
python scripts/update_submission_status.py --submission-id YOUR_SUBMISSION_UUID --status approved
Expected:
- Status updates successfully.
Promote to builder_projects
python scripts/promote_builder_project.py --submission-id YOUR_SUBMISSION_UUID --public
Expected:
- Row inserts/updates in
builder_projects. - Submission status becomes
published.
Export
python scripts/export_builder_projects.py --slug YOUR_PROJECT_SLUG
Expected:
_data/builder_projects.ymlupdates.- Detail page is generated.
- README rendering still works.
12. Final Acceptance Criteria
Phase 3B first-layer hardening is ready when:
- Valid form submission succeeds.
- Preview-before-submit works.
- Make Edits returns focus to the form.
- Frontend required field validation works.
- Backend validation blocks bad payloads.
- Honeypot blocks bot-like submissions.
- Duplicate README URL is blocked.
- Recent exact duplicate is blocked.
- Productive multiple-project submissions are allowed.
- Metadata columns populate.
- Raw IP address is not stored.
- Admin scripts still work.
- Publish/export workflow still works.