- Add new GET endpoint for retrieving a specific training run by run_id - Validate run_id format with regex pattern ^[a-zA-Z0-9_-]+$ before DB access - Return HTTP 400 for invalid run_id format, HTTP 404 for non-existent runs - Ensure DELETE endpoint validation is correctly placed before any DB access - Both endpoints now provide consistent security validation - Mark task 5.8 as completed Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
13 KiB
13 KiB
1. Security Critical — Git & Credentials
- 1.1
[haiku]Add.envto.gitignoreand rungit rm --cached .envto untrack it - 1.2
[haiku]Addmodels/and*.pklto.gitignore - 1.3
[haiku]Replace real credentials in.env.examplewith placeholders (POSTGRES_PASSWORD=change_me_to_a_strong_password) - 1.4
[haiku]Remove SQL comment with credentials fromservices/ml/app/db.pyand add fail-fast check for missingDATABASE_URL - 1.5
[sonnet]Updatedocker-compose.ymlto use${POSTGRES_USER},${POSTGRES_PASSWORD},${POSTGRES_DB}env var interpolation in all DATABASE_URL values - 1.6
[haiku]Bind PostgreSQL port to127.0.0.1:5432:5432indocker-compose.yml - 1.7
[haiku]Bind MLflow port to127.0.0.1:5000:5000indocker-compose.yml - 1.8
[haiku]Bind ML service port to127.0.0.1:8001:8001indocker-compose.yml
2. Security Critical — Input Validation & CORS
- 2.1
[haiku]Validaterun_idmatches/^[a-zA-Z0-9_-]+$/insrc/app/api/training/runs/[run_id]/route.tsbefore interpolation - 2.2
[sonnet]Validaterun_idformat and usePath.resolve()+ directory containment check inservices/ml/app/main.py(model load at line 1203, delete at line 1312) - 2.3
[sonnet]Add file size check (reject >10MB) and row count limit (500,000) tosrc/app/api/upload/route.ts - 2.4
[haiku]Add file type validation (.csvextension, text MIME type) tosrc/app/api/upload/route.ts - 2.5
[haiku]Fix CORS inservices/ml/app/main.py: replaceallow_origins=["*"]with["http://localhost:3000"]and supportCORS_ORIGINSenv var
3. Authentication
- 3.1
[sonnet]Createsrc/middleware.tswith API key auth middleware: readAPI_KEYenv var, checkX-API-Keyheader on all/api/*routes except/api/health, return 401 if invalid - 3.2
[sonnet]Add FastAPIDepends()API key dependency inservices/ml/app/main.py: readAPI_KEYenv var, checkX-API-Keyheader, exempt/healthendpoint - 3.3
[sonnet]Update all Next.js proxy routes to forwardX-API-Keyheader to ML service - 3.4
[haiku]AddAPI_KEYto.env.examplewith placeholder value and instructions
4. API Route Hardening (Next.js)
- 4.1
[sonnet]Add Zod schema validation tosrc/app/api/predict/route.ts(validate pair, timeframe, candles array) - 4.2
[sonnet]Add Zod schema validation tosrc/app/api/predict/batch/route.ts(validate pair, timeframe, start_date, end_date) - 4.3
[sonnet]Add Zod schema validation tosrc/app/api/model/load/route.ts(validate run_id) - 4.4
[sonnet]Add Zod schema validation tosrc/app/api/training/start/route.ts(validate model_type) - 4.5
[sonnet]Add Zod schema validation tosrc/app/api/patterns/detect/route.ts(validate candles, patterns array) - 4.6
[sonnet]Replaceerror.messagewith generic"Internal server error"in all catch blocks across 7+ route files:health/route.ts,candles/route.ts,annotations/route.ts,annotations/[id]/route.ts,upload/route.ts,export/route.ts,span-annotations/export/route.ts - 4.7
[sonnet]RequirechartIdfor bulk delete insrc/app/api/annotations/route.ts— reject?all=truewithout chartId with HTTP 400 - 4.8
[sonnet]Wrap chart cascade delete indb.transaction()and addspanAnnotationsdeletion insrc/app/api/charts/[id]/route.ts - 4.9
[haiku]AddparseInt(value, 10)withisNaN()guard to all routes parsing integer query params - 4.10
[sonnet]Add CSV injection protection (prefix=+@-cells with') to all export routes - 4.11
[sonnet]Addresponse.okchecks before.json()insrc/app/page.tsx(lines 214, 230, 245, 257) - 4.12
[sonnet]Addresponse.okchecks before.json()insrc/components/CandleChart.tsx(lines 163, 178, 192)
5. ML Service Hardening (Python)
- 5.1
[sonnet]Replaceerror.message/ traceback details with generic"Internal server error"in FastAPI exception handlers at lines 640, 778, 1091, 1134, 1199, 1296 ofservices/ml/app/main.py - 5.2
[opus]Add SHA256 model integrity check: createmodels/checksums.sha256manifest, verify hash beforejoblib.load()inservices/ml/app/main.py:266 - 5.3
[sonnet]Add_model_swap_lockto prediction reads (not just writes) inservices/ml/app/main.pyfor thread-safe model access - 5.4
[sonnet]Add date range validation (max 1 year) toPOST /predict/batchinservices/ml/app/main.py - 5.5
[sonnet]Add candle time-sort validation/auto-sort toPOST /predictinservices/ml/app/main.py - 5.6
[sonnet]Implement real health checks:SELECT 1for PostgreSQL, MLflow API ping inservices/ml/app/main.py:396-409 - 5.7
[sonnet]Add training resource limits: 500MB dataset size check, 30-minute timeout with status update on expiry inservices/ml/app/main.py:907-1030 - 5.8
[haiku]Addrun_idformat validation toDELETE /training/runs/{run_id}andGET /training/runs/{run_id}endpoints
6. Infrastructure & Docker
- 6.1
[sonnet]Addheaders()function tonext.config.jswith X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, Content-Security-Policy - 6.2
[sonnet]AddUSER appusertoservices/ml/Dockerfile: create user withuseradd, set ownership, add USER directive before CMD - 6.3
[haiku]Create.dockerignorewith.git,.env,.env*,node_modules,.next,data/,*.md,__pycache__/,mlruns/,models/ - 6.4
[haiku]Change TA-Lib download URL to HTTPS inservices/ml/Dockerfile:10 - 6.5
[sonnet]Add SHA256 checksum verification for TA-Lib download inservices/ml/Dockerfile - 6.6
[haiku]RemoveCOPY --from=builder /app/node_modules ./node_modulesline fromDockerfile:29(standalone doesn't need it) - 6.7
[sonnet]Pin Docker base images to@sha256:digests in both Dockerfiles - 6.8
[haiku]Fix healthcheck tool mismatch: use same tool (curl) in Dockerfile and docker-compose.yml
7. Frontend — Stale Closures & Race Conditions
- 7.1
[opus]Fix stale closure infetchPredictions: extractmodelInfointo auseRefthat stays in sync with state, use ref ingenerateCacheKey(src/app/page.tsx:489-552) - 7.2
[opus]Add AbortController tofetchPredictionsandhandleFetchBatchPredictions: store controller in ref, abort previous on new request, discard stale responses (src/app/page.tsx:494-663) - 7.3
[opus]Fix stale closure in CandleChart click handler: convertdrawingState,selectedLineId,dragState,annotationsto refs, update refs alongside setState, read refs in handler (src/components/CandleChart.tsx:572-971) - 7.4
[opus]Fix stale closure in SpanAnnotationManager keyboard handler: wraphandleDeleteSpaninuseCallback, use ref forselectedSpanId(src/components/SpanAnnotationManager.tsx:461-535)
8. Frontend — Memory Leaks & Performance
- 8.1
[opus]Fix SpanAnnotationManager preview primitive memory leak: replaceuseStatewithuseReffor preview primitive, add cleanup on unmount (src/components/SpanAnnotationManager.tsx:265-324) - 8.2
[sonnet]Usechart.applyOptions()for theme changes instead of re-creating chart (src/components/CandleChart.tsx:333) - 8.3
[sonnet]RemovefitContent()from reconciliation effect, only call on initial load (src/components/SpanAnnotationManager.tsx:160) - 8.4
[opus]Implement incremental primitive updates in SpanAnnotationManager: update only selection state on selection change, full reconciliation only on annotation list changes (src/components/SpanAnnotationManager.tsx:104-161) - 8.5
[sonnet]Add bounded prediction cache (max 100 entries, FIFO eviction) topredictionCacheRef(src/app/page.tsx:195-199) - 8.6
[sonnet]Fix hardcoded 1-minute candle interval: detect interval from data, use for span iteration (src/components/CandleChart.tsx:452) - 8.7
[haiku]Extract magic numbers (8px, 60s, colors) to named constants inCandleChart.tsx - 8.8
[haiku]Movenew Set<string>()default prop to module-level constant inCandleChart.tsx:125
9. Frontend — Shared Types & Type Safety
- 9.1
[sonnet]Createsrc/types/candles.tswithCandleinterface - 9.2
[sonnet]Createsrc/types/annotations.tswithAnnotation,AnnotationType,Geometryinterfaces - 9.3
[sonnet]Createsrc/types/charts.tswithChartinterface - 9.4
[sonnet]Createsrc/types/predictions.tswithPredictionSpan,PredictionState,ModelInfointerfaces - 9.5
[sonnet]Createsrc/types/span-annotations.tswithSpanAnnotation,SpanLabelType,SubSpaninterfaces - 9.6
[haiku]Createsrc/types/index.tsbarrel file re-exporting all types - 9.7
[sonnet]Replace duplicate interfaces inpage.tsx,CandleChart.tsx,SpanAnnotationManager.tsx,Toolbox.tsx,SpanAnnotationList.tsx,SpanPopover.tsxwith imports from@/types - 9.8
[sonnet]Replace allanytypes with proper interfaces:geometry→Geometry | null,sub_spans→SubSpan[], candle arrays →Candle[], prediction cache →Map<string, PredictionSpan[]>
10. Frontend — Error Boundary & UX
- 10.1
[sonnet]Createsrc/components/ErrorBoundary.tsxReact class component with error state, fallback UI (error message + "Try Again" + "Reload" buttons), andconsole.errorlogging - 10.2
[haiku]Wrap{children}with ErrorBoundary insrc/app/layout.tsx - 10.3
[sonnet]Add confirmation dialog before delete-all annotations insrc/app/page.tsx:412-425using Radix Dialog - 10.4
[haiku]FixSpanAnnotationList.tsx:110-115confidence check: replace falsy check with!= nullfor confidence value 0
11. Frontend — Accessibility
- 11.1
[sonnet]Addaria-labelattributes to all toolbar buttons inToolbox.tsx - 11.2
[sonnet]Addrole="dialog",aria-modal="true", and focus trapping toKeyboardShortcutsModal.tsx - 11.3
[sonnet]MakeChartSelector.tsxkeyboard accessible: add arrow key navigation and click-outside close handler - 11.4
[sonnet]Addaria-pressedto toggle buttons (span drawing mode, prediction visibility)
12. Frontend — Polish & Cleanup
- 12.1
[haiku]Remove unused importsTrendingUp,ChevronUpfromToolbox.tsx:4 - 12.2
[haiku]Remove@ts-ignoreinToolbox.tsx:246-247, replace with proper type assertion for CSS custom property - 12.3
[sonnet]Fix dark theme onannotation-types/page.tsxandspan-label-types/page.tsx: replace hardcoded light colors with theme-aware CSS variables - 12.4
[sonnet]Add debounce (150ms) oronPointerUpto confidence slider inPredictionPanel.tsx:148-155 - 12.5
[sonnet]Replace Google Font CSS@importinglobals.csswithnext/font/googleinlayout.tsx - 12.6
[haiku]Remove manual Escape handler inSpanPopover.tsx:114-117(conflicts with Radix Dialog) - 12.7
[sonnet]FixTalibPatternPanel.tsx:39re-fetch when API returns empty array: addhasLoadedflag - 12.8
[haiku]Add[candles]touseImperativeHandledependency array inCandleChart.tsx:202-221 - 12.9
[haiku]AddactiveChartIdto primitive cleanup effect dependency arrays inCandleChart.tsx:1059-1110 - 12.10
[sonnet]Implement or remove no-op Tooltip component inui/tooltip.tsx(replace with Radix Tooltip if used) - 12.11
[haiku]Removeeslint-disableinTrainingPanel.tsx:128-129, include stable callbacks in dependency array - 12.12
[haiku]Remove dead filter code (TODO comment, no-op) inpage.tsx:49-53
13. Package & Dependencies
- 13.1
[haiku]Move@types/node,@types/react,@types/react-dom,@types/papaparse,@types/pgfromdependenciestodevDependenciesinpackage.json - 13.2
[haiku]Movetypescript,eslint,eslint-config-next,autoprefixer,postcssfromdependenciestodevDependenciesinpackage.json - 13.3
[haiku]Addzodtodependenciesinpackage.json
14. Dead Code Removal
- 14.1
[haiku]Deletesrc/lib/db/migrate.ts(dead SQLite migration code) - 14.2
[haiku]Removeget_db_session()function fromservices/ml/app/db.py:99-111 - 14.3
[haiku]Remove deadinference*package reference frompyproject.toml:32 - 14.4
[haiku]Fix inconsistentuuid as uuid_libimport inservices/ml/app/main.py:9— use standardimport uuid - 14.5
[haiku]Remove duplicateTALIB_PATTERNSdict — import from one location (app/patterns.pyorgenerate_talib_annotations.py)
15. Deprecated Python API Replacements
- 15.1
[sonnet]Replace@app.on_event("startup")with FastAPI lifespan pattern inservices/ml/app/main.py:307 - 15.2
[haiku]Replacedeclarative_base()withclass Base(DeclarativeBase)inservices/ml/app/db.py:45 - 15.3
[haiku]Replace alldatetime.utcnow()withdatetime.now(datetime.UTC)inservices/ml/app/main.py:325,1000,1019,1080 - 15.4
[haiku]Add missing fallback return for volume indicators infeatures/talib_features.py:169-190