From 4e0bc2dfadae75f58c2bc8f6b4884f4fd1fb366f Mon Sep 17 00:00:00 2001 From: Caesar Mukama Date: Mon, 9 Mar 2026 14:16:05 +0300 Subject: [PATCH 01/10] chore: record asana comments snapshot --- bugs-plan.md | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++ comments.md | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 bugs-plan.md create mode 100644 comments.md diff --git a/bugs-plan.md b/bugs-plan.md new file mode 100644 index 0000000..d23cd5d --- /dev/null +++ b/bugs-plan.md @@ -0,0 +1,80 @@ +# Asana Comment Bug Fix Workflow + +You are tasked with processing Asana tickets, reading their comments (including attachments), fixing the issues described, and creating a single PR that addresses everything. + +## Inputs + +Asana ticket URLs: +- [PASTE YOUR LINKS HERE] + +## Workflow + +### Step 1: Extract task GIDs +From each Asana URL, extract the task GID (the last numeric segment of the URL, e.g. `https://app.asana.com/0/1234567/8901234` → GID is `8901234`). + +### Step 2: Fetch comments via curl +For each task GID, run: + +```bash +curl -s "https://app.asana.com/api/1.0/tasks/{task_gid}/stories?opt_fields=text,created_by.name,created_at,resource_subtype,html_text" \ + -H "Authorization: Bearer $ASANA_PAT" +``` + +Filter results to only `resource_subtype: "comment_added"`. Parse out the comment text and who wrote it. + +### Step 3: Fetch attachments +For each task, also fetch attachments: + +```bash +curl -s "https://app.asana.com/api/1.0/tasks/{task_gid}/attachments?opt_fields=name,download_url,resource_type" \ + -H "Authorization: Bearer $ASANA_PAT" +``` + +Download any relevant attachments (screenshots, files) to understand the issue. For images, describe what you see if relevant to the bug. + +### Step 4: Fetch task details via Asana MCP +Use the Asana MCP `get_task` tool to get the task title, description, and assignee for additional context. + +### Step 5: Triage and plan +For each ticket, based on comments and attachments: +1. Identify what is being asked/reported +2. Classify as: **fixable** (code change needed) or **out of scope** (design decision, external dependency, not a bug, needs product input, etc.) +3. For fixable items, identify the relevant files and what needs to change + +Present the triage plan and wait for my confirmation before proceeding. + +### Step 6: Implement fixes +- Create a single branch named `fix/asana-comment-fixes-{date}` +- Make all fixes across the codebase +- Keep commits atomic — one commit per Asana ticket, with the commit message referencing the ticket: `fix: [brief description] (Asana: {task_url})` + +### Step 7: Create the PR +Create one PR with: +- **Title:** `fix: address review comments from Asana tickets` +- **Body:** a table summarizing each ticket: + +| Ticket | Title | Status | Resolution | +|--------|-------|--------|------------| +| [link] | ... | ✅ Fixed / ⏭️ Out of scope | 1-2 sentence explanation | + +### Step 8: Comment back on Asana tickets +For each ticket, use curl to post a comment back: + +```bash +curl -s -X POST "https://app.asana.com/api/1.0/tasks/{task_gid}/stories" \ + -H "Authorization: Bearer $ASANA_PAT" \ + -H "Content-Type: application/json" \ + -d '{"data":{"text":"..."}}' +``` + +The comment should follow this format: +- **If fixed:** "Addressed in PR: {pr_url} — {1-2 sentence description of what was changed}" +- **If out of scope:** "Marking as out of scope for this pass — {concise reason}. Will revisit in a follow-up if needed." + +## Rules +- Do NOT guess at fixes. If a comment is ambiguous, ask me before implementing. +- Prefer minimal, targeted changes. Don't refactor unrelated code. +- If an attachment (e.g. screenshot) shows a visual bug, describe what you see and your proposed fix before implementing. +- Ensure all existing tests pass. Add tests if the fix warrants it. +- If a comment thread has back-and-forth, use the **latest consensus** as the source of truth. +- Before using this, make sure you have your Asana Personal Access Token set as an environment variable (`export ASANA_PAT=your_token`). You can generate one from **Asana → My Settings → Apps → Developer Apps → Personal Access Tokens**. \ No newline at end of file diff --git a/comments.md b/comments.md new file mode 100644 index 0000000..1e01c9b --- /dev/null +++ b/comments.md @@ -0,0 +1,77 @@ +# Asana Ticket Comments +_Generated: 2026-03-09_ + +--- + +## GET /auth/site/status/live — [1213140752769899](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213140752769899) +**Assignee:** Caesar Mukama +**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing + +### Comments +| # | Author | Date | Comment | +|---|--------|------|---------|- +| 1 | Parag More | 2026-02-12T07:22:43.450Z | PR: https://github.com/tetherto/miningos-app-node/pull/4 | +| 2 | Unknown | 2026-02-18T09:54:45.678Z | this endpoint is ready for FE review, please sync to proceed to review if it meets FE expectations and with the OWASP security review (integration blocked until after Georgia deployment). | +| 3 | Roberto Dilillo | 2026-02-23T11:24:50.892Z | Summary Verdict — Area Rating Notes: Security Good — Auth works, Cloudflare WAF helps, CORS locked down. Fix the missing Cache-Control, add rate limiting, clean up duplicate headers. FE Readiness Partial — Good data shape for mining metrics, but does NOT fully replace the other header requests (missing site name). The hashrate utilization at 892% and power nominal at 0 are data quality red flags. Response Design Needs Work — Missing units, no data health indicators, no low/info alert levels, timestamp format is ambiguous, excessive float precision. | +| 4 | Unknown | 2026-03-03T12:52:58.129Z | please review with a focus on incorrect API calls, data aggregation issues, and anything else that could affect the feature. | +| 5 | Unknown | 2026-03-03T12:53:20.958Z | this endpoint has passed internal testing by BE team and is ready for FE review. While the endpoint is in Product Design section, please proceed to review if it meets FE expectations and with the OWASP security review. Once you give the greenlight, please move the ticket to Under Estimation and then to In Progress for the integration. | +| 6 | Caesar Mukama | 2026-03-07T15:41:00.717Z | Great, thanks for the review | + +### Attachments +_None_ + +--- + +## GET /auth/alerts/site — [1213140752769902](https://app.asana.com/1/45238840754660/project/1213238597612203/task/1213140752769902) +**Assignee:** Caesar Mukama +**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing + +### Comments +_No comments_ + +### Attachments +_None_ + +--- + +## GET /auth/miners — [1213140752769906](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213140752769906) +**Assignee:** Parag More +**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing + +### Comments +| # | Author | Date | Comment | +|---|--------|------|---------|- +| 1 | Parag More | 2026-02-18T16:42:27.644Z | I have already made some progress on this. Reassigning to myself, will raise PR tomorrow | +| 2 | Parag More | 2026-02-18T16:42:41.582Z | CC: (tagged user) | +| 3 | Parag More | 2026-02-19T13:06:45.006Z | PR: https://github.com/tetherto/miningos-app-node/pull/13 | +| 4 | Parag More | 2026-02-26T14:07:51.629Z | (tagged user) has suggested to create a new subtask and working on it. We can mark it ready for review again after this is implemented. Slack thread: https://tether-to.slack.com/archives/C09T82CH0QG/p1771858738736529?thread_ts=1771506426.046169&cid=C09T82CH0QG | +| 5 | andreu.honzawa@tether.to | 2026-03-03T12:47:21.995Z | (tagged user) has almost completed the subtask, the api is already in review and has review comments. | + +### Attachments +_None_ + +--- + +## GET /auth/containers — [1213140752769908](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213140752769908) +**Assignee:** Roberto Dilillo +**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing + +### Comments +| # | Author | Date | Comment | +|---|--------|------|---------|- +| 1 | andreu.honzawa@tether.to | 2026-03-03T15:01:48.761Z | https://github.com/tetherto/miningos-app-node/pull/25 | + +### Attachments +_None_ + +--- + +## GET /auth/metrics/containers/:id — [1213140752769910](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213140752769910) +**Assignee:** Caesar Mukama +**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing + +### Comments +_No comments_ + +### Attachments +_None_ From 7d707388e87697ae591fa198a8fe6b5ca637c9c9 Mon Sep 17 00:00:00 2001 From: Caesar Mukama Date: Mon, 9 Mar 2026 14:24:07 +0300 Subject: [PATCH 02/10] chore: record asana comments snapshot --- comments.md | 290 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 257 insertions(+), 33 deletions(-) diff --git a/comments.md b/comments.md index 1e01c9b..c1bd7ee 100644 --- a/comments.md +++ b/comments.md @@ -1,77 +1,301 @@ # Asana Ticket Comments -_Generated: 2026-03-09_ +_Generated: 2026-03-09 14:24:03_ --- -## GET /auth/site/status/live — [1213140752769899](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213140752769899) -**Assignee:** Caesar Mukama +## GET /auth/metrics/miners/status — [1213140752769914](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213140752769914) +**Assignee:** Caesar Mukama +**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing + +### Comments +_No comments._ + +### Attachments +_No attachments._ + +--- + +## GET /auth/metrics/power/mode — [1213140752769922](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213140752769922) +**Assignee:** Caesar Mukama +**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing + +### Comments +_No comments._ + +### Attachments +_No attachments._ + +--- + +## GET /auth/metrics/power-mode/timeline — [1213140752769920](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213140752769920) +**Assignee:** Caesar Mukama +**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing + +### Comments +| # | Author | Date | Comment | +|---|--------|------|---------| +| 1 | Caesar Mukama | 2026-02-20 | PR: https://github.com/tetherto/miningos-app-node/pull/21 | +| 2 | Roberto Dilillo | 2026-03-05 | The limit parameter is:
Documented in the endpoint spec (default 10080)
Accepted by the schema (though not explicitly declared — not validated)
Included in cache key (req.query.limit) — different limit values create separate cache entries
NOT used in the handler — never passed to the RPC payload, never used to truncate results

// Handler (metrics.handlers.js:378-405)
async function getPowerModeTimeline (ctx, req) {
  const now = Date.now()
  const star... | +| 3 | Roberto Dilillo | 2026-03-05 | not deployed, tested locally | + +### Attachments +_No attachments._ + +--- + +## GET /auth/metrics/temperature — [1213145436151980](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436151980) +**Assignee:** Caesar Mukama +**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing + +### Comments +| # | Author | Date | Comment | +|---|--------|------|---------| +| 1 | Caesar Mukama | 2026-02-20 | PR: https://github.com/tetherto/miningos-app-node/pull/21 | +| 2 | Roberto Dilillo | 2026-03-05 | this might be a Staging only issue:
"maintenance" Container with Zero Temperatures
Live response includes a container named maintenance with maxC: 0, avgC: 0 across all time points. This appears to be a miner status category leaking into the container namespace via temperature_c_group_max_aggr keys. It's not a physical container — it's miners in maintenance mode being grouped as a "container".
Impact: The FE would show a maintenance entry in the temperature chart with a flat line at 0°C... | +| 3 | Roberto Dilillo | 2026-03-05 | Backend Implementation Review & Improvement Suggestions
A. Filter out non-physical containers
The maintenance group appears because miners in maintenance mode have their keys grouped under temperature_c_group_max_aggr. Add a filter:
const EXCLUDED_CONTAINERS = new Set(['maintenance'])

for (const [name, maxVal] of Object.entries(maxObj)) {
  if (EXCLUDED_CONTAINERS.has(name)) continue
  if (containerFilter && name !== containerFilter) continue
  // ...
}
Or better: ... | +| 4 | Roberto Dilillo | 2026-03-05 | #
Issue
Severity
Effort
Recommendation
1
maintenance container in results skews site average
MEDIUM
Low
Filter out zero-temp containers from siteAvgC calculation
2
Missing Cache-Control header
MEDIUM
Low
Add Cache-Control: no-store
3
Missing X-Content-Type-Options: nosniff
MEDIUM
Low
Add server-wide
4
No capCheck on operational data
LOW-MEDIUM
Low
Add metrics:read permission
5
Response key log/summary vs spec data
L... | + +### Attachments +_No attachments._ + +--- + +## GET /auth/metrics/containers/:id/history — [1213145436151986](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436151986) +**Assignee:** Caesar Mukama +**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing + +### Comments +_No comments._ + +### Attachments +_No attachments._ + +--- + +## GET /auth/finance/revenue — [1213145436151978](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436151978) +**Assignee:** Caesar Mukama +**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing + +### Comments +| # | Author | Date | Comment | +|---|--------|------|---------| +| 1 | Caesar Mukama | 2026-02-19 | PR: https://github.com/tetherto/miningos-app-node/pull/15 | +| 2 | Parag More | 2026-02-26 | https://app.asana.com/1/45238840754660/profile/1209203898446158I dont think this one is merged Please attach correct PR | + +### Attachments +_No attachments._ + +--- + +## GET /auth/finance/revenue-summary — [1213145436151984](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436151984) +**Assignee:** Caesar Mukama +**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing + +### Comments +| # | Author | Date | Comment | +|---|--------|------|---------| +| 1 | Caesar Mukama | 2026-02-19 | PR: https://github.com/tetherto/miningos-app-node/pull/16 | +| 2 | Parag More | 2026-02-26 | https://app.asana.com/1/45238840754660/profile/1209203898446158I dont think this one is merged Please attach correct PR | + +### Attachments +_No attachments._ + +--- + +## GET /auth/finance/ebitda — [1213145436151990](https://app.asana.com/1/45238840754660/project/1213238597612203/task/1213145436151990) +**Assignee:** Caesar Mukama +**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing + +### Comments +| # | Author | Date | Comment | +|---|--------|------|---------| +| 1 | Caesar Mukama | 2026-02-12 | PR: https://github.com/tetherto/miningos-app-node/pull/5 | +| 2 | Caesar Mukama | 2026-02-15 | PR: https://github.com/tetherto/miningos-app-node/pull/11 | +| 3 | Unknown | 2026-02-17 | https://app.asana.com/1/45238840754660/profile/1209203898446158 https://app.asana.com/1/45238840754660/profile/1208374908209019 this endpoint is ready for FE review, please sync to proceed to review if it meets FE expectations and with the OWASP security review (integration blocked until after Georgia deployment). | +| 4 | Parag More | 2026-02-20 | The api is giving 0 values for all fields please verify once. The revenue should not be 0 for sure as I see revenue in revenue summay apis

{
"log": [
{
"ts": 1767225600000,
"revenueBTC": 0,
"revenueUSD": 0,
"btcPrice": 0,
"powerW": 0,
"hashrateMhs": 0,
"consumptionMWh": 0,
"energyCostsUSD": 0,
"operationalCostsUSD": 0,
"tot... | +| 5 | Parag More | 2026-02-20 | Test API Collection | +| 6 | Unknown | 2026-02-23 | https://app.asana.com/1/45238840754660/profile/1207496533136374 please review with a focus on incorrect API calls, data aggregation issues, and anything else that could affect the feature. | +| 7 | Roberto Dilillo | 2026-03-03 | CRITICAL BUG: All Fields Returning Zero
Status: CONFIRMED BY CODE — root cause identified
A peer reviewer reported that this endpoint returns all-zero data:

{
  "log": [
    { "ts": 1767225600000, "revenueBTC": 0, "revenueUSD": 0, "btcPrice": 0, ... }
  ],
  "summary": { "totalRevenueBTC": 0, "totalRevenueUSD": 0, "currentBtcPrice": 0, ... }
}


Meanwhile, the revenue-summary endpoint (legacy API) shows non-zero revenue for the same time range.
Root Cause ... | + +### Attachments +- [MiningOS_Finance_APIs.postman_collection.json](https://asanausercontent.com/us1/assets/45238840754660/1213348817875990/912a9edbacf92127e5b2fc9a1cf3bf34?e=1773057165&v=0&t=zObbwtW3krG48TxsIJ7nr787X5yGqTowoG9rY-rtp9U) + +--- + +## GET /auth/finance/energy-balance — [1213145436151976](https://app.asana.com/1/45238840754660/project/1213238597612203/task/1213145436151976) +**Assignee:** Caesar Mukama +**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing + +### Comments +| # | Author | Date | Comment | +|---|--------|------|---------| +| 1 | Caesar Mukama | 2026-02-12 | PR: https://github.com/tetherto/miningos-app-node/pull/3 | +| 2 | Caesar Mukama | 2026-02-15 | PR: https://github.com/tetherto/miningos-app-node/pull/11 | +| 3 | Unknown | 2026-02-17 | https://app.asana.com/1/45238840754660/profile/1209203898446158 https://app.asana.com/1/45238840754660/profile/1208374908209019 this endpoint is ready for FE review, please sync to proceed to review if it meets FE expectations and with the OWASP security review (integration blocked until after Georgia deployment). | +| 4 | Unknown | 2026-02-18 | https://app.asana.com/1/45238840754660/profile/1209203898446158 https://app.asana.com/1/45238840754660/profile/1208374908209019 this endpoint is ready for FE review, please sync to proceed to review if it meets FE expectations and with the OWASP security review (integration blocked until after Georgia deployment). | +| 5 | Parag More | 2026-02-20 | https://app.asana.com/1/45238840754660/profile/1209203898446158

Negative timestamps should fail but this is giving 200 response. Please run the tests for energy balance api postman collection attached here | +| 6 | Unknown | 2026-02-23 | https://app.asana.com/1/45238840754660/profile/1207496533136374 please review with a focus on incorrect API calls, data aggregation issues, and anything else that could affect the feature. | +| 7 | Roberto Dilillo | 2026-03-03 | Negative timestamps return 200 instead of 400
Status: CONFIRMED BY CODE
GET /auth/finance/energy-balance?start=-1764335313758&end=-1
Returns 200 OK. The handler's validation:

// finance.handlers.js:27-28
if (!start \|\| !end) {
  throw new Error('ERR_MISSING_START_END')
}


Negative numbers are truthy in JavaScript (!(-1764335313758) → false), so they pass. Then new Date(-1764335313758) produces 1914-02-03T10:51:26.242Z — a syntactically valid but absurd dat... | +| 8 | Roberto Dilillo | 2026-03-03 | A. Fix negative timestamp validation
// Current (finance.handlers.js:27-33)
if (!start \|\| !end) {
  throw new Error('ERR_MISSING_START_END')
}
if (start >= end) {
  throw new Error('ERR_INVALID_DATE_RANGE')
}

// Improved
const MIN_TS = 1000000000000 // ~2001-09
const MAX_RANGE_MS = 2 * 365 * 86400000 // 2 years

if (!Number.isInteger(start) \|\| !Number.isInteger(end) \|\| start < MIN_TS \|\| end < MIN_TS) {
  throw new Error('ERR_INVALID_TIMESTAMP')<... | +| 9 | Roberto Dilillo | 2026-03-03 | 5. Priority Remediation Matrix

#
Issue
Severity
Effort
Recommendation
1
Negative timestamps accepted (200)
HIGH
Low
Add start < MIN_TS validation
2
Duplicate electricity RPC call
MEDIUM
Low
Single call, extract both fields
3
Math.abs inflates revenue
MEDIUM
Low
Filter positive values or track credits/debits separately
4
Per-MWh ratios summed in aggregation
MEDIUM
Low
Recalculate ratios post-aggregation
5
No rate... | + +### Attachments +- MiningOS API v2 — Backend Endpoint Analysis +- [MiningOS_Finance_APIs.postman_collection.json](https://asanausercontent.com/us1/assets/45238840754660/1213348817875983/cd82ced7918a6dc91bd01e9034b60b8f?e=1773057165&v=0&t=2rVaLT0HvT0mffkKXnwpFLXof3un8h4Tlp7OFx2aAqQ) + +--- + +## GET /auth/finance/cost-summary — [1213145436151992](https://app.asana.com/1/45238840754660/project/1213238597612203/task/1213145436151992) +**Assignee:** Caesar Mukama +**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing + +### Comments +| # | Author | Date | Comment | +|---|--------|------|---------| +| 1 | Caesar Mukama | 2026-02-12 | PR: https://github.com/tetherto/miningos-app-node/pull/6 | +| 2 | Caesar Mukama | 2026-02-15 | PR: https://github.com/tetherto/miningos-app-node/pull/11 | +| 3 | Unknown | 2026-02-17 | https://app.asana.com/1/45238840754660/profile/1209203898446158 https://app.asana.com/1/45238840754660/profile/1208374908209019 this endpoint is ready for FE review, please sync to proceed to review if it meets FE expectations and with the OWASP security review (integration blocked until after Georgia deployment). | +| 4 | Unknown | 2026-02-18 | https://app.asana.com/1/45238840754660/profile/1209203898446158 https://app.asana.com/1/45238840754660/profile/1208374908209019 this endpoint is ready for FE review, please sync to proceed to review if it meets FE expectations and with the OWASP security review (integration blocked until after Georgia deployment). | +| 5 | Parag More | 2026-02-20 | All the cost values are showing up zero for all interval types , please check https://app.asana.com/1/45238840754660/profile/1209203898446158


{
"log": [
{
"ts": 1767225600000,
"consumptionMWh": 173.3691348,
"energyCostsUSD": 0,
"operationalCostsUSD": 0,
"totalCostsUSD": 0,
"allInCostPerMWh": 0,
"energyCostPerMWh": 0,
"btcPrice": 0,
"y... | +| 6 | Parag More | 2026-02-20 | Postman Collection | +| 7 | Unknown | 2026-02-23 | https://app.asana.com/1/45238840754660/profile/1207496533136374 please review with a focus on incorrect API calls, data aggregation issues, and anything else that could affect the feature. | +| 8 | Roberto Dilillo | 2026-03-04 | All Cost Values Returning Zero
Status: CONFIRMED BY CODE — root cause identified
A peer reviewer reported all cost values are zero for all interval types. Three independent issues contribute.
Root Cause 1: Production costs not configured or getProductionCosts returns empty
The cost data flow:
FE Cost Input page → setProductionCostsData() → LevelDB (key: year*100+month)
                                                          ↓
                               getProductionCos... | +| 9 | Roberto Dilillo | 2026-03-04 | Review & Improvement Suggestions
A. Add "costs configured" indicator to response
return {
  log: aggregated,
  summary,
  meta: {
    costsConfigured: Object.keys(costsByMonth).length > 0,
    monthsCovered: Object.keys(costsByMonth)
  }
}
B. Fix date filter to include first partial month
// Current — excludes first partial month
const startDate = new Date(start)
return entryDate >= startDate && entryDate <= endDate

// Fixed — use start-of-month for ... | +| 10 | Roberto Dilillo | 2026-03-04 | Security
Good
Auth works, site-scoped. Standard finance endpoint gaps: no rate limiting, no Cache-Control, negative timestamps.
FE Readiness
Partially Broken
Cost fields are 0 when production costs aren't configured (likely on dev). btcPrice always 0 (wrong RPC key). No indicator for "costs not configured". Ratio fields wrong for monthly/yearly.
Response Design
Needs Work
No costs-configured indicator, wrong BTC price, ratio aggregation bug, first month excluded.
Backe... | + +### Attachments +- [MiningOS_Finance_APIs.postman_collection.json](https://asanausercontent.com/us1/assets/45238840754660/1213348817875998/d1ecd1804492edc9767612e235b6f64b?e=1773057165&v=0&t=e8-johshej8tzEE8W2Bn-tu-FdmBIFh-RLrfGIPWxKs) + +--- + +## GET /auth/finance/subsidy-fees — [1213145436151988](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436151988) +**Assignee:** Caesar Mukama +**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing + +### Comments +| # | Author | Date | Comment | +|---|--------|------|---------| +| 1 | Caesar Mukama | 2026-02-19 | PR: https://github.com/tetherto/miningos-app-node/pull/14 | +| 2 | Parag More | 2026-02-26 | https://app.asana.com/1/45238840754660/profile/1209203898446158

None of them send back data, log and summary are having empty values

curl --location 'https://dev-moria.tether.to/auth/finance/subsidy-fees?start=1764339562260&end=1772115562260&period=daily' \
--header 'Authorization: Bearer pub:abc-roles:admin'

curl --location 'https://dev-moria.tether.to/auth/finance/subsidy-fees?start=1764339562260&end=1772115562260&period=weekly' \
--header 'Authorization: Bearer pub:... | +| 3 | Parag More | 2026-02-26 | Also IMO we should add validation in all period apis to fail if negative timestamps are passed | +| 4 | Parag More | 2026-02-26 | Collection used for basic tests. and performed manual tests to check the response data and structure | + +### Attachments +- [MiningOS_Finance_Subsidy_Fees_API.postman_collection.json](https://asanausercontent.com/us1/assets/45238840754660/1213453334188221/a62a4b8265a5e7d83437458382ee69dd?e=1773057165&v=0&t=ktg756b3S_VgCYRSt3XNGn4bmR_J6XBPe4sRHzvXxh4) + +--- + +## GET /auth/finance/hash-revenue — [1213145436151974](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436151974) +**Assignee:** Caesar Mukama **Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing ### Comments | # | Author | Date | Comment | -|---|--------|------|---------|- -| 1 | Parag More | 2026-02-12T07:22:43.450Z | PR: https://github.com/tetherto/miningos-app-node/pull/4 | -| 2 | Unknown | 2026-02-18T09:54:45.678Z | this endpoint is ready for FE review, please sync to proceed to review if it meets FE expectations and with the OWASP security review (integration blocked until after Georgia deployment). | -| 3 | Roberto Dilillo | 2026-02-23T11:24:50.892Z | Summary Verdict — Area Rating Notes: Security Good — Auth works, Cloudflare WAF helps, CORS locked down. Fix the missing Cache-Control, add rate limiting, clean up duplicate headers. FE Readiness Partial — Good data shape for mining metrics, but does NOT fully replace the other header requests (missing site name). The hashrate utilization at 892% and power nominal at 0 are data quality red flags. Response Design Needs Work — Missing units, no data health indicators, no low/info alert levels, timestamp format is ambiguous, excessive float precision. | -| 4 | Unknown | 2026-03-03T12:52:58.129Z | please review with a focus on incorrect API calls, data aggregation issues, and anything else that could affect the feature. | -| 5 | Unknown | 2026-03-03T12:53:20.958Z | this endpoint has passed internal testing by BE team and is ready for FE review. While the endpoint is in Product Design section, please proceed to review if it meets FE expectations and with the OWASP security review. Once you give the greenlight, please move the ticket to Under Estimation and then to In Progress for the integration. | -| 6 | Caesar Mukama | 2026-03-07T15:41:00.717Z | Great, thanks for the review | +|---|--------|------|---------| +| 1 | Caesar Mukama | 2026-03-06 | PR: https://github.com/tetherto/miningos-app-node/pull/27 | + +### Attachments +_No attachments._ + +--- + +## GET /auth/mempool/stats/bitcoin — [1213145436151982](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436151982) +**Assignee:** Caesar Mukama +**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing + +### Comments +_No comments._ + +### Attachments +_No attachments._ + +--- + +## GET /auth/mempool/price/bitcoin — [1213145436151996](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436151996) +**Assignee:** Caesar Mukama +**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing + +### Comments +_No comments._ ### Attachments -_None_ +_No attachments._ --- -## GET /auth/alerts/site — [1213140752769902](https://app.asana.com/1/45238840754660/project/1213238597612203/task/1213140752769902) -**Assignee:** Caesar Mukama +## GET /auth/reports/operations — [1213145436152000](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436152000) +**Assignee:** Caesar Mukama **Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing ### Comments -_No comments_ +_No comments._ ### Attachments -_None_ +_No attachments._ --- -## GET /auth/miners — [1213140752769906](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213140752769906) -**Assignee:** Parag More +## /auth/pool-stats/aggregate — [1213145436151998](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436151998) +**Assignee:** Caesar Mukama **Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing ### Comments | # | Author | Date | Comment | -|---|--------|------|---------|- -| 1 | Parag More | 2026-02-18T16:42:27.644Z | I have already made some progress on this. Reassigning to myself, will raise PR tomorrow | -| 2 | Parag More | 2026-02-18T16:42:41.582Z | CC: (tagged user) | -| 3 | Parag More | 2026-02-19T13:06:45.006Z | PR: https://github.com/tetherto/miningos-app-node/pull/13 | -| 4 | Parag More | 2026-02-26T14:07:51.629Z | (tagged user) has suggested to create a new subtask and working on it. We can mark it ready for review again after this is implemented. Slack thread: https://tether-to.slack.com/archives/C09T82CH0QG/p1771858738736529?thread_ts=1771506426.046169&cid=C09T82CH0QG | -| 5 | andreu.honzawa@tether.to | 2026-03-03T12:47:21.995Z | (tagged user) has almost completed the subtask, the api is already in review and has review comments. | +|---|--------|------|---------| +| 1 | Caesar Mukama | 2026-02-12 | PR: https://github.com/tetherto/miningos-app-node/pull/9 | +| 2 | Caesar Mukama | 2026-02-15 | PR: https://github.com/tetherto/miningos-app-node/pull/11 | +| 3 | Unknown | 2026-02-17 | https://app.asana.com/1/45238840754660/profile/1209203898446158 https://app.asana.com/1/45238840754660/profile/1208374908209019 this endpoint is ready for FE review, please sync to proceed to review if it meets FE expectations and with the OWASP security review (integration blocked until after Georgia deployment). | +| 4 | Unknown | 2026-02-18 | https://app.asana.com/1/45238840754660/profile/1209203898446158 https://app.asana.com/1/45238840754660/profile/1208374908209019 this endpoint is ready for FE review, please sync to proceed to review if it meets FE expectations and with the OWASP security review (integration blocked until after Georgia deployment). | +| 5 | Parag More | 2026-02-26 | https://app.asana.com/1/45238840754660/profile/1209203898446158 for

https://dev-moria.tether.to/auth/pool-stats/aggregate?start=1764335313758&end=1772111313758&range=daily

Its giving only 59 days of data, instead of 90 days as per timestamps above | +| 6 | Parag More | 2026-02-26 | https://app.asana.com/1/45238840754660/profile/1209203898446158
Also for range aggregates when we use monthly we see the monthName so its easy to know which month we are working with, but in weekly we get only ts, should we add the timerange over which we are considering the week rather than just timestamp?
One more point to note is its considering Sunday as start of week and not Monday.

Example data for week


{
"ts": 1769299200000,
... | +| 7 | Parag More | 2026-02-26 | https://app.asana.com/1/45238840754660/profile/1209203898446158

The pool filter is not working

curl --location 'https://dev-moria.tether.to/auth/pool-stats/aggregate?start=1764335955846&end=1772111955846&pool=antpool' \
--header 'Authorization: Bearer pub:api:ABC-roles:admin'

This one returns data | +| 8 | Parag More | 2026-02-26 | We also cant see the pool name if its expected in response | +| 9 | Parag More | 2026-02-26 | Used this collection to do basic tests and completed some manual testing by checking the api responses | +| 10 | Roberto Dilillo | 2026-03-02 | Summary Verdict

Area
Rating
Notes
Security
Good
Auth works, Cloudflare WAF active, CORS locked down. Main gaps: no rate limiting, no Cache-Control on financial data, overwriteCache exposed to all users.
FE Readiness
Partial
Core data shape works for pool stats charts, but workerCount is dead, balance is misleading, no per-pool breakdown, no USD conversion.
Response Design
Needs Work
Duplicate/misleading field names, no unit metadata, no data freshness indi... | +| 11 | Roberto Dilillo | 2026-03-02 | 1
Only 59 days instead of 90
CONFIRMED
processTransactionData only creates entries for days with transactions — no gap-filling
2
Weekly uses Sunday as start
CONFIRMED
getUTCDay() returns 0 for Sunday, used directly as offset — should use ISO Monday
3
Weekly lacks range metadata
CONFIRMED
Monthly gets monthName/year/month, weekly only gets bare ts
4
Pool filter doesn't work
CONFIRMED
pool is sent to ORK RPC but processTransactionData has zero pool filt... | +| 12 | Roberto Dilillo | 2026-03-02 | https://app.asana.com/1/45238840754660/profile/1205063919763609 i did the review and owasp of this one, how should the process work? who should i pass my tickets to for checking them? | +| 13 | andreu.honzawa@tether.to | 2026-03-03 | https://app.asana.com/1/45238840754660/profile/1209203898446158 check the feedback provided by https://app.asana.com/1/45238840754660/profile/1208374908209019 in the subtasks, moving this ticket back to you | +| 14 | andreu.honzawa@tether.to | 2026-03-03 | https://github.com/tetherto/miningos-app-node/pull/25 | +| 15 | andreu.honzawa@tether.to | 2026-03-03 | https://app.asana.com/1/45238840754660/profile/1208374908209019 I just check with https://app.asana.com/1/45238840754660/profile/1209203898446158 and he said this is not clear can you please help clarify

https://app.asana.com/app/asana/-/get_asset?asset_id=1213507404731604
| +| 16 | Roberto Dilillo | 2026-03-04 | please feel free to reach out or type here any question https://app.asana.com/1/45238840754660/profile/1209203898446158. Avoid generic "clarify" requests because the above is a report that takes half a day to write and it includes multiple things.

cc https://app.asana.com/1/45238840754660/profile/1205063919763609 | +| 17 | Caesar Mukama | 2026-03-04 | Thanks for the review https://app.asana.com/1/45238840754660/profile/1208374908209019 Absolutely,
Duplicate/misleading field names - what names are misleading?
No unit metadata - what metadata is missing? Also, is there a spec document for expected metadata or are these new features?
No data freshness indicators - what are data freshness indicators? Is there a spec document not being followed or are these new features?
Math.abs accounting issues - is math.abs being ap... | +| 18 | Roberto Dilillo | 2026-03-04 | Duplicate/misleading field names — what names are misleading?
information were written in subtask https://app.asana.com/1/45238840754660/task/1213314123096942/comment/1213497616048404?focus=true, and you can find in the table the owasp number and check details in the subtask

balance in log[] entries. This does not represent the actual pool balance. It's just a copy of revenueBTC (the period's revenue). The handler code at line ~221 does balance: data.revenueBTC. So if the fron... | ### Attachments -_None_ +- [MiningOS_Pool_Stats_Aggregate_API.postman_collection.json](https://asanausercontent.com/us1/assets/45238840754660/1213453334185116/d05c5d269a6b1d292158236e017d5bd6?e=1773057165&v=0&t=gHFGeQSrzn3kp6pURDfZlR8IThRY23IET4w-KQZe3ts) +- [image.png](https://asanausercontent.com/us1/assets/45238840754660/1213507404731603/d726b7c927223a0115911951ea94bd2f?e=1773057165&v=0&t=hJIvo67AT-fZqN_g8D0fxMXiZOgIA-VeyNZ0JGjM54I) --- -## GET /auth/containers — [1213140752769908](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213140752769908) -**Assignee:** Roberto Dilillo +## GET /auth/pools/:pool/balance-history — [1213145436151994](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436151994) +**Assignee:** Roberto Dilillo **Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing ### Comments | # | Author | Date | Comment | -|---|--------|------|---------|- -| 1 | andreu.honzawa@tether.to | 2026-03-03T15:01:48.761Z | https://github.com/tetherto/miningos-app-node/pull/25 | +|---|--------|------|---------| +| 1 | Caesar Mukama | 2026-02-12 | PR: https://github.com/tetherto/miningos-app-node/pull/8 | +| 2 | Caesar Mukama | 2026-02-15 | PR: https://github.com/tetherto/miningos-app-node/pull/11 | +| 3 | Unknown | 2026-02-17 | https://app.asana.com/1/45238840754660/profile/1209203898446158 https://app.asana.com/1/45238840754660/profile/1208374908209019 this endpoint is ready for FE review, please sync to proceed to review if it meets FE expectations and with the OWASP security review (integration blocked until after Georgia deployment). | +| 4 | Unknown | 2026-02-18 | https://app.asana.com/1/45238840754660/profile/1209203898446158 https://app.asana.com/1/45238840754660/profile/1208374908209019 this endpoint is ready for FE review, please sync to proceed to review if it meets FE expectations and with the OWASP security review (integration blocked until after Georgia deployment). | +| 5 | Parag More | 2026-02-26 | https://app.asana.com/1/45238840754660/profile/1209203898446158the pool filter does not work and returns same data for all the pool params

ex:

curl --location 'https://dev-moria.tether.to/auth/pools/ant/balance-history?start=1764338181148&end=1772114181148&range=1W' \
--header 'Authorization: Bearer pub:api:ABC-roles:admin'

give back data, but ant pool does not exist on staging | +| 6 | Parag More | 2026-02-26 | https://app.asana.com/1/45238840754660/profile/1209203898446158the pool-stats/aggregate api uses range: weekly / monthly etc. but

This api expects 1W / 1D / 1M. can we follow same convention for all apis and not implement seperate for each one of them | +| 7 | Parag More | 2026-02-26 | For

curl --location 'https://dev-moria.tether.to/auth/pools/ant/balance-history?start=1764338387569&end=1772114387569&range=1M' \
--header 'Authorization: Bearer pub:ABC:admin'

It should have returned data monthly with month year and other response structure like the pool-stats/aggregate api but thats not the case and the response structure is completely different and returns only one data point.

:

{
"log": [
{
"ts": 1762560000000,<... | +| 8 | Parag More | 2026-02-26 | This api call returns only few datapoints. but ideally should have almost 90

curl --location 'https://dev-moria.tether.to/auth/pools/ant/balance-history?start=1764338513764&end=1772114513764' \
--header 'Authorization: Bearer pub:api:ABC-roles:admin'

returned respons


{
"log": [
{
"ts": 1764374400000,
"balance": 0.0007894665835364325,
"hashrate": 611539599417678,
"revenue": 0.000789466583536... | +| 9 | Parag More | 2026-02-26 | Used this collection for basic testing and then did manual testing of the response structure and api responses expected | +| 10 | andreu.honzawa@tether.to | 2026-03-03 | https://github.com/tetherto/miningos-app-node/pull/25 | ### Attachments -_None_ +- [MiningOS_Pool_Balance_History_API.postman_collection.json](https://asanausercontent.com/us1/assets/45238840754660/1213453334188204/6950bba963a971531c8e67c9bcb7bff6?e=1773057165&v=0&t=RNDl3a4wWSCjXnJ1rek_vVcBepy5kIsAGvUHe-nh4sE) --- -## GET /auth/metrics/containers/:id — [1213140752769910](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213140752769910) -**Assignee:** Caesar Mukama +## GET /auth/alerts/history — [1213145436152002](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436152002) +**Assignee:** Caesar Mukama **Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing ### Comments -_No comments_ +_No comments._ ### Attachments -_None_ +_No attachments._ From 04adc30aba4de278e222dd669770afdc4625cca1 Mon Sep 17 00:00:00 2001 From: Caesar Mukama Date: Tue, 10 Mar 2026 12:34:15 +0300 Subject: [PATCH 03/10] fix: implement limit parameter for power-mode/timeline endpoint The limit param was in the cache key but unused in the handler. Now reads limit from query (default 10080) and truncates results. Adds schema validation with min/max bounds. --- tests/unit/handlers/metrics.handlers.test.js | 40 +++++++++++++++++++ .../lib/server/handlers/metrics.handlers.js | 3 +- workers/lib/server/schemas/metrics.schemas.js | 33 +++++++-------- 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/tests/unit/handlers/metrics.handlers.test.js b/tests/unit/handlers/metrics.handlers.test.js index 9a6355b..202d129 100644 --- a/tests/unit/handlers/metrics.handlers.test.js +++ b/tests/unit/handlers/metrics.handlers.test.js @@ -1127,6 +1127,46 @@ test('getPowerModeTimeline - always uses t-miner tag', async (t) => { t.pass() }) +test('getPowerModeTimeline - uses limit param to truncate results', async (t) => { + const mockCtx = { + conf: { + orks: [{ rpcPublicKey: 'key1' }] + }, + net_r0: { + jRequest: async () => { + const entries = [] + for (let i = 0; i < 5; i++) { + entries.push({ + ts: 1700000000000 + i * 10800000, + power_mode_group_aggr: { [`cont${i}-miner1`]: 'normal' }, + status_group_aggr: { [`cont${i}-miner1`]: 'mining' } + }) + } + return entries + } + } + } + + const result = await getPowerModeTimeline(mockCtx, { + query: { start: 1700000000000, end: 1700100000000, limit: 2 } + }) + + t.is(result.log.length, 2, 'should truncate log to limit') + t.pass() +}) + +test('getPowerModeTimeline - uses default limit when not provided', async (t) => { + const mockCtx = { + conf: { orks: [{ rpcPublicKey: 'key1' }] }, + net_r0: { jRequest: async () => ([]) } + } + + const result = await getPowerModeTimeline(mockCtx, { query: {} }) + t.ok(result.log, 'should return log with default limit applied') + t.ok(Array.isArray(result.log), 'should be array') + t.pass() +}) + test('processPowerModeTimelineData - filters by container post-RPC', (t) => { const results = [[ { diff --git a/workers/lib/server/handlers/metrics.handlers.js b/workers/lib/server/handlers/metrics.handlers.js index 42a4be9..ef2b912 100644 --- a/workers/lib/server/handlers/metrics.handlers.js +++ b/workers/lib/server/handlers/metrics.handlers.js @@ -380,6 +380,7 @@ async function getPowerModeTimeline (ctx, req) { const start = Number(req.query.start) || (now - METRICS_TIME.ONE_MONTH_MS) const end = Number(req.query.end) || now const container = req.query.container || null + const limit = Number(req.query.limit) || METRICS_DEFAULTS.TIMELINE_LIMIT if (start >= end) { throw new Error('ERR_INVALID_DATE_RANGE') @@ -399,7 +400,7 @@ async function getPowerModeTimeline (ctx, req) { const results = await requestRpcEachLimit(ctx, RPC_METHODS.TAIL_LOG, rpcPayload) - const log = processPowerModeTimelineData(results, container) + const log = processPowerModeTimelineData(results, container).slice(0, limit) return { log } } diff --git a/workers/lib/server/schemas/metrics.schemas.js b/workers/lib/server/schemas/metrics.schemas.js index 2a149f8..de4c3c2 100644 --- a/workers/lib/server/schemas/metrics.schemas.js +++ b/workers/lib/server/schemas/metrics.schemas.js @@ -5,8 +5,8 @@ const schemas = { hashrate: { type: 'object', properties: { - start: { type: 'integer' }, - end: { type: 'integer' }, + start: { type: 'integer', minimum: 0 }, + end: { type: 'integer', minimum: 0 }, overwriteCache: { type: 'boolean' } }, required: ['start', 'end'] @@ -14,8 +14,8 @@ const schemas = { consumption: { type: 'object', properties: { - start: { type: 'integer' }, - end: { type: 'integer' }, + start: { type: 'integer', minimum: 0 }, + end: { type: 'integer', minimum: 0 }, overwriteCache: { type: 'boolean' } }, required: ['start', 'end'] @@ -23,8 +23,8 @@ const schemas = { efficiency: { type: 'object', properties: { - start: { type: 'integer' }, - end: { type: 'integer' }, + start: { type: 'integer', minimum: 0 }, + end: { type: 'integer', minimum: 0 }, overwriteCache: { type: 'boolean' } }, required: ['start', 'end'] @@ -32,8 +32,8 @@ const schemas = { minerStatus: { type: 'object', properties: { - start: { type: 'integer' }, - end: { type: 'integer' }, + start: { type: 'integer', minimum: 0 }, + end: { type: 'integer', minimum: 0 }, overwriteCache: { type: 'boolean' } }, required: ['start', 'end'] @@ -41,8 +41,8 @@ const schemas = { powerMode: { type: 'object', properties: { - start: { type: 'integer' }, - end: { type: 'integer' }, + start: { type: 'integer', minimum: 0 }, + end: { type: 'integer', minimum: 0 }, interval: { type: 'string', enum: ['1h', '1d', '1w'] }, overwriteCache: { type: 'boolean' } }, @@ -51,17 +51,18 @@ const schemas = { powerModeTimeline: { type: 'object', properties: { - start: { type: 'integer' }, - end: { type: 'integer' }, + start: { type: 'integer', minimum: 0 }, + end: { type: 'integer', minimum: 0 }, container: { type: 'string' }, + limit: { type: 'integer', minimum: 1, maximum: 50000 }, overwriteCache: { type: 'boolean' } } }, temperature: { type: 'object', properties: { - start: { type: 'integer' }, - end: { type: 'integer' }, + start: { type: 'integer', minimum: 0 }, + end: { type: 'integer', minimum: 0 }, interval: { type: 'string', enum: ['1h', '1d', '1w'] }, container: { type: 'string' }, overwriteCache: { type: 'boolean' } @@ -77,8 +78,8 @@ const schemas = { containerHistory: { type: 'object', properties: { - start: { type: 'integer' }, - end: { type: 'integer' }, + start: { type: 'integer', minimum: 0 }, + end: { type: 'integer', minimum: 0 }, limit: { type: 'integer' }, overwriteCache: { type: 'boolean' } } From 4e5e4e8376e7f8067d12049bd45e99387e9d7567 Mon Sep 17 00:00:00 2001 From: Caesar Mukama Date: Tue, 10 Mar 2026 12:34:21 +0300 Subject: [PATCH 04/10] fix: add minimum:0 timestamp validation to pools schemas Prevents negative timestamps from passing schema validation on balanceHistory and poolStatsAggregate endpoints. --- workers/lib/server/schemas/pools.schemas.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/workers/lib/server/schemas/pools.schemas.js b/workers/lib/server/schemas/pools.schemas.js index d5dcd6f..ec053cb 100644 --- a/workers/lib/server/schemas/pools.schemas.js +++ b/workers/lib/server/schemas/pools.schemas.js @@ -14,8 +14,8 @@ const schemas = { balanceHistory: { type: 'object', properties: { - start: { type: 'integer' }, - end: { type: 'integer' }, + start: { type: 'integer', minimum: 0 }, + end: { type: 'integer', minimum: 0 }, range: { type: 'string', enum: ['1D', '1W', '1M'] }, overwriteCache: { type: 'boolean' } }, @@ -24,8 +24,8 @@ const schemas = { poolStatsAggregate: { type: 'object', properties: { - start: { type: 'integer' }, - end: { type: 'integer' }, + start: { type: 'integer', minimum: 0 }, + end: { type: 'integer', minimum: 0 }, range: { type: 'string', enum: ['daily', 'weekly', 'monthly'] }, pool: { type: 'string' }, overwriteCache: { type: 'boolean' } From 07b71f48c5777ec173f8cd616f3c25c67f4e6ebf Mon Sep 17 00:00:00 2001 From: Caesar Mukama Date: Tue, 10 Mar 2026 12:34:25 +0300 Subject: [PATCH 05/10] fix: sanitize error messages and add security response headers Adds SAFE_ERROR_MESSAGES allowlist to prevent leaking internal error details. Adds X-Content-Type-Options and Cache-Control security headers via onSend hook. --- workers/http.node.wrk.js | 16 +++++++++++++++- workers/lib/constants.js | 15 ++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/workers/http.node.wrk.js b/workers/http.node.wrk.js index aa2b95e..137024c 100644 --- a/workers/http.node.wrk.js +++ b/workers/http.node.wrk.js @@ -10,6 +10,7 @@ const GlobalDataLib = require('./lib/globalData') const { UserService } = require('./lib/users') const { AlertsService } = require('./lib/alerts') const { auditLogger } = require('./lib/server/lib/auditLogger') +const { SAFE_ERROR_MESSAGES } = require('./lib/constants') class WrkServerHttp extends TetherWrkBase { constructor (conf, ctx) { @@ -98,11 +99,24 @@ class WrkServerHttp extends TetherWrkBase { httpd.addRoute(r) }) + httpd.addHook('onSend', async (request, reply) => { + reply.header('X-Content-Type-Options', 'nosniff') + reply.header('Cache-Control', 'no-store') + }) + httpd.addHook('onError', async (request, reply, error) => { + const message = SAFE_ERROR_MESSAGES.has(error.message) + ? error.message + : 'Bad Request' + + if (!SAFE_ERROR_MESSAGES.has(error.message)) { + debug('onError handler:', error.message) + } + return reply.status(400).send({ statusCode: 400, error: 'Bad Request', - message: error.message + message }) }) diff --git a/workers/lib/constants.js b/workers/lib/constants.js index 3b026dc..5fcd535 100644 --- a/workers/lib/constants.js +++ b/workers/lib/constants.js @@ -350,6 +350,18 @@ const RANGE_BUCKETS = { '1M': 2592000000 } +const SAFE_ERROR_MESSAGES = new Set([ + 'ERR_MISSING_START_END', + 'ERR_INVALID_DATE_RANGE', + 'ERR_QUERY_INVALID_JSON', + 'ERR_SORT_INVALID_JSON', + 'ERR_FIELDS_INVALID_JSON', + 'ERR_MISSING_CONTAINER_ID', + 'ERR_INVALID_TIMESTAMP', + 'ERR_INVALID_JSON', + 'ERR_MISSING_POOL_PARAM' +]) + const RPC_TIMEOUT = 15000 const RPC_CONCURRENCY_LIMIT = 2 const RPC_PAGE_LIMIT = 100 @@ -400,5 +412,6 @@ module.exports = { SITE_ALERTS_SEARCH_FIELDS, HISTORY_FILTER_FIELDS, HISTORY_SEARCH_FIELDS, - DEVICE_LIST_FIELDS + DEVICE_LIST_FIELDS, + SAFE_ERROR_MESSAGES } From c89840865124e906f714186aa76ee98dc4e1f979 Mon Sep 17 00:00:00 2001 From: Caesar Mukama Date: Tue, 10 Mar 2026 14:58:48 +0300 Subject: [PATCH 06/10] fix: simplify error sanitization to use ERR_ prefix check Replace SAFE_ERROR_MESSAGES allowlist Set with a simple startsWith('ERR_') check in the onError hook. --- workers/http.node.wrk.js | 8 +++----- workers/lib/constants.js | 15 +-------------- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/workers/http.node.wrk.js b/workers/http.node.wrk.js index 137024c..2a0fe91 100644 --- a/workers/http.node.wrk.js +++ b/workers/http.node.wrk.js @@ -10,7 +10,6 @@ const GlobalDataLib = require('./lib/globalData') const { UserService } = require('./lib/users') const { AlertsService } = require('./lib/alerts') const { auditLogger } = require('./lib/server/lib/auditLogger') -const { SAFE_ERROR_MESSAGES } = require('./lib/constants') class WrkServerHttp extends TetherWrkBase { constructor (conf, ctx) { @@ -105,11 +104,10 @@ class WrkServerHttp extends TetherWrkBase { }) httpd.addHook('onError', async (request, reply, error) => { - const message = SAFE_ERROR_MESSAGES.has(error.message) - ? error.message - : 'Bad Request' + const isSafe = error.message.startsWith('ERR_') + const message = isSafe ? error.message : 'Bad Request' - if (!SAFE_ERROR_MESSAGES.has(error.message)) { + if (!isSafe) { debug('onError handler:', error.message) } diff --git a/workers/lib/constants.js b/workers/lib/constants.js index 5fcd535..3b026dc 100644 --- a/workers/lib/constants.js +++ b/workers/lib/constants.js @@ -350,18 +350,6 @@ const RANGE_BUCKETS = { '1M': 2592000000 } -const SAFE_ERROR_MESSAGES = new Set([ - 'ERR_MISSING_START_END', - 'ERR_INVALID_DATE_RANGE', - 'ERR_QUERY_INVALID_JSON', - 'ERR_SORT_INVALID_JSON', - 'ERR_FIELDS_INVALID_JSON', - 'ERR_MISSING_CONTAINER_ID', - 'ERR_INVALID_TIMESTAMP', - 'ERR_INVALID_JSON', - 'ERR_MISSING_POOL_PARAM' -]) - const RPC_TIMEOUT = 15000 const RPC_CONCURRENCY_LIMIT = 2 const RPC_PAGE_LIMIT = 100 @@ -412,6 +400,5 @@ module.exports = { SITE_ALERTS_SEARCH_FIELDS, HISTORY_FILTER_FIELDS, HISTORY_SEARCH_FIELDS, - DEVICE_LIST_FIELDS, - SAFE_ERROR_MESSAGES + DEVICE_LIST_FIELDS } From 144d3a0581eca8dcee9e107ba4141860d347baed Mon Sep 17 00:00:00 2001 From: Caesar Mukama Date: Tue, 10 Mar 2026 15:00:31 +0300 Subject: [PATCH 07/10] chore: remove scratch files from PR --- bugs-plan.md | 80 -------------- comments.md | 301 --------------------------------------------------- 2 files changed, 381 deletions(-) delete mode 100644 bugs-plan.md delete mode 100644 comments.md diff --git a/bugs-plan.md b/bugs-plan.md deleted file mode 100644 index d23cd5d..0000000 --- a/bugs-plan.md +++ /dev/null @@ -1,80 +0,0 @@ -# Asana Comment Bug Fix Workflow - -You are tasked with processing Asana tickets, reading their comments (including attachments), fixing the issues described, and creating a single PR that addresses everything. - -## Inputs - -Asana ticket URLs: -- [PASTE YOUR LINKS HERE] - -## Workflow - -### Step 1: Extract task GIDs -From each Asana URL, extract the task GID (the last numeric segment of the URL, e.g. `https://app.asana.com/0/1234567/8901234` → GID is `8901234`). - -### Step 2: Fetch comments via curl -For each task GID, run: - -```bash -curl -s "https://app.asana.com/api/1.0/tasks/{task_gid}/stories?opt_fields=text,created_by.name,created_at,resource_subtype,html_text" \ - -H "Authorization: Bearer $ASANA_PAT" -``` - -Filter results to only `resource_subtype: "comment_added"`. Parse out the comment text and who wrote it. - -### Step 3: Fetch attachments -For each task, also fetch attachments: - -```bash -curl -s "https://app.asana.com/api/1.0/tasks/{task_gid}/attachments?opt_fields=name,download_url,resource_type" \ - -H "Authorization: Bearer $ASANA_PAT" -``` - -Download any relevant attachments (screenshots, files) to understand the issue. For images, describe what you see if relevant to the bug. - -### Step 4: Fetch task details via Asana MCP -Use the Asana MCP `get_task` tool to get the task title, description, and assignee for additional context. - -### Step 5: Triage and plan -For each ticket, based on comments and attachments: -1. Identify what is being asked/reported -2. Classify as: **fixable** (code change needed) or **out of scope** (design decision, external dependency, not a bug, needs product input, etc.) -3. For fixable items, identify the relevant files and what needs to change - -Present the triage plan and wait for my confirmation before proceeding. - -### Step 6: Implement fixes -- Create a single branch named `fix/asana-comment-fixes-{date}` -- Make all fixes across the codebase -- Keep commits atomic — one commit per Asana ticket, with the commit message referencing the ticket: `fix: [brief description] (Asana: {task_url})` - -### Step 7: Create the PR -Create one PR with: -- **Title:** `fix: address review comments from Asana tickets` -- **Body:** a table summarizing each ticket: - -| Ticket | Title | Status | Resolution | -|--------|-------|--------|------------| -| [link] | ... | ✅ Fixed / ⏭️ Out of scope | 1-2 sentence explanation | - -### Step 8: Comment back on Asana tickets -For each ticket, use curl to post a comment back: - -```bash -curl -s -X POST "https://app.asana.com/api/1.0/tasks/{task_gid}/stories" \ - -H "Authorization: Bearer $ASANA_PAT" \ - -H "Content-Type: application/json" \ - -d '{"data":{"text":"..."}}' -``` - -The comment should follow this format: -- **If fixed:** "Addressed in PR: {pr_url} — {1-2 sentence description of what was changed}" -- **If out of scope:** "Marking as out of scope for this pass — {concise reason}. Will revisit in a follow-up if needed." - -## Rules -- Do NOT guess at fixes. If a comment is ambiguous, ask me before implementing. -- Prefer minimal, targeted changes. Don't refactor unrelated code. -- If an attachment (e.g. screenshot) shows a visual bug, describe what you see and your proposed fix before implementing. -- Ensure all existing tests pass. Add tests if the fix warrants it. -- If a comment thread has back-and-forth, use the **latest consensus** as the source of truth. -- Before using this, make sure you have your Asana Personal Access Token set as an environment variable (`export ASANA_PAT=your_token`). You can generate one from **Asana → My Settings → Apps → Developer Apps → Personal Access Tokens**. \ No newline at end of file diff --git a/comments.md b/comments.md deleted file mode 100644 index c1bd7ee..0000000 --- a/comments.md +++ /dev/null @@ -1,301 +0,0 @@ -# Asana Ticket Comments -_Generated: 2026-03-09 14:24:03_ - ---- - -## GET /auth/metrics/miners/status — [1213140752769914](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213140752769914) -**Assignee:** Caesar Mukama -**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing - -### Comments -_No comments._ - -### Attachments -_No attachments._ - ---- - -## GET /auth/metrics/power/mode — [1213140752769922](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213140752769922) -**Assignee:** Caesar Mukama -**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing - -### Comments -_No comments._ - -### Attachments -_No attachments._ - ---- - -## GET /auth/metrics/power-mode/timeline — [1213140752769920](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213140752769920) -**Assignee:** Caesar Mukama -**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing - -### Comments -| # | Author | Date | Comment | -|---|--------|------|---------| -| 1 | Caesar Mukama | 2026-02-20 | PR: https://github.com/tetherto/miningos-app-node/pull/21 | -| 2 | Roberto Dilillo | 2026-03-05 | The limit parameter is:
Documented in the endpoint spec (default 10080)
Accepted by the schema (though not explicitly declared — not validated)
Included in cache key (req.query.limit) — different limit values create separate cache entries
NOT used in the handler — never passed to the RPC payload, never used to truncate results

// Handler (metrics.handlers.js:378-405)
async function getPowerModeTimeline (ctx, req) {
  const now = Date.now()
  const star... | -| 3 | Roberto Dilillo | 2026-03-05 | not deployed, tested locally | - -### Attachments -_No attachments._ - ---- - -## GET /auth/metrics/temperature — [1213145436151980](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436151980) -**Assignee:** Caesar Mukama -**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing - -### Comments -| # | Author | Date | Comment | -|---|--------|------|---------| -| 1 | Caesar Mukama | 2026-02-20 | PR: https://github.com/tetherto/miningos-app-node/pull/21 | -| 2 | Roberto Dilillo | 2026-03-05 | this might be a Staging only issue:
"maintenance" Container with Zero Temperatures
Live response includes a container named maintenance with maxC: 0, avgC: 0 across all time points. This appears to be a miner status category leaking into the container namespace via temperature_c_group_max_aggr keys. It's not a physical container — it's miners in maintenance mode being grouped as a "container".
Impact: The FE would show a maintenance entry in the temperature chart with a flat line at 0°C... | -| 3 | Roberto Dilillo | 2026-03-05 | Backend Implementation Review & Improvement Suggestions
A. Filter out non-physical containers
The maintenance group appears because miners in maintenance mode have their keys grouped under temperature_c_group_max_aggr. Add a filter:
const EXCLUDED_CONTAINERS = new Set(['maintenance'])

for (const [name, maxVal] of Object.entries(maxObj)) {
  if (EXCLUDED_CONTAINERS.has(name)) continue
  if (containerFilter && name !== containerFilter) continue
  // ...
}
Or better: ... | -| 4 | Roberto Dilillo | 2026-03-05 | #
Issue
Severity
Effort
Recommendation
1
maintenance container in results skews site average
MEDIUM
Low
Filter out zero-temp containers from siteAvgC calculation
2
Missing Cache-Control header
MEDIUM
Low
Add Cache-Control: no-store
3
Missing X-Content-Type-Options: nosniff
MEDIUM
Low
Add server-wide
4
No capCheck on operational data
LOW-MEDIUM
Low
Add metrics:read permission
5
Response key log/summary vs spec data
L... | - -### Attachments -_No attachments._ - ---- - -## GET /auth/metrics/containers/:id/history — [1213145436151986](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436151986) -**Assignee:** Caesar Mukama -**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing - -### Comments -_No comments._ - -### Attachments -_No attachments._ - ---- - -## GET /auth/finance/revenue — [1213145436151978](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436151978) -**Assignee:** Caesar Mukama -**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing - -### Comments -| # | Author | Date | Comment | -|---|--------|------|---------| -| 1 | Caesar Mukama | 2026-02-19 | PR: https://github.com/tetherto/miningos-app-node/pull/15 | -| 2 | Parag More | 2026-02-26 | https://app.asana.com/1/45238840754660/profile/1209203898446158I dont think this one is merged Please attach correct PR | - -### Attachments -_No attachments._ - ---- - -## GET /auth/finance/revenue-summary — [1213145436151984](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436151984) -**Assignee:** Caesar Mukama -**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing - -### Comments -| # | Author | Date | Comment | -|---|--------|------|---------| -| 1 | Caesar Mukama | 2026-02-19 | PR: https://github.com/tetherto/miningos-app-node/pull/16 | -| 2 | Parag More | 2026-02-26 | https://app.asana.com/1/45238840754660/profile/1209203898446158I dont think this one is merged Please attach correct PR | - -### Attachments -_No attachments._ - ---- - -## GET /auth/finance/ebitda — [1213145436151990](https://app.asana.com/1/45238840754660/project/1213238597612203/task/1213145436151990) -**Assignee:** Caesar Mukama -**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing - -### Comments -| # | Author | Date | Comment | -|---|--------|------|---------| -| 1 | Caesar Mukama | 2026-02-12 | PR: https://github.com/tetherto/miningos-app-node/pull/5 | -| 2 | Caesar Mukama | 2026-02-15 | PR: https://github.com/tetherto/miningos-app-node/pull/11 | -| 3 | Unknown | 2026-02-17 | https://app.asana.com/1/45238840754660/profile/1209203898446158 https://app.asana.com/1/45238840754660/profile/1208374908209019 this endpoint is ready for FE review, please sync to proceed to review if it meets FE expectations and with the OWASP security review (integration blocked until after Georgia deployment). | -| 4 | Parag More | 2026-02-20 | The api is giving 0 values for all fields please verify once. The revenue should not be 0 for sure as I see revenue in revenue summay apis

{
"log": [
{
"ts": 1767225600000,
"revenueBTC": 0,
"revenueUSD": 0,
"btcPrice": 0,
"powerW": 0,
"hashrateMhs": 0,
"consumptionMWh": 0,
"energyCostsUSD": 0,
"operationalCostsUSD": 0,
"tot... | -| 5 | Parag More | 2026-02-20 | Test API Collection | -| 6 | Unknown | 2026-02-23 | https://app.asana.com/1/45238840754660/profile/1207496533136374 please review with a focus on incorrect API calls, data aggregation issues, and anything else that could affect the feature. | -| 7 | Roberto Dilillo | 2026-03-03 | CRITICAL BUG: All Fields Returning Zero
Status: CONFIRMED BY CODE — root cause identified
A peer reviewer reported that this endpoint returns all-zero data:

{
  "log": [
    { "ts": 1767225600000, "revenueBTC": 0, "revenueUSD": 0, "btcPrice": 0, ... }
  ],
  "summary": { "totalRevenueBTC": 0, "totalRevenueUSD": 0, "currentBtcPrice": 0, ... }
}


Meanwhile, the revenue-summary endpoint (legacy API) shows non-zero revenue for the same time range.
Root Cause ... | - -### Attachments -- [MiningOS_Finance_APIs.postman_collection.json](https://asanausercontent.com/us1/assets/45238840754660/1213348817875990/912a9edbacf92127e5b2fc9a1cf3bf34?e=1773057165&v=0&t=zObbwtW3krG48TxsIJ7nr787X5yGqTowoG9rY-rtp9U) - ---- - -## GET /auth/finance/energy-balance — [1213145436151976](https://app.asana.com/1/45238840754660/project/1213238597612203/task/1213145436151976) -**Assignee:** Caesar Mukama -**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing - -### Comments -| # | Author | Date | Comment | -|---|--------|------|---------| -| 1 | Caesar Mukama | 2026-02-12 | PR: https://github.com/tetherto/miningos-app-node/pull/3 | -| 2 | Caesar Mukama | 2026-02-15 | PR: https://github.com/tetherto/miningos-app-node/pull/11 | -| 3 | Unknown | 2026-02-17 | https://app.asana.com/1/45238840754660/profile/1209203898446158 https://app.asana.com/1/45238840754660/profile/1208374908209019 this endpoint is ready for FE review, please sync to proceed to review if it meets FE expectations and with the OWASP security review (integration blocked until after Georgia deployment). | -| 4 | Unknown | 2026-02-18 | https://app.asana.com/1/45238840754660/profile/1209203898446158 https://app.asana.com/1/45238840754660/profile/1208374908209019 this endpoint is ready for FE review, please sync to proceed to review if it meets FE expectations and with the OWASP security review (integration blocked until after Georgia deployment). | -| 5 | Parag More | 2026-02-20 | https://app.asana.com/1/45238840754660/profile/1209203898446158

Negative timestamps should fail but this is giving 200 response. Please run the tests for energy balance api postman collection attached here | -| 6 | Unknown | 2026-02-23 | https://app.asana.com/1/45238840754660/profile/1207496533136374 please review with a focus on incorrect API calls, data aggregation issues, and anything else that could affect the feature. | -| 7 | Roberto Dilillo | 2026-03-03 | Negative timestamps return 200 instead of 400
Status: CONFIRMED BY CODE
GET /auth/finance/energy-balance?start=-1764335313758&end=-1
Returns 200 OK. The handler's validation:

// finance.handlers.js:27-28
if (!start \|\| !end) {
  throw new Error('ERR_MISSING_START_END')
}


Negative numbers are truthy in JavaScript (!(-1764335313758) → false), so they pass. Then new Date(-1764335313758) produces 1914-02-03T10:51:26.242Z — a syntactically valid but absurd dat... | -| 8 | Roberto Dilillo | 2026-03-03 | A. Fix negative timestamp validation
// Current (finance.handlers.js:27-33)
if (!start \|\| !end) {
  throw new Error('ERR_MISSING_START_END')
}
if (start >= end) {
  throw new Error('ERR_INVALID_DATE_RANGE')
}

// Improved
const MIN_TS = 1000000000000 // ~2001-09
const MAX_RANGE_MS = 2 * 365 * 86400000 // 2 years

if (!Number.isInteger(start) \|\| !Number.isInteger(end) \|\| start < MIN_TS \|\| end < MIN_TS) {
  throw new Error('ERR_INVALID_TIMESTAMP')<... | -| 9 | Roberto Dilillo | 2026-03-03 | 5. Priority Remediation Matrix

#
Issue
Severity
Effort
Recommendation
1
Negative timestamps accepted (200)
HIGH
Low
Add start < MIN_TS validation
2
Duplicate electricity RPC call
MEDIUM
Low
Single call, extract both fields
3
Math.abs inflates revenue
MEDIUM
Low
Filter positive values or track credits/debits separately
4
Per-MWh ratios summed in aggregation
MEDIUM
Low
Recalculate ratios post-aggregation
5
No rate... | - -### Attachments -- MiningOS API v2 — Backend Endpoint Analysis -- [MiningOS_Finance_APIs.postman_collection.json](https://asanausercontent.com/us1/assets/45238840754660/1213348817875983/cd82ced7918a6dc91bd01e9034b60b8f?e=1773057165&v=0&t=2rVaLT0HvT0mffkKXnwpFLXof3un8h4Tlp7OFx2aAqQ) - ---- - -## GET /auth/finance/cost-summary — [1213145436151992](https://app.asana.com/1/45238840754660/project/1213238597612203/task/1213145436151992) -**Assignee:** Caesar Mukama -**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing - -### Comments -| # | Author | Date | Comment | -|---|--------|------|---------| -| 1 | Caesar Mukama | 2026-02-12 | PR: https://github.com/tetherto/miningos-app-node/pull/6 | -| 2 | Caesar Mukama | 2026-02-15 | PR: https://github.com/tetherto/miningos-app-node/pull/11 | -| 3 | Unknown | 2026-02-17 | https://app.asana.com/1/45238840754660/profile/1209203898446158 https://app.asana.com/1/45238840754660/profile/1208374908209019 this endpoint is ready for FE review, please sync to proceed to review if it meets FE expectations and with the OWASP security review (integration blocked until after Georgia deployment). | -| 4 | Unknown | 2026-02-18 | https://app.asana.com/1/45238840754660/profile/1209203898446158 https://app.asana.com/1/45238840754660/profile/1208374908209019 this endpoint is ready for FE review, please sync to proceed to review if it meets FE expectations and with the OWASP security review (integration blocked until after Georgia deployment). | -| 5 | Parag More | 2026-02-20 | All the cost values are showing up zero for all interval types , please check https://app.asana.com/1/45238840754660/profile/1209203898446158


{
"log": [
{
"ts": 1767225600000,
"consumptionMWh": 173.3691348,
"energyCostsUSD": 0,
"operationalCostsUSD": 0,
"totalCostsUSD": 0,
"allInCostPerMWh": 0,
"energyCostPerMWh": 0,
"btcPrice": 0,
"y... | -| 6 | Parag More | 2026-02-20 | Postman Collection | -| 7 | Unknown | 2026-02-23 | https://app.asana.com/1/45238840754660/profile/1207496533136374 please review with a focus on incorrect API calls, data aggregation issues, and anything else that could affect the feature. | -| 8 | Roberto Dilillo | 2026-03-04 | All Cost Values Returning Zero
Status: CONFIRMED BY CODE — root cause identified
A peer reviewer reported all cost values are zero for all interval types. Three independent issues contribute.
Root Cause 1: Production costs not configured or getProductionCosts returns empty
The cost data flow:
FE Cost Input page → setProductionCostsData() → LevelDB (key: year*100+month)
                                                          ↓
                               getProductionCos... | -| 9 | Roberto Dilillo | 2026-03-04 | Review & Improvement Suggestions
A. Add "costs configured" indicator to response
return {
  log: aggregated,
  summary,
  meta: {
    costsConfigured: Object.keys(costsByMonth).length > 0,
    monthsCovered: Object.keys(costsByMonth)
  }
}
B. Fix date filter to include first partial month
// Current — excludes first partial month
const startDate = new Date(start)
return entryDate >= startDate && entryDate <= endDate

// Fixed — use start-of-month for ... | -| 10 | Roberto Dilillo | 2026-03-04 | Security
Good
Auth works, site-scoped. Standard finance endpoint gaps: no rate limiting, no Cache-Control, negative timestamps.
FE Readiness
Partially Broken
Cost fields are 0 when production costs aren't configured (likely on dev). btcPrice always 0 (wrong RPC key). No indicator for "costs not configured". Ratio fields wrong for monthly/yearly.
Response Design
Needs Work
No costs-configured indicator, wrong BTC price, ratio aggregation bug, first month excluded.
Backe... | - -### Attachments -- [MiningOS_Finance_APIs.postman_collection.json](https://asanausercontent.com/us1/assets/45238840754660/1213348817875998/d1ecd1804492edc9767612e235b6f64b?e=1773057165&v=0&t=e8-johshej8tzEE8W2Bn-tu-FdmBIFh-RLrfGIPWxKs) - ---- - -## GET /auth/finance/subsidy-fees — [1213145436151988](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436151988) -**Assignee:** Caesar Mukama -**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing - -### Comments -| # | Author | Date | Comment | -|---|--------|------|---------| -| 1 | Caesar Mukama | 2026-02-19 | PR: https://github.com/tetherto/miningos-app-node/pull/14 | -| 2 | Parag More | 2026-02-26 | https://app.asana.com/1/45238840754660/profile/1209203898446158

None of them send back data, log and summary are having empty values

curl --location 'https://dev-moria.tether.to/auth/finance/subsidy-fees?start=1764339562260&end=1772115562260&period=daily' \
--header 'Authorization: Bearer pub:abc-roles:admin'

curl --location 'https://dev-moria.tether.to/auth/finance/subsidy-fees?start=1764339562260&end=1772115562260&period=weekly' \
--header 'Authorization: Bearer pub:... | -| 3 | Parag More | 2026-02-26 | Also IMO we should add validation in all period apis to fail if negative timestamps are passed | -| 4 | Parag More | 2026-02-26 | Collection used for basic tests. and performed manual tests to check the response data and structure | - -### Attachments -- [MiningOS_Finance_Subsidy_Fees_API.postman_collection.json](https://asanausercontent.com/us1/assets/45238840754660/1213453334188221/a62a4b8265a5e7d83437458382ee69dd?e=1773057165&v=0&t=ktg756b3S_VgCYRSt3XNGn4bmR_J6XBPe4sRHzvXxh4) - ---- - -## GET /auth/finance/hash-revenue — [1213145436151974](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436151974) -**Assignee:** Caesar Mukama -**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing - -### Comments -| # | Author | Date | Comment | -|---|--------|------|---------| -| 1 | Caesar Mukama | 2026-03-06 | PR: https://github.com/tetherto/miningos-app-node/pull/27 | - -### Attachments -_No attachments._ - ---- - -## GET /auth/mempool/stats/bitcoin — [1213145436151982](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436151982) -**Assignee:** Caesar Mukama -**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing - -### Comments -_No comments._ - -### Attachments -_No attachments._ - ---- - -## GET /auth/mempool/price/bitcoin — [1213145436151996](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436151996) -**Assignee:** Caesar Mukama -**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing - -### Comments -_No comments._ - -### Attachments -_No attachments._ - ---- - -## GET /auth/reports/operations — [1213145436152000](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436152000) -**Assignee:** Caesar Mukama -**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing - -### Comments -_No comments._ - -### Attachments -_No attachments._ - ---- - -## /auth/pool-stats/aggregate — [1213145436151998](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436151998) -**Assignee:** Caesar Mukama -**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing - -### Comments -| # | Author | Date | Comment | -|---|--------|------|---------| -| 1 | Caesar Mukama | 2026-02-12 | PR: https://github.com/tetherto/miningos-app-node/pull/9 | -| 2 | Caesar Mukama | 2026-02-15 | PR: https://github.com/tetherto/miningos-app-node/pull/11 | -| 3 | Unknown | 2026-02-17 | https://app.asana.com/1/45238840754660/profile/1209203898446158 https://app.asana.com/1/45238840754660/profile/1208374908209019 this endpoint is ready for FE review, please sync to proceed to review if it meets FE expectations and with the OWASP security review (integration blocked until after Georgia deployment). | -| 4 | Unknown | 2026-02-18 | https://app.asana.com/1/45238840754660/profile/1209203898446158 https://app.asana.com/1/45238840754660/profile/1208374908209019 this endpoint is ready for FE review, please sync to proceed to review if it meets FE expectations and with the OWASP security review (integration blocked until after Georgia deployment). | -| 5 | Parag More | 2026-02-26 | https://app.asana.com/1/45238840754660/profile/1209203898446158 for

https://dev-moria.tether.to/auth/pool-stats/aggregate?start=1764335313758&end=1772111313758&range=daily

Its giving only 59 days of data, instead of 90 days as per timestamps above | -| 6 | Parag More | 2026-02-26 | https://app.asana.com/1/45238840754660/profile/1209203898446158
Also for range aggregates when we use monthly we see the monthName so its easy to know which month we are working with, but in weekly we get only ts, should we add the timerange over which we are considering the week rather than just timestamp?
One more point to note is its considering Sunday as start of week and not Monday.

Example data for week


{
"ts": 1769299200000,
... | -| 7 | Parag More | 2026-02-26 | https://app.asana.com/1/45238840754660/profile/1209203898446158

The pool filter is not working

curl --location 'https://dev-moria.tether.to/auth/pool-stats/aggregate?start=1764335955846&end=1772111955846&pool=antpool' \
--header 'Authorization: Bearer pub:api:ABC-roles:admin'

This one returns data | -| 8 | Parag More | 2026-02-26 | We also cant see the pool name if its expected in response | -| 9 | Parag More | 2026-02-26 | Used this collection to do basic tests and completed some manual testing by checking the api responses | -| 10 | Roberto Dilillo | 2026-03-02 | Summary Verdict

Area
Rating
Notes
Security
Good
Auth works, Cloudflare WAF active, CORS locked down. Main gaps: no rate limiting, no Cache-Control on financial data, overwriteCache exposed to all users.
FE Readiness
Partial
Core data shape works for pool stats charts, but workerCount is dead, balance is misleading, no per-pool breakdown, no USD conversion.
Response Design
Needs Work
Duplicate/misleading field names, no unit metadata, no data freshness indi... | -| 11 | Roberto Dilillo | 2026-03-02 | 1
Only 59 days instead of 90
CONFIRMED
processTransactionData only creates entries for days with transactions — no gap-filling
2
Weekly uses Sunday as start
CONFIRMED
getUTCDay() returns 0 for Sunday, used directly as offset — should use ISO Monday
3
Weekly lacks range metadata
CONFIRMED
Monthly gets monthName/year/month, weekly only gets bare ts
4
Pool filter doesn't work
CONFIRMED
pool is sent to ORK RPC but processTransactionData has zero pool filt... | -| 12 | Roberto Dilillo | 2026-03-02 | https://app.asana.com/1/45238840754660/profile/1205063919763609 i did the review and owasp of this one, how should the process work? who should i pass my tickets to for checking them? | -| 13 | andreu.honzawa@tether.to | 2026-03-03 | https://app.asana.com/1/45238840754660/profile/1209203898446158 check the feedback provided by https://app.asana.com/1/45238840754660/profile/1208374908209019 in the subtasks, moving this ticket back to you | -| 14 | andreu.honzawa@tether.to | 2026-03-03 | https://github.com/tetherto/miningos-app-node/pull/25 | -| 15 | andreu.honzawa@tether.to | 2026-03-03 | https://app.asana.com/1/45238840754660/profile/1208374908209019 I just check with https://app.asana.com/1/45238840754660/profile/1209203898446158 and he said this is not clear can you please help clarify

https://app.asana.com/app/asana/-/get_asset?asset_id=1213507404731604
| -| 16 | Roberto Dilillo | 2026-03-04 | please feel free to reach out or type here any question https://app.asana.com/1/45238840754660/profile/1209203898446158. Avoid generic "clarify" requests because the above is a report that takes half a day to write and it includes multiple things.

cc https://app.asana.com/1/45238840754660/profile/1205063919763609 | -| 17 | Caesar Mukama | 2026-03-04 | Thanks for the review https://app.asana.com/1/45238840754660/profile/1208374908209019 Absolutely,
Duplicate/misleading field names - what names are misleading?
No unit metadata - what metadata is missing? Also, is there a spec document for expected metadata or are these new features?
No data freshness indicators - what are data freshness indicators? Is there a spec document not being followed or are these new features?
Math.abs accounting issues - is math.abs being ap... | -| 18 | Roberto Dilillo | 2026-03-04 | Duplicate/misleading field names — what names are misleading?
information were written in subtask https://app.asana.com/1/45238840754660/task/1213314123096942/comment/1213497616048404?focus=true, and you can find in the table the owasp number and check details in the subtask

balance in log[] entries. This does not represent the actual pool balance. It's just a copy of revenueBTC (the period's revenue). The handler code at line ~221 does balance: data.revenueBTC. So if the fron... | - -### Attachments -- [MiningOS_Pool_Stats_Aggregate_API.postman_collection.json](https://asanausercontent.com/us1/assets/45238840754660/1213453334185116/d05c5d269a6b1d292158236e017d5bd6?e=1773057165&v=0&t=gHFGeQSrzn3kp6pURDfZlR8IThRY23IET4w-KQZe3ts) -- [image.png](https://asanausercontent.com/us1/assets/45238840754660/1213507404731603/d726b7c927223a0115911951ea94bd2f?e=1773057165&v=0&t=hJIvo67AT-fZqN_g8D0fxMXiZOgIA-VeyNZ0JGjM54I) - ---- - -## GET /auth/pools/:pool/balance-history — [1213145436151994](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436151994) -**Assignee:** Roberto Dilillo -**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing - -### Comments -| # | Author | Date | Comment | -|---|--------|------|---------| -| 1 | Caesar Mukama | 2026-02-12 | PR: https://github.com/tetherto/miningos-app-node/pull/8 | -| 2 | Caesar Mukama | 2026-02-15 | PR: https://github.com/tetherto/miningos-app-node/pull/11 | -| 3 | Unknown | 2026-02-17 | https://app.asana.com/1/45238840754660/profile/1209203898446158 https://app.asana.com/1/45238840754660/profile/1208374908209019 this endpoint is ready for FE review, please sync to proceed to review if it meets FE expectations and with the OWASP security review (integration blocked until after Georgia deployment). | -| 4 | Unknown | 2026-02-18 | https://app.asana.com/1/45238840754660/profile/1209203898446158 https://app.asana.com/1/45238840754660/profile/1208374908209019 this endpoint is ready for FE review, please sync to proceed to review if it meets FE expectations and with the OWASP security review (integration blocked until after Georgia deployment). | -| 5 | Parag More | 2026-02-26 | https://app.asana.com/1/45238840754660/profile/1209203898446158the pool filter does not work and returns same data for all the pool params

ex:

curl --location 'https://dev-moria.tether.to/auth/pools/ant/balance-history?start=1764338181148&end=1772114181148&range=1W' \
--header 'Authorization: Bearer pub:api:ABC-roles:admin'

give back data, but ant pool does not exist on staging | -| 6 | Parag More | 2026-02-26 | https://app.asana.com/1/45238840754660/profile/1209203898446158the pool-stats/aggregate api uses range: weekly / monthly etc. but

This api expects 1W / 1D / 1M. can we follow same convention for all apis and not implement seperate for each one of them | -| 7 | Parag More | 2026-02-26 | For

curl --location 'https://dev-moria.tether.to/auth/pools/ant/balance-history?start=1764338387569&end=1772114387569&range=1M' \
--header 'Authorization: Bearer pub:ABC:admin'

It should have returned data monthly with month year and other response structure like the pool-stats/aggregate api but thats not the case and the response structure is completely different and returns only one data point.

:

{
"log": [
{
"ts": 1762560000000,<... | -| 8 | Parag More | 2026-02-26 | This api call returns only few datapoints. but ideally should have almost 90

curl --location 'https://dev-moria.tether.to/auth/pools/ant/balance-history?start=1764338513764&end=1772114513764' \
--header 'Authorization: Bearer pub:api:ABC-roles:admin'

returned respons


{
"log": [
{
"ts": 1764374400000,
"balance": 0.0007894665835364325,
"hashrate": 611539599417678,
"revenue": 0.000789466583536... | -| 9 | Parag More | 2026-02-26 | Used this collection for basic testing and then did manual testing of the response structure and api responses expected | -| 10 | andreu.honzawa@tether.to | 2026-03-03 | https://github.com/tetherto/miningos-app-node/pull/25 | - -### Attachments -- [MiningOS_Pool_Balance_History_API.postman_collection.json](https://asanausercontent.com/us1/assets/45238840754660/1213453334188204/6950bba963a971531c8e67c9bcb7bff6?e=1773057165&v=0&t=RNDl3a4wWSCjXnJ1rek_vVcBepy5kIsAGvUHe-nh4sE) - ---- - -## GET /auth/alerts/history — [1213145436152002](https://app.asana.com/1/45238840754660/project/1212897658511275/task/1213145436152002) -**Assignee:** Caesar Mukama -**Description:** https://docs.google.com/document/d/1hkdYCYeS1V8jR6Ot0PdZsEHq4m8g3r753BZJht5mBSM/edit?usp=sharing - -### Comments -_No comments._ - -### Attachments -_No attachments._ From f19060db299f0fe14a93468e73fe6ab9ecc7802f Mon Sep 17 00:00:00 2001 From: Caesar Mukama Date: Tue, 10 Mar 2026 15:09:52 +0300 Subject: [PATCH 08/10] fix: guard against undefined error.message in onError hook --- workers/http.node.wrk.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workers/http.node.wrk.js b/workers/http.node.wrk.js index 2a0fe91..9b5699c 100644 --- a/workers/http.node.wrk.js +++ b/workers/http.node.wrk.js @@ -104,7 +104,7 @@ class WrkServerHttp extends TetherWrkBase { }) httpd.addHook('onError', async (request, reply, error) => { - const isSafe = error.message.startsWith('ERR_') + const isSafe = error.message && error.message.startsWith('ERR_') const message = isSafe ? error.message : 'Bad Request' if (!isSafe) { From e794fec17f80ae1d01b575438c63da3955e7eee0 Mon Sep 17 00:00:00 2001 From: Caesar Mukama Date: Tue, 10 Mar 2026 15:12:46 +0300 Subject: [PATCH 09/10] fix: add minimum:0 timestamp validation to finance and alerts schemas --- workers/lib/server/schemas/alerts.schemas.js | 4 ++-- workers/lib/server/schemas/finance.schemas.js | 24 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/workers/lib/server/schemas/alerts.schemas.js b/workers/lib/server/schemas/alerts.schemas.js index 5173c31..47bb212 100644 --- a/workers/lib/server/schemas/alerts.schemas.js +++ b/workers/lib/server/schemas/alerts.schemas.js @@ -16,8 +16,8 @@ const schemas = { alertsHistory: { type: 'object', properties: { - start: { type: 'integer' }, - end: { type: 'integer' }, + start: { type: 'integer', minimum: 0 }, + end: { type: 'integer', minimum: 0 }, filter: { type: 'string' }, search: { type: 'string' }, sort: { type: 'string' }, diff --git a/workers/lib/server/schemas/finance.schemas.js b/workers/lib/server/schemas/finance.schemas.js index bde6d99..b4fee03 100644 --- a/workers/lib/server/schemas/finance.schemas.js +++ b/workers/lib/server/schemas/finance.schemas.js @@ -5,8 +5,8 @@ const schemas = { energyBalance: { type: 'object', properties: { - start: { type: 'integer' }, - end: { type: 'integer' }, + start: { type: 'integer', minimum: 0 }, + end: { type: 'integer', minimum: 0 }, period: { type: 'string', enum: ['daily', 'monthly', 'yearly'] }, overwriteCache: { type: 'boolean' } }, @@ -15,8 +15,8 @@ const schemas = { ebitda: { type: 'object', properties: { - start: { type: 'integer' }, - end: { type: 'integer' }, + start: { type: 'integer', minimum: 0 }, + end: { type: 'integer', minimum: 0 }, period: { type: 'string', enum: ['daily', 'monthly', 'yearly'] }, overwriteCache: { type: 'boolean' } }, @@ -25,8 +25,8 @@ const schemas = { costSummary: { type: 'object', properties: { - start: { type: 'integer' }, - end: { type: 'integer' }, + start: { type: 'integer', minimum: 0 }, + end: { type: 'integer', minimum: 0 }, period: { type: 'string', enum: ['daily', 'monthly', 'yearly'] }, overwriteCache: { type: 'boolean' } }, @@ -35,8 +35,8 @@ const schemas = { subsidyFees: { type: 'object', properties: { - start: { type: 'integer' }, - end: { type: 'integer' }, + start: { type: 'integer', minimum: 0 }, + end: { type: 'integer', minimum: 0 }, period: { type: 'string', enum: ['daily', 'weekly', 'monthly'] }, overwriteCache: { type: 'boolean' } }, @@ -45,8 +45,8 @@ const schemas = { revenue: { type: 'object', properties: { - start: { type: 'integer' }, - end: { type: 'integer' }, + start: { type: 'integer', minimum: 0 }, + end: { type: 'integer', minimum: 0 }, period: { type: 'string', enum: ['daily', 'weekly', 'monthly', 'yearly'] }, pool: { type: 'string' }, overwriteCache: { type: 'boolean' } @@ -56,8 +56,8 @@ const schemas = { revenueSummary: { type: 'object', properties: { - start: { type: 'integer' }, - end: { type: 'integer' }, + start: { type: 'integer', minimum: 0 }, + end: { type: 'integer', minimum: 0 }, period: { type: 'string', enum: ['daily', 'monthly', 'yearly'] }, overwriteCache: { type: 'boolean' } }, From 4893b82c905fbd1268256e8d4778e3dc06cdc670 Mon Sep 17 00:00:00 2001 From: Caesar Mukama Date: Tue, 10 Mar 2026 16:13:19 +0300 Subject: [PATCH 10/10] fix: address PR review feedback - remove nginx-duplicate headers and unused limit param --- tests/unit/handlers/metrics.handlers.test.js | 18 +++--------------- workers/http.node.wrk.js | 5 ----- workers/lib/constants.js | 1 - .../lib/server/handlers/metrics.handlers.js | 3 +-- workers/lib/server/routes/metrics.routes.js | 3 +-- workers/lib/server/schemas/metrics.schemas.js | 1 - 6 files changed, 5 insertions(+), 26 deletions(-) diff --git a/tests/unit/handlers/metrics.handlers.test.js b/tests/unit/handlers/metrics.handlers.test.js index 202d129..8b3f1a0 100644 --- a/tests/unit/handlers/metrics.handlers.test.js +++ b/tests/unit/handlers/metrics.handlers.test.js @@ -1127,7 +1127,7 @@ test('getPowerModeTimeline - always uses t-miner tag', async (t) => { t.pass() }) -test('getPowerModeTimeline - uses limit param to truncate results', async (t) => { +test('getPowerModeTimeline - returns all results without truncation', async (t) => { const mockCtx = { conf: { orks: [{ rpcPublicKey: 'key1' }] @@ -1148,22 +1148,10 @@ test('getPowerModeTimeline - uses limit param to truncate results', async (t) => } const result = await getPowerModeTimeline(mockCtx, { - query: { start: 1700000000000, end: 1700100000000, limit: 2 } + query: { start: 1700000000000, end: 1700100000000 } }) - t.is(result.log.length, 2, 'should truncate log to limit') - t.pass() -}) - -test('getPowerModeTimeline - uses default limit when not provided', async (t) => { - const mockCtx = { - conf: { orks: [{ rpcPublicKey: 'key1' }] }, - net_r0: { jRequest: async () => ([]) } - } - - const result = await getPowerModeTimeline(mockCtx, { query: {} }) - t.ok(result.log, 'should return log with default limit applied') - t.ok(Array.isArray(result.log), 'should be array') + t.is(result.log.length, 5, 'should return all results') t.pass() }) diff --git a/workers/http.node.wrk.js b/workers/http.node.wrk.js index 9b5699c..a4f80f0 100644 --- a/workers/http.node.wrk.js +++ b/workers/http.node.wrk.js @@ -98,11 +98,6 @@ class WrkServerHttp extends TetherWrkBase { httpd.addRoute(r) }) - httpd.addHook('onSend', async (request, reply) => { - reply.header('X-Content-Type-Options', 'nosniff') - reply.header('Cache-Control', 'no-store') - }) - httpd.addHook('onError', async (request, reply, error) => { const isSafe = error.message && error.message.startsWith('ERR_') const message = isSafe ? error.message : 'Bad Request' diff --git a/workers/lib/constants.js b/workers/lib/constants.js index 3b026dc..bdcbaed 100644 --- a/workers/lib/constants.js +++ b/workers/lib/constants.js @@ -272,7 +272,6 @@ const METRICS_TIME = { } const METRICS_DEFAULTS = { - TIMELINE_LIMIT: 10080, CONTAINER_HISTORY_LIMIT: 10080 } diff --git a/workers/lib/server/handlers/metrics.handlers.js b/workers/lib/server/handlers/metrics.handlers.js index ef2b912..42a4be9 100644 --- a/workers/lib/server/handlers/metrics.handlers.js +++ b/workers/lib/server/handlers/metrics.handlers.js @@ -380,7 +380,6 @@ async function getPowerModeTimeline (ctx, req) { const start = Number(req.query.start) || (now - METRICS_TIME.ONE_MONTH_MS) const end = Number(req.query.end) || now const container = req.query.container || null - const limit = Number(req.query.limit) || METRICS_DEFAULTS.TIMELINE_LIMIT if (start >= end) { throw new Error('ERR_INVALID_DATE_RANGE') @@ -400,7 +399,7 @@ async function getPowerModeTimeline (ctx, req) { const results = await requestRpcEachLimit(ctx, RPC_METHODS.TAIL_LOG, rpcPayload) - const log = processPowerModeTimelineData(results, container).slice(0, limit) + const log = processPowerModeTimelineData(results, container) return { log } } diff --git a/workers/lib/server/routes/metrics.routes.js b/workers/lib/server/routes/metrics.routes.js index f2f27d4..c6a59ac 100644 --- a/workers/lib/server/routes/metrics.routes.js +++ b/workers/lib/server/routes/metrics.routes.js @@ -119,8 +119,7 @@ module.exports = (ctx) => { 'metrics/power-mode/timeline', req.query.start, req.query.end, - req.query.container, - req.query.limit + req.query.container ], ENDPOINTS.METRICS_POWER_MODE_TIMELINE, getPowerModeTimeline diff --git a/workers/lib/server/schemas/metrics.schemas.js b/workers/lib/server/schemas/metrics.schemas.js index de4c3c2..c21404c 100644 --- a/workers/lib/server/schemas/metrics.schemas.js +++ b/workers/lib/server/schemas/metrics.schemas.js @@ -54,7 +54,6 @@ const schemas = { start: { type: 'integer', minimum: 0 }, end: { type: 'integer', minimum: 0 }, container: { type: 'string' }, - limit: { type: 'integer', minimum: 1, maximum: 50000 }, overwriteCache: { type: 'boolean' } } },