docs: de-link spike findings from spike/ code (moved to private repo)
This commit is contained in:
parent
2d4dec5304
commit
5b64fe14b3
1 changed files with 25 additions and 23 deletions
|
|
@ -1,9 +1,9 @@
|
||||||
# Spike — Block 2 (social layer) de-risking findings
|
# Spike — Block 2 (social layer) de-risking findings
|
||||||
|
|
||||||
*Throwaway research spike. Language: English (findings), per code convention.
|
*Throwaway research spike. Language: English (findings), per code convention.
|
||||||
Code lives in [`spike/block2_spike/`](../../spike/block2_spike/) and is marked
|
The throwaway spike code (`spike/block2_spike/`) has been moved out of this
|
||||||
throwaway — **not production, not on the pub workspace, no deps added to Block
|
public repo and preserved privately — it was **not production, not on the pub
|
||||||
1**. This document is the deliverable: what we learned, the risks, and a
|
workspace, no deps added to Block 1**. This document is the deliverable: what we learned, the risks, and a
|
||||||
recommendation on whether/how to take on the social round (Phase 3).*
|
recommendation on whether/how to take on the social round (Phase 3).*
|
||||||
|
|
||||||
> **Status: this is a spike, not a green light to build Block 2.** CLAUDE.md and
|
> **Status: this is a spike, not a green light to build Block 2.** CLAUDE.md and
|
||||||
|
|
@ -34,7 +34,7 @@ See "How to run" at the end.
|
||||||
|
|
||||||
**Result: works, deterministic, one-way. This unblocks "one identity, one backup".**
|
**Result: works, deterministic, one-way. This unblocks "one identity, one backup".**
|
||||||
|
|
||||||
- Implemented [`NostrKey.deriveFromSeed`](../../spike/block2_spike/lib/src/nostr_key.dart):
|
- Implemented `NostrKey.deriveFromSeed`:
|
||||||
`HKDF-SHA256(rootSeed, info: "org.comunes.tane/nostr/secp256k1/v1")` → reduce
|
`HKDF-SHA256(rootSeed, info: "org.comunes.tane/nostr/secp256k1/v1")` → reduce
|
||||||
to a valid secp256k1 scalar `d ∈ [1, n-1]` by rejection (bump a counter in the
|
to a valid secp256k1 scalar `d ∈ [1, n-1]` by rejection (bump a counter in the
|
||||||
HKDF info on the astronomically-rare miss, so the result stays a pure function
|
HKDF info on the astronomically-rare miss, so the result stays a pure function
|
||||||
|
|
@ -80,13 +80,13 @@ trust do NOT fit behind the same interface — they share a *connection*, not a
|
||||||
*contract*.**
|
*contract*.**
|
||||||
|
|
||||||
### The seam works (offers)
|
### The seam works (offers)
|
||||||
- [`OfferTransport`](../../spike/block2_spike/lib/src/offer_transport.dart) =
|
- `OfferTransport` =
|
||||||
`publish(Offer)` / `discover(DiscoveryQuery)` / `retract(id)`. The Nostr
|
`publish(Offer)` / `discover(DiscoveryQuery)` / `retract(id)`. The Nostr
|
||||||
NIP-99 backend ([`NostrOfferTransport`](../../spike/block2_spike/lib/src/nostr_offer_transport.dart)
|
NIP-99 backend (`NostrOfferTransport`
|
||||||
+ [`Nip99Codec`](../../spike/block2_spike/lib/src/nip99.dart)) sits entirely
|
+ `Nip99Codec`) sits entirely
|
||||||
behind it. A second backend (ActivityPub/FEP-0837) could replace it without
|
behind it. A second backend (ActivityPub/FEP-0837) could replace it without
|
||||||
the domain noticing.
|
the domain noticing.
|
||||||
- [`Offer`](../../spike/block2_spike/lib/src/offer.dart) is agnostic by
|
- `Offer` is agnostic by
|
||||||
construction: a chosen *summary* + coarse geohash, **no FK into seed tables,
|
construction: a chosen *summary* + coarse geohash, **no FK into seed tables,
|
||||||
no full inventory, no exact address** — exactly the Offer↔Lot split
|
no full inventory, no exact address** — exactly the Offer↔Lot split
|
||||||
[sharing-model.md](sharing-model.md) §2 and
|
[sharing-model.md](sharing-model.md) §2 and
|
||||||
|
|
@ -114,14 +114,14 @@ manageable**:
|
||||||
private encrypted DM vs. assert/read a signed certification. Forcing DMs and
|
private encrypted DM vs. assert/read a signed certification. Forcing DMs and
|
||||||
certifications behind `OfferTransport.publish/discover` would overload it.
|
certifications behind `OfferTransport.publish/discover` would overload it.
|
||||||
- **Recommendation — now demonstrated in code, not just asserted:**
|
- **Recommendation — now demonstrated in code, not just asserted:**
|
||||||
[`NostrConnection`](../../spike/block2_spike/lib/src/nostr_connection.dart) is
|
`NostrConnection` is
|
||||||
**one shared** socket + key + sign + REQ/EOSE lifecycle, and **all three thin
|
**one shared** socket + key + sign + REQ/EOSE lifecycle, and **all three thin
|
||||||
interfaces sit on top of the same instance** —
|
interfaces sit on top of the same instance** —
|
||||||
[`OfferTransport`](../../spike/block2_spike/lib/src/nostr_offer_transport.dart)
|
`OfferTransport`
|
||||||
(NIP-99),
|
(NIP-99),
|
||||||
[`MessageTransport`](../../spike/block2_spike/lib/src/nostr_message_transport.dart)
|
`MessageTransport`
|
||||||
(NIP-17) and
|
(NIP-17) and
|
||||||
[`TrustTransport`](../../spike/block2_spike/lib/src/nostr_trust_transport.dart)
|
`TrustTransport`
|
||||||
(custom WoT). The trust test even runs offer discovery and trust annotation
|
(custom WoT). The trust test even runs offer discovery and trust annotation
|
||||||
over one connection. This is the shape to lift into `commons_core`: shared
|
over one connection. This is the shape to lift into `commons_core`: shared
|
||||||
connection, per-concern contract. Trying to make `OfferTransport` also carry
|
connection, per-concern contract. Trying to make `OfferTransport` also carry
|
||||||
|
|
@ -139,7 +139,7 @@ that whole happy path now runs — what's left is production hardening (below).
|
||||||
**Result: the flow works end to end. The real risk is NIP maturity/ecosystem,
|
**Result: the flow works end to end. The real risk is NIP maturity/ecosystem,
|
||||||
not the mechanics.**
|
not the mechanics.**
|
||||||
|
|
||||||
- Built a hermetic in-process [`MiniRelay`](../../spike/block2_spike/lib/src/mini_relay.dart)
|
- Built a hermetic in-process `MiniRelay`
|
||||||
(NIP-01 subset: EVENT/REQ/EOSE/CLOSE, filter by `kinds`/`authors`/`#g`,
|
(NIP-01 subset: EVENT/REQ/EOSE/CLOSE, filter by `kinds`/`authors`/`#g`,
|
||||||
addressable-event replacement for kind 30402). No network → CI-safe, no flaky
|
addressable-event replacement for kind 30402). No network → CI-safe, no flaky
|
||||||
public-relay dependency.
|
public-relay dependency.
|
||||||
|
|
@ -183,13 +183,13 @@ The plan ([network-trust.md](network-trust.md) §4) calls messaging "grande" and
|
||||||
[open-decisions.md](open-decisions.md) §D.3 singled it out as the tightest
|
[open-decisions.md](open-decisions.md) §D.3 singled it out as the tightest
|
||||||
coupling to Nostr. So the spike built it rather than hand-waving:
|
coupling to Nostr. So the spike built it rather than hand-waving:
|
||||||
|
|
||||||
- **NIP-44 v2 encryption** ([`Nip44`](../../spike/block2_spike/lib/src/nip44.dart)):
|
- **NIP-44 v2 encryption** (`Nip44`):
|
||||||
secp256k1 ECDH → HKDF conversation key → ChaCha20 + HMAC-SHA256 with
|
secp256k1 ECDH → HKDF conversation key → ChaCha20 + HMAC-SHA256 with
|
||||||
length-hiding padding. Conversation key is symmetric (A→B == B→A, tested); a
|
length-hiding padding. Conversation key is symmetric (A→B == B→A, tested); a
|
||||||
wrong key cannot decrypt (throws, tested); short messages pad to the same
|
wrong key cannot decrypt (throws, tested); short messages pad to the same
|
||||||
bucket so ciphertext length doesn't leak plaintext length (tested).
|
bucket so ciphertext length doesn't leak plaintext length (tested).
|
||||||
- **NIP-17 / NIP-59 gift-wrap onion**
|
- **NIP-17 / NIP-59 gift-wrap onion**
|
||||||
([`NostrMessageTransport`](../../spike/block2_spike/lib/src/nostr_message_transport.dart)):
|
(`NostrMessageTransport`):
|
||||||
rumor (kind 14, unsigned) → seal (kind 13, signed by sender, NIP-44 to
|
rumor (kind 14, unsigned) → seal (kind 13, signed by sender, NIP-44 to
|
||||||
recipient) → gift wrap (kind 1059, signed by a **throwaway ephemeral key**,
|
recipient) → gift wrap (kind 1059, signed by a **throwaway ephemeral key**,
|
||||||
NIP-44 to recipient).
|
NIP-44 to recipient).
|
||||||
|
|
@ -223,12 +223,12 @@ There is no settled NIP for a web of trust, so — exactly as
|
||||||
anticipates — the spike models **its own WoT, Duniter-compatible**, over Nostr:
|
anticipates — the spike models **its own WoT, Duniter-compatible**, over Nostr:
|
||||||
|
|
||||||
- **Certifications as events**
|
- **Certifications as events**
|
||||||
([`NostrTrustTransport`](../../spike/block2_spike/lib/src/nostr_trust_transport.dart)):
|
(`NostrTrustTransport`):
|
||||||
a custom addressable kind (30777) keyed by (issuer, `d`=subject), so one live
|
a custom addressable kind (30777) keyed by (issuer, `d`=subject), so one live
|
||||||
"A vouches for B" per pair; re-certifying renews, revoking replaces (tested).
|
"A vouches for B" per pair; re-certifying renews, revoking replaces (tested).
|
||||||
Certifications expire (Ğ1 semantics) and are public (like the on-chain Ğ1 WoT).
|
Certifications expire (Ğ1 semantics) and are public (like the on-chain Ğ1 WoT).
|
||||||
- **The membership rule is pure and separately tested**
|
- **The membership rule is pure and separately tested**
|
||||||
([`WebOfTrust`](../../spike/block2_spike/lib/src/web_of_trust.dart)) — the
|
(`WebOfTrust`) — the
|
||||||
`commons_core`-worthy piece: Duniter's two rules, **N certifications from
|
`commons_core`-worthy piece: Duniter's two rules, **N certifications from
|
||||||
existing members** (sigQty) and **within distance D of the bootstrap
|
existing members** (sigQty) and **within distance D of the bootstrap
|
||||||
referents** (stepMax), iterated to a fixpoint (becoming a member can push
|
referents** (stepMax), iterated to a fixpoint (becoming a member can push
|
||||||
|
|
@ -263,8 +263,9 @@ entity, and optionally importing the on-chain Ğ1 WoT (level 3) as a trust sourc
|
||||||
([open-decisions.md](open-decisions.md) §D.1, §D.6). That is what should drive
|
([open-decisions.md](open-decisions.md) §D.1, §D.6). That is what should drive
|
||||||
the Phase-3 estimate and the funding ask.
|
the Phase-3 estimate and the funding ask.
|
||||||
4. **Do not start Block 2 from this spike.** It is throwaway research code (not
|
4. **Do not start Block 2 from this spike.** It is throwaway research code (not
|
||||||
vector-verified, no offline delivery, no persistence, single relay). Delete
|
vector-verified, no offline delivery, no persistence, single relay). The
|
||||||
`spike/block2_spike/` once these findings are absorbed. The funded social
|
`spike/block2_spike/` code has been moved out of this public repo (preserved
|
||||||
|
privately) now these findings are captured. The funded social
|
||||||
round should **rebuild on vetted client libraries in `commons_core`**, using
|
round should **rebuild on vetted client libraries in `commons_core`**, using
|
||||||
the shapes proven here — one `NostrConnection`, three interfaces, the pure
|
the shapes proven here — one `NostrConnection`, three interfaces, the pure
|
||||||
`WebOfTrust` rule — and spend its risk budget on hardening and bootstrap, not
|
`WebOfTrust` rule — and spend its risk budget on hardening and bootstrap, not
|
||||||
|
|
@ -283,11 +284,12 @@ entity, and optionally importing the on-chain Ğ1 WoT (level 3) as a trust sourc
|
||||||
|
|
||||||
## How to run
|
## How to run
|
||||||
|
|
||||||
|
The throwaway spike code has been moved out of this public repo and is preserved
|
||||||
|
privately; nothing here was wired into `app_seeds` or `commons_core`'s production
|
||||||
|
graph, and the Block 1 suite is untouched. For the record, it ran as:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cd spike/block2_spike
|
cd spike/block2_spike # in the private archive
|
||||||
dart pub get
|
dart pub get
|
||||||
dart test # derivation · privacy · roundtrip · messaging · trust · web_of_trust (30 tests)
|
dart test # derivation · privacy · roundtrip · messaging · trust · web_of_trust (30 tests)
|
||||||
```
|
```
|
||||||
|
|
||||||
Nothing here is wired into `app_seeds` or `commons_core`'s production graph; the
|
|
||||||
Block 1 suite is untouched.
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue