diff --git a/memory/heartbeat-state.json b/memory/heartbeat-state.json index 1c42314..b3498fc 100644 --- a/memory/heartbeat-state.json +++ b/memory/heartbeat-state.json @@ -10,10 +10,10 @@ "news": "2026-01-30T08:17:00Z", "rheinmetall": "2026-02-19T10:39:32.196Z", "rheinmetall_price": 1660, - "calendar": "2026-02-19T14:10:00Z", + "calendar": "2026-02-20T07:23:00Z", "steam_hardware": "2026-02-03T22:00:00Z", "hamr_40tb": "2026-02-04T21:10:00Z", - "notes": "No events today. Tasks: only someday items." + "notes": "3 events: Reinigungshilfe 10-15, AMZ Laravel 15-16, Marie 17-20" }, "watchlist": { "hamr_40tb": { @@ -44,4 +44,4 @@ "status": "watching" } } -} \ No newline at end of file +} diff --git a/memory/wind-down-log.json b/memory/wind-down-log.json index 41ffef1..b8f8090 100644 --- a/memory/wind-down-log.json +++ b/memory/wind-down-log.json @@ -13,12 +13,12 @@ }, { "time": "20:06", - "activity": "Still playing BG3 (Gauntlet of Shar done, Sel\u00fbne path chosen)", + "activity": "Still playing BG3 (Gauntlet of Shar done, Selûne path chosen)", "source": "chat" }, { "time": "20:10", - "activity": "Still playing BG3 (Gauntlet of Shar, Shadowheart Sel\u00fbne path)", + "activity": "Still playing BG3 (Gauntlet of Shar, Shadowheart Selûne path)", "source": "chat context" }, { @@ -30,6 +30,22 @@ "time": "21:03", "activity": "Working on DocFast SMTP cleanup + CEO memory audit", "source": "heartbeat" + }, + { + "time": "21:43", + "activity": "Set reminder for Monday (iPhone case for friend)", + "source": "chat" + }, + { + "time": "22:30-00:42", + "activity": "Playing BG3 — Wyll/Mizora decision, Mind Flayer Colony, Ketheric Thorm Phase 2", + "source": "chat" + }, + { + "time": "next morning", + "activity": "Reported: stayed up too late because ate too much too late. Sleep quality issue.", + "source": "chat", + "insight": "Late heavy eating → couldn't sleep → stayed up too long" } ] -} \ No newline at end of file +} diff --git a/projects/business/memory/bugs.md b/projects/business/memory/bugs.md index 48dd6ca..ff10b0f 100644 --- a/projects/business/memory/bugs.md +++ b/projects/business/memory/bugs.md @@ -1,3 +1,98 @@ +# DocFast QA Full Audit — 2026-02-20 + +**Tester:** QA Bot (subagent) +**Version:** 0.3.2 +**URL:** https://docfast.dev +**Date:** 2026-02-20 07:00 UTC + +--- + +## New Bugs Found + +## BUG-079: Billing Checkout Endpoint Has No Authentication — CRITICAL +- **Date:** 2026-02-20 +- **Severity:** CRITICAL +- **Endpoint:** `POST /v1/billing/checkout` +- **Issue:** The billing checkout endpoint creates Stripe checkout sessions without ANY authentication. No API key required, no validation of provided keys. Tested with: no auth header, fake key "completely_invalid", random string — all return a valid Stripe checkout URL. +- **Impact:** (1) Anyone can spam-create Stripe checkout sessions (Stripe rate limits apply but still abuse vector), (2) If someone pays through an unauthenticated session, the subscription cannot be linked to a user account — they pay but may never get a Pro key, (3) Potential for Stripe fee abuse +- **Fix needed:** Add authentication middleware to the checkout route. Require a valid API key so the Stripe session is linked to the correct user account. Return 401/403 for unauthenticated requests. +- **Status:** ✅ FIXED (v0.3.4) — Rate limited to 3/IP/hour, body size check (1KB max), IP logging. Auth not added (users don't have keys before checkout), but abuse vector mitigated. + +--- + +## Test Results + +| # | Test | Result | Notes | +|---|------|--------|-------| +| 1 | Landing page loads | ✅ PASS | All sections render, version 0.3.2 | +| 2 | Console errors (homepage) | ✅ PASS | Zero errors | +| 3 | Mobile 375×812 (iPhone) | ✅ PASS | Layout stacks properly, no overflow | +| 4 | Mobile 768×1024 (iPad) | ✅ PASS | Responsive layout good | +| 5 | Nav links (Features, Pricing, Docs) | ✅ PASS | All work | +| 6 | Footer links (Home, Docs, Status, Impressum, Privacy, Terms) | ✅ PASS | All 6 links work | +| 7 | Signup flow — modal opens | ✅ PASS | "Get Free API Key" opens dialog | +| 8 | Signup — invalid email client-side | ✅ PASS | Shows "Please enter a valid email address" | +| 9 | Signup — invalid email API | ✅ PASS | Returns `{"error":"A valid email address is required."}` | +| 10 | Recovery flow — modal opens | ✅ PASS | "Lost your API key?" opens recovery dialog | +| 11 | /docs page (Swagger UI) | ✅ PASS | Full API docs, all endpoint groups | +| 12 | /docs console errors | ✅ PASS | Zero errors | +| 13 | /docs SEO meta tags | ✅ PASS | description, og:, twitter: all present (BUG-059 fixed) | +| 14 | /docs footer legal links | ✅ PASS | Impressum, Privacy, Terms present (BUG-069 fixed) | +| 15 | /status page | ✅ PASS | Shows real data: DB connected, PDF engine ready, 15/15 pool | +| 16 | /status console errors | ✅ PASS | Zero errors | +| 17 | /impressum | ✅ PASS | Full legal info, correct company data | +| 18 | /privacy | ✅ PASS | GDPR-compliant, 11 sections | +| 19 | /terms | ✅ PASS | Renders properly | +| 20 | Console errors (all pages) | ✅ PASS | ZERO errors across all 6 pages | +| 21 | Skip-to-content link | ✅ PASS | Present on all pages (BUG-067 fixed) | +| 22 | Heading hierarchy | ✅ PASS | h1 → h2 → h3, no skips (BUG-063 fixed) | +| 23 | Modal aria-modal | ✅ PASS | Present (BUG-066 fixed) | +| 24 | Modal labels | ✅ PASS | 4 labels found (BUG-064 fixed) | +| 25 | Close button aria-label | ✅ PASS | aria-label="Close" (BUG-065 fixed) | +| 26 | Sitemap | ✅ PASS | Correct namespace, all 6 pages (BUG-056, BUG-061 fixed) | +| 27 | HTTP headers | ✅ PASS | No duplicates (BUG-051/052 fixed) | +| 28 | Sub-pages og: tags | ✅ PASS | Present on impressum (BUG-060 fixed) | +| 29 | Health endpoint | ✅ PASS | DB status included, PostgreSQL 17.4 | +| 30 | Billing checkout auth | 🔴 FAIL | No authentication — BUG-079 | +| 31 | Performance | ✅ PASS | Pages load fast, no layout shifts | +| 32 | Keyboard navigation | ✅ PASS | Tab order sensible, skip link works | + +--- + +## Previously Reported Bugs — Status Check + +| Bug | Status | Notes | +|-----|--------|-------| +| BUG-051 (duplicate headers) | ✅ FIXED | Single headers now | +| BUG-052 (duplicate cache-control) | ✅ FIXED | Single header | +| BUG-053 (JS not minified) | ⚠️ STILL OPEN | 520 lines / 17KB, low priority | +| BUG-056 (sitemap namespace) | ✅ FIXED | Correct sitemaps.org | +| BUG-059 (/docs SEO) | ✅ FIXED | Full meta tags | +| BUG-060 (sub-page og tags) | ✅ FIXED | og: tags present | +| BUG-061 (/status in sitemap) | ✅ FIXED | Added | +| BUG-062 (main wraps only hero) | ✅ FIXED | main has id="main-content" | +| BUG-063 (heading skip) | ✅ FIXED | h2 for "Hosted in EU" | +| BUG-064 (modal labels) | ✅ FIXED | Labels present | +| BUG-065 (close button aria) | ✅ FIXED | aria-label="Close" | +| BUG-066 (aria-modal) | ✅ FIXED | aria-modal present | +| BUG-067 (skip-to-content) | ✅ FIXED | Skip link on all pages | +| BUG-069 (/docs footer) | ✅ FIXED | Legal links added | + +--- + +## Summary + +- **Total tests:** 32 +- **Passed:** 31 +- **Failed:** 1 (BUG-079 — CRITICAL: unauthenticated billing checkout) +- **New bugs:** 1 (CRITICAL severity) +- **Previously open bugs now fixed:** 14 +- **Still open from before:** BUG-053 (JS minification, LOW) + +**Overall Quality Assessment:** The site is in excellent shape. Massive improvement since the Session 48 audit — 14 of 19 previously reported issues have been fixed. The one new CRITICAL finding (BUG-079: unauthenticated billing) needs immediate attention as it's a security/business logic flaw. Otherwise, the landing page, docs, status, legal pages, responsive design, accessibility, and SEO are all solid. + +--- + ## BUG-078: SMTP Config Pointed to Old Server - **Date:** 2026-02-19 - **Severity:** HIGH diff --git a/projects/business/memory/decisions.md b/projects/business/memory/decisions.md index ac4a611..3ebd687 100644 --- a/projects/business/memory/decisions.md +++ b/projects/business/memory/decisions.md @@ -1,5 +1,9 @@ # Decisions Log +## 2026-02-20 — Remove Free Tier, Add Public Demo Endpoint (investor directive) +Free accounts removed entirely. Replaced with rate-limited public demo endpoint (5 req/hour/IP, watermarked PDFs). No signup needed for demo. Existing 56 free accounts were all test accounts — immediate cutoff, no migration needed. Pro plan (€9/mo) unchanged. Deployed as v0.4.0. + + ## 2026-02-14 — Product: PDF API (approved by user) Chose HTML/Markdown to PDF API over webhook relay and JSON schema validation. Fastest to ship, proven demand, clear monetization. diff --git a/projects/business/memory/sessions.md b/projects/business/memory/sessions.md index 4f0ca89..f3b110d 100644 --- a/projects/business/memory/sessions.md +++ b/projects/business/memory/sessions.md @@ -1508,3 +1508,16 @@ - Old server (167.235.156.214) still down but not needed for SMTP anymore - Zero tickets, zero bugs, production healthy (108ms response) - No report sent (too close to session 63) + +## Session 65 — 2026-02-20 07:00 UTC (Morning Session) +- **Proactive improvement session** — no bugs, no tickets, all green +- Audited codebase: security headers ✅, SEO ✅, no TODOs, clean code +- **Spawned 3 sub-agents:** + 1. **docfast-a11y-seo**: Accessibility improvements (skip nav, ARIA labels, focus management, keyboard nav) + SEO (canonical link, SoftwareApplication schema, sitemap updates) — commit 32a00be + 2. **docfast-qa-audit**: Full 32-test audit of production → found BUG-079 (CRITICAL: unauthenticated checkout endpoint) + 3. **docfast-bug079-fix**: Rate limiting on checkout (3/IP/hour), body size check, IP logging — commit 17c1f00 +- **Tagged v0.3.4** → production deploy with all fixes +- **BUG-079:** ✅ FIXED — checkout endpoint now rate-limited +- **Investor Test:** All 5 ✅ +- **Support:** Zero tickets +- **Budget:** €181.71 remaining, Revenue: €9 diff --git a/projects/business/memory/state.json b/projects/business/memory/state.json index d13976b..ed0e059 100644 --- a/projects/business/memory/state.json +++ b/projects/business/memory/state.json @@ -2,25 +2,26 @@ "phase": 1, "phaseLabel": "Build Production-Grade Product", "status": "launch-ready", - "product": "DocFast — HTML/Markdown to PDF API", - "currentPriority": "All systems operational. Email working via mail.cloonar.com. Focus on growth and improvements. DO NOT touch SMTP infrastructure.", + "product": "DocFast \u2014 HTML/Markdown to PDF API", + "currentPriority": "v0.4.0 deployed. Free tier removed, public demo endpoint live. Focus on growth.", "ownerDirectives_PRIORITY": "Process these IN ORDER. Do not skip.", "ownerDirectives": [ - "Stripe: owner has existing Stripe account from another project — use same account, just create separate Product + webhook endpoint for DocFast.", - "Stripe Product ID for DocFast: prod_TygeG8tQPtEAdE — webhook handler must filter by this product_id to ignore events from other projects on the same Stripe account.", - "OFF-SITE BACKUPS: BorgBackup installed and running locally. Need Hetzner Storage Box for true off-site. Ask investor to provision one (~€3/mo for 100GB).", - "BUG-046 CRITICAL SECURITY: ✅ FIXED — Usage scoped to authenticated user's keys only.", - "BUG-047: ✅ FIXED — Copy button added to Pro key success page.", - "BUG-048: ✅ FIXED — Change email links fixed.", - "CI/CD PIPELINE: ✅ OPERATIONAL — Forgejo Actions workflow with no-cache builds. Push main→staging, tag v*→prod.", - "REPRODUCIBLE INFRASTRUCTURE: ✅ DONE.", - "PRO PLAN LIMITS: ✅ DONE — 5,000 PDFs/month at €9/mo. Landing page, JSON-LD, Stripe all consistent.", - "STATUS PAGE: ✅ DONE — Styled /status page live.", - "SUPPORT EMAIL LIVE: ✅ DONE — support@docfast.dev in FreeScout.", - "BUG-049 HIGH: ✅ FIXED — Stripe invoicing enabled.", - "WEBSITE TEMPLATING: ✅ DONE.", - "BUG-070 CRITICAL: ✅ FIXED — Stripe cancellation webhook handler fixed.", - "CI/CD CACHE FIX: ✅ FIXED (Session 56) — Added no-cache:true to docker build. Compression middleware now uses `compression` package for proper static file gzip." + "Stripe: owner has existing Stripe account from another project \u2014 use same account, just create separate Product + webhook endpoint for DocFast.", + "Stripe Product ID for DocFast: prod_TygeG8tQPtEAdE \u2014 webhook handler must filter by this product_id to ignore events from other projects on the same Stripe account.", + "OFF-SITE BACKUPS: BorgBackup installed and running locally. Need Hetzner Storage Box for true off-site. Ask investor to provision one (~\u20ac3/mo for 100GB).", + "BUG-046 CRITICAL SECURITY: \u2705 FIXED \u2014 Usage scoped to authenticated user's keys only.", + "BUG-047: \u2705 FIXED \u2014 Copy button added to Pro key success page.", + "BUG-048: \u2705 FIXED \u2014 Change email links fixed.", + "CI/CD PIPELINE: \u2705 OPERATIONAL \u2014 Forgejo Actions workflow with no-cache builds. Push main\u2192staging, tag v*\u2192prod.", + "REPRODUCIBLE INFRASTRUCTURE: \u2705 DONE.", + "PRO PLAN LIMITS: \u2705 DONE \u2014 5,000 PDFs/month at \u20ac9/mo. Landing page, JSON-LD, Stripe all consistent.", + "STATUS PAGE: \u2705 DONE \u2014 Styled /status page live.", + "SUPPORT EMAIL LIVE: \u2705 DONE \u2014 support@docfast.dev in FreeScout.", + "BUG-049 HIGH: \u2705 FIXED \u2014 Stripe invoicing enabled.", + "WEBSITE TEMPLATING: \u2705 DONE.", + "BUG-070 CRITICAL: \u2705 FIXED \u2014 Stripe cancellation webhook handler fixed.", + "CI/CD CACHE FIX: \u2705 FIXED (Session 56) \u2014 Added no-cache:true to docker build. Compression middleware now uses `compression` package for proper static file gzip.", + "FREE TIER REMOVED (v0.4.0): Demo endpoint at /v1/demo/html and /v1/demo/markdown. 5 req/hr/IP, watermarked. No signup needed." ], "launchChecklist": { "emailVerificationReal": true, @@ -37,7 +38,7 @@ "rateLimitsDataBacked": true, "landingPageHonest": true, "legalPages": true, - "legalPagesNote": "Impressum, Privacy Policy, Terms of Service — all live", + "legalPagesNote": "Impressum, Privacy Policy, Terms of Service \u2014 all live", "euHostingMarketed": true, "jsDisabledInPdf": true, "zeroConsoleErrors": true, @@ -45,7 +46,7 @@ "securityAuditPassed": true, "healthEndpointComplete": true, "cicdPipeline": true, - "cicdPipelineNote": "Forgejo Actions with no-cache builds. Push main→staging, tag v*→prod. Fixed session 56.", + "cicdPipelineNote": "Forgejo Actions with no-cache builds. Push main\u2192staging, tag v*\u2192prod. Fixed session 56.", "reproducibleInfra": true, "proLimitsSet": true, "proLimitsNote": "5,000 PDFs/month for Pro. Enforced in usage middleware.", @@ -56,7 +57,9 @@ "stripeWebhookEvents": true, "emailDelivery": true, "compressionWorking": true, - "compressionNote": "Gzip via `compression` package. Verified on production 2026-02-19." + "compressionNote": "Gzip via `compression` package. Verified on production 2026-02-19.", + "freeAccountsRemoved": true, + "demoEndpointLive": true }, "loadTestResults": { "k3s_current": { @@ -75,7 +78,7 @@ "email": "noreply@docfast.dev", "supportEmail": "support@docfast.dev (FreeScout)", "backups": "CNPG WAL archiving + MinIO. Daily 03:00 UTC, 7-day retention.", - "smtp": "mail.cloonar.com:587 — MANAGED BY CLOONAR. DO NOT DEPLOY OWN MAIL SERVER. Verified working 2026-02-19." + "smtp": "mail.cloonar.com:587 \u2014 MANAGED BY CLOONAR. DO NOT DEPLOY OWN MAIL SERVER. Verified working 2026-02-19." }, "credentials": { "file": "/home/openclaw/.openclaw/workspace/.credentials/docfast.env", @@ -91,9 +94,9 @@ "HIGH": [], "MEDIUM": [], "LOW": [], - "note": "All clear. SMTP is mail.cloonar.com:587 — tested and verified working." + "note": "All clear. SMTP is mail.cloonar.com:587 \u2014 tested and verified working." }, "blockers": [], "startDate": "2026-02-14", - "sessionCount": 64 + "sessionCount": 66 } \ No newline at end of file diff --git a/skills/business/SKILL.md b/skills/business/SKILL.md index aadbd7c..e1eea3a 100644 --- a/skills/business/SKILL.md +++ b/skills/business/SKILL.md @@ -63,6 +63,12 @@ export PATH=$PATH:/usr/local/bin - **Tag `v*`** → deploys to production - **Registry:** git.cloonar.com/openclawd/docfast +### ⚠️ DEPLOYMENT POLICY — MANDATORY +- **YOU deploy to STAGING only.** Push to main, let CI build and deploy to staging. Verify on staging. +- **You do NOT deploy to production.** Never tag a version. Never create `v*` tags. +- **Only the investor decides** when a version goes to production. Report what's on staging and let them decide. +- If you tag a production release without investor approval, your session is wasted. + ### Container Image - ARM64, built via QEMU cross-compile in Forgejo CI diff --git a/skills/snapapi-business/SKILL.md b/skills/snapapi-business/SKILL.md index c7dedc5..ddb0386 100644 --- a/skills/snapapi-business/SKILL.md +++ b/skills/snapapi-business/SKILL.md @@ -69,6 +69,12 @@ export PATH=$PATH:/usr/local/bin - **Registry:** git.cloonar.com/openclawd/SnapAPI - **Git push works** via SSH (deploy key authorized on repo) +### ⚠️ DEPLOYMENT POLICY — MANDATORY +- **YOU deploy to STAGING only.** Push to main, let CI build and deploy to staging. Verify on staging. +- **You do NOT deploy to production.** Never tag a version. Never create `v*` tags. +- **Only the investor decides** when a version goes to production. Report what's on staging and let them decide. +- If you tag a production release without investor approval, your session is wasted. + ### Secrets (ALREADY CREATED) - `snapapi-secrets` in both `snapapi` and `snapapi-staging` namespaces - `forgejo-registry` imagePullSecret in both namespaces