4.3 KiB
4.3 KiB
Refactor 2: Public Launch Hardening
Purpose Overview
This refactor prepares Fiddy for public exposure without changing the core stack (Next.js + external Postgres). The goal is to harden API contracts, improve abuse resistance, tighten security posture, and make deployment/operations repeatable for self-hosted production.
Primary outcomes:
- Keep architecture stable and avoid risky stack rewrite.
- Standardize API response metadata (
request_id) for traceability. - Add layered rate limiting (app + proxy plan) for auth and write paths.
- Remove sensitive logging risk (no full invite codes, no secrets).
- Add health probes and deployment/ops reference artifacts.
- Document rollout, rollback, backup, and monitoring runbooks.
Scope Checklist
- Phase 1: App security + API contract hardening
- Phase 2: Dokploy deployment workflow artifacts
- Phase 3: Nginx + host hardening artifacts
- Phase 4: Observability stack references/configs
- Phase 5: Backup + restore process and scripts/docs
- Verification pass (tests/build/lint where possible)
Running Implementation Log
2026-02-14
- Started
Refactor 2execution from current in-progress workspace baseline. - Confirmed this repo already contains broad uncommitted changes unrelated to this phase; implementation will be done via targeted edits only.
- Established this document as the source log/checklist for all noteworthy decisions, tradeoffs, blockers, and completed steps.
- Added migration
packages/db/migrations/007_rate_limits.sqlfor server-side rate limit state. - Added server limiter
apps/web/lib/server/rate-limit.tsand wired write-path guardrails in server services (groups,group-members,group-invites,entries,buckets,tags,group-settings). - Hardened API error pipeline in
apps/web/lib/server/errors.ts:- Added
RATE_LIMITEDmapping (429). - Added
request_idalias in structured error body. - Extended sensitive-key redaction for invite code keys.
- Removed stray debug
console.log()call.
- Added
- Fixed invite-code leak risk in
apps/web/lib/server/groups.tsby sending onlyinviteCodeLast4in error context. - Standardized API response envelope updates in auth and route handlers so responses include both
requestIdandrequest_idwhile preserving backward compatibility. - Added health probe routes:
apps/web/app/api/health/live/route.tsapps/web/app/api/health/ready/route.ts
- Added security header baseline in
apps/web/next.config.mjs(CSP, frame/referrer/content-type hardening). - Added CI/CD workflow for Dokploy-triggered deploys:
.gitea/workflows/deploy-dokploy.yml
- Added self-host edge + observability + backup artifacts:
docker/nginx/fiddy.confdocker/nginx/includes/fiddy-proxy.confdocker/observability/docker-compose.observability.ymldocker/observability/loki-config.ymldocker/observability/promtail-config.ymlscripts/backup-postgres.shscripts/restore-postgres.shdocs/public-launch-runbook.md
- Added regression tests for request-id contract and limiter behavior:
apps/web/__tests__/errors-response.test.tsapps/web/__tests__/rate-limit.test.ts
- Verification results:
npm test: pass (25 passed,1 skipped).npm run build: pass.npm run lint: still fails due existing workspace lint script invocation issue (next lintresolvesapps/web/lintpath).
- Post-verification fixups:
- Added table auto-bootstrap fallback in
apps/web/lib/server/rate-limit.tsto avoid failures in environments where migration007_rate_limits.sqlhas not been applied yet. - Corrected
Entrymapping consistency inapps/web/lib/server/entries.ts(bucketIdincluded in all return shapes). - Replaced
rowCountchecks withrows.lengthin typed query paths to satisfy current TypeScript/pgtypings.
- Added table auto-bootstrap fallback in
- Implementation correction note:
- A batch replacement briefly introduced invalid destructuring (
request_idingetRequestMetadestructure). This was corrected in all affected routes before final verification.
- A batch replacement briefly introduced invalid destructuring (
Risks / Notes to Revisit
- Workspace is intentionally dirty; commits must be path-scoped to avoid mixing unrelated changes.
npm run lintcurrently fails duenext lintinvocation behavior in this environment; lint verification needs explicit follow-up task.