chore: bump version to 0.3.0

This commit is contained in:
2026-03-14 12:20:47 +01:00
parent 0fbd7008a1
commit 8c8d5a8abb
5 changed files with 14 additions and 161 deletions

View File

@@ -1,6 +1,6 @@
Running 2 comparison run(s)... Running 2 comparison run(s)...
Versions: Versions:
parrhesia 0.2.0 parrhesia 0.3.0
strfry 1.0.4 (nixpkgs) strfry 1.0.4 (nixpkgs)
nostr-rs-relay 0.9.0 nostr-rs-relay 0.9.0
nostr-bench 0.4.0 nostr-bench 0.4.0
@@ -16,18 +16,18 @@ Versions:
=== Bench comparison (averages) === === Bench comparison (averages) ===
metric parrhesia strfry nostr-rs-relay strfry/parrhesia nostr-rs/parrhesia metric parrhesia strfry nostr-rs-relay strfry/parrhesia nostr-rs/parrhesia
-------------------------- --------- -------- -------------- ---------------- ------------------ -------------------------- --------- -------- -------------- ---------------- ------------------
connect avg latency (ms) ↓ 11.50 3.50 2.50 0.30x 0.22x connect avg latency (ms) ↓ 13.50 3.00 2.00 0.22x 0.15x
connect max latency (ms) ↓ 20.00 5.50 3.50 0.28x 0.17x connect max latency (ms) ↓ 22.50 5.50 3.00 0.24x 0.13x
echo throughput (TPS) ↑ 81805.50 62033.50 162281.50 0.76x 1.98x echo throughput (TPS) ↑ 80385.00 61673.00 164516.00 0.77x 2.05x
echo throughput (MiB/s) ↑ 44.75 34.65 88.90 0.77x 1.99x echo throughput (MiB/s) ↑ 44.00 34.45 90.10 0.78x 2.05x
event throughput (TPS) ↑ 1524.50 3518.00 782.50 2.31x 0.51x event throughput (TPS) ↑ 2000.00 3404.50 788.00 1.70x 0.39x
event throughput (MiB/s) ↑ 1.00 2.25 0.50 2.25x 0.50x event throughput (MiB/s) ↑ 1.30 2.20 0.50 1.69x 0.38x
req throughput (TPS) ↑ 2539.00 1809.00 847.00 0.71x 0.33x req throughput (TPS) ↑ 3664.00 1808.50 877.50 0.49x 0.24x
req throughput (MiB/s) ↑ 12.45 11.70 2.35 0.94x 0.19x req throughput (MiB/s) ↑ 20.75 11.75 2.45 0.57x 0.12x
Legend: ↑ higher is better, ↓ lower is better. Legend: ↑ higher is better, ↓ lower is better.
Ratio columns are server/parrhesia (for ↓ metrics, <1.00x means that server is faster). Ratio columns are server/parrhesia (for ↓ metrics, <1.00x means that server is faster).
Run details: Run details:
run 1: parrhesia(echo_tps=80431, event_tps=1427, req_tps=2546, connect_avg_ms=13) | strfry(echo_tps=61421, event_tps=3581, req_tps=1811, connect_avg_ms=3) | nostr-rs-relay(echo_tps=167436, event_tps=792, req_tps=897, connect_avg_ms=3) run 1: parrhesia(echo_tps=81402, event_tps=1979, req_tps=3639, connect_avg_ms=14) | strfry(echo_tps=61745, event_tps=3457, req_tps=1818, connect_avg_ms=3) | nostr-rs-relay(echo_tps=159974, event_tps=784, req_tps=905, connect_avg_ms=2)
run 2: parrhesia(echo_tps=83180, event_tps=1622, req_tps=2532, connect_avg_ms=10) | strfry(echo_tps=62646, event_tps=3455, req_tps=1807, connect_avg_ms=4) | nostr-rs-relay(echo_tps=157127, event_tps=773, req_tps=797, connect_avg_ms=2) run 2: parrhesia(echo_tps=79368, event_tps=2021, req_tps=3689, connect_avg_ms=13) | strfry(echo_tps=61601, event_tps=3352, req_tps=1799, connect_avg_ms=3) | nostr-rs-relay(echo_tps=169058, event_tps=792, req_tps=850, connect_avg_ms=2)

