Vision: FAPP is just one service on a generic platform. Same infrastructure can support: - Housing (rooms, flats) - Repair (craftsmen) - Tutoring - Medical appointments - Legal consultations - Events/tickets - Custom services Key concepts: - Service ID namespacing (32-bit) - Generic ServiceMessage envelope - ServiceRouter with pluggable handlers - ServiceStore trait for per-service caching - Generic verification framework - Migration path for existing FAPP Architecture: Applications → Service Layer → Mesh Layer → Transport
374 lines
12 KiB
Markdown
374 lines
12 KiB
Markdown
# Mesh Service Layer — Generic Application Protocol
|
|
|
|
## Vision
|
|
|
|
FAPP (therapy slots) ist nur **eine** Anwendung. Die gleiche Infrastruktur könnte tragen:
|
|
|
|
| Service | Announce | Query | Reserve |
|
|
|---------|----------|-------|---------|
|
|
| **FAPP** | Therapist slots | Patient search | Book appointment |
|
|
| **Housing** | Available rooms/flats | Tenant search | Reserve viewing |
|
|
| **Repair** | Craftsman availability | Customer search | Book repair |
|
|
| **Tutoring** | Tutor slots | Student search | Book lesson |
|
|
| **Medical** | Doctor appointments | Patient search | Book slot |
|
|
| **Legal** | Lawyer availability | Client search | Book consultation |
|
|
| **Volunteer** | Helper availability | Org search | Coordinate help |
|
|
| **Events** | Open seats/tickets | Attendee search | Reserve seat |
|
|
|
|
**Gemeinsames Muster:**
|
|
1. Provider announces availability
|
|
2. Consumer queries anonymously
|
|
3. Match → encrypted reservation
|
|
4. Confirmation
|
|
|
|
## Design Principles
|
|
|
|
### 1. Service Namespacing
|
|
|
|
Jeder Service hat einen **Service ID** (32-bit):
|
|
|
|
```rust
|
|
pub const SERVICE_FAPP: u32 = 0x0001; // Psychotherapy
|
|
pub const SERVICE_HOUSING: u32 = 0x0002; // Housing/Rooms
|
|
pub const SERVICE_REPAIR: u32 = 0x0003; // Craftsmen
|
|
pub const SERVICE_TUTOR: u32 = 0x0004; // Tutoring
|
|
pub const SERVICE_MEDICAL: u32 = 0x0005; // Medical appointments
|
|
// ...
|
|
pub const SERVICE_CUSTOM: u32 = 0xFFFF; // User-defined
|
|
```
|
|
|
|
### 2. Generic Message Envelope
|
|
|
|
```rust
|
|
/// Generic service message that wraps any application payload.
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
pub struct ServiceMessage {
|
|
/// Service identifier (which application).
|
|
pub service_id: u32,
|
|
/// Message type within service (Announce=1, Query=2, Response=3, etc.).
|
|
pub message_type: u8,
|
|
/// Version for forward compatibility.
|
|
pub version: u8,
|
|
/// Application-specific CBOR payload.
|
|
pub payload: Vec<u8>,
|
|
/// Provider's mesh address.
|
|
pub provider_address: [u8; 16],
|
|
/// Ed25519 signature over (service_id, message_type, version, payload).
|
|
pub signature: Vec<u8>,
|
|
/// Propagation control.
|
|
pub hop_count: u8,
|
|
pub max_hops: u8,
|
|
pub ttl_hours: u16,
|
|
pub timestamp: u64,
|
|
}
|
|
```
|
|
|
|
### 3. Capability System
|
|
|
|
Erweitere die Capability Flags:
|
|
|
|
```rust
|
|
// Base capabilities (existing)
|
|
pub const CAP_RELAY: u16 = 0x0001;
|
|
pub const CAP_STORE: u16 = 0x0002;
|
|
pub const CAP_GATEWAY: u16 = 0x0004;
|
|
|
|
// Service-specific capabilities (dynamic)
|
|
// Format: 0xSSCC where SS = service_id (high byte), CC = capability
|
|
pub const CAP_SERVICE_PROVIDER: u16 = 0x0100; // Can announce
|
|
pub const CAP_SERVICE_RELAY: u16 = 0x0200; // Caches & forwards
|
|
pub const CAP_SERVICE_CONSUMER: u16 = 0x0400; // Can query
|
|
|
|
// Example: FAPP therapist
|
|
// capabilities = CAP_RELAY | (SERVICE_FAPP << 8) | CAP_SERVICE_PROVIDER
|
|
```
|
|
|
|
### 4. Schema Registry
|
|
|
|
Services definieren ihr Schema — aber das Schema ist **nicht im Wire-Protokoll**:
|
|
|
|
```rust
|
|
/// Service schema definition (stored locally, not transmitted).
|
|
pub struct ServiceSchema {
|
|
pub service_id: u32,
|
|
pub name: String,
|
|
pub version: u8,
|
|
/// CBOR schema for Announce payload.
|
|
pub announce_schema: Vec<u8>,
|
|
/// CBOR schema for Query payload.
|
|
pub query_schema: Vec<u8>,
|
|
/// CBOR schema for Response payload.
|
|
pub response_schema: Vec<u8>,
|
|
/// Required verification level.
|
|
pub min_verification: u8,
|
|
/// Human-readable description.
|
|
pub description: String,
|
|
}
|
|
```
|
|
|
|
Nodes können Schemas per Out-of-Band bekommen (Website, Git, DNS TXT records).
|
|
|
|
### 5. Service Router
|
|
|
|
```rust
|
|
pub struct ServiceRouter {
|
|
/// Registered service handlers.
|
|
handlers: HashMap<u32, Box<dyn ServiceHandler>>,
|
|
/// Shared routing table.
|
|
routes: Arc<RwLock<RoutingTable>>,
|
|
/// Transport manager.
|
|
transports: Arc<TransportManager>,
|
|
/// Per-service stores.
|
|
stores: HashMap<u32, Box<dyn ServiceStore>>,
|
|
}
|
|
|
|
pub trait ServiceHandler: Send + Sync {
|
|
fn service_id(&self) -> u32;
|
|
fn handle_announce(&self, msg: &ServiceMessage) -> ServiceAction;
|
|
fn handle_query(&self, msg: &ServiceMessage) -> ServiceAction;
|
|
fn handle_response(&self, msg: &ServiceMessage) -> ServiceAction;
|
|
}
|
|
|
|
pub trait ServiceStore: Send + Sync {
|
|
fn store(&mut self, msg: ServiceMessage) -> bool;
|
|
fn query(&self, filter: &[u8]) -> Vec<ServiceMessage>;
|
|
fn gc_expired(&mut self) -> usize;
|
|
}
|
|
```
|
|
|
|
## Wire Protocol
|
|
|
|
### Message Format
|
|
|
|
```
|
|
┌──────────────────────────────────────────────────────────┐
|
|
│ Byte 0-3: Service ID (u32 LE) │
|
|
│ Byte 4: Message Type (1=Announce, 2=Query, 3=Resp) │
|
|
│ Byte 5: Version │
|
|
│ Byte 6-7: Payload Length (u16 LE) │
|
|
│ Byte 8-23: Provider Address (16 bytes) │
|
|
│ Byte 24-87: Signature (64 bytes) │
|
|
│ Byte 88: Hop Count │
|
|
│ Byte 89: Max Hops │
|
|
│ Byte 90-91: TTL Hours (u16 LE) │
|
|
│ Byte 92-99: Timestamp (u64 LE) │
|
|
│ Byte 100+: CBOR Payload │
|
|
└──────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
**Total header: 100 bytes** + variable payload.
|
|
|
|
### Message Types
|
|
|
|
| Type | Value | Direction |
|
|
|------|-------|-----------|
|
|
| Announce | 0x01 | Provider → Mesh |
|
|
| Query | 0x02 | Consumer → Mesh |
|
|
| Response | 0x03 | Relay/Provider → Consumer |
|
|
| Reserve | 0x04 | Consumer → Provider |
|
|
| Confirm | 0x05 | Provider → Consumer |
|
|
| Cancel | 0x06 | Either → Other |
|
|
| Update | 0x07 | Provider → Mesh (partial update) |
|
|
| Revoke | 0x08 | Provider → Mesh (cancel announce) |
|
|
|
|
## Example: Housing Service
|
|
|
|
```rust
|
|
// Define the service
|
|
pub const SERVICE_HOUSING: u32 = 0x0002;
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
pub struct HousingAnnounce {
|
|
pub room_type: RoomType, // WG, Apartment, House
|
|
pub size_sqm: u16,
|
|
pub rent_euros: u16,
|
|
pub available_from: u64,
|
|
pub plz: String,
|
|
pub amenities: Vec<Amenity>,
|
|
pub landlord_profile_url: Option<String>,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
pub struct HousingQuery {
|
|
pub room_type: Option<RoomType>,
|
|
pub max_rent: Option<u16>,
|
|
pub min_size: Option<u16>,
|
|
pub plz_prefix: Option<String>,
|
|
pub available_before: Option<u64>,
|
|
}
|
|
|
|
// Register with ServiceRouter
|
|
router.register(HousingHandler::new(housing_store));
|
|
```
|
|
|
|
## Migration Path for FAPP
|
|
|
|
FAPP kann auf die generische Schicht migriert werden:
|
|
|
|
```rust
|
|
// Before: FAPP-specific
|
|
let announce = SlotAnnounce::new(...);
|
|
fapp_router.broadcast_announce(announce)?;
|
|
|
|
// After: Generic service layer
|
|
let payload = FappAnnouncePayload { ... };
|
|
let msg = ServiceMessage::announce(SERVICE_FAPP, &identity, payload)?;
|
|
service_router.broadcast(msg)?;
|
|
```
|
|
|
|
**Backwards compatibility:**
|
|
- Alte FAPP-Nodes verstehen nur FAPP-Wire-Format
|
|
- Neue Nodes können beide Formate
|
|
- Transition über 6 Monate, dann deprecate altes Format
|
|
|
|
## Verification Framework
|
|
|
|
Generische Verification die für alle Services gilt:
|
|
|
|
```rust
|
|
pub struct Verification {
|
|
/// Who endorsed this provider.
|
|
pub endorser_address: [u8; 16],
|
|
/// Signature over (provider_address, service_id, timestamp).
|
|
pub signature: [u8; 64],
|
|
/// Unix timestamp.
|
|
pub timestamp: u64,
|
|
/// Verification level achieved.
|
|
pub level: u8,
|
|
/// Service-specific verification data (e.g., license number).
|
|
pub credential_hash: Option<[u8; 32]>,
|
|
/// Human-readable reason.
|
|
pub reason: String,
|
|
}
|
|
|
|
/// Verification levels (generic across services).
|
|
pub const VERIFY_NONE: u8 = 0;
|
|
pub const VERIFY_ENDORSED: u8 = 1; // Web-of-trust
|
|
pub const VERIFY_REGISTRY: u8 = 2; // Official registry
|
|
pub const VERIFY_CREDENTIAL: u8 = 3; // Verified credential (eHBA, etc.)
|
|
```
|
|
|
|
## Service Discovery
|
|
|
|
Wie finden Nodes heraus welche Services existieren?
|
|
|
|
### Option A: Hardcoded Core Services
|
|
|
|
```rust
|
|
const CORE_SERVICES: &[u32] = &[
|
|
SERVICE_FAPP,
|
|
SERVICE_HOUSING,
|
|
SERVICE_REPAIR,
|
|
];
|
|
```
|
|
|
|
### Option B: Service Announce
|
|
|
|
```rust
|
|
/// Node announces which services it supports.
|
|
pub struct ServiceCapabilityAnnounce {
|
|
pub node_address: [u8; 16],
|
|
pub services: Vec<ServiceCapability>,
|
|
pub signature: [u8; 64],
|
|
}
|
|
|
|
pub struct ServiceCapability {
|
|
pub service_id: u32,
|
|
pub roles: u8, // Provider | Relay | Consumer
|
|
pub version: u8,
|
|
}
|
|
```
|
|
|
|
### Option C: DNS-SD / mDNS
|
|
|
|
```
|
|
_fapp._mesh._udp.local.
|
|
_housing._mesh._udp.local.
|
|
```
|
|
|
|
**Recommendation:** Start with Option A (hardcoded), add Option B when needed.
|
|
|
|
## Privacy Considerations
|
|
|
|
| Aspect | Design |
|
|
|--------|--------|
|
|
| Provider identity | Public (bound to credential) |
|
|
| Consumer identity | Anonymous (no ID in queries) |
|
|
| Query content | Visible to relays (filter by service) |
|
|
| Reservation | E2E encrypted to provider |
|
|
| Location | Coarse only (PLZ, not address) |
|
|
|
|
## Cost Model
|
|
|
|
Relay nodes do work. How to compensate?
|
|
|
|
| Model | Pros | Cons |
|
|
|-------|------|------|
|
|
| **Altruism** | Simple, no tokens | Free-rider problem |
|
|
| **Reciprocity** | "I relay, you relay" | Complex accounting |
|
|
| **Micropayments** | Fair, incentivizes | Needs payment rails |
|
|
| **Subscription** | Predictable | Centralization risk |
|
|
|
|
**Recommendation:** Start altruistic, add optional micropayments later.
|
|
|
|
## Implementation Roadmap
|
|
|
|
### Phase 1: Generic Layer (Now)
|
|
|
|
1. `ServiceMessage` struct
|
|
2. `ServiceRouter` with handler registration
|
|
3. `ServiceStore` trait
|
|
4. Migrate FAPP to generic layer
|
|
5. Tests
|
|
|
|
### Phase 2: Second Service (Q2 2026)
|
|
|
|
1. Pick one: Housing or Tutoring
|
|
2. Implement as second service on same layer
|
|
3. Prove the abstraction works
|
|
|
|
### Phase 3: Verification Framework (Q3 2026)
|
|
|
|
1. Generic endorsement messages
|
|
2. Verification levels
|
|
3. Trusted relay network
|
|
|
|
### Phase 4: Service Discovery (Q4 2026)
|
|
|
|
1. ServiceCapabilityAnnounce
|
|
2. Dynamic service registration
|
|
3. Schema distribution
|
|
|
|
## Open Questions
|
|
|
|
1. **Payload size limits?** LoRa vs. TCP have very different constraints.
|
|
2. **Query routing?** Flood vs. DHT vs. gossip?
|
|
3. **Cross-service queries?** "Find therapist OR coach near me"
|
|
4. **Service-specific rate limits?** Housing might need different limits than FAPP.
|
|
5. **Governance?** Who assigns service IDs? IANA-style registry?
|
|
|
|
## Conclusion
|
|
|
|
QuicProQuo's mesh layer can become a **generic decentralized service platform**:
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Application Services │
|
|
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
|
│ │ FAPP │ │ Housing │ │ Repair │ │ Custom │ ... │
|
|
│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │
|
|
│ │ │ │ │ │
|
|
│ ─────┴────────────┴────────────┴────────────┴────────── │
|
|
│ Service Layer │
|
|
│ ServiceMessage, ServiceRouter, Verification │
|
|
│ ─────────────────────────────────────────────────────── │
|
|
│ Mesh Layer │
|
|
│ MeshRouter, RoutingTable, Announce, Store-and-Forward │
|
|
│ ─────────────────────────────────────────────────────── │
|
|
│ Transport Layer │
|
|
│ Iroh (QUIC), TCP, LoRa, Serial │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
**The mesh IS the platform.** No central servers, no vendor lock-in, no single point of failure.
|