Skip to content

docs: add detailed spec for real-time web analytics dashboard#861

Closed
grunch wants to merge 1 commit into
mainfrom
claude/bot-analytics-dashboard-spec-1qhaiy
Closed

docs: add detailed spec for real-time web analytics dashboard#861
grunch wants to merge 1 commit into
mainfrom
claude/bot-analytics-dashboard-spec-1qhaiy

Conversation

@grunch

@grunch grunch commented Jul 4, 2026

Copy link
Copy Markdown
Member

Add a comprehensive implementation guide for a read-only web dashboard
that connects to the bot's MongoDB and surfaces real-time operational and
financial statistics: top fiat currencies by successful orders, daily/
monthly/custom-range metrics, filters by order type and status, node
inbound/outbound sat flow, and earnings reconciliation.

Covers data model, canonical metric definitions, system architecture,
REST + WebSocket API, MongoDB aggregation pipelines, the exact fee/
earnings reconciliation formulas mirrored from the bot, Lightning node
fund-flow tracking, real-time via change streams, frontend views/filters,
security/privacy, indexing/caching, deployment, a phased plan, and tests.

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01X5uNqd26cC88p5HVqErRDU

Summary by CodeRabbit

  • Documentation
    • Added a comprehensive specification for a read-only Analytics Dashboard.
    • Defines key metrics, real-time updates, rankings, filters, financial reconciliation, and node activity views.
    • Outlines API endpoints, frontend layout, security/privacy rules, caching and indexing guidance, and a phased implementation plan.

Add a comprehensive implementation guide for a read-only web dashboard
that connects to the bot's MongoDB and surfaces real-time operational and
financial statistics: top fiat currencies by successful orders, daily/
monthly/custom-range metrics, filters by order type and status, node
inbound/outbound sat flow, and earnings reconciliation.

Covers data model, canonical metric definitions, system architecture,
REST + WebSocket API, MongoDB aggregation pipelines, the exact fee/
earnings reconciliation formulas mirrored from the bot, Lightning node
fund-flow tracking, real-time via change streams, frontend views/filters,
security/privacy, indexing/caching, deployment, a phased plan, and tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X5uNqd26cC88p5HVqErRDU
@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

This PR adds a single new documentation file, docs/ANALYTICS_DASHBOARD_SPEC.md, specifying a read-only analytics dashboard for lnp2pBot: scope, data model, metric definitions, architecture, REST API, MongoDB aggregation pseudocode, financial reconciliation, node fund flow, realtime strategy, frontend design, security, performance, deployment, testing, and appendices.

Changes

Analytics Dashboard Spec

Layer / File(s) Summary
Scope, context and data model
docs/ANALYTICS_DASHBOARD_SPEC.md
Adds document header/TOC, goals and out-of-scope items, bot buy/sell context, and data model fields for orders/users/communities/disputes/pendingpayments/configs.
Metrics definitions
docs/ANALYTICS_DASHBOARD_SPEC.md
Specifies canonical metrics for time bucketing, order success/volume rates, fiat rankings, finance, and node metrics.
Architecture and API design
docs/ANALYTICS_DASHBOARD_SPEC.md
Proposes SPA/Node.js architecture with REST+WS/SSE and caching, and defines REST endpoints, filter conventions, and realtime event payloads.
Aggregation pipelines and reconciliation
docs/ANALYTICS_DASHBOARD_SPEC.md
Adds MongoDB aggregation pseudocode, fee/earnings reconciliation formulas, and node incoming/outgoing/escrow fund flow specification.
Realtime strategy and frontend design
docs/ANALYTICS_DASHBOARD_SPEC.md
Describes change-streams/polling realtime approach with resilience, plus frontend pages, filters, and components.
Security, performance, deployment, testing
docs/ANALYTICS_DASHBOARD_SPEC.md
Covers auth/privacy rules, indexing/caching recommendations, deployment/env config, phased implementation plan, test strategy, and appendices.

Estimated code review effort: 2 (Simple) | ~10 minutes

Poem

A rabbit hops through docs so vast,
Metrics, sats, and rankings amassed 🐇
No code was touched, just words laid clear,
A dashboard's blueprint, drawing near.
Hop hop hooray, the spec is done!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the PR’s main change: adding a detailed real-time analytics dashboard specification in docs.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/bot-analytics-dashboard-spec-1qhaiy

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
docs/ANALYTICS_DASHBOARD_SPEC.md (1)

1030-1037: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Add index coverage for reconciliation and payout filters.

The proposed indexes miss community_id, but your reconciliation and earnings/withdrawal queries filter on it. Without that field in the compound keys, those paths will stay scan-heavy as the dataset grows.

📈 Suggested index adjustments
-orders: { status: 1, calculated: 1 }                  // conciliación
-pendingpayments: { paid: 1, last_error: 1 }
+orders: { community_id: 1, status: 1, calculated: 1 } // conciliación
+pendingpayments: { community_id: 1, paid: 1, last_error: 1 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/ANALYTICS_DASHBOARD_SPEC.md` around lines 1030 - 1037, The index list in
the analytics dashboard spec is missing `community_id` coverage for the
reconciliation and payout-related query paths, so update the index
recommendations around the `orders` index definitions to include a compound key
that starts with or includes `community_id` alongside the existing `status`,
`created_at`, `type`, or `calculated` filters. Use the `orders` index entries in
this section to locate the affected recommendations and adjust them so the
reconciliation and earnings/withdrawal queries can use an index instead of
scanning.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/ANALYTICS_DASHBOARD_SPEC.md`:
- Around line 426-433: Clarify the semantics of the orders analytics endpoints
in ANALYTICS_DASHBOARD_SPEC so the time axis is explicitly based on created_at
and not on status-transition time; update the wording around GET
/api/v1/orders/count, GET /api/v1/orders/summary, GET /api/v1/orders/timeseries,
and GET /api/v1/orders/status-breakdown to say “orders created in the period and
currently in the selected status/type” rather than “orders canceled/successful
during the period.” If event-time analytics are intended, note that the model
must expose transition timestamps such as canceled_at and success_at, or
otherwise narrow the endpoint descriptions accordingly.
- Line 1071: The example Mongo URI in the analytics dashboard spec includes
embedded credentials, which should be removed from the sample. Update the
ANALYTICS_MONGO_URI example to use a redacted host-only URI and keep
authentication material out of the documented config; locate the example by the
ANALYTICS_MONGO_URI symbol in the docs and replace the credentialed form with a
safer placeholder.
- Around line 538-557: The ranking pipeline in the analytics spec currently
computes only unique buyers via traders/$addToSet on buyer_id, which does not
match the defined unique_traders metric. Update the aggregation in
ANALYTICS_DASHBOARD_SPEC to either compute the buyer_id ∪ seller_id union before
$size (using the existing unique_traders definition) or rename the exposed field
everywhere to unique_buyers so the metric and pipeline stay consistent.

---

Nitpick comments:
In `@docs/ANALYTICS_DASHBOARD_SPEC.md`:
- Around line 1030-1037: The index list in the analytics dashboard spec is
missing `community_id` coverage for the reconciliation and payout-related query
paths, so update the index recommendations around the `orders` index definitions
to include a compound key that starts with or includes `community_id` alongside
the existing `status`, `created_at`, `type`, or `calculated` filters. Use the
`orders` index entries in this section to locate the affected recommendations
and adjust them so the reconciliation and earnings/withdrawal queries can use an
index instead of scanning.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 8dc63b0a-1768-4b2d-8001-78cf32ff3138

📥 Commits

Reviewing files that changed from the base of the PR and between b80cb35 and 03f8243.

📒 Files selected for processing (1)
  • docs/ANALYTICS_DASHBOARD_SPEC.md

Comment on lines +426 to +433
- `GET /api/v1/orders/summary` — conteos por estado y por tipo en el rango.
- `GET /api/v1/orders/timeseries` — serie temporal por `granularity` de una
métrica (`metric=count|volume_sats|volume_fiat|success_rate`), opcionalmente
desglosada (`groupBy=status|type|fiat`).
- `GET /api/v1/orders/status-breakdown` — distribución por estado (para donut).
- `GET /api/v1/orders/count?status=CANCELED&from=…&to=…` — caso de uso explícito:
"número de órdenes canceladas en un periodo". (Atajo conveniente.)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Clarify the time axis for status counts.

These queries count orders by created_at, so “canceladas en un periodo” means “created in the period and currently canceled,” not “canceled during the period.” If you need event-time analytics, the model needs explicit transition timestamps (canceled_at, success_at, etc.) or the endpoint wording should be narrowed.

Also applies to: 559-566

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/ANALYTICS_DASHBOARD_SPEC.md` around lines 426 - 433, Clarify the
semantics of the orders analytics endpoints in ANALYTICS_DASHBOARD_SPEC so the
time axis is explicitly based on created_at and not on status-transition time;
update the wording around GET /api/v1/orders/count, GET /api/v1/orders/summary,
GET /api/v1/orders/timeseries, and GET /api/v1/orders/status-breakdown to say
“orders created in the period and currently in the selected status/type” rather
than “orders canceled/successful during the period.” If event-time analytics are
intended, note that the model must expose transition timestamps such as
canceled_at and success_at, or otherwise narrow the endpoint descriptions
accordingly.

Comment on lines +538 to +557
```js
db.orders.aggregate([
{ $match: { status: "SUCCESS", created_at: { $gte: from, $lt: to } } },
{ $group: {
_id: "$fiat_code",
successful_orders: { $sum: 1 },
volume_sats: { $sum: "$amount" },
volume_fiat: { $sum: { $ifNull: ["$fiat_amount", 0] } },
avg_ticket_sats: { $avg: "$amount" },
traders: { $addToSet: "$buyer_id" } // aproximación; ver nota
}},
{ $addFields: { unique_buyers: { $size: "$traders" } } },
{ $project: { traders: 0 } },
{ $sort: { successful_orders: -1 } },
{ $limit: limit }
])
```

> Para `unique_traders` exacto (compradores ∪ vendedores) usar dos `$addToSet`
> (`buyer_id`, `seller_id`) y unir con `$setUnion` antes de `$size`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Align the ranking pipeline with unique_traders.

The metric definition says buyer ∪ seller cardinality, but the pipeline only deduplicates buyer_id and then exposes unique_buyers. Either compute the union here or rename the metric, otherwise the ranking will systematically undercount.

♻️ Proposed fix
-      traders: { $addToSet: "$buyer_id" }      // aproximación; ver nota
-  }},
-  { $addFields: { unique_buyers: { $size: "$traders" } } },
-  { $project: { traders: 0 } },
+      buyers: { $addToSet: "$buyer_id" },
+      sellers: { $addToSet: "$seller_id" }
+  }},
+  { $addFields: {
+      unique_traders: {
+        $size: { $setUnion: ["$buyers", "$sellers"] }
+      }
+  }},
+  { $project: { buyers: 0, sellers: 0 } },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
```js
db.orders.aggregate([
{ $match: { status: "SUCCESS", created_at: { $gte: from, $lt: to } } },
{ $group: {
_id: "$fiat_code",
successful_orders: { $sum: 1 },
volume_sats: { $sum: "$amount" },
volume_fiat: { $sum: { $ifNull: ["$fiat_amount", 0] } },
avg_ticket_sats: { $avg: "$amount" },
traders: { $addToSet: "$buyer_id" } // aproximación; ver nota
}},
{ $addFields: { unique_buyers: { $size: "$traders" } } },
{ $project: { traders: 0 } },
{ $sort: { successful_orders: -1 } },
{ $limit: limit }
])
```
> Para `unique_traders` exacto (compradores ∪ vendedores) usar dos `$addToSet`
> (`buyer_id`, `seller_id`) y unir con `$setUnion` antes de `$size`.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/ANALYTICS_DASHBOARD_SPEC.md` around lines 538 - 557, The ranking
pipeline in the analytics spec currently computes only unique buyers via
traders/$addToSet on buyer_id, which does not match the defined unique_traders
metric. Update the aggregation in ANALYTICS_DASHBOARD_SPEC to either compute the
buyer_id ∪ seller_id union before $size (using the existing unique_traders
definition) or rename the exposed field everywhere to unique_buyers so the
metric and pipeline stay consistent.


```bash
# Conexión DB (solo lectura)
ANALYTICS_MONGO_URI='mongodb://readonly_user:pass@host:27017/p2plnbot?authSource=admin&readPreference=secondaryPreferred'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Remove credentials from the example Mongo URI.

Even as a sample, readonly_user:pass@... encourages putting auth material directly in config. Prefer a redacted host-only URI and separate secret delivery for credentials.

🔐 Safer example
-ANALYTICS_MONGO_URI='mongodb://readonly_user:pass@host:27017/p2plnbot?authSource=admin&readPreference=secondaryPreferred'
+ANALYTICS_MONGO_URI='mongodb://host:27017/p2plnbot?authSource=admin&readPreference=secondaryPreferred'
+# Provide username/password via your secret store or separate env vars.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ANALYTICS_MONGO_URI='mongodb://readonly_user:pass@host:27017/p2plnbot?authSource=admin&readPreference=secondaryPreferred'
ANALYTICS_MONGO_URI='mongodb://host:27017/p2plnbot?authSource=admin&readPreference=secondaryPreferred'
# Provide username/password via your secret store or separate env vars.
🧰 Tools
🪛 Betterleaks (1.6.0)

[high] 1071-1071: Detected a MongoDB connection string with embedded credentials, potentially exposing direct database access and sensitive application data.

(mongodb-connection-string)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/ANALYTICS_DASHBOARD_SPEC.md` at line 1071, The example Mongo URI in the
analytics dashboard spec includes embedded credentials, which should be removed
from the sample. Update the ANALYTICS_MONGO_URI example to use a redacted
host-only URI and keep authentication material out of the documented config;
locate the example by the ANALYTICS_MONGO_URI symbol in the docs and replace the
credentialed form with a safer placeholder.

@grunch grunch closed this Jul 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants