diff --git a/memory/2026-03-03.md b/memory/2026-03-03.md new file mode 100644 index 0000000..0c5f37c --- /dev/null +++ b/memory/2026-03-03.md @@ -0,0 +1,16 @@ +# 2026-03-03 — Tuesday + +## Key Events +- **USA-Iran conflict**: Major escalation. US & Israel struck Iran Feb 28 ("Operation Epic Fury"). Iran retaliating with missiles/drones on US bases in Persian Gulf. Active conflict ongoing. +- **Sessel Lieferung**: Scheduled 12:00-17:00, no confirmation received +- **Portfolio**: RHM closed ~€1,611 (-1%), PICK dropped -6.84% to $59.96, DFNS closed €62.04 (+10.31% total return) +- **News briefings disabled**: User asked to stop Der Standard and AI News cron jobs — both disabled (not deleted) +- **RHM analysis**: Analysts say Iran conflict NOT a direct catalyst for RHM — European rearmament is the thesis. Consolidation until March 11 earnings. +- **No response to evening wind-down messages** (19:15 and 20:20 WhatsApp) + +## Portfolio Notes +- PICK significant drop — possible rotation from broad metals to nuclear/uranium +- URA ETF +5.6% — uranium sector surging +- Consider checking URA availability on N26 +- RHM earnings March 11 key catalyst +- DFNS volatile session, hit €64.04 intraday before pullback to €62.04 diff --git a/memory/portfolio.json b/memory/portfolio.json index efad348..671f612 100644 --- a/memory/portfolio.json +++ b/memory/portfolio.json @@ -52,14 +52,15 @@ ], "notes": "N26 uses Xetra tickers. Always provide ISIN for orders. Fractional shares by EUR amount supported.", "created": "2026-02-12T20:00:00Z", - "lastUpdated": "2026-03-02T17:15:00Z", + "lastUpdated": "2026-03-03T17:15:00Z", "closingSnapshot": { - "date": "2026-03-02", - "DFNS": 61.89, - "portfolioValue": 1100.74, - "dailyPL": 45.35, - "dailyPLpct": 4.3, - "totalReturn": 10.07 + "date": "2026-03-03", + "DFNS": 62.04, + "portfolioValue": 1103.07, + "dailyPL": -5.16, + "dailyPLpct": -0.47, + "totalReturn": 10.31 }, - "pendingActions": [] + "pendingActions": [], + "lastUpdated": "2026-03-03T17:15:00Z" } \ No newline at end of file diff --git a/memory/real-portfolio.json b/memory/real-portfolio.json index dcd19ce..504b692 100644 --- a/memory/real-portfolio.json +++ b/memory/real-portfolio.json @@ -27,6 +27,18 @@ ], "totalInvested": 22200, "priceHistory": [ + { + "timestamp": "2026-03-03T15:03:00Z", + "RHM.DE": 1627.50, + "PICK": 64.36, + "note": "3:03 PM Vienna - RHM.DE stable €1,627.50. PICK $64.36 (+0.03%). No new opportunities; thesis intact on geopolitical support. Web search rate-limited. HOLD all." + }, + { + "timestamp": "2026-03-03T13:03:00Z", + "RHM.DE": 1627.50, + "PICK": 64.36, + "note": "1:03 PM Vienna - RHM.DE flat €1,627.50. PICK flat $64.36. Defense thesis intact; geopolitical tensions (US-Iran) supporting allocations despite intraday volatility. No new opportunities at this time (API rate limits). HOLD all positions. RHM earnings March 11 catalyst remains key." + }, { "timestamp": "2026-03-03T12:01:00Z", "RHM.DE": 1627.50, @@ -96,6 +108,22 @@ "note": "RHM at €1,663.50; recent earnings miss (-22.78%). Gold/metals/mining outperforming in 2026. Defense sector stable amid geopolitical tensions." } ], - "lastAnalysis": "2026-03-03T12:01:00Z", - "updateNote": "12:01 PM Vienna Tuesday - RHM.DE retreated to €1,627.50 (-€36 from morning, ~-2.2%). Defense thesis still valid amid geopolitical tensions but profit-taking visible. PICK holding $64.36. DFNS.PA data unavailable. Broad market weakness continues, defense outperforming but volatility elevated. RHM earnings March 11 remain key catalyst. No compelling new opportunities; portfolio thesis intact despite intraday pullback. HOLD all." -} + "lastAnalysis": "2026-03-03T18:21:00Z", + "updateNote": "6:21 PM Vienna Tuesday - PICK still under pressure near $59.96 (-6.84% today). RHM.DE €1,627.50 per last 3 PM check (geopolitical support holding). Finnhub/stonks API gaps. Clean energy thesis strong (NextEra, solar/wind +15% global investment 2025). Mining weakness suggests potential sector rotation away from commodities into clean tech/semiconductors (5.8% EPS growth estimated 2026). RHM earnings March 11 catalyst. No immediate rebalancing recommended; thesis intact despite intraday volatility. HOLD positions.", + "priceHistory": [ + { + "timestamp": "2026-03-03T18:21:00Z", + "PICK": 59.96, + "note": "6:21 PM Vienna - PICK holding $59.96 (-6.84% day). RHM.DE €1,627.50 (3 PM data, geopolitical support). Clean energy outperforming (5.8% EPS growth 2026). Mining weakness vs. clean tech strength signals potential rotation. RHM earnings catalyst March 11. HOLD all positions; thesis intact despite volatility." + }, + { + "timestamp": "2026-03-03T17:08:00Z", + "PICK": 59.96, + "note": "5:08 PM Vienna - PICK down 6.84% to $59.96 (from $64.36). Mining ETF weakness vs. uranium strength. URA +5.58%. RHM.DE/DFNS.PA data unavailable. Broad market weakness pressuring commodities but defense thesis intact. RHM earnings March 11 catalyst." + }, + { + "timestamp": "2026-03-03T15:03:00Z", + "RHM.DE": 1627.50, + "PICK": 64.36, + "note": "3:03 PM Vienna - RHM.DE stable €1,627.50. PICK $64.36 (+0.03%). No new opportunities; thesis intact on geopolitical support. Web search rate-limited. HOLD all." + } diff --git a/memory/wind-down-log.json b/memory/wind-down-log.json index 3cde966..0eee0f6 100644 --- a/memory/wind-down-log.json +++ b/memory/wind-down-log.json @@ -31,5 +31,22 @@ "type": "status", "note": "No response to 19:12 check-in. Not nudging again this late." } + ], + "2026-03-03": [ + { + "time": "19:15", + "type": "check-in", + "note": "Sent WhatsApp asking what they are doing + Sessel question" + }, + { + "time": "20:20", + "type": "suggestion", + "note": "Sent Conan/audiobook suggestion + nose shower reminder. No response to 19:15." + }, + { + "time": "22:04", + "type": "status", + "note": "No response to either message. Not nudging again." + } ] -} +} \ No newline at end of file diff --git a/projects/business/memory/bugs.md b/projects/business/memory/bugs.md index f1322d2..c88b2ef 100644 --- a/projects/business/memory/bugs.md +++ b/projects/business/memory/bugs.md @@ -1,3 +1,11 @@ +## BUG-099: provisionedSessions Set in billing.ts grows unbounded (memory leak) +- **Date:** 2026-03-03 +- **Severity:** LOW +- **Issue:** `provisionedSessions` in `src/routes/billing.ts` is an unbounded `Set` that stores every Stripe checkout session ID forever. Used to prevent duplicate key provisioning on success page refresh. DB-level dedup (`findKeyByCustomerId`) handles correctness across pod restarts, but the in-memory Set grows without bound. +- **Impact:** Over months/years, memory usage increases linearly with purchases. Low real-world impact given expected volume, but a code quality issue. +- **Fix:** Replace with a TTL Map that auto-expires entries after 24h. +- **Status:** ✅ FIXED — commit 5f776db. Replaced Set with TTL Map (24h expiry, hourly cleanup). 4 TDD tests added. 447 tests total, all passing. Pushed to main (staging auto-deploy). + ## BUG-098: Request interceptor leaks across browser pool pages after URL-to-PDF conversion - **Date:** 2026-03-02 - **Severity:** MEDIUM diff --git a/projects/business/memory/sessions.md b/projects/business/memory/sessions.md index 54d11dd..6505f39 100644 --- a/projects/business/memory/sessions.md +++ b/projects/business/memory/sessions.md @@ -1,5 +1,20 @@ # Session Log +## Session 123 — 2026-03-04 07:00 UTC (Wednesday Morning) +- **Production:** v0.5.1 ✅ healthy, 2 replicas, 0 restarts, ~6.5d uptime +- **Staging:** v0.5.2 ✅ healthy, commit 646a94d (31 commits ahead of prod) +- **K8s cluster:** All 3 nodes Ready +- **Support:** Zero tickets +- **Completed:** + 1. **Infrastructure health check** — All 3 K8s nodes Ready, both prod replicas healthy (0 restarts), DB connected (PostgreSQL 17.4), browser pool 15/15. Both prod and staging demo endpoints generating PDFs successfully. + 2. **Dependency update** — Sub-agent updated all safe dependencies (patch/minor only). @types/node 22.19.11→22.19.13 plus transitive dependency updates. Skipped major bumps (Express 5, vitest 4, marked 17, express-rate-limit 8). 447 tests passing, 0 vulnerabilities. Commit 646a94d pushed to main. + 3. **Codebase audit** — Reviewed Dockerfile (clean, non-root user), CORS headers (correct), rate limit headers (present), robots.txt (correct), sitemap (7 pages, valid namespace), heading hierarchy (correct), 24 ARIA attributes on landing page. No TODOs/FIXMEs in source. +- **Total tests:** 447 (all passing), 27 test files +- **Open bugs:** ZERO 🎉 +- **CI runner:** Still absent. No runner pods on cluster. Managed by Cloonar — needs investor action. +- **Investor test:** All 5 checks pass ✅ +- **Recommendation:** Staging v0.5.2 is production-ready with ZERO open bugs, 447 tests, 31 commits ahead. Request investor approval for production tag. + ## Session 122 — 2026-03-03 19:00 UTC (Tuesday Evening) - **Production:** v0.5.1 ✅ healthy, 2 replicas, 0 restarts, ~6d uptime - **Staging:** v0.5.2 ✅ healthy, commit 5f776db (30 commits ahead of prod) diff --git a/projects/business/memory/state.json b/projects/business/memory/state.json index cafd290..077f541 100644 --- a/projects/business/memory/state.json +++ b/projects/business/memory/state.json @@ -3,7 +3,7 @@ "phaseLabel": "Build Production-Grade Product", "status": "launch-ready", "product": "DocFast — HTML/Markdown to PDF API", - "currentPriority": "Production on v0.5.1. Staging updated to v0.5.2 (30 commits ahead, commit 5f776db). CI runner still DOWN. npm audit 0 vulns. 447 tests passing (27 files). ZERO open bugs. Ready for production tag when investor approves.", + "currentPriority": "Production on v0.5.1. Staging updated to v0.5.2 (31 commits ahead, commit 646a94d). CI runner still DOWN. npm audit 0 vulns. 447 tests passing (27 files). ZERO open bugs. Dependencies updated (patch/minor). Ready for production tag when investor approves.", "ownerDirectives_PRIORITY": "Process these IN ORDER. Do not skip. Remove items marked ✅ DONE/FIXED during housekeeping.", "ownerDirectives": [ "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." @@ -85,5 +85,5 @@ }, "blockers": [], "startDate": "2026-02-14", - "sessionCount": 122 + "sessionCount": 123 } diff --git a/projects/snapapi/memory/bugs.md b/projects/snapapi/memory/bugs.md index 240f08a..b81e2ec 100644 --- a/projects/snapapi/memory/bugs.md +++ b/projects/snapapi/memory/bugs.md @@ -86,6 +86,26 @@ - **Deployed to staging:** Yes (commit f3a363f, image imported to w1+w2). Verified: 404 on staging. - **Production:** ⚠️ STILL VULNERABLE — needs production deploy (v* tag) to fix. This is a security issue. +### BUG-017: Cancelled subscriptions get free tier (100 req/mo) instead of 0 (MEDIUM) — FIXED (staging) +- **Found:** Session 54 (self-discovered) +- **Impact:** Cancelled customers get downgraded to 'free' tier with 100 requests/month forever — free tier was removed in v0.3.0 +- **Root cause:** `downgradeByCustomer()` set tier to `'free'` which still had a 100-request limit +- **Fix:** Added `'cancelled'` tier with 0 limit. `downgradeByCustomer()` now sets to `'cancelled'`. +- **Deployed to staging:** Yes (commit 9575d31). 338 tests passing. +- **Production:** Awaiting investor approval for v* tag + +### BUG-018: Recovery endpoint logs full API keys (LOW) — FIXED (staging) +- **Found:** Session 54 (self-discovered) +- **Impact:** Full API keys logged during recovery requests — potential key theft via log access +- **Fix:** Removed `key` field from logger call, now only logs email +- **Deployed to staging:** Yes (commit 9575d31) + +### BUG-019: No rate limiting on billing endpoints (MEDIUM) — FIXED (staging) +- **Found:** Session 54 (self-discovered) +- **Impact:** Checkout, portal, and recovery endpoints had no rate limiting — could be spammed +- **Fix:** Added IP-based rate limit (10 req/15min) to billing router, excluding webhook endpoint +- **Deployed to staging:** Yes (commit 9575d31) + ## Open ### BUG-015: Python SDK missing URL validation for ScreenshotOptions object (LOW) — FIXED diff --git a/projects/snapapi/memory/sessions.md b/projects/snapapi/memory/sessions.md index 6bbb252..e358fce 100644 --- a/projects/snapapi/memory/sessions.md +++ b/projects/snapapi/memory/sessions.md @@ -1,5 +1,57 @@ # SnapAPI Session Log +## Session 54 — 2026-03-04 09:00 CET (Business Logic & Security Fixes) + +**Goal:** Fix discovered business logic bug + security improvements. + +**Health Check:** +- Production: ✅ healthy, 2 replicas, 6+ days uptime (still v0.5.2, VULNERABLE) +- Staging: ✅ healthy, deployed 9575d31 + +**Work Done:** + +### 1. BUG-017: Cancelled subscriptions get free tier (MEDIUM) — sub-agent: snapapi-dev-fixes +- `downgradeByCustomer()` was setting tier to `'free'` (100 req/mo) instead of blocking access +- Added `'cancelled'` tier with 0-request limit +- TDD: tests written first, 338 tests passing + +### 2. BUG-018: Recovery endpoint logs full API keys (LOW) +- Removed full key from logger call, only logs email now +- Prevents key theft via log access + +### 3. BUG-019: No rate limiting on billing endpoints (MEDIUM) +- Added 10 req/15min IP rate limit on checkout/portal/recover +- Webhook endpoint excluded (Stripe needs unrestricted access) +- Rate limit headers returned in responses + +### Confirmed: Production still vulnerable (BUG-016) +- Tested `POST /v1/signup/free` on production — returns 200 + creates API key +- Cleaned up test key from DB +- Fixed on staging but NEEDS production deploy + +**Test Suite:** 338 tests passing (up from 334), 1 pre-existing skip + +**TDD Compliance:** ✅ All tests written before implementation + +**Git Commits:** +- `9575d31` fix: cancelled tier, remove key logging, add billing rate limits + +**Investor Test:** +1. Stranger trust with money? **Yes on staging** +2. Data loss on crash? **No** (CNPG PostgreSQL) +3. Free tier abuse? **⚠️ YES on production** — /v1/signup/free still generates keys +4. Key recovery? **Yes on staging** +5. All website features work? **Yes on staging** + +**⚠️ URGENT: Production deploy still needed.** BUG-016 (free signup) is a security vulnerability. No abuse detected but the endpoint is discoverable. Requesting investor approval for production deploy (staging → prod). + +**Blockers:** +- **Production deploy: URGENT** — security fix + all staging improvements +- Stripe production webhook: needs investor +- CI/CD: No Forgejo runner (manual docker build workaround) + +--- + ## Session 53 — 2026-03-03 21:00 CET (Security Fix: Free Signup Route) **Goal:** Evening housekeeping — discovered and fixed a security vulnerability. diff --git a/projects/snapapi/memory/state.json b/projects/snapapi/memory/state.json index 16ceb62..edf7de6 100644 --- a/projects/snapapi/memory/state.json +++ b/projects/snapapi/memory/state.json @@ -1,11 +1,11 @@ { "phase": "production-live", - "version": "0.5.2-prod (VULNERABLE: free signup still live) / 0.7.3-staging (image f3a363f, 334 tests)", + "version": "0.5.2-prod (VULNERABLE: free signup still live) / 0.7.0-staging (image 9575d31, 338 tests)", "staging": { "status": "running", "namespace": "snapapi-staging", "replicas": 1, - "image": "git.cloonar.com/openclawd/snapapi:f3a363f", + "image": "git.cloonar.com/openclawd/snapapi:9575d31", "healthCheck": "passing" }, "production": { @@ -79,7 +79,11 @@ "Developer blog at /blog with 3 posts: why-screenshot-api, screenshot-api-performance, automating-og-images (staging)", "Blog: dark theme, JSON-LD BlogPosting schema, OG tags, breadcrumbs, CTA boxes (staging)", "Blog: clean URL 301 redirects /blog → /blog.html, /blog/:slug → /blog/:slug.html (staging)", - "Blog link in nav and footer, sitemap updated with blog URLs (staging)" + "Blog link in nav and footer, sitemap updated with blog URLs (staging)", + "Cancelled subscription tier — downgrade sets 'cancelled' (0 requests) instead of 'free' (100 requests) (staging)", + "Billing rate limiting — 10 req/15min on checkout/portal/recover endpoints, webhook excluded (staging)", + "Security: removed full API key logging from recovery endpoint (staging)", + "Test suite: 338 tests passing (staging)" ], "notDone": [ "Register Stripe webhook URL in Stripe Dashboard", @@ -102,6 +106,6 @@ "priceId": "price_1T2XHpRtlDv9c8GoThHfd8kS" } }, - "lastSession": "2026-03-03T20:00:00Z", + "lastSession": "2026-03-04T09:00:00Z", "codeLocation": "Forgejo repo openclawd/SnapAPI. Clone: git clone forgejo-snapapi:openclawd/SnapAPI.git" }