3 minute read

This section marks the end of the secure submission pipeline breakdown.

Debugging Error 1: Invalid API Key

First error:

Database insert failed.
Invalid API key.
Double check your Supabase anon or service_role API key.

Cause:

The backend write secret was not set correctly.

Fix:

npx supabase secrets set DID_SUPABASE_WRITE_KEY="SECRET_OR_SERVICE_ROLE_KEY"

Lesson:

The browser uses the publishable key.
The Edge Function uses the secret/service write key.
They are not interchangeable.

Debugging Error 2: Permission Denied

After setting the secret key, the next error was:

Database insert failed.
permission denied for table builder_project_submissions
Grant the required privileges to the current role with:
GRANT SELECT, INSERT ON public.builder_project_submissions TO service_role;
42501

Fix:

grant usage on schema public to service_role;

grant select, insert, update
on public.builder_project_submissions
to service_role;

For the future published-project table:

grant select, insert, update
on public.projects_builder
to service_role;

Important:

Do not grant browser/anon direct write access for this MVP.
The Edge Function should perform the server-side insert.

Successful Insert

After fixing the function secret and granting privileges, the form returned:

Project submitted successfully. Your submission is now in review.

The row appeared in:

public.builder_project_submissions

That confirmed the full pipeline:

Jekyll form
    ↓
JavaScript fetch
    ↓
Supabase Edge Function
    ↓
Server-side validation
    ↓
Postgres insert
    ↓
Submission review queue

This was the first working backend ingestion path for the Builder Showcase / ProofMe experiment.

Git Ignore Notes

Keep these tracked:

supabase/functions/submit-builder-project/index.ts
supabase/config.toml
supabase/deno.json

Do not track local secrets or temp files:

.env
*.env
supabase/.env
supabase/.env.*
supabase/.temp/

If a docs folder was accidentally tracked and should be kept locally but removed from Git tracking:

echo "/docs/" >> .gitignore
git rm -r --cached docs/
git add .gitignore
git commit -m "Stop tracking docs folder"

Security Lessons

Key security decisions:

Do not expose service/secret keys in browser JavaScript.
Do not put database passwords in Jekyll files.
Keep RLS enabled.
Do not create public insert policies casually.
Use Edge Function as the write gate.
Validate payloads server-side.
Use a honeypot field.
Use max-length checks.
Use GitHub URL validation.
Use CORS allowlist, but do not treat CORS as full security.

The publishable key is allowed in the browser, but it is not a full security barrier. Anyone can inspect browser JavaScript.

The real protection comes from the backend function and database design.

What Worked

Successful proof points:

  • Supabase Postgres database connected
  • schema created and extended
  • notebook psycopg2 insert tested
  • SQLAlchemy read helper tested
  • Supabase CLI worked through npx
  • personal access token worked for CLI commands
  • Edge Function created
  • function deployed
  • frontend form sent payload
  • Edge Function received payload
  • database insert succeeded
  • row appeared in Postgres immediately

Next Steps

The next layer is GitHub README automation.

Planned flow:

repo_url submitted
    ↓
parse GitHub owner / repo / branch / path
    ↓
fetch README from GitHub API
    ↓
store readme_markdown
    ↓
set readme_fetch_status
    ↓
review stored README directly from database

Additional future work:

  • add GitHub README fetch logic
  • add project approval workflow into projects_builder
  • create admin review queries
  • add unit tests
  • refactor notebook helpers into src/
  • move frontend Supabase config into _data/supabase.yml
  • create diagrams in draw.io
  • write architecture blog post
  • add first-party dashboard metrics

Final Architecture State

Current working MVP:

DataInsideData™ Static Site
    ↓
Builder Showcase Submit Form
    ↓
JavaScript Payload
    ↓
Supabase Edge Function
    ↓
Validation + Write Key
    ↓
Supabase Postgres
    ↓
builder_project_submissions
    ↓
Manual Review

This is now a real backend intake system, not just a static page.

References


Data Inside Data™.

Tech Hands, a Science Mind, and a Heart for Community.

Updated: