Initial commit

This commit is contained in:
Michilis
2025-12-19 23:56:07 -03:00
commit 23f716255e
48 changed files with 14834 additions and 0 deletions

View 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
View File

@@ -0,0 +1,229 @@
# Cashumints.space API Endpoints
Base path:
/v1
All endpoints are readonly unless stated otherwise.
All timestamps are ISO8601 UTC.
All mintspecific 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 (NUT06)
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

View File

@@ -0,0 +1,240 @@
# Cashumints.space API Full Overview
## Purpose
The Cashumints.space API is a public, readonly 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 NUT06
- Ingest and expose Nostrbased mint reviews (NIP87)
- Compute transparent and explainable trust scores
- Provide rich analytics and timeseries 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. Selfhostable by default
SQLite is the default database. PostgreSQL is optional. No Redis or external queues.
---
## HighLevel Architecture
### Layers
1. HTTP API
- Serves public readonly 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 (NIP87)
- 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`
- Longterm 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 (NUT06)
- 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 (NIP87)
- 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 0100.
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
- Shortlived 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)
---
## OneSentence Summary
Cashumints.space is a decentralized, historical observability and reputation layer for the Cashu mint ecosystem.

207
starter-docs/logic.md Normal file
View 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 NUT06
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: 0100
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
- Sessionbased
- 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.