Skip to content

WQ-0382: route /stocks through the nginx direct-API whitelist - #28

Open
Tarrant64 wants to merge 6 commits into
mainfrom
hermes/WQ-0382
Open

Tarrant64 wants to merge 6 commits into
mainfrom
hermes/WQ-0382

Conversation

@Tarrant64

Copy link
Copy Markdown
Owner

WQ-0382 follow-up: nginx must route /stocks (found in post-deploy verification)

Deployed container at 12aed7b: GET /stocks from the browser returns the static SPA HTML, not JSON — the direct-API whitelist regex (the no-/api path shape the classic frontend uses, same as /custom-tokens) lacks stocks in BOTH nginx configs. FastAPI routes are live (present in the container's openapi.json); only the proxy whitelist is missing the prefix.

  • abct-docker/nginx.conf + nginx-ssl.conf: add stocks to the whitelist alternation.
  • tests/unit/test_nginx_stocks_route.py: pins both configs' whitelist, emulates the regex against the real client paths (/stocks, /stocks/{id}/history, /stocks/scheduler, /stocks/search), asserts /stocks.html and /stockings still fall through to the SPA, no legacy prefix lost, and the two configs stay identical.

Verdict WQ-0382-D8: full offline suite exit 0 at dabd6d6 (venv:abct).


Opened by hub-pr for the Hermes lead agent on hub01 (branch hermes/WQ-0382, head 3caaddf3bb41, 5 commit(s) on main). Not reviewed by a person; merging is the owner's decision.

hermes added 5 commits October 20, 2026 22:23
…sdaq feed

New backend service separate from the crypto price paths:
- services/stock_data.py: CNBC batch quotes (primary, 1 call/all symbols),
  Nasdaq per-symbol fallback + daily-bar history; parsers pinned by
  captured-payload tests; unpriced symbols never zeroed.
- services/stock_scheduler.py: AsyncIOScheduler cron 09:35/12:00/16:05 ET
  Mon-Fri (market open/midday/close per user 2026-10-20), market-tz aware,
  advisory lock, kill switch STOCK_SCHEDULER_ENABLED (on by default).
- manual_stocks + stock_price_history tables and CRUD in database.py.
- routers/stocks.py: CRUD + history + search + scheduler status/run.
- tests/unit/test_stock_engine.py: offline, canned live payloads, real
  temp SQLite.
- add_manual_stock: ON CONFLICT path left lastrowid unset; resolve id via SELECT
- CNBC parser: only price symbols actually requested (code!=0 marker + requested-set guard)
- Nasdaq parser: verify echoed symbol matches the request before storing
- tests: cache table in fixture DB; per-symbol fake payloads
…v2 hero

- assets.html: 'Stocks' tab (+ Add Stock modal with live ticker validation
  against the keyless feed, live lookup result, ETF/stock auto-class).
- stocks-tab.js: list/add/toggle/delete against /stocks; rows show price,
  day change, tracked value, optional cost-basis P&L, last-refresh stamp
  (formatRefreshTimestamp contract).
- app.js: stocksValue feeds liquid + grand total; breakdown carries its own
  'stocks' bucket (chart values + tooltips never mislabel it as tokens).
- v2: hero liquid and reconcileStatCards include the manual_stock bucket.
- backend portfolio: manual_stocks join portfolio_positions (source_type
  manual_stock, like custom_token), /portfolio/totals gains
  manual_stocks_usd, TOTALS_VALUATION_VERSION 3->4 so cached pre-stocks
  totals rows expire; top-holdings rows for stocks skip crypto logos.
- cache-bust every ?v= (repo convention); v2-cache knows /stocks.
- tests: node behavior check + pytest source-of-record contract pins.
…t literal 3

The v4 bump (manual_stocks_usd bucket) is exactly the kind of recompute this
test exists to verify; the literal pin made the test about the number.
The classic frontend fetches ${API_BASE}/stocks with API_BASE='' -- the same
no-prefix path shape as the tokens tab -- but the direct-API whitelist regex
in both nginx configs lacked 'stocks', so GET /stocks from a browser fell
through to the static SPA and returned index.html instead of JSON (verified
against the deployed container at 12aed7b: /custom-tokens proxies, /stocks
does not; the FastAPI routes themselves are live in openapi.json).

Adds 'stocks' to the whitelist in nginx.conf + nginx-ssl.conf and pins it
with tests/unit/test_nginx_stocks_route.py (regex emulation: the real client
paths proxy, /stocks.html and /stockings still fall through to the SPA, no
pre-existing prefix lost, both configs identical).
@github-actions

Copy link
Copy Markdown

Overview

Image reference tarrant64/abct:latest tarrant64/abct:pr-28
- digest d95c726e50fc bc6d24833cd6
- tag latest pr-28
- provenance 12aed7b
- vulnerabilities critical: 5 high: 11 medium: 18 low: 64 critical: 4 high: 11 medium: 18 low: 64
- platform linux/amd64 linux/amd64
- size 111 MB 126 MB (+16 MB)
- packages 285 285
Labels (5 changes)
  • - 2 removed
  • ± 3 changed
  • 8 unchanged
 org.opencontainers.image.authors=Chris Catalano
 org.opencontainers.image.base.name=python:3.11-slim
-org.opencontainers.image.created=2026-10-21T04:02:27.450Z
-org.opencontainers.image.description=A Better Crypto Tracker
+org.opencontainers.image.description=Multi-chain cryptocurrency portfolio tracker supporting Cardano, Ethereum, Bitcoin, Solana, Polygon, and Base
 org.opencontainers.image.documentation=https://github.com/Tarrant64/abct/blob/main/README.md
 org.opencontainers.image.icon=https://raw.githubusercontent.com/Tarrant64/abct/main/frontend/static/apple-touch-icon.png
 org.opencontainers.image.licenses=MIT
-org.opencontainers.image.revision=12aed7b446c2375e4edad20a92959022a51773f4
 org.opencontainers.image.source=https://github.com/Tarrant64/abct
-org.opencontainers.image.title=abct
+org.opencontainers.image.title=ABCT - A Better Crypto Tracker
 org.opencontainers.image.url=https://github.com/Tarrant64/abct
 org.opencontainers.image.vendor=ABCT Project
-org.opencontainers.image.version=latest
+org.opencontainers.image.version=1.12.3
Packages and Vulnerabilities (5 package changes and 1 vulnerability changes)
  • ♾️ 5 packages changed
  • 271 packages unchanged
  • ✔️ 1 vulnerabilities removed
Changes for packages of type deb (3 changes)
Package Version
tarrant64/abct:latest
Version
tarrant64/abct:pr-28
♾️ ca-certificates 20250419 20250419+deb13u1
♾️ liblzma5 5.8.1-1+deb13u1 5.8.1-1+deb13u2
♾️ xz-utils 5.8.1-1+deb13u1 5.8.1-1+deb13u2
Changes for packages of type pypi (2 changes)
Package Version
tarrant64/abct:latest
Version
tarrant64/abct:pr-28
♾️ certifi 2026.10.18 2026.10.19
critical: 1 high: 0 medium: 0 low: 0
Removed vulnerabilities (1):
  • critical : GHSA--6q48--6c7w--9gw2
♾️ websockets 17.2 17.3

…gacy

User order 2026-10-21: deprecate the old standard dashboard, default
everything to /next; the old dashboard stays reachable at /legacy.

- backend: '/' 302s to /next/; /legacy/ serves the V1 index and
  /legacy/<page> resolves V1 pages (with or without .html). Every old
  V1 URL keeps working unchanged (bookmarks and deep links).
- nginx (both configs): exact 'location = /' 302s to /next/ ahead of the
  SPA try_files fallback; '/legacy' proxies to FastAPI.
- v2 Assets page gains the Stocks tab (WQ-0382 parity): tab button,
  panel, v2 modal for manual add with live ticker validation
  (/stocks/search), tracked-toggle and delete, lazy load on first visit,
  hash routing. New frontend/v2/js/v2-stocks.js.
- cache-bust stamp bumped repo-wide.
- tests: tests/unit/test_next_default_routing.py pins root redirect,
  legacy routes, nginx ordering, and the v2 stocks wiring.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant