Type an item name or filter to start browsing
Try T6 Bag, Minor Healing Potion, or Expert's Bow to see live prices across all 7 cities.
Fetching market data...
Click Scan Markets to find profitable flips
Compares buy prices vs sell prices across all cities to surface arbitrage opportunities.
Fetching city prices...
Fetching live prices...
🛒 Shopping List
Materials needed, grouped by where to buy them cheapest.
Sell Orders
Buy Orders
Market History
🐘 Bulk Transport Profits
Find profitable transport routes with realistic haul planning. Accounts for carry weight, inventory slots, and daily sell volume. Click any haul plan to expand the full item list.
🏪 Black Market Flipper
Find profitable items to buy from city markets and sell to the Black Market in Caerleon. Compares real-time prices to identify the best flips.
Scanning Black Market prices...
Click "Find BM Flips" to find profitable items to flip to the Black Market.
Compares buy prices in royal cities against Black Market sell orders.
⚡ Top-N Craft Right Now
Ranks every recipe by profit against your spec, city, and focus budget. The killer competitive feature — no other tool does this.
Ranking recipes against live prices...
Click Rank Now to score every recipe against your spec/city/focus and surface the most profitable crafts right now.
🔥 Refining Lab
Refining is a different game from crafting — different city, different focus loop, different time horizon. This tab is tuned for daily-focus refiners.
Scanning refining recipes...
Click Refresh to rank today's best refines or switch to Daily Focus Planner to allocate your focus budget.
📒 Journals Calculator
Calculate labourer journal profits. Find the best journals to fill and sell based on current market prices.
Calculating journal profits...
Click "Calculate" to see journal profit across all types and tiers.
Shows buy-empty / sell-full profit with ROI for each journal type.
📊 Resource Return Rate Calculator
Calculate your effective resource return rate based on specialization, city bonuses, focus, and premium status.
Results
🔧 Repair Cost Calculator
Calculate the silver cost to repair your gear. Search for an item and see the exact repair cost based on quality and durability.
Search for an item and click "Calculate" to see repair costs.
Shows cost breakdown by tier, enchantment, and quality level.
Repair Cost Breakdown
⚡ Item Power Price Checker
Compare item power vs price to find the best value gear. Lower silver per IP point = better deal.
Analyzing item power values...
Click "Compare IP" to analyze item power vs price across gear.
Lower silver per IP = better value for money.
⭐ Favorites
Save and manage custom item lists for quick price checking. All lists are stored locally in your browser.
Loading favorite list prices...
Create a new list or load a saved one to see prices.
Click "+ New List" to get started.
📊 Top Traded Items
See the most actively traded items based on daily volume. Higher volume means more liquidity and faster trades.
Analyzing trading volumes...
Click "Load Top Items" to see the most actively traded items.
Ranked by 7-day trading volume from the Charts API.
Live Flips
Real-time profitable flip opportunities detected from the live market stream. Includes cross-city transports and same-city instant flips. Requires a free account.
Account Required
Create a free account to access live flip detection. It only takes a few seconds.
Waiting for flips...
Profitable opportunities will appear here in real-time as they're detected from the market stream.
💼 Portfolio Tracker
Track your trades, calculate realized profit/loss, and monitor your trading performance. All data stored locally.
Log a Trade
📨 Recent Sales (auto-detected from in-game mail)
🌾 Farm & Breed Calculator
Calculate profit for farming crops, herbs, and breeding animals on your personal island.
Fetching farming prices...
Click "Calculate" to see farming profit for each crop, herb, or animal.
Shows seed cost vs harvest revenue and profit per hour.
📖 How to set up your first alert (click to expand/collapse)
- Invite the bot to your Discord server — click here to invite Coldtouch Market Bot.
- Get a Channel ID: in Discord, enable Developer Mode (User Settings → Advanced → Developer Mode ON), then right-click any channel and choose "Copy Channel ID".
- Paste the Channel ID below, pick a minimum profit threshold, and click Create Alert.
- Run
/setup_alertsin that Discord channel once so the bot can verify it can post.
🔔 Dawnsong · Martlock → Black Market · Buy 2.1M → Sell 3.4M · +1.19M profit (+56% ROI) · Confidence 78%
🔔 Market Alert Manager
Create and manage arbitrage alerts. When a profitable flip is detected, you'll be notified in your Discord channel.
No alerts configured yet
Enter a Discord Channel ID and minimum profit threshold to create your first alert.
Features
Guild Syphon Check
Paste your in-game Siphoned Energy log and instantly flag any guildmate who withdrew more than they deposited. Per-player totals, date range, and a one-click Discord summary you can drop in your officer channel. Pure client-side — no log uploads, no auth.
Market Browser
Browse all items in the Albion Online marketplace. Filter by tier, enchantment, category, and quality. See real-time prices across all cities with freshness indicators.
Market Flipping
Find profitable arbitrage routes between cities. Each flip shows profit, ROI, tax, and a confidence score based on 7 days of historical data so you know which routes are consistently profitable.
City Comparison
Compare prices for any item across all cities side-by-side. Instantly see where to buy low and sell high with visual price charts.
Crafting Calculator
Calculate crafting profits using live market prices. Accounts for material costs, return rates, and selling prices across cities.
Discord Alerts
Get real-time flip alerts delivered to your Discord server. Set minimum profit thresholds and confidence filters. Never miss a profitable opportunity.
Live Data Sync
Prices update automatically via 4 data sources: server scans every 5 minutes, live NATS player orders, Charts API historical data, and community contributions.
Confidence Scores
Every trade route has a reliability score calculated from historical spread analysis. High confidence means the route has been consistently profitable over the past week.
Bulk Transport
Find the best items to haul in bulk with your mammoth. Budget-based trip profit calculations, daily volume data, and transport score ranking for optimal routes.
Community Scanners
Contribute to the data pool by refreshing item prices. Climb the leaderboard and earn tier ranks: Bronze, Silver, Gold, and Diamond.
BM Flipper
Dedicated Black Market flipping tool. Find profitable items to buy from royal cities and sell to the Black Market with confidence scoring.
Journals Calculator
Calculate labourer journal profits for all 10 types across T3-T8. See buy-empty, sell-full prices, profit, and ROI at a glance.
RRR Calculator
Resource Return Rate calculator with spec level, city bonus, and focus support. Visual breakdown of each bonus contribution.
Repair Cost
Estimate repair costs for any item. Accounts for tier, enchantment, quality, and durability level with quick reference grids.
Item Power Checker
Compare item power vs price to find the best value gear. Sort by silver-per-IP ratio across weapons, armor, and accessories.
Favorites
Save custom item lists for quick price checking. Create named lists, load them to see prices across all cities with color-coded best deals.
Top Traded Items
See the most actively traded items ranked by 7-day volume. Higher volume means more liquidity and faster trades.
Portfolio Tracker
Track your trades with FIFO cost basis matching. Log buys and sells, monitor realized P/L, and export to CSV.
Craft Runs
Track full crafting cycles: buy materials, refine, craft, haul, sell. Log purchases via manual entry or chest tab scans. Live P&L dashboard with tax estimates and margin %. Hideout Power Level and Core bonus support.
Farming Calculator
Calculate farming profits for crops, herbs, and animals. Shows seed cost, harvest revenue, growth times, and profit per hour.
Coldtouch Data Client
An all-in-one game data client that does three things at once: contributes live market prices to the community, captures chest and vault contents with item weights, and logs all loot pickups for guild accountability. Built on top of the Albion Online Data Project client.
We encourage you to run the client whenever you play Albion Online. Everyone benefits from fresher market prices while you use all the other features.
Live Market Prices
- Contributes real-time market prices to the public AODP network
- Helps keep prices fresh for everyone using market tools
- Gold rates and auction data captured automatically
- Runs silently in the background while you play
Chest & Vault Capture
- Open any chest or bank — all items captured instantly
- Tab names, item quantities, quality, and weight included
- Works with guild chests, personal banks, and island chests
- Powers the Loot Buyer feature (evaluate, plan sells, track profit)
Loot Logger
- Logs every loot pickup by any nearby player in real time
- Tracks who looted what, from whom, with guild/alliance info
- Always active while the client runs — no setup needed
- Powers the Loot Accountability feature (coming soon)
Setup Guide
- Download the latest release from GitHub Releases (Windows installer, Linux, or macOS)
- Download
itemmap.jsonandweightmap.jsonfrom the same release page and place them next to the client executable - Create an account on this website (or login if you already have one)
- Run the client — it will show a device code and a link
- Open the link in your browser and enter the code to link your account
- Play Albion! Keep the client running while you play. Here is what happens automatically:
How It Works
- Reads network packets from Albion Online (same method as AODP) — does NOT modify the game client or inject code
- Fully SBI-compliant: packet reading is an approved method used by thousands of players
- Standard market data goes to the public AODP NATS server (helps the community)
- Custom data (chest contents, loot events) goes only to your private account via secure WebSocket
- Links to your website account via Device Authorization (one-time setup, no passwords shared)
Comparison with AODP Client
| Feature | AODP Client | Coldtouch Client |
|---|---|---|
| Market prices & gold rates | Yes | Yes |
| Contributes to public AODP | Yes | Yes |
| Chest/vault content capture | No | Yes — all items, weights, tab names |
| Item weight data | No | Yes — 11,500+ items |
| Loot logger (who looted what) | No | Yes — real-time, with guild info |
| Loot Buyer integration | No | Yes — evaluate, sell plan, track profit |
| Loot Accountability | No | Yes — who deposited, who didn’t |
| Trade tracking (buy/sell) | No | Yes — insta-buy, listings, mail sales |
| Sale notifications from mail | No | Yes — auto-detects sold items |
| Website account linking | No | Yes — Device Authorization |
| SBI-compliant | Yes | Yes |
| Windows / Mac / Linux | Yes | Yes |
Trade Tracking Guide
The client tracks your marketplace activity in real-time. Here’s what gets captured and how:
Keyboard Shortcuts
Power-user shortcuts for faster navigation. Shortcuts don't fire while typing in a text field.
Global (any tab)
Loot Logger tab
Changelog
- Accountability results now show the selected chest capture scan time next to each tab name after a check runs.
- Per-player missing-loot Discord text and generated image reports include the same timestamp, so screenshots show which chest snapshot was used.
- Uploaded loot logs now save in one backend transaction and get their session id back quickly, so the Upload report can show Share and Accountability actions without waiting for the session list to refresh.
- The upload flow now shows a saving state, reports server-save failures, refreshes the Accountability dropdown after save, and waits before pre-selecting the new session.
- The frontend now boots its startup initializer exactly once after scripts load, restoring the normal startup path for tab handlers, initial data loading, live sync, portfolio render, and Favorites hydration.
- Corrupted Favorites data in browser storage no longer crashes startup or Favorites tab actions; invalid stored data is ignored safely.
- SpreadStats stuck-run recovery now invalidates stale async runs before a replacement can write, matching the backend analytics generation-token guard.
- Backend maintenance jobs now use per-item historical queries instead of broad tier/prefix scans, reducing the risk that stats, analytics, or price-reference refreshes freeze the public service.
- Automatic SpreadStats, analytics, and historical price-reference refreshes are disabled by default until those enrichment jobs run outside the public web process; existing cached stats continue serving.
- Routine WAL checkpoints now avoid reader-waiting modes, and live NATS prices remain buffered for retry if SQLite is briefly busy.
- Transport routes now fetch recent Albion Data sold-count history and show Sold/Day on route cards.
- Haul quantities are capped by live source availability, destination sell-through, or a conservative scout cap when quantity is unknown.
- Haul plans now respect those route caps in both packing passes, so planned stacks cannot exceed known availability.
- Live death events now keep session, zone, alliance, and equipment-at-death data, and correctly mark live sessions unsaved.
- Repeated-death corpse loot attribution is now windowed and tested so one player's second death does not reuse loot from the first.
- Public session shares are owner-scoped and include richer death/item metadata; merged sessions preserve death equipment/location.
- Chest-log verification now shows mapping confidence and waits for a verified client mapping before using deposit rows as green per-player proof.
- Offline client logs now preserve optional zone and death-equipment data while staying backward-compatible with older ao-loot-logger imports.
- Accountability player cards now show Discord Text and Image actions when that player has missing items. Text opens the editable Markdown preview; Image generates a PNG card with Albion item icons, missing quantities, partial-deposit context, estimated silver, and pickup time/source/zone details when available.
- Root cause: the live DB file was 15.3 GB, but ~6.3 GB was already SQLite freelist pages.
checkDiskUsage()used total file pages, so it launched aggressive compaction after every restart even though live pages were closer to 9 GB. Compaction then hit 60 s event-loop stalls and systemd restarted the service. - Fix: DiskSafety now thresholds on live pages (
page_count - freelist_count) and logs live, total, and free-page sizes. Compaction, analytics, spreadStats, and priceRefCache now avoid overlapping, and compaction uses smaller chunks with yields between read/write/delete phases.
- The migration (May 1-3): dropped
node-sqlite3entirely in favour ofbetter-sqlite3. The async-callback orphan bug class that caused 44+ unplanned restarts/day is now structurally impossible. Site went from ~94 unplanned restarts in 36 hours to zero. - The emergency (May 3-4 overnight): a hung site root-caused to
compactOldData()loading 30 M rows synchronously into one transaction. Rewritten as chunked async withsetImmediateyields, RSS guard, andwal_checkpoint(TRUNCATE). One-time offline cleanup with bulk-copy keepers shrunk the DB 19.7 GB → 11.7 GB and process memory 9.7 GB → 191 MB. - The hardening (May 4 afternoon): classified transient network errors so a flaky AODP timeout no longer wipes in-flight compaction state. Hardened the 30 s timeout middleware against destroyed sockets. Added a libuv-level event-loop watchdog (
monitorEventLoopDelay) that warns at 5 s and aborts at 60 s — catches sync wedges that the JS event loop itself can't observe. - The follow-up (May 4 evening): the new watchdog caught its first wedge on its first cycle — a 49.4 s sync block in
computeSpreadStats's big GROUP BY aggregate. Fixed by chunking the aggregate across 10 item_id ranges; each chunk now completes in 1-3 s with event-loop yields between. Headroom restored. - The chain reaction (May 4 later evening): the watchdog caught two more wedges of the same anti-pattern —
refreshPriceRefCache(10-min interval, 22.6 s wedge) and concurrent collisions withcomputeAnalytics. Applied identical chunking to both, plus a mutex flag so the three heavy aggregates (spreadStats,priceRefCache,analytics) defer 90s and retry rather than colliding on the same SQLite connection. BumpedstatsDbpage cache 16→128 MB so each chunk's working set stays warm. - Backlog cleanup (May 4 later): reduced
price_hourlyretention from 30 days to 14 days — at ~8 M new rows/day, that cuts the steady-state table size in half. Charts requesting more than 14 days now show hourly OHLC bars for the last 14 days and daily-resolution data for older periods (the historical price line plot was already mixed-resolution fromprice_averages). Also fixed an analytics scheduling bug that was firing the job twice within 5 minutes after every restart. - The real root cause (May 4 final pass): 23 s wedges persisted even after chunking + mutex + larger cache. CLI EXPLAIN of the same query on the same chunk completed in 1.78 s — the difference was WAL frame traversal cost on cross-connection reads. NATS flushes between cycles refill the WAL toward its 64 MB cap; each subsequent read pays an O(WAL frames) per-page penalty. Fix: lower
wal_autocheckpoint1000→500 pages, forcewal_checkpoint(RESTART)at the end of every priceRefCache cycle, and force another at the start of every spreadStats cycle. Verified at 18:43:55 — spreadStats completes in 25 s with WAL log=25 frames, zero EventLoop warnings, all flags clean. - Site stability over the last 24 h:
NRestarts=0,0 FATAL, all HTTP routes 200 OK at <300 ms.
- Service had been restarting roughly every 17 minutes (63 times in 22 hours) due to a misclassification in yesterday's stability work.
SQLITE_BUSY— a normal, transient lock-contention error — was being treated as database corruption and triggering an immediate process abort. Each restart began a fresh cache rebuild under the same load, hit BUSY again, aborted again. Self-perpetuating loop. - Fix:
SQLITE_BUSYandSQLITE_LOCKEDare no longer fatal. They log loudly and let SQLite's built-in busy_timeout retry. Real corruption (SQLITE_CORRUPT,SQLITE_IOERR,SQLITE_MISUSE) still aborts as designed, and the per-transaction 90s watchdog still catches genuine wedges. - Verified post-deploy through a queue-depth-3954 contention burst (the exact load that caused 8 FATAL aborts in the prior 6 hours) — it drained cleanly without restart. Service has been stable since 18:25 UTC.
- New tab for guild officers — paste the in-game Siphoned Energy log directly from the clipboard, and the page parses every transaction, aggregates per-player totals, and flags anyone who withdrew more than they deposited.
- Output: a summary card row (date range, transactions, players, totals), a red Owe syphon table sorted by deficit, a collapsible "everyone else" section, and a Discord-ready summary you can copy with one click and drop in your officer channel.
- Pure client-side — no log uploads, no backend, no authentication. Last paste persists in localStorage so a refresh doesn't lose work. Min-deficit filter to ignore trivial -10 entries.
- The bug: a player's row could show both ✗ missing AND ✓ verified by chest log on the same item — contradictory and confusing. Reported on a real session for LaboringWolf's
T4_SHOES_LEATHER_ROYAL@3. - Why: the two flags were computed from independent sources. The ✓ verified flag read per-player rows from the chest log batches (ground truth, every entry has
playerName). The ✗ missing math came from chest captures (a snapshot of items in the chest at the moment you opened it) and used a proportional-share formula across all guild members. If a guild member deposited an item AFTER the snapshot, or the snapshot only covered some items, the proportional math could allocate "missing" to a player who actually deposited correctly. - The fix: when the chest log has a deposit row for
(player, item), use that count directly as their deposited qty. The proportional capture-based math is now a fallback for items the chest log doesn't cover (no batch selected, or item not present in the selected batches). Chest log is ground truth; capture is partial. - Verified against the actual LaboringWolf session: the contradiction is gone (now
missing=0, verified=true, fullyVerified=true); all spot-checked items still behave correctly (trash still missing — no chest log row, falls back to proportional, capture has 0 → correctly still flagged).
- Five small low-risk edits on the per-packet/per-event hot path that fires hardest during PvP:
- Hoisted the mapstructure decode hook +
reflect.TypeOfcalls from per-call closures to package-level (was reallocating per decoded event at 50–200/sec during ZvZ) - Reuse the
uint8→stringparam map viasync.Poolinstead ofmake(map[string]interface{})per call — the dominant per-event allocation source - Cache source IPv4 as
uint32on the listener — game server IP never moves mid-session, so skip the per-packet.String()alloc + albionstate mutex grab on >99.9% of packets - Drop four
log.Tracef/log.Tracecalls that fired per packet — args evaluated even with trace logging off - Reslice the unreliable-packet header drop instead of
make+copy— same semantics, no alloc
- Hoisted the mapstructure decode hook +
- NATS connection leak fix — the dispatcher rebuilt the entire uploader chain (including a brand-new
nats.Connect) for EVERY dispatched message, leaking a TCP connection per message in the NATS path and defeating HTTP keep-alive in the POW path. Now reuses per-target uploaders via a smallRWMutex-guarded map keyed by the resolved URL string (typically 1–4 keys per session). - Validated against a real PvP session before tagging — no regressions, no freezes during the run. Recommended upgrade for any guild member running v1.3.x.
- Installer: github.com/coldtouch/albiondata-client/releases/tag/v1.3.4
- The bug: a stale
itemmap.jsonin an older Go client (April 11 build) was producing wrong enchant levels (e.g. T6.3 Knight Armor showing as T6.4) because the April 13 game patch shifted ~75% of item IDs by exactly one position. Wrong strings got uploaded via .txt and the backend stored them as-is. - The fix: backend now loads
itemmap.jsonat startup and re-resolves every uploaded item from the rawnumericIdusing the canonical map. Stale-client uploads get normalized to the correct itemId on ingest. WS loot events, WS chest-log batches, and TXT uploads (when col 11 = numericId is present) all benefit. - Backwards-compatible: old 10-column .txt files still parse — numericId defaults to 0, backend skips re-resolution and uses the client's string. New uploads from updated Go clients get the full re-resolution treatment.
- Phase 2 (DB backfill of historical wrong data) is intentionally NOT run yet — most affected rows came from .txt uploads where numeric_id was never captured, so we can't re-resolve them. Going forward, all new uploads are clean.
- The NSIS installer was registering a scheduled task that ran the client at every Windows login. Removed by user request — explicit control over when the client runs is preferred. Existing installs need a one-shot cleanup:
schtasks /Delete /TN "Albion Data Client" /F(run as admin).
cluster/world.xml!- The names were in the bin dumps all along — just in a file we hadn't checked.
cluster/world.xml(13 MB) has every cluster'sdisplaynameattribute alongside theidwe already had. 1423 entries covering every numeric zone ID + named special clusters. - User's actual zones from today's testing now resolve correctly:
3312→ Battlebrae Plain (T5 Highland Outland)3348→ Battlebrae Grassland (T7 Highland Outland)@HIDEOUT@3312@<UUID>→ Hideout in Battlebrae Plain2000→ Bridgewatch,0000→ Thetford,1000→ Lymhurst,3004→ Martlock,4000→ Fort Sterling,3003→ Caerleon,5000→ Brecilien
- All 4 display sites light up automatically — death tooltips, missing-item hover tooltip, rich pickup-detail tooltip, player-card "died with" preview tooltip. They already called
formatZone()— just had to swap the pass-through stub for the lookup logic. - Verified end-to-end in browser preview: 16 test cases (royal cities, user's zones, hideouts, unknown numeric fallbacks, named clusters, edge cases) — all green, no console errors.
- Future-proof: regenerate
zonemap.jsviatmp_check/generate_zonemap.pywhenever ao-bin-dumps publishes new clusters (expansions, new outland zones).
- Auto-derived labels removed. The "T5 Highland Keeper Outland Q5"–style descriptions generated from cluster filenames turned out to confuse more than help — players don't recognize them as zone names. Display reverts to raw cluster IDs (
3312,@HIDEOUT@3312@…) which is at least unambiguous, until we source real names like "Bridgewatch" or "Holy Lake". - Infrastructure preserved. The 474-entry
zonemap.js+formatZone()helper + display-site wiring all stay in place.formatZone()is currently a pass-through; swapping it back to the lookup body is one edit when we have real names. - Research underway: agents firing now to find community-maintained zone-name lists on GitHub, deeper-search ao-bin-dumps for anything missed, and investigate whether unhandled packet opcodes carry the display name (most promising lead:
evClusterInfoUpdate,opGetClusterMapInfo).
- Raw cluster IDs now display as readable labels. The Go client v1.3.1 emits zone identifiers like
3312for open-world zones and@HIDEOUT@3312@<UUID>for hideouts — unambiguous but unreadable. The newformatZone()helper looks them up against a 474-entry zone map auto-generated from the ao-bin-dumps cluster filenames. - What you'll see:
3312→T5 Highland Keeper Outland Q53348→T7 Highland Undead Outland Q5@HIDEOUT@3312@<UUID>→Hideout in T5 Highland Keeper Outland Q50007→Bridgewatch(curated city name)
- Wired into 4 display sites: player-card "died with" preview tooltip, death section header tooltip, missing-item hover tooltip (📍 line), and the rich pickup-detail tooltip (📍 per-pickup).
- Future-proof: the
tmp_check/generate_zonemap.pyscript regenerates the map whenever ao-bin-dumps publishes new cluster files (new zones, expansion releases). 7 royal cities + Brecilien are hand-curated; everything else auto-derives from the filename pattern (tier, biome, faction, region, quadrant).
- Root cause for 290 empty-location events identified. Not the OpJoin field — but the fact that
opChangeCluster(the in-session zone-transition opcode) was never handled at all. OpJoin only fires on initial connect, so every walk between zones during a session was silent. Loot/death events captured after that first connect carried whatever location was set at startup (often empty if the client started mid-session). - New
opChangeClusterhandler. Reads destination zone from param 0 — verified end-to-end on a 4-transition walk test (hideout → 3312 → 3348 → 3312 → hideout). Each transition correctly updated player location. - OpJoin field reverted to its original index. Earlier today I incorrectly switched it based on misread diag data; the 3-zone test proved the original location field was right all along, just compounded with the missing opChangeCluster handler made it look broken.
- Net effect: the
📍 Zonetooltip on accountability pages will finally populate correctly for ZvZ scenarios. Loot pickups, death locations, and per-event zone tagging now reflect the actual current zone — not a stale connect-time value. - 5-second invulnerability bubble note: death events practically never fired during the 4-second post-fix OpJoin re-sync window anyway, so the original race wasn't corrupting death-zone data in practice. Loot pickups during that window were the realistic risk, now fixed.
- Released as Go client v1.3.1 — auto-built by GitHub Actions on tag push.
- Zone identifier finally captured. The April 2026 game opcode shift moved the zone field from OpJoin param 8 → param 67. Identified via the diagnostic binary's
[ZONE-DIAG]dump (189 param entries across multiple joins). Format:@HIDEOUT@<id>@<UUID>for hideouts, plain UUID for open-world zones. Fix shipped in the Go client; the long-brokenUpdating player location to ...log line now fires with real data. - Downstream effect: WS-uploaded
LootEvent.LocationandDeathEvent.Locationwill populate for new captures, which means the📍 Zonetooltip on accountability missing-item hovers and death cards will render correctly going forward. - Device-auth rate limit raised 3 → 10/15min per IP. The 3-request cap was too tight when users retry during setup or troubleshoot a broken auth flow; combined with the Go client's silent error-swallowing this looked like a "timed out" failure with no explanation. Both server-side limit and client-side error surfacing fixed.
- "Network error" on Authorize is fixed. CORS was hardcoded to allow only
https://coldtouch.github.io, so any browser running onhttps://albionaitool.xyzgot its auth response blocked by the browser's CORS check. Allowlist now includes both production origins; same-origin / curl requests still pass through. - Redirect now preserves
?device=query string. Visitinghttps://albionaitool.xyz/?device=ABC-DEFpreviously redirected to the GitHub Pages root WITHOUT the device parameter, so the auth modal never opened. Fixed. - Go client console output cleaned up. The auth URL was printed inside a 46-char box but the URL is ~68 chars long — users only saw the truncated
https://coldtouch.github.io/coldtouch-marprefix and couldn't copy the full link. URL now prints on its own line outside the box, fully visible. Misleading "enter code" step removed (the code is already embedded in the URL — no manual entry on the site). - Zone-test exe rebuilt with the new console output. Available at
D:\Coding\albiondata-client-custom\albiondata-client-zone-test.exe.
- Catches the silent-wedge failure mode. The April 25
process.abort()handler caught synchronous SQLITE_BUSY thrown viauncaughtException— but today's outage was a transaction that silently hung for 10 hours with no FATAL line, no exception, no abort. The handler had nothing to fire on. The 90s per-tx watchdog catches exactly this case. - Single-writer queue. All 10 batch-write sites (recordSnapshots, NATS flush, spread-stats, analytics bulk + EMA, compaction tier1→2 + tier2→3, backfill, priceRefCache init + incremental) now go through
withWriteLock(label, fn)— a JS-side Promise queue that ensures only one writer holdsBEGINat any moment, regardless of which connection (db vs statsDb). SQLite WAL allows concurrent readers but only ONE writer at the file level — the previous cross-connection contention is now structurally impossible. - Watchdog. Each lock-holder is wrapped in
setTimeout(90_000). Ifdone()isn't called in 90s the process aborts for clean systemd restart. Caps any future silent wedge at 90s instead of 10 hours. - Telemetry. Queue depth >5 logs a warning. Any single write held >30s logs a warning every 30s. Any write held >5s logs the elapsed time on completion. Early warning before the watchdog fires.
- Today's outage: SIGKILL on PID 489379 (32 min CPU consumed, peaked at 10.2 GB memory before settling at 2.9 GB),
systemctl start. Sub-10s recovery to PID 490291. Tier 4 ships immediately to prevent recurrence.
- Cross-reference at a glance. When a slot's items are corroborated by the chest log, the hover tooltip now shows a green
✓ Verified by chest log (N/M)bar between the status banner and the Pickups section. Partial verification reads(N/M of pickup). - Silent when no match. If the slot has no chest-log evidence, the line is omitted entirely — no "not verified" noise.
- Aggregated correctly. Strip slots represent N pickups of an item with a status; the verified count sums across all matching rows so the displayed N/M reflects the full slot, not just one pickup.
- Bigger, clearer status badges. Replaced the small corner dots with 16px ✓/✗ badges in the top-right of each icon. Deposited = green ✓, missing = red ✗ (with a soft red glow on the icon border so misses pop visually), partial = yellow ½, lost on death = 💀. Both deposited and missing now stand out at a glance — no need to expand the card.
- Hover any preview icon for pickup detail. Tooltip now shows a status banner (
✗ Missing 4 of 4,½ Partial 3/5, etc.) plus a Pickups list with one row per pickup: time · looter name · guild · 📍 zone. Zone shown when Go client v1.3.0+ captured it. Up to 8 pickups inline; longer histories show "+N more". - Source thread-through. Pickup events now also carry
looted_from_name+ guild, so the tooltip shows whose corpse items came from — fast triage when a guildmate's pickups disappear (died with vs picked up pre-death).
- Pickups visible at a glance. Accountability player cards now show an icon-strip preview in the header (same pattern as the regular session view), with status overlays per item: green border + dot for deposited, yellow for partial, red for missing, greyed for lost-on-death, faint red for enemy loot.
- Aggregated by itemId + status so the same item lost-on-death and surviving stay separated visually. Sorted by total silver value descending — most-valuable hits lead. Hover any slot for the rich item tooltip (name, tier, market value, crafter).
- Re-aggregates on perspective flip — switching the Friendly guild dropdown causes the strips to recompute, so a guildmate flipped to "enemy" perspective immediately shows their items as enemy-loot rather than deposited/missing.
- Auto-detect was guessing wrong when your guild was in the minority of captured events — guildmates got tagged as enemies and the enemy's deposits were credited to your side. Common in small-roster fights near a larger enemy guild.
- New "Friendly guild" dropdown above the action buttons in the accountability report. Lists every guild seen in the session sorted by item count, with the auto-detected pick marked
(auto). Picking a different guild flips the perspective:isGuildMembermath, primary-guild banner, deaths section, andplayerResultsfriendly/enemy tagging all update. - Persisted per-session in localStorage. Picking the auto-detected guild — or hitting Reset — drops the override and falls back to auto-detect. If a previously-selected guild isn't in the current session, the override is silently ignored.
- Override clears
primaryAllianceso guild-only matching kicks in — only that exact guild is friendly, not its alliance peers.
- Two tooltips, one hover. Session-timeline bars carry both
data-tip-html(rich death-info card) anddata-tip(plain text). Both document-level mouseover handlers fired on a single hover, each creating a singleton tooltip positioned over the bar — they stacked at the same screen coords. - Fix: the global tooltip handler now skips elements that have
data-tip-html— those are owned by the dedicated rich-tooltip handler. Plaindata-tip-only elements (status dots, item rows) still get the global tooltip as before.
- Cast to REAL inside SUM.
computeAnalyticswas logging[Analytics] 7d query FAILED: SQLITE_ERROR: integer overflowevery cycle (first surfaced April 25 at 19:57). TheSUM((min_sell - max_buy)²)term overflowed int64 when summed across the 7-dayprice_averageswindow — squared spreads on high-value items are ~10¹⁴, and the cumulative sum easily blew past9.2 × 10¹⁸. - Fix:
CAST(min_sell - max_buy AS REAL)on one operand promotes the multiplication to double-precision float, which then accumulates safely in the SUM. Variance/stddev downstream loses no meaningful precision. - No outage — error was cleanly handled by the existing
finalize('7d-err')path. But analytics rows weren't being written each cycle, leavingprice_analyticsdata stale.
- Yesterday's fix didn't actually exit. Tier 1 logged the FATAL but
setTimeout(() => process.exit(1), 500)never fired — the event loop was wedged inside the native sqlite3 mutex, so the timer never ticked andprocess.exit()'s cleanup hooks hung on the same lock. Process stayed alive for 43 minutes with ports bound and zero log activity. - Switched to
process.abort()— synchronous SIGABRT, no event-loop tick required, no async cleanup. Systemd catches it and restarts in ~5 s. Same change in the RSS watchdog. - Skip
flushNatsBuffer()in the SQLite path. It doesdb.serialize(() => db.run('BEGIN TRANSACTION'))on the locked connection — that was the second wedge step after the FATAL log fired. RSS-driven exit still flushes (DB likely healthy there). _abortingre-entrancy guard so a second SQLITE_BUSY landing while we're already aborting can't double-call abort.
- Died-with items on player cards: players who died during the session now show the items looted off their corpse in their card's preview strip — after a 💀 divider, rendered greyed + red-bordered so they read as "lost". Hover any icon for full context: time, zone, killer, and who looted it ("Died at 2:30 AM in Thetford Outskirts — killed by Gank — looted by Bob (2 items)"). Handles multiple deaths per session ("Died 3× — last at …"). Zone shown when the uploader was running Go client v1.3.0+.
- Seven batch-write sites hardened: NATS flush, hourly snapshot, spreadstats, analytics bulk + EMA, compaction tier 1→2 + 2→3, and Charts-API backfill now wrap BEGIN → prepare → run-loop → finalize → COMMIT with per-step error callbacks and explicit ROLLBACK on failure. Eliminates the orphan-transaction / unfinalized-statement state that caused the recurring 15-min silent-wedge outages on April 22-23.
- Fatal-error handler:
uncaughtException/unhandledRejectionnowprocess.exit(1)on SQLite state-corrupting errors (SQLITE_BUSY / LOCKED / CORRUPT / IOERR / MISUSE) so systemd restarts us cleanly in <5s instead of the process wedging for 15 min with 11 GB RSS. - Smaller batches:
recordSnapshots5000 → 500,computeSpreadStats500 → 100. Shorter WAL lock windows so concurrent connections don't pile up waiting. - RSS watchdog: memory log cadence 10 min → 1 min; if RSS crosses 8 GB the process exits cleanly for a fresh-heap restart instead of inheriting a pathologically-bloated one.
- Recipients see exactly what the uploader sees: clicking a loot-session share link used to render the session inside a full-screen overlay with a "Continue to Coldtouch" button. Now it renders inline in the normal Loot Logger → Upload mode pane — same summary strip, deaths section, player cards, and export buttons the uploader had. A thin banner at the top marks it read-only.
- Accountability dropdowns — HTML artifact fix: session / capture / chest-log dropdowns were showing literal
<span class="time-ago" data-ts="...">5m ago</span>text inside each option (caused bytimeAgo()returning an HTML wrapper that<option>can't render). Switched all three to the plain-text_computeTimeAgo(). - Uploaded sessions now group by upload time: a file uploaded 2 min ago with last-week's events used to show as "7d ago" in the Older group. Now renders as "📤 Uploaded 5m ago · events from 7d ago — 500 events · 12 players", grouped under "Recently uploaded" (24 h window so it survives refreshes). Duplicate emoji prefixes (🆕/⚠) on each row removed.
- Share button on uploaded sessions: after uploading a
.txtloot log, the report's action row now includes 🔗 Share and ✓ Accountability alongside CSV / .txt / JSON. Share uses the existing public-link system (anyone with the URL can view the session; revoke any time). - sw.js CACHE_NAME fix: the deploy-time auto-bumper kept appending an extra
'every deploy, producing a syntactically broken cache-name string. Reset to clean form and patched the bumper so future deploys stay clean.
- SQLITE_BUSY hardening:
readDbbusy_timeout bumped 5s → 30s (matchesdbandstatsDb). All three connections now retry for up to 30 seconds before failing, eliminating SQLITE_BUSY on the read path during analytics batch writes. - Accountability missing-item hover tooltip: hovering (or tapping on mobile) a red "Missing" item row now shows a tooltip with who picked it up, at what time(s), and in which zone (📍 pin). Pickup events are tracked during the accountability pass and rendered per item. Requires the v1.3.0 custom client for zone data; older events still render cleanly without the pin.
- Portfolio — Completed Craft Runs: the Portfolio Tracker tab now shows a collapsible table of all completed craft runs (requires login) with cost, revenue, net P/L after tax, and margin — totalled across all runs.
- Stop Live Session now auto-saves + renders: previously Stop only flipped a flag; the user had to click Save Session then click the session card. Now Stop: auto-saves in-memory events via
/api/loot-session/consolidate(if not already saved), opens the detail panel, and renders the run viashowLiveSession(). No-op if there are no events or the session is already saved. - Accountability share now includes chest-log batches: shared links were rendering the accountability check without any "verified deposited" badges because the snapshot omitted the opcode-157 chest-log batches (deposit/withdraw ground truth). Recipients saw pre-chest-log logic.
- Schema: new
chest_logs_jsoncolumn onaccountability_shares, with an idempotentALTER TABLE…ADD COLUMNmigration for existing DBs. - Backend:
POST /api/accountability/sharenow accepts achestLogsarray (user's selected batches or all loaded), size-capped at 40 batches, 400 entries/batch, 500 KB JSON.GET /api/accountability/public/:tokenreturns the parsed batches. - Frontend:
shareAccountability()snapshots the relevant batches into the POST body._renderPublicAccountabilityView()restores them intowindow._chestLogBatches, rebuilds theacc-chestlog-selectdropdown with shared batches auto-selected, and marks it as user-interacted so it can't be rebuilt out from under the shared view. Banner footer now shows the batch count. - VPS outage recovery: backend process was stuck in a
SQLITE_BUSYloop that theuncaughtExceptionhandler swallowed without unblocking the event loop — logs went silent for 22 min. Force-killed stuck PID, clean restart via systemd.
- Zone tracking: client now detects zone transitions via
operationJoinResponseand attaches the current zone to every loot event and death event sent to the VPS. Download from the v1.3.0 GitHub release. - Death cards: accountability deaths section now splits into three categories — 🛡️ Friendly (our members died), 💀 Enemy (we killed them), 👁️ Other (bystanders, collapsed by default).
- Zone badge:
📍 ZoneNameshown on each death card when location is known. - Missing-item tooltip: hover tooltip in accountability now shows the zone where the pickup happened alongside the timestamp. Mobile tap-to-toggle supported.
- No behavior change: every loot, death, and chest event is captured exactly as before. Download the new
albiondata-client-custom.exefrom the v1.2.0 GitHub release. - Loot writer:
bufio.Writerover the.txtlog; per-eventfile.Sync()removed. Background ticker flushes to the kernel every 5s;CloseLootFiledrains on shutdown. Eliminates 50+ fsync syscalls/sec during ZvZ. - Logging: per-event
log.Infoffor loot + deaths downgraded toDebugf. New 30s aggregated Info summary ("Captured N loot event(s) and M death(s) in the last 30s"). Synchronous journald writes were stalling the event goroutine at 100+ events/sec. - VPS relay: pooled
bytes.Buffer+json.Encoderin a newbuildRelayMessagehelper used by all sixSend*functions. Drops themap[string]interface{}+ fresh buffer allocation per event. - Atomic connected flag:
connected bool→atomic.Bool. Disconnected fast-path insendOrQueueno longer contends with an in-flightWriteMessage. - Reusable auth timer: replaced
time.After(30s)withtime.NewTimer+defer Stop()so reconnect churn doesn't leak runtime timers. - WebSocket broadcast:
{topic,data}envelope built into one pre-sized[]byteviaappendinstead of three string concatenations. 1 allocation instead of 3 per broadcast. - GUID construction: three
fmt.Sprintf("%02x", byte(b))loops in container-open handlers replaced with a sharedguidHex()helper usingencoding/hex. Cuts 16+ allocations per container open to one small[]byte. - Vault info parsing:
names,icons,guids,vi.Tabsslices preallocated to their final length. - Estimated combined impact: during sustained 100+ event/sec ZvZ phases, ~30–50% CPU reduction, ~80% disk-I/O latency reduction on the loot writer, ~20–30% GC pause reduction.
- JWT never in URL (CRITICAL): Discord OAuth callback now issues a short-lived exchange code (60s TTL) instead of embedding the JWT in the redirect URL. Frontend exchanges the code for the token via
POST /api/auth/exchange— token goes straight to localStorage, never into browser history or server logs. - Transport-routes-live hardened (HIGH): added dedicated rate limiter (5 req/min) and 30s server-side cache so the O(n²) join isn't computed on every unauthenticated hit.
- Health endpoints stripped (HIGH):
/healthand/healthznow return only{"status":"ok"}. Full diagnostics (uptime, DB sizes, job timings) moved to/api/admin/healthbehind JWT. - Device code hard cap (HIGH): added per-IP rate limit (3 per 15 min) and a 200-entry global cap on the
deviceCodesmap to prevent unbounded memory growth. - Password reset token removed from URL (HIGH): added
?reset=param handler + modal in the frontend so the reset link exchanges the token immediately on page load and strips it from the URL bar. - Email HTML injection (MEDIUM): added
escHtml()helper — username is now escaped before insertion into email templates. - WS IP extraction (MEDIUM):
x-forwarded-forheader is now split on comma and the first entry taken, preventing client-spoofed IPs via multi-value headers. - Admin Discord ID (MEDIUM): hardcoded string replaced with
ADMIN_DISCORD_IDenv constant (defaulting to existing value). - SRI on Chart.js (MEDIUM): CDN script tag pinned to
chart.js@4.4.9withsha384integrity hash andcrossorigin="anonymous". - Password complexity (MEDIUM): registration and password-change now require at least one letter and one digit. Error message and input placeholder updated.
- Loot upload cap (MEDIUM): file uploads now reject payloads >5,000 lines or >2 MB with a clear error message.
- Login rate limiter (UX/SEC):
loginLimiter(10 per 15 min) wired toPOST /api/login. - SW auto-bump (DevOps):
deploy_saas.pynow auto-incrementssw.jsCACHE_NAMEversion on every deploy so stale assets are always evicted. - Go client cleanup (CODE):
device_auth.gowriteConfigFilerewritten using stdlibstringspackage; customsplitLines/trimSpace/startsWithhelpers removed. - Toast callback registry (CODE):
showConfirm/showPromptreplaced inlineonclickfunction serialisation with a_toastCallbacksID registry — eliminates the XSS vector from arbitrary content reachingonclickattributes. - Toast stack cap (UX): confirm/prompt toasts are capped at
MAX_VISIBLE_TOASTS(5) to prevent stacking loops from burying the UI. - Offline indicator (UX): banner appears when the browser goes offline; a success toast fires when connectivity returns.
- Tab titles (UX): browser tab title now reflects the active tab (e.g. “Market Flipping — Albion Market Analyzer”).
- Header shrunk: title reduced to ~60% of previous size; SEO keyword line hidden (kept in DOM for crawlers). Recovers ~45 px of vertical space.
- Timers in status bar: Daily Reset & Monthly countdown are now inline in the top status bar — removed the floating bottom-right widget.
- Dynamic tab title: browser tab now reflects the active section (e.g. "Market Flipping — Coldtouch Market Analyzer").
- Footer anchored: footer now sticks to the bottom of the viewport or content, whichever is lower — no more floating in dead space.
- Craft Runs empty state: runs with no transactions show "0" for cost/revenue and "—" for Net P&L instead of the broken "— / — / +— (—%)" display. Phase strip emoji enlarged.
- Market Flipping empty state: shows a hint placeholder instead of a blank area on first load.
- Loot logger restore banner: auto-dismisses after 30 seconds; message condensed.
- Crafter profile pill: collapses to icon-only after first view — reduces persistent visual noise when no profile is set.
- 12-hour outage resolved. Live site was timing out (HTTP 000) because the scheduled analytics job was running 1,700 SQL batches that took ~22 min total — over the 25-min "stuck" reset — and each reset spawned an overlapping run on top of the old one. 20+ concurrent EMA chains pegged the event loop.
- Analytics rewrite: added a generation token so stale callbacks from reset runs abort silently, AND replaced the 1,700-query batch loop with one ordered streaming pass. First cycle after deploy finalized in 504s — the success signal that had never fired before. New composite index
idx_pa_ema_streamcovers the ORDER BY. - Read-path isolation: moved
/api/craft-runs,/api/loot-tabs,/api/loot-session,/api/alerts,/api/transport-routes,/api/spread-statsand others to the dedicated read-only DB connection (readDb). They used to queue behind writes on the main connection and stall during analytics. Reads now return in <200 ms regardless of analytics activity. - Craft Runs "network error" fix: user-reported. Turned out to be a pure JavaScript
ReferenceError: fmtSilver is not definedincrRunCardHTML— the broadcatch {}in the fetch wrapper swallowed it and showed the misleading "Could not reach server" message. 8 typo'dfmtSilver(...)calls renamed toformatSilver(...), 1fmtNumreplaced withtoLocaleString(). Cache bumped to v55. - DB busy_timeout 5s → 30s: absorbs SQLITE_BUSY during analytics bulk flush (was spamming the log with
[FATAL]every 30s).
- Chest-log selector fixes: each in-game chest log viewing produces two batches (📥 deposits + 📤 withdraws). Selector now auto-selects all batches on render (users were having to Ctrl-click) and has a taller default height so both entries fit visibly.
- Date cross-check: chest logs retain ~4 weeks of history. Deposits from outside the session's time window (±buffer) are now automatically excluded from verification — a 2-week-old deposit won't get credited toward today's fight. Verify banner shows the exact date range + how many entries were dropped.
- Loot-logger audit: extracted
sanitizeLootEventsas the single cleanup pass. Applied in both session view + accountability. Dedupes (matches backend UNIQUE INDEX), drops emptyitem_ids, filters special internals (SILVER / GOLD / FAME_CREDIT / POUCHes / TOME_OF_INSIGHT / SEASONAL_TOKEN). Defensive — Go client already skips silver, but belt-and-suspenders at the JS layer prevents any leakage.
- A 74-death ZvZ used to be a flat wall of rows. Now the Deaths section body splits into two collapsible sub-groups.
- 🛡️ Friendly deaths — auto-expanded, sorted by silver lost. Header shows total regear exposure.
- 💀 Enemy kills — collapsed by default with “click to expand” hint. Sorted by silver taken. Kept for audit but out of the way.
- Fixed:
__live__session event mapping was strippinglooted_from_guild/looted_from_alliance, making every death render as enemy in live sessions.
- Old logic: items were only marked “lost on death” when another tracked player looted them off the corpse. This missed losses whenever the victim died out of range of all tracked looters, or when enemies out of range did the looting.
- New logic: if a player died at time T, every item they picked up BEFORE T is lost on death. Multiple deaths per player supported (pickups between two deaths attribute to the next one). Post-death pickups still count toward “should have deposited”.
- Implemented as a two-pass scan: pass 1 collects
deathTimesByPlayer[name]from __DEATH__ events; pass 2 flags every pickup whose player has any later death timestamp as lost. - Lost rows render with the existing red
.ll-item-diedoutline + “Lost on Death” status. - Chest Log Captures card now warns that viewing chest logs requires the View Chest Logs permission on your guild role (Officer+). Without it, the Log tab doesn’t appear in-game at all.
- New Chest Log Captures card in Accountability (parallel to Chest Captures). Start Capturing → open any chest Log tab in-game → the client decodes opcode 157 and streams deposit/withdraw records to your browser.
- Deposit vs withdraw tagging — the game doesn’t mark direction in the response; we pair each response to its originating request via the Photon invocation counter and infer direction from REQUEST param 6 (filter 1 = withdraw, 28 = deposit).
- 🔗 Merge & Verify button — cross-checks each player’s pickup events against chest-log deposit records by `(player, itemId)`. Matches get a green ring on the icon + ✓ badge next to the item name; hover reveals “Verified: chest log shows {player} deposited {qty}”. Partial matches (log qty < pickup) show a yellow ring.
- New Verified count in the summary strip; verify banner above it reports batches + deposit/withdraw totals.
- Important scope: chest log is a verification layer, not a replacement — it only sees deposits/withdrawals, not field pickups. The loot client remains the source of truth for “who picked up what”. Merge only raises confidence on matched items; absence of a badge isn’t evidence of theft.
- Problem: expanded death cards were an anonymous grid of 36px icons. In a ZvZ death with 8+ items and multiple looters, you had to hover each one to learn what was taken — unreadable.
- New layout: one card per looter with
Name [Guild] · N items · silverheader, then one row per item (icon · name ·×qty· value). Stackables collapse. Items sorted most-valuable-first within each pile. - Worn-at-death moved into its own collapsible
<details>(auto-open for small sets, collapsed for long ones) — keeps the focus on who looted what. - Empty-range deaths now render a clean “No items recovered in tracked range” state instead of a blank strip.
- Mobile: grid drops the silver column but keeps name + qty readable on one line.
- Bug: a friend ran a CTA and shared the accountability report — every one of 651 events rendered as “Unknown 1954”, “Unknown 2409”, “Unknown 9090”… Regear was impossible.
- Cause: the Go client resolves numeric item IDs via a companion
itemmap.jsonnext to the binary. Missing/stale file →resolveItemNamefalls back toUNKNOWN_<numericID>→ every event streams with the sentinel name instead of the real string ID. - Fix — website recovers without waiting for client re-install: bundled
itemmap.json(11,175 entries) on the frontend; newrewriteUnknownItemIdhelper mapsUNKNOWN_1954→T4_RUNE→ “Adept’s Rune” using eithernumeric_idfrom the payload or the suffix parsed out of the item ID. Normalization runs at every ingestion point: accountability fetch (session / live / shared), live WebSocket loot events, and chest-capture handler (before the cosmetic filter — otherwise mapped items would be wrongly filtered). - Verified against the friend’s real share link: 651/651 events resolved, 429 item rows now show proper names (“Grandmaster’s Bag”, “Major Gigantify Potion”, “Grandmaster’s Hellion Jacket”…). Works for viewers who never ran the Go client themselves.
- Checkbox on every capture card — tick 2+ tabs and a combine bar appears with live “N tabs · M item lines · X total qty · Y kg” summary.
- 🔗 Combine & Analyze merges selected tabs: stackables dedup by
(itemId, quality, enchantment)with quantities summed; equipment stays separate (each instance is unique). - Each merged item keeps a
_sourceTabreference so downstream UI knows which tab contributed it. - Phase 1 evaluate, Phase 2 sell plan, and Phase 3 track all work on the combined tab unchanged — no code paths had to be rewritten.
- Bug: chest captures sometimes included items that weren’t physically in the tab — most notably
UNIQUE_UNLOCK_SKIN_HORSE_UNICORN_WHITE_TELLAFRIEND(a Tell-a-Friend recruiter reward) appearing in a personal “sell” tab. Reproducible on rescan. - Cause: the Go client’s global item cache includes account-bound items (mount skin unlocks, avatars, TELLAFRIEND rewards) that are always in awareness. The game’s
AttachItemContainerslot map occasionally references these slots, leaking cosmetics into chest captures. - Fix (two layers): new
IsNonTradeableItem/isNonTradeableItemIdfilter in both the Go client and the website. SkipsUNIQUE_UNLOCK_*,SKIN_*,UNIQUE_AVATAR*,UNIQUE_HIDEOUT*,UNKNOWN_*, and anything containing_TELLAFRIEND. Tradeable mounts (Mammoth, Ox, regular horses) are unaffected. - Go client now logs each filtered item at Info level and reports a
filteredcount in the capture summary.
- 📦 From Scan button in run detail — attach a chest capture directly to an active run. Cost is split across items by quantity (or by market value); each line becomes a
tab_scan-sourced buy transaction. - 📊 Sync to Portfolio button — pushes every buy/sell transaction from a run into the Portfolio Tracker (FIFO cost basis preserved). Re-sync is idempotent — prior syncs for the same run are replaced, not duplicated. Only market-facing lines sync; internal refine/craft pipeline steps stay in the run log.
- ⚒️ Refining Planner — collapsible helper at the top of the Craft Runs tab. Pick material type (ore / wood / fiber / hide / rock) and input quantity; shows best royal city + bonus, or hideout mode (PL + Core %), applies RRR formula with optional Focus, and displays expected output and materials saved. Live recalc on every change.
- Escape now closes the Scan picker modal too.
- New “Craft Runs” tab in Trading group — track every crafting cycle from material purchase to final sale.
- 3 DB tables:
craft_runs,craft_run_transactions,craft_run_scansfor full lifecycle storage. - 8 API endpoints: create/list/get/update/delete runs; add transactions; link chest tab scans with proportional cost allocation; P&L summary.
- Run list with status badges (Buying → Refining → Crafting → Hauling → Selling → Complete), mini flow strip, and running cost/revenue/margin.
- Run detail view: visual progress bar, P&L dashboard (cost, revenue, 5.5% tax estimate, net profit), full transaction log with type/item/qty/price/city/source columns.
- Add Transaction modal: 6 transaction types (buy, refine in/out, craft in/out, sell) with item, qty, unit price, and city fields.
- Hideout support in Crafting Profits: new “Hideout (Black Zone)” location option reveals Power Level (0-8) and Core Bonus (0-30%) inputs; effective bonus = 15% base + PL×2% + core %.
- City refining guide:
GET /api/refine/optimal-cityandGET /api/craft/hideout-bonushelper endpoints.
- Guild Leaderboard scroll bug fixed — tall modals now scroll correctly. Root cause:
align-items: centerwith nooverflow-yclipped content above & below viewport with no escape. Fixed withalign-items: flex-start; overflow-y: autoon.modal. - Escape key now closes all 11 modals — previously only 3 were covered. New handler covers: Copy Preview, Guild Leaderboard, Session Compare, Session Merge, Share Session, Trip Summary, Loot Split, Whitelist, Feedback, Chart, and the dynamic Shortcuts Help card.
- 20 audit findings fixed across backend security, Python deploy script, and frontend JS.
- Backend: trust proxy, admin-only guard on db-stats, 100-line upload cap, tighter batch-prices rate limit, https-only news links, HTML-strip in loot sanitiser, generic DB error messages, 30-day share token expiry, .env now uploaded via SFTP (no secrets in process cmdline).
- Frontend: two unescaped
e.messageXSS paths closed, foodBuff escaped, market fetch gets a 30s abort timeout, WS error handler no longer silently swallows logic bugs, localStorage JSON parses wrapped in try/catch,_consumedFlipspruned on load (cap 1000),spreadStatsCachesize-capped at 2000, WS URL derived fromVPS_BASEconstant, IDB upgrade guard usesDB_VERSIONconstant. - Service worker: v44 → v45; strategy changed from cache-first to stale-while-revalidate; registration uses
updateViaCache: 'none'. - Cleanup: 19 scratch/test files deleted,
.gitignoreupdated with loot-event logs, audit reports, and test file patterns.
- Bear Paws + ~70 other artifact weapons now have recipes — Market Browser Craft button now renders on every weapon, Crafting Profits opens every artifact. Previously KEEPER/HELL/MORGANA/AVALON/CRYSTAL faction variants were silently missing from the recipe generator.
- Transport Routes now shows food, potions, raw materials. Backend was filtering out anything under 100 silver/unit profit — bulk cargo has 5–60 s/unit margins but dominates total trip profit. Dropped the floor to 1; the frontend's ROI cap + sort-by-trip-profit still handle outliers.
- Community + Profile contribution score updates again. The contributions endpoint required a different payload than what the frontend sent, and the Transport activity was weighted but never tracked. Both fixed.
- Loot Logger item-mismatch fix — "Assassin Hood 6.3" that was actually a different item came from a stale itemmap (game shipped Protocol18 on April 13; our map was from April 1). Regenerated item/weight maps from the latest dump and rebuilt the Go client exe.
- In-game chest log capture prep. The Go client now dumps the authoritative chest log packets when you open the Log tab in-game (with
LogUnknownEventson). Next session we'll use that data to cross-check our loot capture and flag mismatches in real time. - Security pack: leaderboard avatar XSS closed, device-auth no longer kicks your other client offline, WebSocket auth now rate-limited per IP, leaderboard score can no longer be gamed (per-type daily caps), device-token endpoint returns uniform errors to stop token enumeration.
- Latency wins: chart opens, Profile tab, analytics reads moved off the main DB connection — they were queueing behind NATS batch writes. Chart modal should feel instant now.
- Live Flips reliability: validation runs 5-at-a-time (was 1 serial); stale flips are dropped instead of broadcast; when AODP is down, flips are marked unverified instead of silently passing through.
- Transport accuracy: trophies/furniture/mount tokens/bags are no longer treated as 999-stackable (no more "buy 20k Mammoth kits"); weapon categorization operator precedence fixed.
- Service worker cache v40 → v41.
- Shared accountability links show death loot — each death row in the Accountability view now expands on click to reveal Recovered items (with qty badges and price tooltips), Worn-at-death equipment, and who looted the corpse. Before, the share view showed only a flat "victim → killer" strip with no way to see what was dropped or picked up.
- Owner view and shared view now render deaths identically — both use the same expandable row component from the main session view.
- Fix: "Share failed: Unexpected token '<'" on big content. Express was rejecting POSTs over 100 KB with an HTML error page, and the client choked trying to JSON.parse it. Bumped body limit to 5 MB.
- Service worker cache v39 → v40.
- Community leaderboard by Activity Score — no longer just "top scanners". Your combined 30-day activity (loot sessions ×5, chest captures ×3, accountability ×3, sales ×2, market scans ×1, transport + crafting ×1) ranks you against everyone else. Top section explains the formula in a collapsible panel.
- Profile page overhaul — stats now lead with Activity Score + Community Rank + Tier instead of just scans. New Activity Breakdown panel shows per-category contribution counts and point totals.
- Profile wizard fixed — removed the "Run with
--capture" step. Capture is on by default in the client; users don't need flags. - Transport: Route Risk slider — set a gank rate (0-40%) and every route card gets a "Risk-Adj Net" column = profit × (1−rate) − cost × rate. Red-zone routes are now honestly priced.
- Transport: Auto-refresh — toggle in the control panel. Routes update every 60 seconds when you're viewing the tab + in live mode.
- Transport: My Haul Plans — save/load named filter configurations. Every setting (cities, mount, budget, confidence, freshness, gank rate, sort) persists across sessions.
- Transport: Swap cities button — flips buy↔sell and re-scans. Quick round-trip planning.
- Transport: Discord Embed Shopping List — new button renders the haul as a Discord markdown code block with aligned columns (Item / Qty / Unit / Total / Risk-Adj Net). Preview modal lets you trim before pasting.
- Service worker cache v28 → v29.
- Live Flips working again — default filter was 50k silver but backend broadcasts 10k+. Dropped default to 10k. Filter-persistence was also broken due to wrong DOM IDs. Softened the low-side outlier guard so legitimately cheap resources aren't rejected.
- Transport mount weights corrected — our values were 5-10× too low. T8 Elder's Mammoth is 22,521 kg (we had 1,764!), T7 Grandmaster's Ox is 2,667 kg (we had 1,262). Added Mule, T3 Horse, Swiftclaw, Moose, Giant Stag, Grizzly Bear, full T4-T8 Ox ladder. Dropdown reorganized into clean categories.
- Market Browser — the "Flips" button on item cards is now "Craft" for items that have a recipe, leading straight to the crafting detail with material breakdown.
- Recent Sales moved to Portfolio — lives next to trade history where it belongs. Still auto-detects sales from in-game mail.
- Loot Logger — sessions grouped into collapsible 📅 Today / Yesterday / This Week / Older buckets. Massive space saving for users with lots of saved sessions.
- Loot Logger — pick a session, list hides. Previously both were visible at once. "← Back" button restores the list.
- Loot Logger timeline hover — bars now show a rich tooltip with death count + victim names, guild-colored via a hash palette consistent with the player cards.
- Loot Logger deaths — color fixed: friends = green, enemies = red (was reversed). Whole deaths section is now one big collapsible card with compact one-liner rows that expand on click. No more 20 massive cards dominating the page.
- Loot Logger player cards — all loot icons shown. No more "+N more" truncation. Icons bumped from ~32px to 48px with quantity badge and hover value tooltip.
- Accountability — new Event View mode. See the same per-player layout as the normal session view, with green/yellow/red/grey status dots on every item row (deposited / partial / missing / lost on death).
- Service worker cache v27 → v28.
- Backend tax fix — the server was using the stale 3% tax everywhere (Loot Buyer, Transport Live, Live Flips, spread stats). Now premium-aware: 4%/8% instant, 6.5%/10.5% sell-order, driven by your Premium toggle. Every server-computed "net after tax" is now correct for your account.
- Loot Buyer patient-sell — was using instant-sell tax (no setup fee) for sell-order math. Patient totals were inflated by 2.5-3.5 points, skewing BUY/MAYBE/SKIP verdicts. Fixed.
- Freshness bug fixed — NATS price updates were overwriting recent dates with empty strings, making fresh data look stale. The freshness dot now stays green when prices update via NATS.
- ⭐ Favorites hub — every Market Browser card gets a star button. Favorites rows gain action buttons (chart, browser, compare, craft, remove). Favorites is no longer an island.
- Live Flips cards are clickable — click to open the chart, dismiss × to hide a flip you've already taken. Filter state persists across reloads.
- Loot Buyer Sell Strategy accordion — every tracked tab gets a "📊 Sell Strategy" expandable that re-runs Phase 2 on the remaining unsold items without restarting from capture.
- Alerts onboarding wizard — inline "How to set this up" with Invite Bot button, Channel ID instructions, and a preview of what the Discord alert looks like.
- Profile Data Client wizard — 5 numbered steps with a big Download button so you can go from zero to live chest capture without hopping tabs.
- Black Market excluded from sell-city loops for refined materials (Top-N Ranker + Refining Lab). BM only buys finished gear in-game; rankings were skewed toward a price you can't actually realise.
- Market Browser Q=All now defaults to Q1 for card math (previously mixed Q1 sells with Q5 buys → fictional spreads).
- Item Power quality-aware — new Quality dropdown; effective IP includes +20/+40/+60/+80/+100 bonus for Good → Masterpiece.
- Portfolio quality field — record the actual quality on manual trades (previously all Q1).
- Portfolio per-item sync — tracking a loot tab now creates one portfolio row per item, not a single "primary" row.
- Loot Logger min-value filter — hide players whose looted value is below a silver threshold.
- Shareable deep links work for all tabs (fixed stale VALID_TABS set).
- Dev-only fields removed from Crafting settings (the "Station % (old)" and "Base PB 15/18" selectors were leaking research artifacts).
- Service worker cache v26 → v27.
- Tax rate bug fixed (was hardcoded 3% from pre-2021). Now correctly shows 4% Premium / 8% Non-Premium via a live Premium toggle. Every tab that uses tax (Transport, BM Flipper, Portfolio) auto-updates. Non-premium users were being under-projected on tax by 167%.
- ⚡ Top-N Crafting Ranker (new tab) — ranks every recipe by silver/focus, silver/hour, profit, or ROI against live prices + your spec. Auto-applies city specialty bonuses. Min liquidity filter keeps you from crafting items you can't sell. No other tool does this.
- 🔥 Refining Lab (new tab) — three modes: Today's Best (sorted grid), Single Material Deep-Dive, and Daily Focus Planner (allocates your 10k-30k daily focus across refines).
- 🗺️ City Heatmap — on any crafting detail, see a 7×2 matrix (7 cities × focus on/off) with profit + RRR per cell. Best cell highlighted.
- 🌳 Sub-recipe Tree with buy-vs-craft toggles — expand any material into its own recipe. Toggle each node 🛒 Buy or 🔨 Craft. "Auto-optimize" picks the cheaper path per node. Savings counter vs all-buy baseline.
- 🎯 Inverse Calc — target-margin slider shows max unit price you can pay per material.
- 🧑🔧 Crafter Profiles — multiple named profiles (e.g. "Plate Specialist", "Cloth Refiner"). Spec/mastery/city/food buff/premium all propagate across Crafting, RRR, Refining Lab, Top-N simultaneously. Nav pill shows active profile.
- 🎲 Monte-Carlo Craft Simulator (bonus) — simulates 400 crafting sessions with your RRR + quality distribution. Shows silver-earned histogram + p5/p50/p95 outcomes. Turns "expected profit" into "expected profit ± realistic range".
- Focus formula fixed — was linear (wrong slope), now exponential
cost = base × 0.5^(efficiency/10000)per wiki & forum research. - Item Value + Station Fee helpers added — new "Station s/100 Nutrition" input replaces the flat % and matches the in-game station UI.
- Quality EV mode — optional toggle weights sell prices across the quality distribution at your spec. Huge for masterpiece-target items.
- Food buff — Pork Omelette (+18%) / Avalonian Pork (+30%) focus efficiency.
- Service worker cache v25 → v26.
- Loot Split Calculator — new modal under Loot Tools dropdown. Splits silver across guildmates with per-person weights and bonuses, supports % or fixed-silver off-the-top deductions, imports totals from current loot session, and one-click Discord copy.
- Equipment at death — Go client now tracks each player's gear via
EvCharacterEquipmentChanged. Death cards show a teal-bordered "Worn at death" item strip alongside the recovered loot — you can now see what was on the corpse vs what was looted. - Health endpoint — new
/healthzreports DB connectivity (3 connections), NATS state, deploy version stamp, and uptime — ready for UptimeRobot/BetterStack pings. - Backups — deploy script now installs a 6-hourly SQLite backup cron with 7-day retention. The April 4 corruption incident is now recoverable from snapshots.
- Rollback —
python deploy_saas.py rollbackrestores the previous backend.js from a snapshot taken on every deploy. - Go client
--versionnow also prints build date, OS/arch, and Go version — easier to diagnose user reports.
- JWT hardened — all
jwt.verify()calls pinned to HS256; server crashes on missingSESSION_SECRETinstead of silently continuing. - Discord OAuth state HMAC-signed — prevents account-linking hijack via forged state parameter.
- Rate limits added — device authorization (10/15min), loot evaluation (10/min per user).
- XSS eliminated — news banner no longer injects server data into inline
onclickattributes; URL?tab=now validated against a whitelist before use inquerySelector. - No more blocking dialogs — all
confirm()/prompt()calls replaced with non-blocking toast dialogs (showConfirm/showPrompt). - Analytics cache capped at 500 entries with FIFO eviction; concurrent fetches for the same item deduplicated.
- Go client —
matchContainerToVaultTabnow holdsvaultMu.RLock(), fixing a data race in vault tab lookups. - All external links now include
rel="noopener noreferrer"; mobile menu button adds ARIA attributes.
- JWT hardened — all
jwt.verify()calls pinned to HS256; server crashes on missingSESSION_SECRETinstead of silently continuing. - Discord OAuth state HMAC-signed — prevents account-linking hijack via forged state parameter.
- Rate limits added — device authorization (10/15min), loot evaluation (10/min per user).
- XSS eliminated — news banner no longer injects server data into inline
onclickattributes; URL?tab=now validated against a whitelist before use inquerySelector. - No more blocking dialogs — all
confirm()/prompt()calls replaced with non-blocking toast dialogs (showConfirm/showPrompt). - Analytics cache capped at 500 entries with FIFO eviction; concurrent fetches for the same item deduplicated.
- Go client —
matchContainerToVaultTabnow holdsvaultMu.RLock(), fixing a data race in vault tab lookups. - All external links now include
rel="noopener noreferrer"; mobile menu button adds ARIA attributes.
- Every player card now shows a compact lifetime trend line when the player has appeared in 2+ of your saved sessions: "📊 8 sessions · 1,250 items lifetime · 💀 3 · last seen 2d ago".
- Great for officer-level context — who's a consistent contributor, who's a recurring enemy, how recently someone was last seen.
- New backend endpoint
POST /api/player-trends-bulkaggregates stats in one roundtrip per session. - Service worker cache bumped v19 → v20.
- Shareable session links (G4) — click the 🔗 on any saved session to generate a public URL. Guildmates view the full read-only session without logging in. Revoke any time.
- 🔗 shared badge on session cards highlights which sessions currently have an active link.
- Backend: new
loot_session_sharestable + 3 endpoints. Unauth endpoint exposes only what you chose to share — no user_id, no other sessions. - Internal: E3 live-session state consolidation —
liveSessionState()snapshot helper +resetLiveSessionFlags(). No user-visible change. - Service worker cache bumped v18 → v19.
- Days-held badge on open/partial tracked tabs —
Ndnext to the status. Tabs >14 days get a red "stale" variant. - Break-even tick on tab progress bars — gold marker at the 100% position. Percentage text is now unbounded so 180% reads as 180% (bar still capped at 100% width).
- Service worker cache bumped v17 → v18.
- About tab: new Keyboard Shortcuts reference card with every shortcut in one place (global + Loot Logger specific).
- Session
.txtexport in ao-loot-logger format — round-trips cleanly with other tools. - Service worker cache bumped v16 → v17.
- Recent Sales search — filter the feed by item or city.
- Shortcut hint chip on Loot Logger session view — discover keyboard shortcuts without opening the help modal.
- Bug fix:
renderRecentSalesreferenced undefinedgetItemIcon, now uses the CDN URL fallback. - Bug fix:
timeAgoexpected ISO string but WS pushes gave a ms number — normalized. - Service worker cache bumped v15 → v16.
- Profile → Loot Lifetime Stats — totals across all saved sessions + tracked tabs (sessions, events, tabs, paid, revenue, net profit).
- Copy All Trips now routes through the edit-preview modal like every other Discord copy flow.
- Tracked tab sales history — sort picker (Newest / Oldest / Highest $ / Lowest $) + per-tab CSV export.
- Service worker cache bumped v14 → v15.
- Filter chips on the captured items list (T6+/T7+/T8+/Weapons/Bags/Equipment only). Stacks with search, persists across captures.
- Per-trip Discord — the sell-plan
Copy Listbutton now opens the edit-preview modal so you can trim before sharing. - Global shortcuts: Ctrl+Shift+T Trip Summary • Ctrl+Shift+C Compare Sessions — work from any tab.
- Service worker cache bumped v13 → v14.
- Recent Sales → 📋 Discord — new button on the Loot Buyer tab copies the last 15 sales as a formatted table (item / qty / price / total) with total silver + auto-match count summary. Goes through the edit-preview modal so you can trim before sharing.
- Service worker cache bumped v12 → v13.
- Summary header at the top of tracked tabs — total tabs, Open/Partial/Sold breakdown, aggregate Paid / Revenue / Net across all tabs.
- Sort picker (Newest / Oldest / Highest profit / Lowest profit / Open first) with localStorage persistence.
- Service worker cache bumped v11 → v12.
- Loot Buyer empty-state cards — three clickable onboarding cards (capture in-game / add manually / jump to Loot Logger) replace the old flat empty message.
- Sort, filter, and chip preferences persist across reloads — the Loot Logger session view remembers your last workflow.
- Service worker cache bumped v10 → v11.
- Loot Logger mode pills — Sessions / Upload / Accountability now pill-style with badge counts (
Sessions (12),Accountability (3)). - Landing cards — empty state shows three onboarding cards: 🎮 Start a live session · 📥 Upload a log · ✓ Run accountability.
- Bounded live queue — live sessions capped at 10k events with save warnings at 9k to prevent runaway memory.
- Price-map memoization — same session re-rendered (filter toggles, sorts) no longer refetches prices. 5-min TTL cache.
- Service worker cache bumped v9 → v10.
- ⚖ Compare Sessions in the Loot Tools dropdown — pick two saved sessions, see events / items / players / deaths / duration / value side-by-side with gain/loss deltas + top looters per side.
- 📌 Favorite items — items in any of your Favorites lists now show a pin badge on both Loot Logger and Loot Buyer item rows.
- Global drop zone — drag a .txt loot log anywhere on the page and a full-screen drop target appears. Files import into Loot Logger automatically.
- Service worker cache bumped v8 → v9.
- 📊 Trip Summary in the Loot Tools dropdown — cross-feature dashboard with 24h / 7d / all-time window picker pulling sessions, tracked tabs, revenue, and recent sales.
- ▼ Why? on BUY/MAYBE/SKIP verdicts — expands to plain-language reasoning about spread, risk, best city, and bottom-line outcome.
- 💰 Sale cross-reference — Loot Logger item rows flag when a matching item shows up in your Recent Sales feed post-pickup.
- Service worker cache bumped v7 → v8.
- 💡 Auto-name button next to the session label — suggests names like
Alpha vs Evil · Apr 16from detected guild + top enemy + first-event date. - Inline session rename — clicking ✏️ on a saved session now edits in-place. Enter saves, Esc cancels.
- Copy preview modal — every Copy-to-Discord flow (session templates, death reports, accountability, regear) now shows a preview you can edit before the text hits your clipboard.
- Service worker cache bumped v6 → v7.
- Heatmap timeline above session player cards — visual density of events over time with 💀 markers on deaths.
- Friendly-fire badge 🤝 on rows where looter and victim share a guild. Pink left border too.
- Top-value ⭐ on the priciest item in each player card (>10k silver).
- Keyboard shortcuts: E expand all, C collapse all, F focus search, W whitelist, ? help.
- Service worker cache bumped v5 → v6.
- Death tracking: every session view now has a Deaths section above the player cards showing who died, to whom, when, and estimated silver recovered off the corpse. Click Filter to narrow to one death's loot chain, or 📋 Discord to copy a formatted report.
- Crafter attribution: hover any chest-captured item to see who crafted it. For pure loot drops, still shows "Unknown — looted" (game protocol limitation).
- Cross-feature shortcuts: session → accountability, accountability suspects → Loot Buyer (value missing items), chest capture → track directly (skip Phase 1 eval).
- Whitelist presets: one-click "My guild only", "My alliance only", "Just me" in the whitelist modal — auto-detected from the current session.
- Item filter chips: multi-select T6+ / T7+ / T8+ / Weapons / Bags / >100k above the session view. Tier chips are exclusive, category chips stack.
- Discord copy templates: session Copy dropdown gets GvG Summary / Top Looters / Deaths Report. Accountability Copy gets a new Regear Report template.
- Service worker cache bumped v4 → v5. Hard refresh if needed.
- New "Loot Tools" nav group: Loot Buyer and Loot Logger promoted out of Trading into their own top-level menu.
- Bigger, readable icons: preview strip 22→32 px, expanded item rows 28→40 px, Loot Buyer grid 24→40 px. Preview strip caps at 10 with `+N` overflow.
- Hover tooltips: rich cards show item name, tier, enchantment, quality, market value, and crafter (on chest captures). For pure loot drops, shows "Unknown — looted" honestly rather than hiding the field (game doesn’t include crafter in loot packets).
- Session overview strip: events, players, items looted, est. value, deaths, duration at the top of every session view.
- Color-coded player cards: green border for friendly guild, red for enemy loot source, grey for unknown.
- Mobile & a11y: new 420 px breakpoint, always-visible touch-friendly remove button, ARIA labels on every icon button, `Esc` closes the whitelist modal.
- Service worker cache bumped v3 → v4. Hard refresh once if you see stale UI.
- Loot Logger: name your live sessions and rename saved ones; optional player/guild/alliance whitelist filters events you care about; opt-in auto-save writes a localStorage draft every 5 min so a crashed tab doesn’t lose data.
- CSV Exports everywhere: Transport, Live Flips, Crafting, and Arbitrage now have an Export CSV button that respects the current filters. Portfolio export was already live.
- 🔮 Upgrade Flips: new button on the Market Flipper tab finds enchantment upgrades (@0→@1, @1→@2, …) where the higher-enchant sell price covers buy price + estimated rune/soul/relic cost + 5.5% sell-order tax. Upgrade material costs are tier-banded ballparks — verify rune prices in-game before committing silver.
- Service worker cache bumped v2 → v3 so returning users pick up the new app.js on next load. Hard refresh (Ctrl+Shift+R) once if you see stale UI.
- Ctrl+K Search: Instantly search items, tabs, and features from anywhere
- In-Game Timers: Daily reset & monthly countdown widget (bottom-right corner)
- PWA Install: App is now installable on desktop and mobile
- Loot Logger: Suspects banner with missing silver, Copy to Discord, proportional deposit matching, alliance-based enemy detection, item tier filters, Expand/Collapse All, drag-and-drop multi-file upload, remove players from view
- Death Items: Items lost on death shown with red outline + "Lost on Death" label (not counted as stolen)
- Deep Linking: Shareable URLs with ?tab=, ?item=, ?from=, ?to= params
- Password Reset: Forgot your password? Email-based recovery now available
- Consumed Flips: Mark flips as taken so you don't chase stale opportunities
- Go Client v0.7.0: Memory leak fixes (cache eviction), thread-safe state, --config-dir flag
- Backend Hardening: Discord bot health monitor, NATS retry, request timeouts, audit logging, email masking
- Critical: April 13 game patch changed the network protocol — older clients will crash. Download v0.6.0 from GitHub Releases.
- Full Protocol18 decoder — zigzag varint, compressed integers, little-endian shorts, zero-value types
- All features confirmed working: chest capture, mail tracking, market data, loot logger, death events
- Auto sale detection — Go client reads marketplace sale mails and relays to VPS in real-time
- Auto-match to tracked loot tabs — sales automatically recorded against matching open tabs
- Recent Sales feed on Loot Buyer tab — last 10 sales with item, price, and match status
- Toast notifications when items sell while the website is open
- Fixed chest capture after game update (int16 overflow in slot IDs)
- Item icon preview in each player header — see at a glance what someone looted without expanding the card
- Guild color grouping — same-guild players share a matching border and guild name color
- Click any item row to jump to Market Browser with that item searched
- Search bar on loot session results — filter by player name, guild, or item name with live results count
- Sort players by Value, Items, Weight, or Name A-Z
- Sessions tab no longer hangs on “Loading sessions…” when not logged in — shows instant message with upload mode hint
- Network errors show a Retry button instead of a misleading “Login required” message
- Switching the Server dropdown (Europe / Americas West / Asia East) now correctly clears and reloads prices — stale prices from the previous server are immediately removed
- Market Browser re-renders instantly with fresh data after switching; other scan tabs update when you re-run your scan
- Background price refresh no longer overwrites your cache with Europe data when you are browsing a different server
- Live Session toolbar with Start/Stop toggle, Save, and New Session buttons — events only accumulate while active
- Redesigned player cards with avatar, per-player item count, estimated silver value, and weight at a glance
- Item rows now show icons, quantity, estimated value (Caerleon-preferred price cache), and weight
- Accountability tab: explicit "Start/Stop Capturing Chests" toggle with pulsing indicator; captured tabs shown as chips
- Accountability coloring in-place: green = deposited, red = missing, yellow = partial, gray = died with
- Deposit progress bar on each player card in accountability mode
- Death event support:
death-eventfrom Go client marks player's items as "died with" (gray)
- Discord login no longer breaks during background database jobs — a dedicated read-only connection now handles login checks so they never queue behind bulk writes
- Login survives temporary VPS slowdowns: if the server is momentarily unreachable, your saved session is used automatically without showing an error
- Login check timeout increased from 5s to 8s with one automatic retry
- Expanded title tag with targeted keywords for Albion Online market search rankings
- Richer meta description covering all major tool features
- Added Open Graph tags for Discord/social media link previews
- Added Twitter Card tags for Twitter/X link previews
- Added JSON-LD structured data (WebApplication schema) for Google rich results
- Added inline SVG favicon — site now shows a chart icon in browser tabs
- Added
robots.txtandsitemap.xml - Added
rel="canonical",meta robots, andmeta keywords - Added
preconnecthint for Google Fonts static assets
- Analytics chart now shows EMA 7d and VWAP lines alongside SMA for better price analysis
- Stale data badges on Market Flipper cards — red warning when prices are 6+ hours old
- Toast notifications replace all popup alerts — non-blocking, auto-dismiss
- Cross-feature links: “Craft?” button on flip cards, “Flips” button on browser cards
- Faster Market Browser — price data cached for 30 seconds between page flips and filters
- Fixed analytics engine, Loot Buyer sale form names, and security hardening
- New Loot Logger tab — view live loot events from the client or upload log files from ao-loot-logger
- Per-player breakdown: who looted what, with guild info, item icons, and quantities
- Accountability Check — cross-reference loot pickups vs chest deposits to see who deposited and who didn’t
- Item weight data from game files now shown across the website — Market Browser cards, Transport haul plans, Loot Buyer captures and sell plans
- Transport haul summary now shows total weight vs mount capacity
- You can now delete tracked loot tabs you no longer need
- Chest/vault scanning now fully working — open any chest and all tab contents are captured with correct item names, quantities, and weights
- Added item weight data (11,235 items) — per-item and total tab weight shown in captures
- Now captures 6 item types: equipment, stackables, journals, furniture, mounts, kill trophies, and laborer contracts
- Updated item database to latest game version (11,963 items)
- Fixed Discord login appearing broken when SpreadStats was running — a 90-second database query was blocking all user-facing requests including
/api/me - SpreadStats now uses a separate database connection so background bulk writes never block the login flow
- Analytics and SpreadStats now check each other’s state before starting to prevent simultaneous heavy DB runs
- Mammoth weight corrected: 1,696 kg → 1,764 kg
- Mounts only add carry weight — no extra inventory slots; slot limit is always your “Free Slots” input
- “No Mount” now uses 600 kg base weight instead of ignoring weight entirely
- Carry capacity info line below the mount dropdown updates live on selection change
- Changing the mount immediately re-renders results without a full rescan
- Chart modal now has Live Prices / Analytics tabs — Analytics tab shows our own historical price line with SMA 7-day (gold) and SMA 30-day (blue) overlays. Updates when you switch cities.
- Market Flipper & BM Flipper cards now show a small trend arrow badge (▲ green if +2%, ▼ red if −2%, — neutral) loaded from our analytics engine
- Market Flipper, BM Flipper & Transport cards show an orange Volatile badge when a route is profitable less than 50% of the time — warns against deals that look good on average but swing wildly
- New price_analytics table stores pre-computed SMA 7d/30d, EMA 7d, VWAP 7d, price trend, and spread volatility per item+city+quality — computed every 30 minutes
- New price_hourly OHLC table (open/high/low/close + volume) holds hourly data from 7–30 days old
- Three-tier data retention: raw hourly → price_hourly (7d) → daily (30d) → forever
- New GET /api/analytics/:itemId endpoint returns all pre-computed metrics with optional city/quality filters
- GET /api/price-history now returns
{ history, ohlc, analytics }— OHLC data and moving averages alongside the historical price series - Disk safety: checkDiskUsage() runs every 2 hours — auto-reduces raw retention to 3 days at 10 GB, 1 day at 20 GB
- Admin endpoint GET /api/admin/db-stats (JWT-protected): DB size, row counts per table, oldest/newest timestamps
- Node heap raised to 6 GB to match new Contabo VPS 20 (11 GB RAM, 6 vCPUs)
- Spread stats engine rewritten: SQL GROUP BY aggregation replaces loading 1M+ rows into memory — drastically lower memory usage per hourly run
- Composite SQLite indexes added on price_averages and spread_stats for faster query times
- WAL checkpoint (TRUNCATE) every 6 hours to prevent WAL file bloat
- Conditional VACUUM after large compaction runs — scheduled for 2–4 AM UTC low-traffic window to reclaim disk space
- Market tax corrected to 3% (insta-sell) + 2.5% setup fee (sell orders) = 5.5% combined — was incorrectly 6.5% everywhere
- Crafting station fee now calculated on item sell price (item value), not material cost — matches Albion Online mechanics
- Profit labels updated: crafting shows "Tax+Setup (5.5%)", transport insta-sell shows "Tax (3%)", transport sell orders show "Tax+Setup (5.5%)"
- Portfolio Net P/L tax estimate corrected to 5.5% for sell orders
- RRR formula verified: 15.2% base in royal city (18% PB), focus bonus (59% PB flat) — all within correct range
- Reduced live flip false positives — tighter Black Market freshness, global price outlier check
- Portfolio Tracker XSS hardened — safe rendering of localStorage data
- Mobile responsive fixes for Loot Buyer, sale form, and sell plan
- New Data Client section in About tab — setup guide and AODP comparison
- Add items manually without the game client — search by name, set quality and quantity
- Use with Buy Decision or Sell Optimizer analysis, same as auto-captured chest data
- Suggested travel route based on Royal Continent geography when selling across multiple cities
- Negative item IDs (silver, gold, fame credits, etc.) now show proper names instead of "UNKNOWN_-6"
- Internal/currency items are filtered from chest captures — only tradable items shown in loot analysis
- Replaced browser prompt() dialogs with an inline form for recording sales on tracked loot tabs
- Item dropdown populated from tab contents, auto-fills quantity, preserves quality
- New floating feedback button (bottom-right) opens a modal to submit bug reports or suggestions
- Submissions are delivered to Discord via webhook; rate-limited to 1 per minute per user/IP
- Max Age dropdown was not visible on page load due to missing initial state sync — fixed
- New My Tracked Tabs section — saved tabs show paid, revenue, net profit, and a progress bar
- "I Bought This" button appears after any loot analysis — saves tab + purchase price to your account
- Manual sale recording per tab — record each item sold with quantity and price per unit
- Per-tab status badges: Open / Partial / Sold — update manually from the expanded detail view
- DB tables:
loot_tabsandloot_tab_sales— full purchase history per user
- City trip grouping — items grouped by best sell destination, sorted by total value
- 85% instant/market threshold — instant sell preferred unless listing earns >15% more
- Per-item Instant/Market badges with price/ea and total silver columns
- Copy List per trip and Copy All Trips buttons with human-readable clipboard output
- Loot tab evaluation: instant vs patient-sell value across all cities
- BUY / MAYBE / SKIP verdict with margin % when asking price is set
- Risk badges per item: no data, no buy orders, stale data, low liquidity
- Auth-aware: shows login prompt instead of 401 error
- Email verification system — verification emails with branded template, auto-verify when SMTP not configured
- User Profile page — view stats, change username, change password, link/unlink Discord
- Same-city instant flips — detect profitable buy order > sell offer spreads within the same city
- Enhanced Live Flips filters — city filter, flip type filter (Transport vs Instant), sound alerts, desktop notifications
- Flip stats bar showing count and total potential silver
- Flip buffer doubled to 200 for richer history
- New email/password registration — create an account without Discord to unlock premium features
- Live Flips tab — real-time profitable flip opportunities detected from the market stream
- Live flips gated behind free registration — create an account to access
- Discord bot /setup_alerts now requires a registered website account
- Link your Discord account to your email account for unified features
- Fixed haul plan cards collapsing when clicking refresh buttons
- Discord bot alerts are now firing — fixed stale freshness dates that silently blocked all alerts
- Alert threshold lowered from 500k to 50k — 100x more routes now qualify for alerts
- Transport haul plans now pack 3+ items per trip (two-pass algorithm with 40% per-item budget cap)
- Collapsible haul plan cards with item thumbnails, profit, ROI, and freshness at a glance
- Copy Shopping List button — clipboard-friendly list for each haul plan
- Refresh buttons on every haul plan item + Refresh All for the entire plan
- Buy/sell prices shown with freshness dots and time ago on every item row
- Free Slots input — set your actual available inventory slots (not hardcoded 48)
- Backend query optimization: 10-50x faster transport route API via CTE
- Migrated to new high-performance VPS (6 CPU / 12 GB RAM) — was hitting 100% CPU on old server
- Eliminated price_snapshots table (22M rows) — NATS data writes directly to price_averages
- Accurate spread calculation using min_sell/max_buy instead of averaged prices
- SQLite WAL mode for better write concurrency
- Discord login fully working again after event loop starvation fix
- New domain: albionaitool.xyz (replaces slow nip.io wildcard DNS)
- Discord login rewritten for reliability — no more infinite "Redirecting..." spinner
- Server stays responsive during background market scans
- Live sync WebSocket now uses the new domain
- XSS hardening: all user-facing data now escaped before rendering
- Market Flipping rescan fix: changing filters and rescanning works correctly now
- Server memory optimization: automatic cleanup of old analytics data
- Gear weight system: calculates real item weight from tier & slot type
- Mount carry weight selector (T3 Ox to Saddled Mammoth)
- Respects 48 inventory slots, daily sell volume, and budget
- Haul Plans: groups items per trip to maximize budget usage
- Shows limiting factor per item (weight/volume/slots/budget)
- Added empty-state hints to all new tabs (no more blank screens)
- Fixed missing UI elements: spinners, error messages, mount type filter
- Fixed RRR Calculator rendering and auto-calculation on load
- Improved Item Power and Mounts filtering/sorting options
- Reorganized 19 tabs into 4 dropdown groups: Market, Crafting, Trading, Game Tools
- Cleaner navigation with dropdown menus and chevron indicators
- Mobile-friendly responsive dropdowns
- BM Flipper: dedicated Black Market flipping tool with profit/confidence scoring
- Journals Calculator: all 10 labourer types, T3-T8, with buy-empty/sell-full profit
- RRR Calculator: resource return rate with spec, city, and focus breakdown
- Repair Cost Calculator: estimate repair costs for any item by tier/enchant/quality
- Item Power Checker: compare IP vs price for best silver-per-IP value
- Favorites: save custom item lists with cross-city price comparison
- Mounts Database: browse all mounts with live prices by type
- Top Traded Items: ranked by 7-day volume from Charts API
- Portfolio Tracker: trade journal with FIFO P/L and CSV export
- Farm & Breed Calculator: crop, herb, and animal profit analysis
- Builds Browser: community builds from AlbionFreeMarket API
- Crafting upgrades: save/load setups and shopping list
- VPS now scans Europe server (was incorrectly scanning Americas West)
- Junk price filtering: skips placeholder listings like 999,999 silver orders
- 10x more spread stats loaded (2,000 vs 200) for better confidence coverage
- Auto server detection: website matches the VPS game server automatically
- New Transport tab for mammoth runs and bulk hauling between cities
- Budget-based calculations: enter your silver to see units and trip profit
- Transport Score ranking: profit x daily volume for best bulk routes
- 5 sort modes, city filters, and confidence integration
- Black Market default as sell target
- New About tab with features overview and simplified changelog
- Fresh filter upgraded: filter by Buy From fresh, Sell To fresh, or Both
- Added Community tab with leaderboard showing top scanners
- Tier system: Bronze, Silver, Gold, Diamond based on 30-day scan activity
- Discord commands:
/scan,/leaderboard,/mystats - Every item refresh now contributes to your rank
- Discord alerts now show confidence scores and reliability ratings
- Color-coded embeds based on confidence level
- Filter alerts by minimum confidence with
/setup_alertsand/set_confidence
- Server scans every 5 minutes for all 11,000+ items
- Live NATS stream with 1,000+ real-time player orders per minute
- 28-day Charts API historical backfill for confidence scoring
- History API integration for 6-hour granularity price averages
- Confidence scores for every trade route based on 7-day spread analysis
- Sort flips by confidence, profit, or ROI
- Filter by minimum confidence threshold
- "Fresh Only" toggle to prioritize recently updated prices
- Market Browser with search, filters, and pagination
- City Comparison tool with price charts
- Crafting profit calculator with material cost breakdown
- Discord OAuth login and bot integration
- Live WebSocket sync from NATS stream
- Black Market flipping support
👥 Community Contributors
Everything you do on the site counts — market scans, loot sessions, chest captures, sale recording, accountability checks, transport plans, crafting calcs. Rankings are based on your combined Activity Score (last 30 days).
How Activity Score is calculated
🏆 Top Contributors (30 Days)
No scanning activity yet
Be the first to contribute by refreshing item prices!
Contribution Stats (last 30 days)
📦 Loot Lifetime Stats
Totals aggregated from your saved loot sessions and tracked loot-buyer tabs.
Account Settings
Paste this in your client's config.yaml (token: "…"). Keep it secret.
🧰 Set up the Coldtouch Data Client
Capture chests, track your loot, and power Loot Buyer, Loot Logger, and Live Flip alerts from inside your Albion session.
⬇ Windows / macOS / Linux builds
config.yaml next to the client: token: "paste-here". An example file ships with the download.🔋 Guild Syphon Check
Paste the in-game Siphoned Energy log. Players who withdrew more than they deposited get flagged. Generates a Discord-ready summary you can copy.
▸ Everyone (deposits ≥ withdrawals)
📋 Routine Reports
Output from scheduled cloud routines (Daily Health Sweep, Weekly Audits, etc.). Click a row to expand the full markdown.
Loading…
🔨 Craft Runs
Track full buy → refine → craft → sell cycles. Log costs and revenue in one place.
No craft runs yet. Click + New Run to start tracking your first buy → craft → sell cycle.
Add Transaction
📦 Attach Chest Capture
Pick a chest capture to log as a bulk buy. Cost will be split across all items by quantity.
No captures available. Open a chest in-game first — the custom client pushes captures to the Loot Buyer tab.
Loot Buyer
Evaluate guild loot tabs before buying. Run the Coldtouch Data Client while playing — open a chest and items appear here automatically. Or analyze manually.
How Trade Tracking Works
Chest Capture: Open any chest in-game — items appear here instantly.
Insta-Buy Tracking: Browse an item on the marketplace first, then buy it. The client caches orders when you view them, so it knows what you bought.
Sell Order Tracking: When you list a sell order, the client captures the item and price automatically.
Sale Notifications: When your listing sells, open your mailbox and click the sale mail — the client reads it and records the sale.
Insta-Sell (not trackable): Selling to a buy order generates no packet and no mail. To keep your Loot Buyer tab tracking accurate, always list sell orders instead of insta-selling.
No chest captures yet. Pick how you want to get started:
Selected Items (0)
My Tracked Tabs
No tracked tabs yet. Analyze a loot tab then click I Bought This to start tracking.
Loot Logger
Track who looted what during PvP/PvE. Start a live session with the Coldtouch client, or upload a log file. Run the Accountability Check to cross-reference pickups against chest deposits.
Loading sessions...
Upload a .txt file from the ao-loot-logger.
Format: timestamp;alliance;guild;name;item_id;item_name;qty;from_alliance;from_guild;from_name
Chest Captures
Open a chest in-game with the Coldtouch client running to record its contents.
Chest Log Captures VERIFICATION
Open the Log tab inside any chest in-game — the client captures deposit/withdraw records used to cross-check what people picked up.
⚠ Requires the View Chest Logs permission on your guild role (typically Officer+). Members without it won't see a Log tab in the chest UI — ask a guild leader to enable the permission.
Run Accountability Check
Select a loot session (who picked up what) and chest captures (what was deposited), then compare.