View File

@@ -1,86 +0,0 @@
# PROGRESS (ephemeral)
Implementation checklist for Parrhesia relay.
## Phase 0 — foundation
- [x] Confirm architecture doc with final NIP scope (`docs/ARCH.md`)
- [x] Add core deps (websocket/http server, ecto_sql/postgrex, telemetry, test tooling)
- [x] Establish application config structure (limits, policies, feature flags)
- [x] Wire initial supervision tree skeleton
## Phase 1 — protocol core (NIP-01)
- [x] Implement websocket endpoint + per-connection process
- [x] Implement message decode/encode for `EVENT`, `REQ`, `CLOSE`
- [x] Implement strict event validation (`id`, `sig`, shape, timestamps)
- [x] Implement filter evaluation engine (AND/OR semantics)
- [x] Implement subscription lifecycle + `EOSE` behavior
- [x] Implement canonical `OK`, `NOTICE`, `CLOSED` responses + prefixes
## Phase 2 — storage boundary + postgres adapter
- [x] Define `Parrhesia.Storage.*` behaviors (events/moderation/groups/admin)
- [x] Implement Postgres adapter modules behind behaviors
- [x] Create migrations for events, tags, moderation, membership
- [x] Implement replaceable/addressable semantics at storage layer
- [x] Add adapter contract test suite
## Phase 3 — fanout + performance primitives
- [x] Build ETS-backed subscription index
- [x] Implement candidate narrowing by kind/author/tag
- [x] Add bounded outbound queues/backpressure per connection
- [x] Add telemetry for ingest/query/fanout latency + queue depth
## Phase 4 — relay metadata and auth
- [x] NIP-11 endpoint (`application/nostr+json`)
- [x] NIP-42 challenge/auth flow
- [x] Enforce NIP-70 protected events (default reject, auth override)
- [x] Add auth-required/restricted response paths for writes and reqs
## Phase 5 — lifecycle and moderation features
- [x] NIP-09 deletion requests
- [x] NIP-40 expiration handling + purge worker
- [x] NIP-62 vanish requests (hard delete semantics)
- [x] NIP-13 PoW gate (configurable minimum)
- [x] Moderation tables + policy hooks (ban/allow/event/ip)
## Phase 6 — query extensions
- [x] NIP-45 `COUNT` (exact)
- [x] Optional HLL response support
- [x] NIP-50 search (`search` filter + ranking)
- [x] NIP-77 negentropy (`NEG-OPEN/MSG/CLOSE`)
## Phase 7 — private messaging, groups, and MLS
- [x] NIP-17/59 recipient-protected giftwrap read path (`kind:1059`)
- [x] NIP-29 group event policy + relay metadata events
- [x] NIP-43 membership request flow (`28934/28935/28936`, `8000/8001`, `13534`)
- [x] Marmot MIP relay surface: `443`, `445`, `10051` handling
- [x] MLS retention policy + tests for commit race edge cases
## Phase 8 — management API + operations
- [x] NIP-86 HTTP management endpoint
- [x] NIP-98 auth validation for management calls
- [x] Implement supported management methods + audit logging
- [x] Build health/readiness and Prometheus-compatible `/metrics` endpoints
## Phase 9 — full test + hardening pass
- [x] Unit + integration + property test coverage for all critical modules
- [x] End-to-end websocket conformance scenarios
- [x] Load/soak tests with target p95 latency budgets
- [x] Fault-injection tests (DB outages, high churn, restart recovery)
- [x] Final precommit run and fix all issues
## Nice-to-have / backlog
- [x] Multi-node fanout via PG LISTEN/NOTIFY or external bus
- [x] Partitioned event storage + archival strategy
- [x] Alternate storage adapter prototype (non-Postgres)
- [x] Compatibility mode for Marmot protocol transition (not required per user)

View File

