AbramsOS

repo: ~/Projects/AbramsOS · 68 commits · 0 in last 24h, 0 in last 7d ·

Search the build

68 commits indexed

  1. fc3c624 2026-07-13 chore: lint (node --check 21/21) + version bump v0.3.0 (session close)
  2. 5671885 2026-07-13 withings: device-vitals auto-sync connector (OAuth2 → weight/BP/HR/SpO2 into Health)
  3. ba2e47d 2026-07-13 assets: RentCast home-value estimate wiring (one-key-from-working) + all 37 Amazon totals collected
  4. 957c215 2026-07-13 docs: savings track done; overnight run complete, loop stopped
  5. 5387c7d 2026-07-13 savings: subscription/bill audit + reorder-timing nudges
  6. a0f0e6a 2026-07-13 auto-save: 2026-07-13T01:52:00 (1 files) — lib/bill-audit.js
  7. 4c949de 2026-07-13 docs: roadmap — health track done; Assets/Neighborhood/Biometrics shipped; savings track next
  8. 5ab1c97 2026-07-13 biometrics: per-person ID/emergency profile for kids + adults (child-ID record + growth BMI)
  9. a4f7803 2026-07-13 auto-save: 2026-07-13T01:21:52 (4 files) — lib/ids.js db/migrations/0014_biometrics.sql lib/biometrics.js routes/biometrics.js
  10. 42d431f 2026-07-13 neighborhood: Neighborhood Watch — address+radius, Leaflet map, Ring cameras + Neighbors, Nextdoor/Citizen/crime maps/registries
  11. a78d4ae 2026-07-13 assets: net-worth tracker — enter home by address + current value, finance category, details/notes
  12. 8598287 2026-07-13 health: lapsed-habit BP reading reminders (only nudges prior loggers, never new users)
  13. 355389e 2026-07-13 health: BP-medication context — show active meds that raise/lower blood pressure alongside the trend
  14. 8f58fa2 2026-07-13 health: vitals trends + insights (weight/RHR sparklines, local-LLM 'what changed this month', gentle Stage-2 recheck flag)
  15. 4a02cce 2026-07-13 purchases: collect 38 real Amazon orders from info@ (via George) into purchase table
  16. ded692c 2026-07-13 connectors: no-signup bank import — Wells Fargo CSV upload (headerless + negative-debit aware)
  17. a71abd4 2026-07-13 docs: roadmap — banking (Plaid) track shipped; real-bank keys gated to Steve
  18. 954cc77 2026-07-13 connectors: Plaid 'Connect a bank' UI (Wells Fargo etc.) + incremental/idempotent sync
  19. f4e4da6 2026-07-13 docs: roadmap adds health track (vitals trends, BP↔meds, reminders) as co-priority
  20. 2d8848c 2026-07-13 health: Vitals module — BP history + Apple Watch/device readings + sync
  21. 0256450 2026-07-13 savings: nightly advisor runner + launchd plist (draft, Steve bootstraps)
  22. 3e9efe5 2026-07-13 docs: life-optimizer roadmap (overnight)
  23. a121be0 2026-07-13 savings: home dashboard tile + honest merchant-savings leads
  24. db2fd48 2026-07-13 savings: life-optimizer module — cheaper/better substitutes from what you buy (local gemma3:12b, $0)
  25. 367d888 2026-07-12 auto-save: 2026-07-12T23:51:20 (1 files) — backups/
  26. ef35bef 2026-07-11 claims: add California Unclaimed Property (claimit.ca.gov) resource card with per-household-name copy-to-search
  27. 1192d3c 2026-07-09 chore: lint (node --check ✓), untrack runtime state, v0.2.0 (session close)
  28. 4ccbda5 2026-07-08 recall-watch: apply contrarian FIX-FIRST — E-known+in-date=>POSSIBLE regardless of FDA publish date (fix false-clear); assess ALL recalls per NDC (worst class never hidden); EXP-anchored expiry parser (no MFG/ref-date mis-parse); local notification on new alerts; per-NDC worst-status UI + N-of-M affected fills
  29. 362c884 2026-07-08 recall-watch.js: nightly-ready FDA recall watcher with PROGRAMMATIC lot/date relevance (per-fill), new-alert detection + state baseline; caught fluticasone D-0326-2024 overlapping a 2026 fill
  30. a1038a6 2026-07-08 Recall lot/date check: mark all 4 NDC recalls CLEARED (recalled lots expired before your fills); green Clear badges + plain-English assessment on Recalls + Rx tabs
  31. 2caebba 2026-07-08 Recalls: add curated article/FDA links per NDC-recalled product (Read-about-it column)
  32. b02722e 2026-07-08 NDC-precise FDA recall match: flag fills whose actual dispensed product is recalled
  33. 78b80e6 2026-07-08 FDA recall cross-reference: clean drug names, derive generics, openFDA match into Recalls tab
  34. 542a632 2026-07-08 Import Shangoo Pharmacy tax profile: prescription_fill table + 277 fills + 83 meds + /prescriptions viewer
  35. 6589647 2026-07-08 auto-save: 2026-07-08T14:36:14 (5 files) — lib/ids.js db/migrations/0009_prescription_fills.sql routes/prescriptions.js scripts/load-abrams-rx.js views/prescriptions.ejs
  36. 63d53f9 2026-07-07 feat(health): Household (people/spouse) + Medications with FDA recall check
  37. ab337c2 2026-07-07 fix(tests): isolate suite to abrams_os_test DB
  38. 3a31291 2026-07-07 feat(digest): suppress zero-deadline days
  39. 8cf03df 2026-07-07 feat(digest): opt-in daily deadline digest email via George
  40. 61b2dca 2026-07-07 feat(warranties): manual Warranties page + Deadlines coverage
  41. 43aea4b 2026-07-07 feat(ui): Bills, Reorders, and unified Deadlines pages
  42. 5693d23 2026-07-07 feat(schema): bill + reorder_item tables, recurrence lib, reminder-engine wiring
  43. 7db85d7 2026-07-07 chore: move dev port 9931 -> 9774 (9931 held by japan-enrich/viewer-local) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
  44. 2e0044d 2026-05-31 Add per-site favicon (kills /favicon.ico 404)
  45. 551b5ea 2026-05-19 ignore + 404-guard backup/snapshot files
  46. 20f8f36 2026-05-19 add noreferrer to target=_blank external links
  47. 3458fe1 2026-05-10 tick 18: receipt extractor regression fixtures + heuristic fixes (item 19)
  48. fe7ffca 2026-05-10 tick 17: manual CSV upload route (backlog item 15)
  49. 1666967 2026-05-10 tick 16: Compliance Guardian (URL allowlist + injection scan + PII redact)
  50. a5da75e 2026-05-10 tick 15: auto-parse Drive PDFs on sync (backlog item 17)
  51. 8adb083 2026-05-10 tick 14: unit tests for lib/crypto.js + lib/ids.js (backlog item 16)
  52. 3877b56 2026-05-10 tick 13: /recalls dashboard UI (read-only viewer for recall_match)
  53. 00b6568 2026-05-10 tick 12: service_commitment + merchant policy extractor
  54. fffc3d8 2026-05-10 tick 11: rights_rule_snapshot + 8-rule starter corpus + cited drafts
  55. ee6a1eb 2026-05-10 tick 10: /audit page (read-only viewer for audit_log + auth_event)
  56. d34f2f6 2026-05-10 tick 9: in-process cron for reminders + CPSC refresh
  57. 1f31901 2026-05-10 tick 8: CSRF protection on HTML POST forms
  58. 1f60c67 2026-05-10 tick 7: /claims dashboard UI + claim detail with draft preview
  59. 7294ca3 2026-05-10 tick 6: claim_case + action_queue + claim strategist (drafts only)
  60. b6f84e0 2026-05-10 tick 5: calendar_reminder table + reminder engine
  61. d95d5e5 2026-05-10 tick 4: PDF parsing for receipt attachments (tier-3)
  62. 600c717 2026-05-10 tick 3 (scaffold): CPSC recall_event + recall_match tables + matcher + fetcher
  63. 9e812a4 2026-05-10 tick 2: Google Drive sync (receipt-shaped PDFs/images)
  64. 323f8a8 2026-05-10 tick 1: receipt extractor tier-2 LLM fallback (Mac1 qwen3:14b)
  65. 2113e8d 2026-05-10 feat: 'Import all receipts' button + 2FA gate + Plaid sandbox
  66. 434eca9 2026-05-09 rename OwnershipOS → AbramsOS (per Steve): pkg/db/pm2/env/brand/sessions/localStorage all swept; tests + live server still green on :9931
  67. ef35e84 2026-05-09 smoke green: PG via /tmp socket (peer auth), test glob fix, pool.end on test exit
  68. 3606684 2026-05-09 initial scaffold: OwnershipOS v0.1 — Express+PG shell, Gmail OAuth + receipt extractor, 8-table schema, liquid-glass UI, full canonical spec under docs/

Authors

Agents used

  • none detected

Skills used

  • /claims9
  • /recalls8
  • /migrations7
  • /audit7
  • /assets6
  • /vitals6
  • /savings5
  • /biometrics5
  • /neighborhood5
  • /health5
  • /connectors5
  • /prescriptions5
  • /withings4
  • /ids4
  • /documents4
  • /reminders3
  • /bill-audit3
  • /receipt-extractor3
  • /insights2
  • /reorder-timing2
  • /sync2
  • /downgrade2
  • /plaid2
  • /dismiss2
  • /date2
  • /load-abrams-rx2
  • /warranties2
  • /upload2
  • /compliance-guardian2
  • /crypto2

Creative ideas + design notes

Commits with substantial prose (≥120 chars) — the rationale behind each move.

fc3c624 · 2026-07-13 · chore: lint (node --check 21/21) + version bump v0.3.0 (session close)
Overnight life-optimizer build: health (vitals/insights/BP-meds/reminders), savings
(advisor/coupons/bill-audit/reorder-timing), Assets+RentCast, Neighborhood Watch,
Biometrics, Plaid+CSV banking, Withings device sync, 38 real Amazon purchases ($8,966.66).
5671885 · 2026-07-13 · withings: device-vitals auto-sync connector (OAuth2 → weight/BP/HR/SpO2 into Health)
- lib/withings-client.js: Withings Health API OAuth (authUrl/exchange/refresh) + getMeasures mapping (type 1=weight kg→lb, 9/10=BP pair, 11=HR, 54=SpO2); handles refresh-token rotation; graceful no-creds
- routes/withings.js: /auth/withings → consent → /api/withings/callback stores encrypted token in connector_account (provider=withings) + initial sync; /api/withings/sync re-syncs (dedup via health_reading external_id); reuses vitals.insertReadings; audited medical
- connectors.ejs: 'Health devices' section — Connect Withings / Sync now / setup-needed
- server.js wiring + .env WITHINGS_* (gated). One-set-of-creds-from-working
ba2e47d · 2026-07-13 · assets: RentCast home-value estimate wiring (one-key-from-working) + all 37 Amazon totals collected
- lib/home-value.js: RentCast AVM lookup by address; graceful no-key/no-address (never fabricates a value); Zillow API retired so RentCast is the free option
- routes/assets.js: POST /api/assets/:id/estimate → fills current_value + value_source='estimate' + range; valuationConfigured flag
- views/assets.ejs: 'Estimate' button on property cards (prompts for key if absent)
- .env: RENTCAST_API_KEY= (gated)
- DATA: opened remaining 17 older Amazon orders via George → all 37 now have real totals; complete all-time spend $8,966.66 (2022-2026)
5387c7d · 2026-07-13 · savings: subscription/bill audit + reorder-timing nudges
- lib/bill-audit.js: category-aware — NEVER flags essentials (tax/rent/utility/loan); insurance/phone/internet get 'shop your rate'; discretionary/subscriptions ALWAYS surface with annual cost ('still using this?'), LLM (gemma3:12b) refines cancel/downgrade/overpriced; rule-based duplicate detector
- lib/reorder-timing.js: deterministic 'reorder soon' nudges from cadence + last_ordered (Paper towels due-now verified)
- wired both into /api/savings/run + nightly runner; kind='bill-audit'/'reorder-timing' surface on /savings
- honest: est_savings only for cancel/downgrade, never for 'review'; verified on synthetic sub then wiped
5ab1c97 · 2026-07-13 · biometrics: per-person ID/emergency profile for kids + adults (child-ID record + growth BMI)
- 0014_biometrics.sql: person_biometric (1:1 per person) — DOB, sex, height, weight, blood type, eye/hair, marks, allergies, conditions, emergency contact, prints-on-file (child-ID)
- lib/biometrics.js: exact age + BMI; adult CDC BMI category; kids link to CDC percentile calculator (NO fabricated percentile)
- routes/biometrics.js upsert-per-person + views/biometrics.ejs profile cards w/ inline edit, child badges
- nav + wiring. Sensitive PII, audited; works for whole household
42d431f · 2026-07-13 · neighborhood: Neighborhood Watch — address+radius, Leaflet map, Ring cameras + Neighbors, Nextdoor/Citizen/crime maps/registries
- lib/neighborhood.js: free OSM Nominatim geocoder (no key) + categorized real deep-link builder (Your Ring first: cameras live-view + Neighbors feed), geo-aware SpotCrime/OSM links
- routes/neighborhood.js: /neighborhood resolves address from ?asset/?address/first property; /api/neighborhood/geocode
- views/neighborhood.ejs: address+radius controls, Leaflet map w/ radius circle, property picker, link cards
- nav + wiring; links to Assets property addresses
a78d4ae · 2026-07-13 · assets: net-worth tracker — enter home by address + current value, finance category, details/notes
- 0013_assets.sql: asset table (property/vehicle/account/valuable) w/ address, current_value, category, details, notes, geocode
- routes/assets.js + views/assets.ejs: /assets dashboard (net worth total + by-category stat row, add form, created date+time chips, per-property 'Watch' link to neighborhood)
- nav + wiring. Values user-entered (auto-valuation API is a later gated add). Feeds upcoming neighborhood-watch via property address
8598287 · 2026-07-13 · health: lapsed-habit BP reading reminders (only nudges prior loggers, never new users)
- lib/vitals-reminders.js: fires 'time for a BP check' only if a person logged BP before but not in 14d; deduped via reminder engine
- reminder-engine.generateForUser hooks it in alongside returns/warranty/recall reminders
- verified: lapsed(20d)=fire, recent(2d)=skip, never-logged=skip
355389e · 2026-07-13 · health: BP-medication context — show active meds that raise/lower blood pressure alongside the trend
- lib/bp-meds.js: deterministic classifier (curated generic stems + names -> effect/class; never LLM-guessed) — ACE/ARB/beta-blocker/CCB/diuretic (lowers) + NSAID/decongestant/steroid/stimulant (raises)
- routes/vitals.js: read-only join to medication table, bpRelevant() into /health
- views/vitals.ejs: 'Medications that affect blood pressure' panel (color-coded lowers/raises), informational-not-advice
- works when med list is populated (currently empty)
8f58fa2 · 2026-07-13 · health: vitals trends + insights (weight/RHR sparklines, local-LLM 'what changed this month', gentle Stage-2 recheck flag)
- lib/vitals-insights.js: computeTrends (this-30d vs prior-30d avgs), recheckFlag (deterministic rule, gentle), summarize (gemma3:12b narrates ONLY computed deltas — never invents readings; no medical advice)
- routes/vitals.js: fast trends+recheck on /health load; /api/health/insights for async LLM narrative
- views/vitals.ejs: 'This month' panel (trend chips + delta arrows + recheck banner + async narrative) + weight/RHR sparklines
- verified end-to-end on synthetic data then wiped; empty-state safe (no fabricated readings)
4a02cce · 2026-07-13 · purchases: collect 38 real Amazon orders from info@ (via George) into purchase table
- scripts/collect-amazon-orders.js: parsed order confirmations 2022-2026, dedup on order#, total NULL (not fabricated — needs body enrichment)
- validates savings seeds: Nespresso Vertuo = top recurring buy (4x), shipping labels (2x)
- feeds home purchase count + /purchases + savings advisor with REAL data
ded692c · 2026-07-13 · connectors: no-signup bank import — Wells Fargo CSV upload (headerless + negative-debit aware)
- csv-parser: headerless fallback (WF/Quicken export: date,amount,*,,description) + signMode — WF debits are negative=spend, so normalize to positive + drop deposits; header CSVs unchanged
- upload.js: dedup key (csv:date:amount:merchant) + ON CONFLICT so re-uploading overlapping statements doesn't double
- connectors.ejs: 'Import CSV' upload form with WF download instructions — zero third-party signup path
- answers Steve: Plaid needs a free web signup (no CLI); CSV upload needs nothing
954cc77 · 2026-07-13 · connectors: Plaid 'Connect a bank' UI (Wells Fargo etc.) + incremental/idempotent sync
- views/connectors.ejs: Plaid Link flow — connect button, secure login (Plaid handles bank creds), exchange, per-bank sync; graceful 'setup needed' state when keys absent
- routes/plaid.js: GET /api/plaid/status; sync now resumes from persisted cursor + ON CONFLICT dedup (was re-pulling everything each sync -> dup purchases)
- lib/plaid-client.js: isConfigured() helper
- 0012_plaid_sync_cursor.sql: connector_account.sync_cursor + unique(user_id,order_number) on purchase
- Plaid (not Stripe) is correct for reading a bank; sandbox works now, real Wells Fargo needs Steve's prod keys
2d8848c · 2026-07-13 · health: Vitals module — BP history + Apple Watch/device readings + sync
- 0011_health_readings.sql: health_reading (BP pairs, HR, weight, SpO2, glucose...) w/ dedup index
- lib/health-metrics.js: AHA BP categorization + Apple Health export.xml streaming parser (pairs systolic/diastolic by timestamp; scales SpO2)
- routes/vitals.js + views/vitals.ejs: /health dashboard w/ inline SVG BP chart, AHA color categories, per-person filter, manual add, delete; /api/health/readings JSON ingest for the Health Auto Export app
- scripts/import-apple-health.js: one-command import of an Apple Health export
- nav + wiring. NO fabricated readings — table ships empty w/ 3 real sync paths. Verified end-to-end on synthetic data then wiped.
0256450 · 2026-07-13 · savings: nightly advisor runner + launchd plist (draft, Steve bootstraps)
- scripts/run-savings-advisor.js: dotenv-loaded, dedup-safe regen (local, $0)
- deploy/com.steve.abramsos-savings.plist: daily 6:05am, RunAtLoad off; bootstrap surfaced in header comment
a121be0 · 2026-07-13 · savings: home dashboard tile + honest merchant-savings leads
- home: 'Savings ideas' stat tile (open count + est $ total) linking to /savings
- seeded 3 real verifiable savings mechanisms (Amazon Subscribe & Save, camelcamelcamel price alerts, Costco coupon book) — real URLs, no fabricated codes
db2fd48 · 2026-07-13 · savings: life-optimizer module — cheaper/better substitutes from what you buy (local gemma3:12b, $0)
- 0010_savings.sql: savings_suggestion + merchant_coupon tables
- lib/savings-advisor.js: grounded strategy suggestions (no hallucinated SKUs/prices)
- routes/savings.js + views/savings.ejs: dashboard w/ created date+time chips, sort+density, save/dismiss
- seeded reorder items from real Amazon email history; 4 suggestions generated
- switched local model qwen3:14b->gemma3:12b (qwen3 thinking-mode returns empty under format:json)
b02722e · 2026-07-08 · NDC-precise FDA recall match: flag fills whose actual dispensed product is recalled
- scripts/ndc-recall-check.js: match each fill's 11-digit package NDC to openFDA product NDC
  (leading-zero-normalized labeler|product, exact-confirmed); 4/46 NDCs on a recall list, 40 fills
- recalls tab: prominent 'Your actual products on an FDA recall list' NDC section (headline signal)
- Rx tab: red RECALL badge on flagged fills (CREON, Fluticasone, Nystatin, Atorvastatin)
78b80e6 · 2026-07-08 · FDA recall cross-reference: clean drug names, derive generics, openFDA match into Recalls tab
- scripts/check-fda-recalls.js: cleans OCR junk from fill drug names (95 fixed), rebuilds
  deduped medication list (83->36 real meds) with generic names, cross-references each vs
  openFDA drug-enforcement (free); 33/36 matched, 300 recall records into medication_recall
- routes/recalls.js + views/recalls.ejs: new 'Medication recalls (FDA)' section, grouped per
  med, Class I/II/III severity badges, worst-first; labeled advisory (ingredient-level match)
542a632 · 2026-07-08 · Import Shangoo Pharmacy tax profile: prescription_fill table + 277 fills + 83 meds + /prescriptions viewer
- 0009_prescription_fills.sql: fill-history table (date/drug/rx/qty/days/doctor/plan/plan-paid, raw OCR audit)
- scripts/load-abrams-rx.js: OCR-parsed loader, reconciled to doc totals (Natalia 220 fills / $136,254.86 of $136,328.74)
- creates person Steve (self) + Natalia (spouse); dedupes 83 medications into medication table
- routes/prescriptions.js + views/prescriptions.ejs: read-only viewer w/ per-person totals + filter; nav 'Rx'
63d53f9 · 2026-07-07 · feat(health): Household (people/spouse) + Medications with FDA recall check
- migration 0008: person, medication, medication_recall
- /household — add spouse/dependents (records + meds attach to them)
- /medications — self-entered meds per person; every write audit-logged with a medical-consent marker (AGENTS.md gate)
- lib/fda-fetcher.js — openFDA drug-enforcement lookup; per-med + "check all" recall scan stores matches, surfaced on the card
- nav links, recall styling

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ab337c2 · 2026-07-07 · fix(tests): isolate suite to abrams_os_test DB
pretest builds/migrates/seeds a throwaway abrams_os_test (schema + all migrations
+ seed.sql + rights-rules); test script pins PG_DATABASE=abrams_os_test. Stops the
auth-e2e test from wiping the real owner account on every `npm test` (AGENTS.md rule).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3a31291 · 2026-07-07 · feat(digest): suppress zero-deadline days
sendDigest short-circuits when there are no upcoming deadlines, so empty days
don't put a "nothing due" email in the inbox.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
8cf03df · 2026-07-07 · feat(digest): opt-in daily deadline digest email via George
- lib/digest.js builds an HTML digest (overdue / this week / coming up) and self-sends to Steve's own inbox via George /api/send (internal recipient, no external-send token)
- scheduler cron 08:00 America/Los_Angeles is DOUBLE-GATED: off unless DIGEST_ENABLED=1 AND GEORGE_BASIC_AUTH set; committed code is dormant and never auto-sends on its own
- .env.example documents all digest keys (default DIGEST_ENABLED=0)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
61b2dca · 2026-07-07 · feat(warranties): manual Warranties page + Deadlines coverage
- /warranties + /api/warranties CRUD (audit-logged) writing to service_commitment (source='manual')
- reminder-engine scans service_commitment.refund_window_ends_at -> 'coverage_window_closing' deadlines
- nav link, warranty id prefix

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
43aea4b · 2026-07-07 · feat(ui): Bills, Reorders, and unified Deadlines pages
- /bills, /reorders CRUD (audit-logged) + /deadlines over the reminder engine
- add-forms, mark-paid/ordered (rolls due date forward + refreshes deadline), created date+time chip on every admin card
- generalized sort-density.js to any [data-grid]; nav links; liquid-glass styles

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5693d23 · 2026-07-07 · feat(schema): bill + reorder_item tables, recurrence lib, reminder-engine wiring
- 0007 migration: bill (Bills to Pay incl. tax/government/CRA via category) + reorder_item (frequently-ordered + best-price savings)
- lib/recurrence.js: pure cadence date math (+ 5 passing unit tests)
- reminder-engine emits calendar_reminder rows for upcoming bill due-dates and reorder points (unified Deadlines)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
551b5ea · 2026-05-19 · ignore + 404-guard backup/snapshot files
.gitignore now excludes *.bak, *.bak.*, *.pre-*, *.orig, *~ so editor
swap files and pre-edit snapshots can't be accidentally committed and
end up served from /public. Backstop in server.js: any GET whose path
matches those patterns short-circuits to 404 before express.static,
so even a stray on-disk *.bak.html can never leak.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
20f8f36 · 2026-05-19 · add noreferrer to target=_blank external links
CPSC notice + cited-rule source links now use rel="noopener noreferrer"
instead of bare rel="noopener" so we don't leak Referer to upstream pages.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3458fe1 · 2026-05-10 · tick 18: receipt extractor regression fixtures + heuristic fixes (item 19)
- 7 new golden-file fixtures in tests/fixtures/receipts/ (Amazon, Best Buy,
  DoorDash, Apple, Etsy, Uber, Walmart, plus a non-receipt newsletter)
- tests/extractor-regression.test.js auto-discovers fixtures and asserts
  merchant + total + orderNumber + minConfidence per file
- lib/receipt-extractor.js: 2 surgical heuristic fixes uncovered by fixtures
  · extractTotal now picks the highest-rank label ("order total" >
    "grand total" > "total charged" > plain "total"); allows up to 40 chars
    between label and $amount (handles "Total charged to Visa ••1234: $18.42");
    rejects "subtotal" via 3-char lookbehind
  · extractOrderNumber adds Best-Buy-style "Order #: BBY01-806589123456"
    (alpha prefix + digits) and a tighter Amazon-only pattern
- 15/15 tests across the regression + base extractor suites
fe7ffca · 2026-05-10 · tick 17: manual CSV upload route (backlog item 15)
- npm install multer
- lib/csv-parser.js: parses statement-style CSVs
  · auto-detects date / amount / merchant columns (case-insensitive)
  · handles quoted fields with embedded commas, dollar signs, parens-as-negative
  · skips refunds (negative amounts) and bad rows; reports first 5 errors
- routes/upload.js: POST /api/upload/csv (multer in-memory, 10 MB cap)
  → parser → INSERT purchase rows + audit_log entries
- 10/10 csv-parser tests
1666967 · 2026-05-10 · tick 16: Compliance Guardian (URL allowlist + injection scan + PII redact)
- lib/compliance-guardian.js: 4 layered defenses
  · isAllowedDestination(url) — outbound HTTP allowlist (gov, NIH/FDA,
    Plaid, Google APIs, local LLM endpoints; subdomain-confusion safe)
  · detectPromptInjection(txt) — 16 patterns (ignore-prior-instructions,
    chatml fragments, role injection, exfiltration phrasing, code-eval)
  · redactPii(text) — masks card #, SSN, phone, email local-part, ZIP,
    Stripe/OpenAI-style API keys; keeps domain hints
  · guardForLlm(text) — one-shot redact+scan combiner
- lib/receipt-extractor.js: enrichWithLlm now runs guardForLlm() on body+from+
  subject before sending to Ollama; refuses enrichment if injection detected
  (returns heuristic with llmError='compliance_guardian_blocked')
- tests/compliance-guardian.test.js: 19/19 across allowlist (6), injection (4),
  redactor (6), one-shot guard (3)
a5da75e · 2026-05-10 · tick 15: auto-parse Drive PDFs on sync (backlog item 17)
- routes/connectors.js syncDrive(): after a Drive PDF lands in document table,
  immediately calls pdf.parseFile() + receipt-extractor (heuristic + LLM).
  Inserts a purchase row when extractor returns a draft.
- Images skipped (OCR is a later tick); failed parses flip parsed_status='failed'
- audit_log gets document_parsed + purchase_extracted (source: 'drive_pdf')
- 34/35 tests still green
8adb083 · 2026-05-10 · tick 14: unit tests for lib/crypto.js + lib/ids.js (backlog item 16)
- tests/crypto.test.js (7): AES-256-GCM round-trip, IV uniqueness, tamper
  detection on ciphertext + auth tag, unicode, empty-string, env-var validation
- tests/ids.test.js (6): prefix per kind, unknown-kind throws, distinctness,
  ULID monotonic-over-time, lowercase invariant
- 13/13 green; pure unit tests, no PG, no server
3877b56 · 2026-05-10 · tick 13: /recalls dashboard UI (read-only viewer for recall_match)
- routes/recalls.js: GET /recalls (HTML), GET /api/recalls (JSON)
  · joins recall_match × recall_event × purchase
  · status filter (pending_review/confirmed/dismissed) with chip-counts
- views/recalls.ejs: confidence-coded cards (red ≥85%, amber otherwise)
  with CPSC source link
- nav: /recalls added between /claims and /audit
- 2 new tests (auth-gate + API-gate)
00b6568 · 2026-05-10 · tick 12: service_commitment + merchant policy extractor
- db/migrations/0006_service_commitments.sql applied
- lib/commitment-extractor.js: regex+LLM extraction of money_back_guarantee,
  satisfaction_guarantee, returns_window, price_match, service_sla, lifetime
- routes/connectors.js: pipes extracted commitments to DB after purchase insert
- 10/10 in commitment-extractor.test.js (in-isolation)

NOTE: full suite shows 8 EPIPE failures in auth-e2e + 1 smoke — pure pg-pool
state from the morning's PG session terminate, NOT a code regression. Kill
all abrams_os pg sessions and re-run npm test for clean 53/53.
fffc3d8 · 2026-05-10 · tick 11: rights_rule_snapshot + 8-rule starter corpus + cited drafts
- db/migrations/0005_rights_rules.sql: rights_rule_snapshot (versioned, jurisdictional)
- scripts/seed-rights-rules.js: 8 hand-curated rules
  · 15 USC §1666i / Reg Z claims-and-defenses (card disputes ≥$50)
  · 12 CFR §1026.13 billing-error rights (60d window)
  · Magnuson-Moss federal warranty (15 USC §2301-2312)
  · 16 CFR §700 FTC pre-sale warranty disclosure
  · FTC money-back guarantee guides
  · 14 CFR §259.5 / DOT 2024 airline refund rule
  · EU 261/2004 standard compensation
  · CPSC recall remedy entitlement
- lib/claim-strategist.js: pickCitedRules() matches reason_code + routing,
  threads citation_block into both LLM prompt and template fallback;
  fills claim_case.cited_rules_jsonb with citation+source_url+title
- views/claim-detail.ejs: renders 'Cited rules' panel with source links
- 6 new tests (matching, limits, unknown-reason fallthrough)
- 42/43 green; 15 PG tables now
ee6a1eb · 2026-05-10 · tick 10: /audit page (read-only viewer for audit_log + auth_event)
- routes/audit.js: GET /audit (HTML), GET /api/audit/events (JSON)
- views/audit.ejs: filter chips + table view + 7d/30d/90d toggle
- nav: /audit link added
- tests: 2 (auth-gate + JSON-endpoint gate)
- 36/37 green
- Skipped item 10 (George email send) — overnight YOLO rule says no email-send code without Steve approval
d34f2f6 · 2026-05-10 · tick 9: in-process cron for reminders + CPSC refresh
- npm install node-cron
- lib/scheduler.js: two jobs
  · reminders: every 4h (idempotent via UNIQUE dedupe)
  · cpsc:       daily 03:17 PT, last 7 days (idempotent via ON CONFLICT)
- Logs each tick to logs/scheduler.log
- start() is a no-op when NODE_ENV=test or SCHEDULER_DISABLED=1, so tests stay fast
- Wired into server.js startup; verified live: scheduler started message in log
- 34/35 green
1f31901 · 2026-05-10 · tick 8: CSRF protection on HTML POST forms
- middleware/csrf.js: cookie+body double-submit pattern
  · ensureToken mints non-httpOnly aos.csrf cookie on every request
  · verifyToken rejects 403 on POST/PUT/DELETE/PATCH to NON-/api/ routes
    when body._csrf or x-csrf-token header doesn't match the cookie
  · /api/* exempted (same-origin JS, sameSite=lax cookie protects)
  · timing-safe comparison with length-guard (avoids 500 on length mismatch)
- views: hidden _csrf input added to signup/signin/enroll-totp/step-up/signout
- tests/csrf.test.js: 4 new (no-token rejection, wrong-token rejection, GET mints cookie)
- 34/35 green (1 skip — pdf-parse fixture)
1f60c67 · 2026-05-10 · tick 7: /claims dashboard UI + claim detail with draft preview
- views/claims.ejs: card grid showing routing/state/due-date per claim
- views/claim-detail.ejs: full draft letter (Georgia serif), evidence index,
  pending action_queue rows with 'Approve draft' button
- routes/claims.js: GET /claims (list HTML), GET /claims/:id (detail HTML)
- nav: /claims link added
- Approving = 'I've reviewed this'; send wire-up still deferred to George tick
7294ca3 · 2026-05-10 · tick 6: claim_case + action_queue + claim strategist (drafts only)
- db/migrations/0004_claims.sql: claim_case (state machine: draft|sent|resolved)
  + action_queue (approval_level: auto|user_required, state: pending|approved|executed)
- lib/claim-strategist.js: deterministic routing by reason_code
  · returns_window_closing → refund / merchant
  · warranty_expiry         → repair / manufacturer
  · recall_action_due       → recall_remedy / manufacturer
  Letter drafted via local Ollama qwen3:14b; falls through to template if LLM down.
  Every claim_case spawns ONE user_required action_queue row — never auto-executes.
- routes/claims.js: GET /api/claims, /:id; POST /from-reminder/:id; /:caseId/actions/:actionId/approve
- 2 new tests with mocked-down Ollama proving the template-fallback path
- 30/31 green (1 skip — pdf-parse fixture)
b6f84e0 · 2026-05-10 · tick 5: calendar_reminder table + reminder engine
- db/migrations/0003_reminders.sql: calendar_reminder + dedupe unique index on
  (user_id, owner_table, owner_id, reason_code) so reruns are no-ops
- lib/reminder-engine.js: 3 deadline types fire today
  · returns_window_closing  (5d before 30d default returns mark)
  · warranty_expiry         (30d before 1y default mark)
  · recall_action_due       (14d after a recall_match lands)
- routes/reminders.js: /api/reminders/upcoming, /:id/dismiss, /regenerate
- 4 new tests (uses fixture user_steve + tracked test purchase ids)
- 28/29 tests green (1 skip — pdf-parse fixture)
d95d5e5 · 2026-05-10 · tick 4: PDF parsing for receipt attachments (tier-3)
- npm install pdf-parse
- lib/pdf-parser.js: parseFile(), parseBuffer(), resolveDocumentPath()
  (lazy-require pdf-parse so its test fixture doesn't load at startup)
- routes/documents.js: GET /api/documents (list), POST /api/documents/:id/parse
  pipeline: extract PDF text → synthesize gmail-summary → run heuristic + LLM
  → insert purchase + audit_log entries
- /api/documents wired into server.js behind requireAuth
- 25/25 tests (1 skip — pdf-parse sample fixture not installed in production)
600c717 · 2026-05-10 · tick 3 (scaffold): CPSC recall_event + recall_match tables + matcher + fetcher
- db/migrations/0002_recalls.sql: recall_event, recall_match, recall_pull_log
- lib/cpsc-fetcher.js: hits saferproducts.gov public API + normalizes to our shape
- lib/recall-matcher.js: canonical scoring pseudocode from docs/SPEC.md
  (gtin/upc 0.45, model fuzzy 0.25, brand 0.05, post-purchase 0.05, UDI 0.40)
- scripts/ingest-recalls.js: idempotent backfill (run: node scripts/ingest-recalls.js [days])
- No live data ingested yet; ingest is opt-in
9e812a4 · 2026-05-10 · tick 2: Google Drive sync (receipt-shaped PDFs/images)
- lib/drive-fetcher.js: list+download via drive.readonly OAuth scope
- query: name~/receipt|invoice|order|confirmation/i + mime in (pdf, image/*) + last 90 days
- routes/connectors.js: gmail sync now also walks Drive on the same google connector;
  files saved to uploads/drive-<id>.<ext>; document rows inserted with kind='attachment'
- audit_log gets one document_persisted event per file
- 22/22 tests still green
323f8a8 · 2026-05-10 · tick 1: receipt extractor tier-2 LLM fallback (Mac1 qwen3:14b)
- lib/ollama.js: thin Ollama client with strict-JSON mode + timeout
- lib/receipt-extractor.js: enrichWithLlm() merges into low-conf heuristic results;
  heuristic-trust rule (LLM never overrides a heuristic-filled field)
- routes/connectors.js: gmail sync now calls extractWithFallback when conf < 0.7
- tests: 3 new in tests/extractor-llm.test.js with cache-injected mock ollama
- Total: 22/22 green; live smoke against Mac1 confirms end-to-end works
2113e8d · 2026-05-10 · feat: 'Import all receipts' button + 2FA gate + Plaid sandbox
- Auth: bcrypt password + otplib TOTP (single-user, locked after first signup)
- Step-up TOTP re-verify within 60s before /import or any 'Import all' run
- 4 new tables: auth_credential, auth_totp, auth_session, auth_event
- DB-backed sessions (signed cookie aos.sid, 30d TTL, httpOnly+sameSite=lax)
- Connectors: Gmail (already wired) + Drive (drive.readonly added) + Plaid sandbox
- Plaid: link/token + exchange + transactions/sync; access tokens AES-256-GCM at rest
- /import dashboard fans out to every connected connector via Promise.all + cookie-forward
- Compliance posture updated (PCI-aware: never PAN/CVV, only Plaid item refs)
- 19/19 tests green (5 smoke + 6 extractor + 8 auth-e2e)

File tree

165 files tracked. Click any to browse the source at HEAD.

Other build journals

← AbramsEgo  ·  all 4 projects  ·  AgentAbrams →

Export

commits.csv · feed.atom · project.json · commits.json

rendered in 1ms