Initial commit
This commit is contained in:
327
starter-docs/admin_endpoints.md
Normal file
327
starter-docs/admin_endpoints.md
Normal file
@@ -0,0 +1,327 @@
|
||||
# Cashumints.space – Admin Endpoints
|
||||
|
||||
This document defines the **admin-only API surface** of Cashumints.space.
|
||||
|
||||
These endpoints exist to:
|
||||
|
||||
* curate mint data safely
|
||||
* correct discovery or URL issues
|
||||
* resolve identity conflicts
|
||||
* force recomputation when rules change
|
||||
* debug the background system
|
||||
|
||||
Admin endpoints **never fabricate reality**. They annotate, correct routing, or trigger recomputation, but they do not delete historical data.
|
||||
|
||||
---
|
||||
|
||||
## General Rules
|
||||
|
||||
* Base path: `/v1/admin`
|
||||
* Authentication: `ADMIN_API_KEY` (static header)
|
||||
* All admin actions are **audited**
|
||||
* No admin endpoint deletes raw data
|
||||
* Every mutation writes to the admin audit log
|
||||
|
||||
Audit log fields:
|
||||
|
||||
* admin_id
|
||||
* action
|
||||
* target
|
||||
* before_state
|
||||
* after_state
|
||||
* timestamp
|
||||
|
||||
---
|
||||
|
||||
## POST /v1/admin/mints
|
||||
|
||||
### Purpose
|
||||
|
||||
Manually add a mint to the system.
|
||||
|
||||
Used for:
|
||||
|
||||
* trusted bootstrap
|
||||
* known operators
|
||||
* recovery when auto-discovery fails
|
||||
|
||||
### Request body
|
||||
|
||||
```
|
||||
{
|
||||
"mint_url": "https://mint.example",
|
||||
"notes": "optional internal notes"
|
||||
}
|
||||
```
|
||||
|
||||
### Logic
|
||||
|
||||
1. Normalize the URL
|
||||
2. Check if URL already exists in `mint_urls`
|
||||
3. If exists:
|
||||
|
||||
* return existing mint_id
|
||||
4. If not:
|
||||
|
||||
* create new mint record
|
||||
* status = `unknown`
|
||||
* discovered_from = `manual`
|
||||
* create mint_url entry (active)
|
||||
5. Enqueue immediate probe job
|
||||
|
||||
### Response
|
||||
|
||||
```
|
||||
{
|
||||
"mint_id": "uuid",
|
||||
"status": "unknown",
|
||||
"message": "Mint added and scheduled for probing"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## POST /v1/admin/mints/{mint_id}/urls
|
||||
|
||||
### Purpose
|
||||
|
||||
Manually attach an additional URL (clearnet, Tor, mirror) to an existing mint.
|
||||
|
||||
### Request body
|
||||
|
||||
```
|
||||
{
|
||||
"url": "http://example.onion",
|
||||
"type": "tor",
|
||||
"active": true
|
||||
}
|
||||
```
|
||||
|
||||
### Logic
|
||||
|
||||
1. Normalize URL
|
||||
2. Ensure URL is not linked to another mint
|
||||
3. Create mint_urls entry
|
||||
4. Mark source = `admin`
|
||||
5. Enqueue probe for new URL
|
||||
|
||||
### Rules
|
||||
|
||||
* URLs are never deleted
|
||||
* If duplicate URL exists, return 409
|
||||
|
||||
---
|
||||
|
||||
## POST /v1/admin/mints/merge
|
||||
|
||||
### Purpose
|
||||
|
||||
Merge two mints that represent the same operator.
|
||||
|
||||
### Request body
|
||||
|
||||
```
|
||||
{
|
||||
"source_mint_id": "uuid",
|
||||
"target_mint_id": "uuid",
|
||||
"reason": "Same pubkey, different URLs"
|
||||
}
|
||||
```
|
||||
|
||||
### Logic
|
||||
|
||||
1. Validate both mint IDs exist
|
||||
2. Ensure source != target
|
||||
3. Create merge record
|
||||
4. Reassign all related data:
|
||||
|
||||
* mint_urls
|
||||
* probes
|
||||
* metadata history
|
||||
* reviews
|
||||
* rollups
|
||||
5. Mark source mint as `merged`
|
||||
6. Target mint becomes canonical
|
||||
|
||||
### Rules
|
||||
|
||||
* No data is deleted
|
||||
* Merge is reversible
|
||||
|
||||
---
|
||||
|
||||
## POST /v1/admin/mints/split
|
||||
|
||||
### Purpose
|
||||
|
||||
Undo a previous mint merge.
|
||||
|
||||
### Request body
|
||||
|
||||
```
|
||||
{
|
||||
"merge_id": "uuid"
|
||||
}
|
||||
```
|
||||
|
||||
### Logic
|
||||
|
||||
1. Load merge record
|
||||
2. Restore original mint records
|
||||
3. Reassign data back to original mint
|
||||
4. Mark merge record as reverted
|
||||
|
||||
### Rules
|
||||
|
||||
* Only one split per merge
|
||||
* Full restoration required
|
||||
|
||||
---
|
||||
|
||||
## POST /v1/admin/mints/{mint_id}/disable
|
||||
|
||||
### Purpose
|
||||
|
||||
Hide a mint from public listings without deleting it.
|
||||
|
||||
### Logic
|
||||
|
||||
1. Set mint.visibility = `hidden`
|
||||
2. Mint continues to be probed
|
||||
3. Mint remains accessible by direct ID or URL
|
||||
|
||||
### Use cases
|
||||
|
||||
* scam submissions
|
||||
* spam mints
|
||||
* broken test instances
|
||||
|
||||
---
|
||||
|
||||
## POST /v1/admin/mints/{mint_id}/enable
|
||||
|
||||
### Purpose
|
||||
|
||||
Re-enable a previously hidden mint.
|
||||
|
||||
### Logic
|
||||
|
||||
1. Set mint.visibility = `public`
|
||||
2. No other state changes
|
||||
|
||||
---
|
||||
|
||||
## POST /v1/admin/mints/{mint_id}/metadata/refresh
|
||||
|
||||
### Purpose
|
||||
|
||||
Force metadata fetch, bypassing the hourly limit.
|
||||
|
||||
### Logic
|
||||
|
||||
1. Enqueue metadata fetch job
|
||||
2. Ignore METADATA_FETCH_INTERVAL
|
||||
3. Metadata still validated normally
|
||||
|
||||
### Rules
|
||||
|
||||
* Does not fabricate metadata
|
||||
* Failure does not erase existing metadata
|
||||
|
||||
---
|
||||
|
||||
## POST /v1/admin/mints/{mint_id}/trust/recompute
|
||||
|
||||
### Purpose
|
||||
|
||||
Force trust score recomputation.
|
||||
|
||||
### Logic
|
||||
|
||||
1. Enqueue trust recompute job
|
||||
2. Uses current rollups, reviews, metadata
|
||||
3. Stores new score and breakdown
|
||||
|
||||
### Use cases
|
||||
|
||||
* scoring logic changes
|
||||
* review moderation
|
||||
* metadata correction
|
||||
|
||||
---
|
||||
|
||||
## GET /v1/admin/jobs
|
||||
|
||||
### Purpose
|
||||
|
||||
Inspect the background job queue.
|
||||
|
||||
### Returns
|
||||
|
||||
```
|
||||
[
|
||||
{
|
||||
"job_id": "uuid",
|
||||
"type": "probe_mint",
|
||||
"status": "pending",
|
||||
"run_at": "timestamp",
|
||||
"attempts": 2,
|
||||
"last_error": null
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Rules
|
||||
|
||||
* Read-only
|
||||
* No mutation
|
||||
|
||||
---
|
||||
|
||||
## GET /v1/admin/system/metrics
|
||||
|
||||
### Purpose
|
||||
|
||||
High-level system health view.
|
||||
|
||||
### Returns
|
||||
|
||||
* total_mints
|
||||
* online_mints
|
||||
* offline_mints
|
||||
* probes_last_minute
|
||||
* failed_probes_last_minute
|
||||
* job_backlog
|
||||
* oldest_job_age_seconds
|
||||
* database_size_mb
|
||||
* worker_heartbeat
|
||||
|
||||
Used for operations and debugging.
|
||||
|
||||
---
|
||||
|
||||
## POST /v1/admin/mints/{mint_id}/status/reset
|
||||
|
||||
### Purpose
|
||||
|
||||
Clear a stuck mint state caused by transient infrastructure issues.
|
||||
|
||||
### Logic
|
||||
|
||||
1. Reset consecutive_failures to 0
|
||||
2. Clear offline_since
|
||||
3. Do NOT change historical probes
|
||||
4. Enqueue immediate probe
|
||||
|
||||
### Rules
|
||||
|
||||
* Does not fabricate uptime
|
||||
* Next probe determines real status
|
||||
|
||||
---
|
||||
|
||||
## Final Admin Rule
|
||||
|
||||
Admins may correct **structure and routing**, but never rewrite **history or truth**.
|
||||
|
||||
If an action cannot be explained in the audit log, it does not belong in the admin API.
|
||||
229
starter-docs/endpoints.md
Normal file
229
starter-docs/endpoints.md
Normal file
@@ -0,0 +1,229 @@
|
||||
# Cashumints.space API – Endpoints
|
||||
|
||||
Base path:
|
||||
|
||||
/v1
|
||||
|
||||
All endpoints are read‑only unless stated otherwise.
|
||||
All timestamps are ISO‑8601 UTC.
|
||||
All mint‑specific endpoints accept either a mint ID or a mint URL.
|
||||
|
||||
---
|
||||
|
||||
## Resolution Rules
|
||||
|
||||
Endpoints support:
|
||||
- `/v1/mints/{mint_id}`
|
||||
- `/v1/mints/by-url?url=...`
|
||||
|
||||
The API resolves URLs to the canonical mint_id internally.
|
||||
|
||||
---
|
||||
|
||||
## Single Mint – Core
|
||||
|
||||
GET /v1/mints/{mint_id}
|
||||
GET /v1/mints/by-url?url=
|
||||
|
||||
Returns:
|
||||
- mint_id
|
||||
- canonical_url
|
||||
- urls[]
|
||||
- name
|
||||
- icon_url
|
||||
- status
|
||||
- offline_since
|
||||
- last_success_at
|
||||
- last_failure_at
|
||||
- uptime_24h
|
||||
- uptime_7d
|
||||
- uptime_30d
|
||||
- incidents_7d
|
||||
- incidents_30d
|
||||
- trust_score
|
||||
- trust_level
|
||||
|
||||
---
|
||||
|
||||
## Mint URLs
|
||||
|
||||
GET /v1/mints/{mint_id}/urls
|
||||
GET /v1/mints/by-url/urls?url=
|
||||
|
||||
Returns:
|
||||
- canonical_url
|
||||
- urls[]:
|
||||
- url
|
||||
- type (clearnet | tor | mirror)
|
||||
- active
|
||||
|
||||
---
|
||||
|
||||
## Metadata (NUT‑06)
|
||||
|
||||
GET /v1/mints/{mint_id}/metadata
|
||||
GET /v1/mints/by-url/metadata?url=
|
||||
|
||||
Returns:
|
||||
- name
|
||||
- pubkey
|
||||
- version
|
||||
- description
|
||||
- description_long
|
||||
- contact
|
||||
- motd
|
||||
- icon_url
|
||||
- urls
|
||||
- tos_url
|
||||
- nuts
|
||||
- server_time
|
||||
- last_fetched_at
|
||||
|
||||
---
|
||||
|
||||
GET /v1/mints/{mint_id}/metadata/history
|
||||
GET /v1/mints/by-url/metadata/history?url=
|
||||
|
||||
Returns:
|
||||
- fetched_at
|
||||
- change_type
|
||||
- diff
|
||||
- version
|
||||
|
||||
---
|
||||
|
||||
## Status (Lightweight)
|
||||
|
||||
GET /v1/mints/{mint_id}/status
|
||||
GET /v1/mints/by-url/status?url=
|
||||
|
||||
Returns:
|
||||
- status
|
||||
- offline_since
|
||||
- last_checked_at
|
||||
- current_rtt_ms
|
||||
|
||||
---
|
||||
|
||||
## Uptime & Reliability
|
||||
|
||||
GET /v1/mints/{mint_id}/uptime
|
||||
GET /v1/mints/by-url/uptime?url=
|
||||
|
||||
Query:
|
||||
- window=24h | 7d | 30d
|
||||
|
||||
Returns:
|
||||
- uptime_pct
|
||||
- downtime_seconds
|
||||
- avg_rtt_ms
|
||||
- p95_rtt_ms
|
||||
- total_checks
|
||||
- ok_checks
|
||||
|
||||
---
|
||||
|
||||
GET /v1/mints/{mint_id}/uptime/timeseries
|
||||
GET /v1/mints/by-url/uptime/timeseries?url=
|
||||
|
||||
Query:
|
||||
- window=24h | 7d | 30d
|
||||
- bucket=5m | 15m | 1h
|
||||
|
||||
Returns:
|
||||
- timestamp
|
||||
- state
|
||||
- ok
|
||||
- rtt_ms
|
||||
|
||||
---
|
||||
|
||||
## Incidents
|
||||
|
||||
GET /v1/mints/{mint_id}/incidents
|
||||
GET /v1/mints/by-url/incidents?url=
|
||||
|
||||
Returns:
|
||||
- started_at
|
||||
- resolved_at
|
||||
- duration_seconds
|
||||
- severity
|
||||
|
||||
---
|
||||
|
||||
## Trust
|
||||
|
||||
GET /v1/mints/{mint_id}/trust
|
||||
GET /v1/mints/by-url/trust?url=
|
||||
|
||||
Returns:
|
||||
- score_total
|
||||
- score_level
|
||||
- breakdown
|
||||
- computed_at
|
||||
|
||||
---
|
||||
|
||||
## Reviews (Nostr)
|
||||
|
||||
GET /v1/mints/{mint_id}/reviews
|
||||
GET /v1/mints/by-url/reviews?url=
|
||||
|
||||
Returns:
|
||||
- event_id
|
||||
- pubkey
|
||||
- created_at
|
||||
- rating
|
||||
- content
|
||||
|
||||
---
|
||||
|
||||
## Popularity
|
||||
|
||||
GET /v1/mints/{mint_id}/views
|
||||
GET /v1/mints/by-url/views?url=
|
||||
|
||||
Returns:
|
||||
- views_24h
|
||||
- views_7d
|
||||
- views_30d
|
||||
- unique_sessions_30d
|
||||
- view_velocity
|
||||
|
||||
---
|
||||
|
||||
## Derived Features
|
||||
|
||||
GET /v1/mints/{mint_id}/features
|
||||
GET /v1/mints/by-url/features?url=
|
||||
|
||||
Returns:
|
||||
- supported_nuts
|
||||
- supports_bolt11
|
||||
- min_amount
|
||||
- max_amount
|
||||
- has_tor_endpoint
|
||||
- has_multiple_urls
|
||||
- feature_completeness_score
|
||||
|
||||
---
|
||||
|
||||
## Submission
|
||||
|
||||
POST /v1/mints/submit
|
||||
|
||||
Body:
|
||||
- mint_url
|
||||
|
||||
Returns:
|
||||
- mint_id
|
||||
- status
|
||||
- message
|
||||
|
||||
---
|
||||
|
||||
## Health & Stats
|
||||
|
||||
GET /v1/health
|
||||
GET /v1/stats
|
||||
|
||||
240
starter-docs/full_overview.md
Normal file
240
starter-docs/full_overview.md
Normal file
@@ -0,0 +1,240 @@
|
||||
# Cashumints.space API – Full Overview
|
||||
|
||||
## Purpose
|
||||
The Cashumints.space API is a public, read‑only observability, discovery, and reputation API for the Cashu mint ecosystem.
|
||||
|
||||
It exists to:
|
||||
- Discover Cashu mints in a decentralized way
|
||||
- Track availability, uptime, and incidents over time
|
||||
- Fetch and keep mint metadata up to date using NUT‑06
|
||||
- Ingest and expose Nostr‑based mint reviews (NIP‑87)
|
||||
- Compute transparent and explainable trust scores
|
||||
- Provide rich analytics and time‑series data for frontends and wallets
|
||||
|
||||
It explicitly does NOT:
|
||||
- Custody funds
|
||||
- Interact with wallets
|
||||
- Simulate balances or volume
|
||||
- Require authentication for read access
|
||||
|
||||
The API is infrastructure, not a wallet.
|
||||
|
||||
---
|
||||
|
||||
## Core Design Principles
|
||||
|
||||
1. History is never erased
|
||||
All raw data is stored and aggregated later. Nothing is overwritten without keeping history.
|
||||
|
||||
2. Offline does not mean dead
|
||||
Mints move through states: unknown → online → degraded → offline → abandoned. Recovery is always possible.
|
||||
|
||||
3. URL is not identity
|
||||
Mint identity is stable even if URLs change. One mint can have multiple URLs.
|
||||
|
||||
4. Trust is derived, not asserted
|
||||
Every trust signal is computed from stored data and exposed with a breakdown.
|
||||
|
||||
5. Self‑hostable by default
|
||||
SQLite is the default database. PostgreSQL is optional. No Redis or external queues.
|
||||
|
||||
---
|
||||
|
||||
## High‑Level Architecture
|
||||
|
||||
### Layers
|
||||
|
||||
1. HTTP API
|
||||
- Serves public read‑only endpoints
|
||||
- Records pageviews
|
||||
- Accepts mint submissions
|
||||
- Enqueues background jobs
|
||||
|
||||
2. Database
|
||||
- SQLite by default
|
||||
- PostgreSQL optional
|
||||
- Single source of truth for:
|
||||
- mints
|
||||
- mint URLs
|
||||
- probes
|
||||
- metadata snapshots and history
|
||||
- uptime rollups
|
||||
- incidents
|
||||
- reviews
|
||||
- trust scores
|
||||
- pageviews
|
||||
- jobs
|
||||
|
||||
3. Workers
|
||||
- Stateless background processes
|
||||
- Poll database for jobs
|
||||
- Perform probes, aggregation, ingestion, scoring
|
||||
- Never serve user traffic
|
||||
|
||||
---
|
||||
|
||||
## Mint Identity Model
|
||||
|
||||
### Mint
|
||||
A mint is a logical entity identified internally by a stable `mint_id` (UUID).
|
||||
|
||||
### Mint URLs
|
||||
A mint may expose multiple URLs:
|
||||
- clearnet
|
||||
- Tor (.onion)
|
||||
- mirrors
|
||||
|
||||
URLs are aliases, not identities.
|
||||
|
||||
Any known URL resolves to the same mint_id.
|
||||
|
||||
---
|
||||
|
||||
## Mint Lifecycle
|
||||
|
||||
### Discovery
|
||||
Mints are discovered via:
|
||||
- Nostr review events (NIP‑87)
|
||||
- User submissions
|
||||
- Manual/admin additions
|
||||
- Imports
|
||||
|
||||
Initial state: `unknown`
|
||||
|
||||
### Verification
|
||||
After the first successful probe:
|
||||
- Status becomes `online`
|
||||
- Uptime tracking begins
|
||||
- Metadata fetching is enabled
|
||||
|
||||
### Failure and Recovery
|
||||
- Consecutive probe failures move the mint to `offline`
|
||||
- Long‑term offline mints become `abandoned`
|
||||
- A successful probe at any time revives the mint
|
||||
|
||||
---
|
||||
|
||||
## Status Model
|
||||
|
||||
Each mint is always in exactly one state:
|
||||
|
||||
- unknown: never successfully probed
|
||||
- online: recently reachable
|
||||
- degraded: reachable but unstable or slow
|
||||
- offline: previously online, now unreachable
|
||||
- abandoned: offline longer than configured threshold
|
||||
|
||||
---
|
||||
|
||||
## Probing and Uptime
|
||||
|
||||
- Probes are HTTP requests to mint endpoints
|
||||
- Every probe stores a result, success or failure
|
||||
- Probe frequency adapts to mint status
|
||||
- Raw probe data is aggregated into uptime rollups
|
||||
|
||||
Rollup windows:
|
||||
- 1 hour
|
||||
- 24 hours
|
||||
- 7 days
|
||||
- 30 days
|
||||
|
||||
Each rollup stores:
|
||||
- uptime percentage
|
||||
- average and percentile RTT
|
||||
- downtime duration
|
||||
- incident count
|
||||
|
||||
---
|
||||
|
||||
## Metadata (NUT‑06)
|
||||
|
||||
- Fetched from `/v1/info`
|
||||
- Only fetched after a successful probe
|
||||
- Fetched at most once per hour per mint
|
||||
- Stored as a current snapshot
|
||||
- All changes stored in history
|
||||
|
||||
Metadata includes:
|
||||
- name
|
||||
- pubkey
|
||||
- version
|
||||
- descriptions
|
||||
- contact info
|
||||
- MOTD
|
||||
- icon_url (stored as URL only)
|
||||
- supported NUTs
|
||||
- advertised URLs
|
||||
- TOS URL
|
||||
|
||||
---
|
||||
|
||||
## Nostr Reviews (NIP‑87)
|
||||
|
||||
- Ingested continuously from configured relays
|
||||
- Raw events stored immutably
|
||||
- Reviews linked to mints via URLs or identifiers
|
||||
- Ratings and content parsed when present
|
||||
|
||||
Used for:
|
||||
- Display
|
||||
- Trust scoring
|
||||
- Ecosystem analytics
|
||||
|
||||
---
|
||||
|
||||
## Trust Score
|
||||
|
||||
Each mint has a score from 0–100.
|
||||
|
||||
Derived from:
|
||||
- Uptime reliability
|
||||
- Response speed
|
||||
- Review quantity and quality
|
||||
- Metadata completeness
|
||||
- Penalties for downtime and instability
|
||||
|
||||
Scores are:
|
||||
- Computed asynchronously
|
||||
- Stored with full breakdown
|
||||
- Fully explainable
|
||||
|
||||
---
|
||||
|
||||
## Pageviews and Popularity
|
||||
|
||||
- Pageviews tracked per mint page
|
||||
- Short‑lived session identifiers
|
||||
- No raw IP storage
|
||||
|
||||
Aggregated metrics:
|
||||
- views_24h / 7d / 30d
|
||||
- unique sessions
|
||||
- view velocity
|
||||
- trending detection
|
||||
|
||||
Used as adoption proxies only.
|
||||
|
||||
---
|
||||
|
||||
## Database Philosophy
|
||||
|
||||
- Append raw data
|
||||
- Derive aggregates
|
||||
- Never delete history
|
||||
- Always allow recomputation
|
||||
|
||||
---
|
||||
|
||||
## Intended Consumers
|
||||
|
||||
- Frontends (explorers, dashboards)
|
||||
- Wallets (mint selection, warnings)
|
||||
- Operators (transparency)
|
||||
|
||||
---
|
||||
|
||||
## One‑Sentence Summary
|
||||
|
||||
Cashumints.space is a decentralized, historical observability and reputation layer for the Cashu mint ecosystem.
|
||||
|
||||
207
starter-docs/logic.md
Normal file
207
starter-docs/logic.md
Normal file
@@ -0,0 +1,207 @@
|
||||
# Cashumints.space API – Logic
|
||||
|
||||
This document defines exactly how the system behaves internally.
|
||||
|
||||
---
|
||||
|
||||
## URL Normalization
|
||||
|
||||
All URLs are normalized before storage:
|
||||
- force https if available
|
||||
- lowercase hostname
|
||||
- remove trailing slashes
|
||||
- strip default ports
|
||||
|
||||
Normalized URLs are used for identity resolution.
|
||||
|
||||
---
|
||||
|
||||
## Mint Resolution
|
||||
|
||||
If request uses mint_id:
|
||||
- direct lookup
|
||||
|
||||
If request uses URL:
|
||||
- normalize
|
||||
- lookup in mint_urls
|
||||
- resolve mint_id
|
||||
|
||||
If URL unknown:
|
||||
- return 404
|
||||
|
||||
---
|
||||
|
||||
## Probing Logic
|
||||
|
||||
### Probe Execution
|
||||
|
||||
- HTTP GET to mint endpoints
|
||||
- strict timeout
|
||||
- record RTT
|
||||
- record status code or error
|
||||
|
||||
### State Transitions
|
||||
|
||||
On success:
|
||||
- last_success_at = now
|
||||
- consecutive_failures = 0
|
||||
- status = online or degraded
|
||||
- offline_since = null
|
||||
|
||||
On failure:
|
||||
- last_failure_at = now
|
||||
- consecutive_failures += 1
|
||||
- if threshold reached:
|
||||
- status = offline
|
||||
- offline_since = now (if not set)
|
||||
|
||||
If offline longer than ABANDONED_AFTER:
|
||||
- status = abandoned
|
||||
|
||||
---
|
||||
|
||||
## Metadata Fetch Logic
|
||||
|
||||
- Only fetch metadata after successful probe
|
||||
- Only fetch if last_fetched_at older than 1 hour
|
||||
|
||||
Steps:
|
||||
1. GET /v1/info
|
||||
2. Validate against NUT‑06
|
||||
3. Normalize payload
|
||||
4. Compute hash
|
||||
5. If hash changed:
|
||||
- store history record
|
||||
- update snapshot
|
||||
|
||||
Metadata is never deleted on failure.
|
||||
|
||||
---
|
||||
|
||||
## URL Discovery
|
||||
|
||||
URLs are discovered from:
|
||||
- metadata.urls
|
||||
- Nostr review references
|
||||
- user submissions
|
||||
|
||||
New URLs:
|
||||
- linked to existing mint
|
||||
- marked active
|
||||
|
||||
Removed URLs:
|
||||
- marked inactive
|
||||
- never deleted
|
||||
|
||||
---
|
||||
|
||||
## Uptime Rollups
|
||||
|
||||
Raw probes are aggregated into windows:
|
||||
- 1h, 24h, 7d, 30d
|
||||
|
||||
Computed values:
|
||||
- uptime_pct
|
||||
- avg_rtt
|
||||
- p95_rtt
|
||||
- downtime_seconds
|
||||
- incident count
|
||||
|
||||
Rollups are recomputable at any time.
|
||||
|
||||
---
|
||||
|
||||
## Incident Detection
|
||||
|
||||
Incident starts when:
|
||||
- status transitions online → offline
|
||||
|
||||
Incident ends when:
|
||||
- first successful probe after offline
|
||||
|
||||
Incident data:
|
||||
- start
|
||||
- end
|
||||
- duration
|
||||
- severity
|
||||
|
||||
---
|
||||
|
||||
## Trust Score Calculation
|
||||
|
||||
Score range: 0–100
|
||||
|
||||
Components:
|
||||
- uptime (max 40)
|
||||
- speed (max 25)
|
||||
- reviews (max 20)
|
||||
- identity (max 10)
|
||||
- penalties (up to ‑15)
|
||||
|
||||
Total score = sum, clamped.
|
||||
|
||||
Scores are recomputed:
|
||||
- after rollups
|
||||
- after new reviews
|
||||
- periodically
|
||||
|
||||
---
|
||||
|
||||
## Review Aggregation
|
||||
|
||||
- One review per pubkey per mint per window
|
||||
- Raw reviews stored forever
|
||||
- Aggregates computed separately
|
||||
|
||||
---
|
||||
|
||||
## Pageviews
|
||||
|
||||
- Recorded per mint page load
|
||||
- Session‑based
|
||||
- No IP storage
|
||||
|
||||
Aggregated into:
|
||||
- daily counts
|
||||
- rolling windows
|
||||
|
||||
---
|
||||
|
||||
## Job System
|
||||
|
||||
Jobs stored in database:
|
||||
- type
|
||||
- payload
|
||||
- run_at
|
||||
- status
|
||||
- retries
|
||||
|
||||
Workers:
|
||||
- poll jobs
|
||||
- lock atomically
|
||||
- execute
|
||||
- retry with backoff
|
||||
|
||||
---
|
||||
|
||||
## Failure Handling
|
||||
|
||||
- All failures are recorded
|
||||
- No silent drops
|
||||
- History preserved
|
||||
|
||||
---
|
||||
|
||||
## Determinism Guarantees
|
||||
|
||||
- Same input data always produces same rollups
|
||||
- Same rollups always produce same trust score
|
||||
- System can be fully rebuilt from raw tables
|
||||
|
||||
---
|
||||
|
||||
## Final Rule
|
||||
|
||||
If data is not stored, it does not exist.
|
||||
If it exists, it must be explainable.
|
||||
|
||||
Reference in New Issue
Block a user