@@ -1,61 +0,0 @@
# PROGRESS_MARMOT (ephemeral)
Marmot-specific implementation checklist for Parrhesia relay interoperability.
Spec source: `~/marmot/README.md` + MIP-00..05.
## M0 — spec lock + interoperability profile
- [ ] Freeze target profile to MIP-00..03 (mandatory)
- [ ] Keep MIP-04 and MIP-05 behind feature flags (optional)
- [ ] Document that legacy NIP-EE is superseded and no dedicated transition compatibility mode is planned
- [ ] Publish operator-facing compatibility statement in docs
## M1 — MIP-00 (credentials + keypackages)
- [x] Enforce kind `443` required tags and encoding (`encoding=base64`)
- [x] Validate `mls_protocol_version`, `mls_ciphersuite`, `mls_extensions`, `relays`, and `i` tag shape
- [x] Add efficient `#i` query/index path for KeyPackageRef lookup
- [x] Keep replaceable behavior for kind `10051` relay-list events
- [x] Add conformance tests for valid/invalid KeyPackage envelopes
## M2 — MIP-01 (group construction data expectations)
- [x] Enforce relay-side routing prerequisites for Marmot groups (`#h` query path)
- [x] Keep deterministic ordering for group-event catch-up (`created_at` + `id` tie-break)
- [x] Add guardrails for group metadata traffic volume and filter windows
- [x] Add tests for `#h` routing and ordering invariants
## M3 — MIP-02 (welcome events)
- [x] Support wrapped Welcome delivery via NIP-59 (`1059`) recipient-gated reads
- [x] Validate relay behavior for unsigned inner Welcome semantics (kind `444` envelope expectations)
- [x] Ensure durability/ack semantics support Commit-then-Welcome sequencing requirements
- [x] Add negative tests for malformed wrapped Welcome payloads
## M4 — MIP-03 (group events)
- [x] Enforce kind `445` envelope validation (`#h` tag presence/shape, base64 content shape)
- [x] Keep relay MLS-agnostic (no MLS decrypt/inspect in relay hot path)
- [x] Add configurable retention policy for kind `445` traffic
- [x] Add tests for high-volume fanout behavior and deterministic query results
## M5 — optional MIP-04 (encrypted media)
- [x] Accept/store MIP-04 metadata-bearing events as regular Nostr events
- [x] Add policy hooks for media metadata limits and abuse controls
- [x] Add tests for search/filter interactions with media metadata tags
## M6 — optional MIP-05 (push notifications)
- [x] Accept/store notification coordination events required by enabled profile
- [x] Add policy/rate-limit controls for push-related event traffic
- [x] Add abuse and replay protection tests for notification trigger paths
## M7 — hardening + operations
- [x] Add Marmot-focused telemetry breakdowns (ingest/query/fanout, queue pressure)
- [x] Add query-plan regression checks for `#h` and `#i` heavy workloads
- [x] Add fault-injection scenarios for relay outage/reordering behavior in group flows
- [x] Add docs for operator limits tuned for Marmot traffic patterns
- [x] Final `mix precommit` before merge

View File

@@ -10,7 +10,7 @@
vips, vips,
}: let }: let
pname = "parrhesia"; pname = "parrhesia";
version = "0.2.0"; version = "0.3.0";
beamPackages = beam.packages.erlang_28.extend ( beamPackages = beam.packages.erlang_28.extend (
final: _prev: { final: _prev: {
@@ -48,7 +48,7 @@
beamPackages.fetchMixDeps { beamPackages.fetchMixDeps {
pname = "${pname}-mix-deps"; pname = "${pname}-mix-deps";
inherit version src; inherit version src;
hash = "sha256-1v2+Q1MHbu09r5OBaLehiR+JfMP0Q5OHaWuwrQDzZJU="; hash = "sha256-0KOyYRbYM0jjmp3tPn64qkp0YkmZKlqkGrlu/wCr4m8=";
} }
else null; else null;

View File

@@ -4,7 +4,7 @@ defmodule Parrhesia.MixProject do
def project do def project do
[ [
app: :parrhesia, app: :parrhesia,
version: "0.2.0", version: "0.3.0",
elixir: "~> 1.19", elixir: "~> 1.19",
start_permanent: Mix.env() == :prod, start_permanent: Mix.env() == :prod,
deps: deps(), deps: deps(),