Skip to content

Market readiness, phase 1+2: self-enforcing privacy, CI, rate limiting, de-echo - #16

Closed
ArneeMe wants to merge 6 commits into
mainfrom
claude/page-market-readiness-x35fdx
Closed

Market readiness, phase 1+2: self-enforcing privacy, CI, rate limiting, de-echo#16
ArneeMe wants to merge 6 commits into
mainfrom
claude/page-market-readiness-x35fdx

Conversation

@ArneeMe

@ArneeMe ArneeMe commented Jul 9, 2026

Copy link
Copy Markdown
Owner

First two iterations of the market-readiness roadmap.

Phase 1 — trust foundation

  • Auto-delete submissions on certificate issuance. The certificates POST route now deletes the submission row in the same Hasura mutation (one transaction) that inserts the cert, so the privacy guarantee no longer depends on an admin clicking "Slett innsendingen nå". The dashboard keeps issued data in memory so a failed PDF render can be retried, and the post-generation dialog reports the automatic deletion. CLAUDE.md/README updated.
  • CI. New GitHub Actions workflow: tsc --noEmit, ESLint, vitest, next build on every push/PR. ESLint (flat config, next/core-web-vitals + next/typescript) is newly set up — the codebase passes with zero errors.
  • Rate limiting. Per-IP fixed-window throttle (20/10 min, CF-Connecting-IP) on the anonymous submissions POST, with unit tests. In-memory per edge isolate — best-effort by design.
  • Reproducible schema. scripts/migrations/0000-baseline-schema.sql reconstructs all tables incl. the core ones that only existed in the live Nhost project. All IF NOT EXISTS — a no-op against production, everything needed for a fresh install.

Phase 2 — de-echo

  • / is a real landing page (product pitch, privacy explanation, org directory, admin login, onboarding contact) instead of a hard redirect to /org/echo.
  • Generic root metadata ("attester.no" with title template) instead of "echo Attest"; per-org generateMetadata on the form and verify pages.
  • The in-app starter gallery was already neutral; echo's bundled template is only used by echo's own seed scripts and stays.

Notes

  • certificates.submission_id is intentionally kept: it is the lookup key the verify route resolves the QR URL's id= param against, not personal data.
  • No Hasura console action needed for deploy — the auto-delete uses the already-tracked delete_submissions_by_pk.
  • Legacy /verify untouched, per CLAUDE.md.

Verification

  • 99 vitest tests pass (7 new for the rate limiter), typecheck and lint clean, production build succeeds.
  • Landing page smoke-tested against an unreachable DB — renders with the org directory gracefully omitted.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BFHkXUuHJME4cF9AJWbavB


Generated by Claude Code

claude added 6 commits July 9, 2026 13:20
The privacy guarantee (no personal data at rest after issuance) used to
depend on an admin clicking 'Slett innsendingen nå'. Now the certificates
POST route deletes the submission in the same Hasura mutation that inserts
the cert, so both happen in one transaction.

The dashboard keeps issued submission data in memory so a failed PDF
render can be retried without re-hitting the certificates route, and the
post-generation dialog now reports the automatic deletion instead of
asking the admin to delete manually.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BFHkXUuHJME4cF9AJWbavB
Per-IP fixed-window throttle (20 per 10 min) on POST /api/org/[slug]/
submissions, keyed on CF-Connecting-IP. In-memory per edge isolate —
best-effort by design; the size caps already bound payloads, this bounds
request volume so one machine can't flood an org's review queue.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BFHkXUuHJME4cF9AJWbavB
New GitHub Actions workflow runs tsc --noEmit, eslint, vitest, and
next build. ESLint (flat config, next/core-web-vitals + next/typescript)
was not set up in the repo before — the codebase passes with zero errors.
Adds lint and typecheck npm scripts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BFHkXUuHJME4cF9AJWbavB
organizations, user_organizations, templates, certificates and
legacy_certificates only existed in the live Nhost project — a fresh
install could not be built from the repo. New 0000-baseline-schema.sql
reconstructs the full schema (all IF NOT EXISTS, no-op on the existing
DB) with the privacy constraints documented inline, plus an index for
the verify lookup. README points fresh installs at the baseline file.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BFHkXUuHJME4cF9AJWbavB
next build regenerates the file with a triple-slash reference that
trips @typescript-eslint/triple-slash-reference; it is Next.js output,
not project code.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BFHkXUuHJME4cF9AJWbavB
The root page hard-redirected to /org/echo and the site title was
'echo Attest' — the product had no identity of its own. Now:

- / is a real landing page: what attester.no is, the privacy pitch,
  a directory of participating orgs (renders without the directory if
  the DB is unreachable), admin login, and an onboarding contact link.
- Root metadata is generic with a title template; the org form and
  verify pages get per-org titles via generateMetadata.
- New src/lib/server/orgs.ts exposes the public org identity fields
  (slug, name) for server components.

The echo-specific customTemplate/echoFieldBindings stay: they are only
imported by echo's own seed scripts, not shipped in any app bundle, and
the in-app starter gallery (starterTemplates.ts) was already neutral.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BFHkXUuHJME4cF9AJWbavB
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying inf319-certificate with  Cloudflare Pages  Cloudflare Pages

Latest commit: 94e8195
Status: ✅  Deploy successful!
Preview URL: https://8579175c.inf319-certificate.pages.dev
Branch Preview URL: https://claude-page-market-readiness.inf319-certificate.pages.dev

View logs

ArneeMe commented Jul 12, 2026

Copy link
Copy Markdown
Owner Author

Superseded by the review-ordered stack #25#26#27#28#29, which re-slices all nine phase PRs by review difficulty (tooling/content/tests first, core & security concentrated in #29) so the whole set can be handled in one sitting. The final tree is byte-identical to the sum of the phase branches. Closing.


Generated by Claude Code

@ArneeMe ArneeMe closed this Jul 12, 2026
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