Commit Graph
55 Commits
Author SHA1 Message Date
magnusandClaude Opus 5 7ea25ee4fd Retry the Harbor manifest copy instead of a probe for it
pull-request / validate (pull_request) Successful in 32s
The companion SHA tag step failed on the last build even though the image had
already been pushed and deployed. Harbor's vulnerability policy blocks manifest
reads while Trivy's scan is Running, and `imagetools create` copies the manifest,
so Harbor answered 412 Precondition Failed.

Two faults compounded. The loop gated on `imagetools inspect`, but a probe passing
is no guarantee the copy will be allowed. And `create` sat outside the condition,
so under the default `bash -e` its first failure aborted the step before `exit 0`
or any further attempt: the log shows one waiting line, then the error, with 58 of
60 retries unused.

Retry the real operation instead, inside the condition so a blocked copy is a
reason to wait rather than fatal. The trade-off is that a permanently failing copy
now takes the full ten minutes to report instead of failing fast; the previous
behaviour failed fast but wrongly, on a transient block.

Also records that only the primary tag matters for rollout, since the Flux image
policy matches the timestamp tag, so a failure in this step costs the audit tag
rather than the deployment.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-11 09:56:26 +02:00
magnus ac01388117 Merge pull request 'Recover from a btcdata restart without reloading the page' (#2) from ws-reconnect into main
build / build (push) Failing after 3m11s
Reviewed-on: #2
2026-10-11 07:26:42 +00:00
magnusandClaude Opus 5 4a2d8fabad Recover from a btcdata restart without reloading the page
pull-request / validate (pull_request) Successful in 24s
htmx's WebSocket extension reconnects only after close codes 1006/1011/1012/1013.
_ws_proxy closed the browser socket with a normal 1000 on every upstream exit, so
htmx read a btcdata restart as a deliberate shutdown and left both panels frozen
until the visitor reloaded. New browser connections always worked, which hid the
defect from non-browser checks.

The proxy now reconnects upstream behind the still-open browser socket on a bounded
schedule, resets that schedule after a connection that lasted long enough to count
as healthy, and closes with 1012 only once the schedule runs out, so recovery falls
back to htmx's own backoff. A concurrent reader detects a departed browser, which a
dead upstream would otherwise be indistinguishable from, and an unrenderable payload
is logged and skipped rather than ending the stream.

tests/test_ws_proxy.py covers this against a real loopback WebSocket server: same
socket recovery across an upstream restart for both streams, the retryable close
code when the upstream stays down, and skip-on-unrenderable.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-11 09:21:19 +02:00
magnus dd7058b6bd Add agent project guidance
build / build (push) Successful in 2m49s
2026-09-17 15:02:42 +02:00
magnus 161834a512 Merge pull request 'Show midnight price change in page title' (#1) from title-change into main
build / build (push) Successful in 3m7s
Reviewed-on: #1
2026-09-17 12:55:18 +00:00
magnus 0c86cf3b59 Show midnight change below heading
pull-request / validate (pull_request) Successful in 12s
2026-09-17 14:53:05 +02:00
magnus b5bbde8acb Show midnight price change in page title 2026-09-17 14:49:25 +02:00
magnus b30637ee4e Add pull request deployment workflow
build / build (push) Successful in 2m43s
2026-09-17 14:00:26 +02:00
magnus 6c21f172db Show live Bitcoin price in page title
build / build (push) Successful in 2m45s
2026-09-15 19:51:55 +02:00
magnus 61d6d21d88 Document live GitOps production deployment
build / build (push) Successful in 2m48s
2026-09-15 18:42:09 +02:00
magnus 645c00d8de Document btcprice GitOps deployment
build / build (push) Successful in 2m48s
2026-09-15 18:35:31 +02:00
magnus dd67eb7b23 Remove vulnerable build tooling from runtime image
build / build (push) Successful in 3m42s
2026-09-15 18:03:38 +02:00
magnus 62a02ba093 Upgrade vulnerable runtime Python packages
build / build (push) Failing after 2m56s
2026-09-15 17:59:09 +02:00
magnus 919d53cdf7 Use updated Alpine runtime image
build / build (push) Failing after 2m49s
2026-09-15 17:55:35 +02:00
magnus 9b42497e58 Avoid unavailable act runner cache service
build / build (push) Failing after 2m55s
2026-09-15 17:50:19 +02:00
magnus 87bd53ca65 Verify repaired Gitea repository hooks
build / build (push) Failing after 7m22s
2026-09-15 17:41:50 +02:00
magnus 29e5bd0548 Exercise btcprice build pipeline 2026-09-15 17:39:58 +02:00
magnus 69d0e4f3e7 Run registered btcprice workflow 2026-09-15 17:38:37 +02:00
magnus ea0d46c538 Trigger initial btcprice CI build 2026-09-15 17:22:53 +02:00
magnus 0470862cb4 Build and publish btcprice images in Gitea Actions 2026-09-15 17:16:35 +02:00
magnus 1b65330960 Record completion of deployment preparation 2026-09-15 17:12:55 +02:00
magnus 573eba2d86 Prepare btcprice for Kubernetes deployment 2026-09-15 17:12:25 +02:00
magnus dda00da77a Test for btc-data availbe 2026-09-14 16:20:28 +02:00
magnusandClaude Opus 5 864674bd09 Point citadel btcprice at the local btcdata over btc-network
omarchy is gone, but the citadel deployment still set
BTCDATA_URL=http://192.168.50.42:4102 and ran standalone on its own
compose network. Every request that proxies to btcdata failed with
httpx.ConnectError: All connection attempts failed.

btcdata now runs on citadel too, so attach btcprice to the external
btc-network there and reach it by service name at http://btcdata:4102.
deploy-citadel.sh creates the network on the remote if missing, as
btcdata's own deploy script already does.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TRkiLhK5qhkZjP2adxpA3e
2026-09-11 18:52:49 +02:00
magnusandClaude Opus 5 2af8b6f62d Add citadel deployment
Port of ../elprice/deploy-citadel.sh: build the image locally for the
remote's architecture, ship it over SSH with docker save | docker load,
and run docker compose up -d --no-build in /home/pmp/apps/btcprice.

The deployment compose is standalone rather than joining btc-network,
because citadel runs no btcdata — BTCDATA_URL points at the instance
already running on omarchy (http://192.168.50.42:4102).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BdMTk61JgUdNH86ttMi4ce
2026-09-10 14:24:38 +02:00
magnus e15f00e98c Update doc 2026-09-10 13:12:35 +02:00
magnus d5e5b78334 Fix 2026-09-10 13:01:11 +02:00
magnus 7c68220404 Merge branch 'fastapi' 2026-03-13 12:34:10 +01:00
magnusandClaude Opus 4.6 c999d831e7 Rewrite btcprice from Clojure to Python FastAPI
Replace the Clojure Kit application with a Python FastAPI app that
produces identical HTML output. WebSocket proxy, Danish number
formatting, and HTMX integration all preserved.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:33:03 +01:00
magnusandClaude Opus 4.6 ae676f2b6c Use quote-sats from btcdata instead of local EUR/BTC calculation
Sats value now comes from btcdata's Strike quote endpoint which
includes the actual fee/spread, matching the Strike app.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 11:42:51 +01:00
magnusandClaude Opus 4.6 6b4c8034f1 Make sats EUR amount configurable, default 54.46
Configurable via SATS_EUR_AMOUNT env var.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 10:43:48 +01:00
magnusandClaude Opus 4.6 161737d4c7 Style Strike ticker: single column, currency symbols, Danish formatting, sats display
Show 54€ equivalent in sats with dark blue styling, light gray background,
and Danish number formatting for BTC/USDT and BTC/EUR values.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 10:39:26 +01:00
magnusandClaude Opus 4.6 5990b8d735 Render price and strike HTML in btcprice from btcdata JSON WebSockets
Receive raw JSON from btcdata, transform to HTML in ws_proxy.clj.
Added data.json dependency, price and strike rendering, safelist updates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 10:18:56 +01:00
magnusandClaude Opus 4.6 134ee27ca6 Rename shared network to btc-network
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 09:10:57 +01:00
magnusandClaude Opus 4.6 71918ee4fd Use shared Docker network to connect to btcdata independently
Remove btcdata compose include, use external shared network instead
so both projects can run as separate Docker stacks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 08:51:47 +01:00
magnusandClaude Opus 4.6 a9b7874f36 Use idiomatic undertow/websocket maps instead of raw WebSocket API
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 07:50:53 +01:00
magnusandClaude Opus 4.6 32a1509482 Proxy btcdata WebSocket through btcprice for remote access
Browser can't reach the LAN-only btcdata WebSocket when accessing
btcprice remotely (Tailscale/Cloudflare Tunnel). Add a /ws/price
proxy route that relays btcdata frames to the browser so only
btcprice needs to be reachable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 13:43:05 +01:00
magnusandClaude Opus 4.6 6afaa228c3 Safelist text-2xl and mt-1 Tailwind classes for larger currency prices
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 14:52:10 +01:00
magnusandClaude Opus 4.6 5c1a080831 Add EUR/DKK rate display support and run-docker Makefile target
Safelist Tailwind classes for currency rate HTML fragments from btcdata
WebSocket. Add make run-docker target that connects to Docker btcdata
on port 4101.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 14:28:17 +01:00
magnusandClaude Opus 4.6 13a53a26d0 Switch to HTMX WebSocket, use LAN IP for btcdata URL
- Replace vanilla JS WebSocket with HTMX ws extension (hx-ext="ws")
- Add HTMX + ws extension CDN scripts to page head
- Zero client-side JavaScript — HTMX handles connection, reconnect, and
  DOM swap of HTML fragments from btcdata
- Hidden div safelists Tailwind classes used in btcdata HTML fragments
- Update BTCDATA_URL to LAN IP (192.168.50.42) for cross-machine access
- Update CLAUDE.md and README.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:28:29 +01:00
magnusandClaude Opus 4.6 02cc607e73 Replace EventSource with WebSocket for price streaming
- Switch from SSE EventSource to WebSocket client connecting to
  btcdata's new /api/price/ws endpoint
- Add automatic reconnect on connection loss (3s delay)
- Update Dockerfile BTCDATA_URL to use btcdata's new Docker port 4101

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 21:32:21 +01:00
magnusandClaude Opus 4.6 ce343dfcf6 Add README, update docker-compose and CLAUDE.md
Docker runs on port 4041 alongside local dev on 4000.
Include btcdata docker-compose for unified startup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:48:56 +01:00
magnusandClaude Opus 4.6 397d9f7b5c Split data layer into btcdata service
Remove DB, Binance WebSocket, and Kraken pollers from btcprice.
UI now uses vanilla EventSource connecting to btcdata for live
price updates. btcprice is now a pure UI service with no database.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:07:48 +01:00
magnusandClaude Opus 4.6 c688846a26 Add Kraken daily OHLC poller with database storage
Polls Kraken API for 1-day BTC/USD candles aligned to 00:01 UTC,
mirroring the existing hourly poller pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:53:50 +01:00
magnusandClaude Opus 4.6 30aa52cdc7 Schedule Kraken OHLC polls at HH:01 UTC instead of fixed 5-min interval
Hourly candles only finalize on the hour, so polling every 5 minutes
was wasteful. Now the poller sleeps until 1 minute past each hour,
fetches immediately on first run when no data exists, and logs time
to next fetch on startup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:40:36 +01:00
magnusandClaude Opus 4.6 553dac3069 Add Kraken hourly OHLC poller with database storage
Fetches Bitcoin hourly candles from the Kraken public REST API
and upserts them into a kraken_hour table on a 5-minute poll interval,
following the existing Integrant component pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:32:55 +01:00
magnusandClaude Opus 4.6 2c576aff4e Fix Dockerfile base images and add docker-compose
Switch to available base images (temurin-21) since clojure:openjdk-25
and azul/zulu-openjdk-alpine:25 no longer exist. Add docker-compose.yml
for single-command app deployment.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 16:55:34 +01:00
magnusandClaude Opus 4.6 201155c0b2 Update Dockerfile with Tailwind build stage and prod database
Add Node.js stage for CSS build, cache Clojure deps in separate layer,
add .dockerignore, and default JDBC_URL to btcprod database.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 16:36:38 +01:00
magnusandClaude Opus 4.6 8169796eb9 Color price green/red based on direction, fix SSE middleware error
Show price in green when rising, red when falling. Use Tailwind
classes with a safelist comment so JIT includes them. Remove
middleware from SSE route to prevent "response already started" error.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 16:32:40 +01:00
magnusandClaude Opus 4.6 08793c5099 Switch price updates from HTMX polling to SSE
Replace 2s polling with Server-Sent Events for instant price updates.
Write directly to Undertow exchange output stream to ensure proper
flushing, since the Ring adapter buffers InputStream bodies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 16:09:47 +01:00
magnusandClaude Opus 4.6 a50256a042 Add real-time BTC price feed via Binance WebSocket
Connect to Binance trade stream, persist prices to binance_price table
(throttled to every 5s), and live-update the home page via HTMX polling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 15:51:10 +01:00
magnusandClaude Opus 4.6 bb604b302a Set PORT=4040 in Dockerfile to match EXPOSE
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 15:30:30 +01:00
magnusandClaude Opus 4.6 5f4800ccc0 Simplify DB connection config to single JDBC_URL for all profiles
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 15:27:32 +01:00
magnusandClaude Opus 4.6 5c5834e497 Use .env for database config, upgrade integrant/repl to 0.5.0
Load .env vars via Makefile, use #env JDBC_URL for all profiles in
system.edn, switch ig/prep to ig/expand, and add missing namespace
requires in core.clj to match elprice project conventions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 15:03:41 +01:00
magnusandClaude Opus 4.6 f7b571f670 Initial project setup: Clojure Kit web app for BTC price tracking
Kit framework with Undertow, Reitit routing, Hiccup + HTMX templating,
Tailwind CSS v4, PostgreSQL (empty database), and mobile-first index page.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 14:50:42 +01:00