saorsa-core 0.6.2

Saorsa - Core P2P networking library with DHT, QUIC transport, and four-word addresses
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
# Saorsa Core API Documentation (v0.3.16+)

Copyright (C) 2024 Saorsa Labs Limited — Licensed under AGPL-3.0-or-later.

## Overview

Saorsa Core provides a clean, multi-device API for decentralized identity, presence, and storage. The architecture supports users with multiple devices (computers, phones, headless storage nodes) and automatically optimizes storage strategies based on group size.

This document describes the new simplified API surface introduced in v0.3.16, replacing the previous complex API structure with a clean, intuitive interface focused on real-world usage patterns.

Status: Production-ready. All calls are panic-free with comprehensive error handling. The API uses Rust async/await patterns with tokio runtime.

## Core Concepts

### 1. Identity
- **Four-Word Address**: Human-readable identifiers that hash to network keys
- **ML-DSA Keypair**: Post-quantum digital signatures for authentication
- **IdentityHandle**: Opaque handle returned after registration

### 2. Presence
- **Multi-Device Support**: Users can register multiple devices
- **Device Types**: Active (user machines) vs Headless (storage nodes)
- **Presence Packets**: DHT-stored signed packets with device lists

### 3. Storage
- **Automatic Strategy Selection**: Based on group size
- **saorsa-seal**: Encryption for data at rest
- **saorsa-fec**: Forward error correction for redundancy

## New Simplified API (v0.3.16+)

### Identity Management

```rust
/// Register a new identity with four-word address
pub async fn register_identity(
    words: [&str; 4],
    keypair: &MlDsaKeyPair,
) -> Result<IdentityHandle>
```

**Example:**
```rust
use saorsa_core::{register_identity, MlDsaKeyPair};

let words = ["welfare", "absurd", "king", "ridge"];
let keypair = MlDsaKeyPair::generate()?;
let handle = register_identity(words, &keypair).await?;
```

```rust
/// Retrieve an existing identity
pub async fn get_identity(key: &str) -> Result<Identity>
```

### Presence Management

```rust
/// Register devices and mark active device
pub async fn register_presence(
    handle: &IdentityHandle,
    devices: Vec<Device>,
    active_device: DeviceId,
) -> Result<PresenceReceipt>
```

**Device Structure:**
```rust
pub struct Device {
    pub id: DeviceId,
    pub device_type: DeviceType,  // Active or Headless
    pub storage_gb: u32,
    pub endpoint: Endpoint,
    pub capabilities: DeviceCapabilities,
}
```

### Data Storage

```rust
/// Store data with automatic strategy selection
pub async fn store_data(
    handle: &IdentityHandle,
    data: Vec<u8>,
    group_size: usize,
) -> Result<StorageHandle>
```

**Storage Strategy Selection:**
- `1`: Direct storage (single user)
- `2`: Full replication (dyad)
- `3-5`: FEC(3,2) encoding
- `6-10`: FEC(4,3) encoding
- `11-20`: FEC(6,4) encoding
- `20+`: FEC(8,5) encoding

```rust
/// Optimized storage for two-person groups
pub async fn store_dyad(
    handle1: &IdentityHandle,
    other_key: &str,
    data: Vec<u8>,
) -> Result<StorageHandle>
```

```rust
/// Store with custom FEC parameters
pub async fn store_with_fec(
    handle: &IdentityHandle,
    data: Vec<u8>,
    data_shards: usize,
    parity_shards: usize,
) -> Result<StorageHandle>
```

```rust
/// Retrieve stored data
pub async fn get_data(
    storage_handle: &StorageHandle,
) -> Result<Vec<u8>>
```


## Principles

- Trust-minimized: Identities, groups, and data are addressed by four-word identifiers hashed to 32-byte keys.
- Zero-panic production: No `unwrap`/`expect`/`panic!` in production code. Errors are explicit and typed.
- End-to-end encryption: ML-DSA for identity auth; MLS and PQC symmetric crypto for content.
- Two-tier storage: DHT distribution with FEC-sealed containers; optional local member disks and friend-mesh repair.
- Human-verifiable addressing: Four-word addressing prevents lookalike/phishing through a constrained dictionary and checksum.
- Structured telemetry and tracing: All subsystems emit structured events for observability.


## Quick Start for Agents

### Essential API Flow for P2P Applications

**Step 1: Initialize Identity**
```rust
// 1. Generate keypair and claim four-word identity
let words = ["river", "spark", "honest", "lion"];
let (pk, sk) = mldsa_generate();
let sig = mldsa_sign(&sk, words.join("-"));
identity_claim(words.clone(), PubKey::new(pk), Sig::new(sig)).await?;
```

**Step 2: Setup Connectivity**  
```rust
// 2. Publish endpoints and device forwards
identity_publish_endpoints_signed(id_key, endpoints, ep_sig).await?;
device_publish_forward_signed(id_key, forward, sig).await?;
```

**Step 3: Enable Messaging**
```rust
// 3. Initialize messaging service
let messaging = MessagingService::new(four_word_address, dht_client).await?;
```

### Common Application Patterns

- **1:1 Chat App**: Identity API + Messaging API + Transport API
- **Group Collaboration**: + Group API + Virtual Disk API + Real-Time Media API  
- **Public Website**: + Virtual Disk API (website publishing)
- **Secure File Sharing**: + Storage Control API + Friend Mesh Backup API
- **Video Conferencing**: + Real-Time Media API + Group API

### Agent Decision Matrix

| Use Case | Primary APIs | Secondary APIs |
|----------|--------------|----------------|
| User onboarding | Identity | Transport, DHT |
| Send message | Messaging | DHT, Transport |  
| Group chat | Group, Messaging | Real-Time Media |
| File sharing | Virtual Disk, Storage Control | Friend Mesh Backup |
| Video call | Real-Time Media, Messaging | Group, Transport |
| Website publishing | Virtual Disk, DHT | Identity |

## Addressing and Keys

- Four-Word Address: `[Word; 4]` (e.g., "river-spark-honest-lion"). Validated by the Four Word Networking (FWN) dictionary and encoding rules.
- Identity Key (`Key`): `blake3(utf8(join(words,'-')))` → 32 bytes.
- Context Keys: `compute_key(context: &str, content: &[u8])` → 32 bytes. Used for derived records such as device sets, manifests, websites, and virtual disks.
- Network Endpoints: Public IP endpoints can be represented as four-word strings for display (FW4/FW6 encodings).


## Object Model (Core Records)

- IdentityPacketV1
  - `v: u8`
  - `words: [String; 4]` — user-chosen four words
  - `id: Key` — blake3(utf8(words))
  - `pk: Vec<u8>` — ML-DSA public key
  - `sig: Vec<u8>` — ML-DSA signature over `utf8(words)`
  - `endpoints: Vec<NetworkEndpoint>` — optional public reachability
  - `ep_sig: Option<Vec<u8>>` — signature over `(id || pk || CBOR(endpoints))`
  - `website_root: Option<Key>` — public website root object key (see Website Disk)
  - `device_set_root: Key` — device forwards CRDT root (derived)

- DeviceSetV1
  - OR-Set of `Forward { proto, addr, meta }` entries for the identity’s devices and forwards

- GroupIdentityPacketV1
  - `v: u8`, `words: [String;4]`, `id: Key` — group identifier
  - `group_pk: Vec<u8>`, `group_sig: Vec<u8>` — ML-DSA of the group
  - `members: Vec<MemberRef { member_id: Key, member_pk: Vec<u8> }>`
  - `membership_root: Key` — Merkle root of sorted member IDs
  - `created_at: u64`, `mls_ciphersuite: Option<u16>`

- GroupPacketV1
  - Current group epoch state and container bindings: `membership`, `forwards_root`, `container_root`

- GroupForwardsV1
  - `endpoints: Vec<GroupEndpoint { member_pub, forward, ts }>` per member

- ContainerManifestV1
  - `object: Key`, `fec: { k, m, shard_size }`, `assets: Vec<Key>`, `sealed_meta: Option<Key>`
  - Represents a sealed container (object root) with FEC parameters and asset references


## Identity API

Purpose: Claim and fetch identities, publish reachability and device forwards, and subscribe to changes.

- identity_claim(words: [Word; 4], pubkey: PubKey, sig: Sig) -> Result<()>
  - Validates words (FWN), verifies ML-DSA signature over `utf8(words)` with `pubkey`, computes `id` and `device_set_root`, then stores IdentityPacketV1 under `id` in the DHT with quorum policy.
  - Errors: invalid words, invalid pubkey/sig, DHT policy violations.

- identity_fetch(key: Key) -> Result<IdentityPacketV1>
  - Fetches identity packet by `id` key from the DHT.

- identity_publish_endpoints_signed(id_key: Key, endpoints: Vec<NetworkEndpoint>, ep_sig: Sig) -> Result<()>
  - Verifies `ep_sig` over `(id || pk || CBOR(endpoints))` using the stored identity `pk` and updates the packet.
  - Auto-computes FW4/FW6 display forms when possible.

- device_publish_forward(id_key: Key, fwd: Forward) -> Result<()>
  - Adds or updates a forward in `DeviceSetV1` under `device_set_root`. Uses delegated write auth; emits events.

- device_publish_forward_signed(id_key: Key, fwd: Forward, sig: Sig) -> Result<()>
  - Same as above with explicit signature material for authorization contexts that require proof on canonical content.

- device_subscribe(id_key: Key) -> Subscription<Forward>
  - Subscribes to forward updates for an identity.

- identity_set_website_root(id_key: Key, website_root: Key, sig: Sig) -> Result<()>
  - Updates an identity's website root with signature verification.
  - Canonical signing: Message bytes: `b"saorsa-identity:website_root:v1" || id || pk || CBOR(website_root)`
  - Verifies `sig` matches canonical message using stored identity `pk`, then updates IdentityPacketV1.

- group_identity_canonical_sign_bytes(id: &Key, membership_root: &Key) -> Vec<u8>
  - Returns canonical bytes for group identity signing: `b"saorsa-group:identity:v1" || id || membership_root`
  - Used for consistent signature verification across group operations.

Notes
- `WriteAuth` enforces signatures at `dht_put` time. For identity and group canonical records, signatures are verified against canonical bytes to prevent malleability.
- `NetworkEndpoint { ipv4, ipv6, fw4, fw6 }` supports both raw and four-word display addressing.


## Group API

Purpose: Create and publish group identities, maintain group state, endpoints, and storage containers.

- group_identity_create(words: [Word; 4], members: Vec<MemberRef>) -> Result<(GroupIdentityPacketV1, GroupKeyPair)>
  - Derives `id` from words, computes `membership_root` from sorted `member_id`s, generates ML-DSA group keypair, signs canonical message `(id || membership_root)`.

- group_identity_publish(packet: GroupIdentityPacketV1) -> Result<()>
  - Validates words/id and signature; stores canonical packet at `id` key.

- group_identity_fetch(id_key: Key) -> Result<GroupIdentityPacketV1>
  - Reads group identity by id key.

- group_forwards_put(fwd: &GroupForwardsV1, group_id: &[u8], policy: &PutPolicy) -> Result<PutReceipt>
  - Stores under `blake3("group-fwd" || group_id)`; used for up-to-date group forwarding meta.

- group_forwards_fetch(group_id: &[u8]) -> Result<GroupForwardsV1>

- group_put(pkt: &GroupPacketV1, policy: &PutPolicy) -> Result<PutReceipt>
  - Stores current group epoch/control record under `blake3("group" || group_id)`.

- group_fetch(group_id: &[u8]) -> Result<GroupPacketV1>

- group_identity_update_members_signed(id_key: Key, new_members: Vec<MemberRef>, group_pk: Vec<u8>, group_sig: Sig) -> Result<()>
  - Updates group membership with signature verification.
  - Canonical signing: Message bytes: `group_identity_canonical_sign_bytes(id, new_root)`
  - Verifies `group_sig` with `group_pk`, replaces members, recomputes `membership_root`, stores updated packet.

- group_member_add(id_key: Key, member: MemberRef, group_pk: Vec<u8>, group_sig: Sig) -> Result<()>
  - Convenience function to add a member to existing group.
  - Internally fetches current packet, adds member, calls `group_identity_update_members_signed`.

- group_member_remove(id_key: Key, member_id: Key, group_pk: Vec<u8>, group_sig: Sig) -> Result<()>
  - Convenience function to remove a member from existing group.
  - Internally fetches current packet, removes member, calls `group_identity_update_members_signed`.

- group_epoch_bump(id_key: Key, proof: Option<Vec<u8>>, group_pk: Vec<u8>, group_sig: Sig) -> Result<()>
  - Increments group epoch with signature verification.
  - Canonical signing: Message bytes: `b"saorsa-group:epoch:v1" || id || epoch`
  - Verifies `group_sig` with `group_pk`, increments epoch, stores updated GroupPacketV1.

Conventions
- Group storage containers are referenced via `GroupPacketV1.container_root` and described by `ContainerManifestV1`.
- For MLS, `mls_ciphersuite` and `proof` fields are carried as opaque bytes for verification by MLS-capable clients.


## DHT API

Purpose: Authenticated, policy-driven reads/writes to the Trust-Weighted Kademlia (TwDHT).

- dht_put(key: Key, bytes: Bytes, policy: &PutPolicy) -> Result<PutReceipt>
  - `PutPolicy { quorum: usize, ttl: Option<Duration>, auth: Box<dyn WriteAuth> }`
  - Performs record-type aware verification (Identity/Group canonical checks, DeviceSet CRDT semantics, etc.), publishes change events, and records telemetry.
  - PutReceipt: `{ key, timestamp, storing_nodes: Vec<Vec<u8>> }`.

- dht_get(key: Key, quorum: usize) -> Result<Bytes>
  - Fetches with quorum and records telemetry.

- dht_watch(key: Key) -> Subscription<Bytes>
  - Event stream of updates for a DHT key.

- set_dht_instance(dht: Arc<TwDht>) -> bool
  - Installs a process-global DHT for the API.

Security
- Identity and Group records enforce word validity, id/key matching, and ML-DSA signature verification on canonical bytes.
- Endpoint updates require explicit `ep_sig` independent from base identity `sig`.


## Routing & Trust API

- record_interaction(peer: Vec<u8>, outcome: Outcome) -> Result<()>
  - Updates EigenTrust with interaction outcome and records telemetry.
  - `Outcome = { Ok, Timeout, BadData, Refused }`.

- eigen_trust_epoch() -> Result<()>
  - Triggers a maintenance tick; used for scheduling trust recomputations.

- route_next_hop(target: Vec<u8>) -> Option<Contact>
  - Returns a trust-weighted best next-hop `Contact { node_id, endpoint }` for target routing (simplified selection combining XOR-distance and trust).


## Transport API (QUIC)

Provides low-level primitives for direct connections and typed streams. WebRTC bridging is available via messaging modules for real-time A/V.

- quic_connect(ep: &Endpoint { address: String }) -> Result<Conn { peer: Vec<u8> }>
  - Creates/initializes a P2P node if needed and connects to `address`.

- quic_open(conn: &Conn, class: StreamClass) -> Result<Stream { id: u64, class: StreamClass }>
  - `StreamClass = { Control, Mls, File, Media }` (telemetry-tagged).

Media Notes
- Real-time audio/video/screen-share flows are supported via WebRTC over QUIC with signaling handled by the messaging/webrtc bridge. Agents generally don't open raw media streams; they invoke call flows in the Messaging API (see below) which use these transport primitives under the hood.


## Real-Time Media API

Provides high-level audio/video calling with WebRTC-over-QUIC transport, supporting 1:1 and group calls with screen sharing.

### Call Management

- call_initiate(recipient: FourWordAddress, media_config: MediaConfig) -> Result<CallHandle>
  - Initiates call with specified recipient  
  - `MediaConfig { audio: bool, video: bool, screen_share: bool, quality: QualityProfile }`
  - Returns handle for call control operations

- call_answer(call_id: CallId, media_config: MediaConfig) -> Result<CallHandle>
  - Accepts incoming call with specified media capabilities

- call_reject(call_id: CallId, reason: RejectReason) -> Result<()>
  - Rejects incoming call with reason code
  - `RejectReason = { Busy, Declined, Unavailable, UnsupportedMedia }`

- call_hangup(handle: CallHandle) -> Result<CallSummary>
  - Ends active call and returns summary statistics
  - `CallSummary { duration, quality_metrics, participant_count, bytes_transferred }`

### Group Calls

- group_call_create(group_id: Key, media_config: MediaConfig) -> Result<GroupCallHandle>
  - Creates group call session within existing group
  - Automatically invites all group members

- group_call_join(call_id: GroupCallId, media_config: MediaConfig) -> Result<GroupCallHandle>
  - Joins existing group call session

- group_call_invite(handle: GroupCallHandle, participants: Vec<FourWordAddress>) -> Result<Vec<InviteStatus>>
  - Invites additional participants to group call
  - Returns per-participant invitation status

- group_call_remove(handle: GroupCallHandle, participant: FourWordAddress) -> Result<()>
  - Removes participant from group call (admin operation)

### Media Control

- media_toggle_audio(handle: CallHandle, enabled: bool) -> Result<()>
  - Mutes/unmutes audio during active call

- media_toggle_video(handle: CallHandle, enabled: bool) -> Result<()>
  - Enables/disables video during active call  

- media_toggle_screen_share(handle: CallHandle, enabled: bool) -> Result<()>
  - Starts/stops screen sharing

- media_set_audio_device(handle: CallHandle, device_id: AudioDeviceId) -> Result<()>
  - Switches audio input/output device

- media_set_video_device(handle: CallHandle, device_id: VideoDeviceId) -> Result<()>
  - Switches camera device

- media_adjust_quality(handle: CallHandle, quality: QualityProfile) -> Result<()>
  - Dynamically adjusts media quality based on network conditions
  - `QualityProfile = { Low, Medium, High, Auto }`

### Call Events and Monitoring

- call_subscribe_events(handle: CallHandle) -> Subscription<CallEvent>
  - Subscribe to call state changes and events
  - `CallEvent = { ParticipantJoined, ParticipantLeft, MediaToggled, QualityChanged, NetworkEvent }`

- call_get_stats(handle: CallHandle) -> Result<CallStats>
  - Retrieves real-time call quality statistics
  - `CallStats { latency, packet_loss, bitrate, jitter, participants: Vec<ParticipantStats> }`

- call_record(handle: CallHandle, config: RecordingConfig) -> Result<RecordingHandle>
  - Starts call recording (requires participant consent)
  - `RecordingConfig { audio_only: bool, include_screen: bool, storage_location: StorageTarget }`

### Advanced Features

- call_create_breakout(handle: GroupCallHandle, participants: Vec<FourWordAddress>) -> Result<GroupCallHandle>
  - Creates breakout room with subset of participants

- call_enable_noise_cancellation(handle: CallHandle, enabled: bool) -> Result<()>
  - Toggles AI-powered noise cancellation

- call_set_background(handle: CallHandle, background: BackgroundEffect) -> Result<()>
  - Sets virtual background or blur effect
  - `BackgroundEffect = { None, Blur, Image(data), Video(data) }`


## Virtual Disk API

Every entity (individual, group, organization, channel) can have two virtual disks: private (encrypted) and public (website). This API provides file system operations over the DHT with FEC protection.

### Core Virtual Disk Operations

- disk_create(entity_id: Key, disk_type: DiskType, config: DiskConfig) -> Result<DiskHandle>
  - `DiskType = { Private, Website }`
  - `DiskConfig { fec_params: FecParams, encryption: EncryptionConfig, cache_policy: CachePolicy }`
  - Creates virtual disk root and initializes metadata

- disk_mount(entity_id: Key, disk_type: DiskType) -> Result<DiskHandle>
  - Mounts existing virtual disk for operations

- disk_write(handle: DiskHandle, path: &str, content: &[u8], metadata: FileMetadata) -> Result<WriteReceipt>
  - Writes file to path with automatic FEC sealing and DHT distribution
  - `FileMetadata { mime_type, permissions, created_at, tags }`

- disk_read(handle: DiskHandle, path: &str) -> Result<Vec<u8>>
  - Reads file, reconstructing from FEC shards if needed

- disk_list(handle: DiskHandle, path: &str, recursive: bool) -> Result<Vec<FileEntry>>
  - Lists directory contents with metadata
  - `FileEntry { path, size, modified_at, file_type, permissions }`

- disk_delete(handle: DiskHandle, path: &str) -> Result<()>
  - Marks file as deleted and schedules shard cleanup

- disk_sync(handle: DiskHandle) -> Result<SyncStatus>
  - Forces synchronization of pending changes to DHT
  - Returns `SyncStatus { pending_writes, conflicts, last_sync }`

### Website Publishing Operations

- website_set_home(handle: DiskHandle, markdown_content: &str, assets: Vec<Asset>) -> Result<()>
  - Sets `home.md` as website entry point with linked assets
  - `Asset { path, content, mime_type }` for images, CSS, etc.

- website_publish(entity_id: Key, website_root: Key) -> Result<PublishReceipt>
  - Updates entity's IdentityPacket with new website_root
  - Makes website publicly accessible via four-word address

- website_get_manifest(website_root: Key) -> Result<WebsiteManifest>
  - Retrieves website structure and asset references
  - `WebsiteManifest { home_md_key, assets: Vec<AssetRef>, navigation, metadata }`

### Collaborative Operations

- disk_share(handle: DiskHandle, path: &str, permissions: Permissions, members: Vec<Key>) -> Result<ShareToken>
  - Shares file/directory with specific members
  - `Permissions { read, write, admin }` with role-based access

- disk_collaborate(handle: DiskHandle, path: &str, session_id: SessionId) -> Result<CollabSession>
  - Initiates real-time collaborative editing session
  - Returns conflict-free replicated data type (CRDT) session

- disk_resolve_conflict(handle: DiskHandle, conflict: FileConflict, resolution: ConflictResolution) -> Result<()>
  - Resolves file conflicts using specified strategy
  - `ConflictResolution = { TakeLocal, TakeRemote, Merge(strategy), Manual(content) }`

### Advanced Operations

- disk_snapshot(handle: DiskHandle, name: &str) -> Result<SnapshotId>
  - Creates immutable snapshot of current disk state

- disk_restore(handle: DiskHandle, snapshot_id: SnapshotId) -> Result<()>
  - Restores disk to previous snapshot state

- disk_encrypt_for_group(handle: DiskHandle, group_id: Key, mls_key: &[u8]) -> Result<()>
  - Re-encrypts disk content for group access using MLS derived keys

## Virtual Disks and Websites

Every entity (individual, group, organization, channel) can expose two logical disks:

1) Private Disk (entity-scoped, group-encrypted)
   - Root Key: `disk_root = compute_key("disk", entity_id.as_bytes())`
   - Organization: content addressed by path → object key mapping using `ContainerManifestV1` for each root object.
   - Encryption: MLS or group ML-DSA derived symmetric keys; objects are sealed and sharded with FEC `(k,m,shard_size)` across DHT, with optional member-local caches.
   - Access: membership governed; members reconstruct via DHT + local caches.

2) Website Disk (public)
   - Root Key: `website_root` in `IdentityPacketV1` or `compute_key("website", entity_id.as_bytes())` if not set.
   - Convention: `home.md` is the entry file (Markdown-only web). Assets referenced by relative paths resolve to `assets/` keyed objects in the same container or sibling keys.
   - Publishing: write manifests and assets to DHT under context keys, set/refresh `website_root` on identity.
   - Browsing: agents fetch `IdentityPacketV1`, read `website_root`, fetch `ContainerManifestV1` at root, then fetch `home.md` and linked assets.

Addressing Examples
- Individual disk: `disk_root = blake3("disk" || ID)` where `ID = blake3(words)`.
- Group disk: same construction with the group's `id` from `GroupIdentityPacketV1`.
- Channel disk: derive channel key: `channel_id = compute_key("channel", group_id.as_bytes())` then `disk_root = compute_key("disk", channel_id.as_bytes())`.


## Storage Control API

High-level placement and maintenance helpers for FEC-sealed content.

- place_shards(object_id: [u8; 32], count: usize) -> Vec<Vec<u8>>
  - Returns node IDs for shard placement using trust-weighted proximity.

- provider_advertise_space(free: u64, total: u64)
  - Publishes capacity to the DHT under a well-known key pattern.

- repair_request(object_id: [u8; 32]) -> RepairPlan
  - Returns `RepairPlan { object_id, missing_shards: Vec<usize>, repair_nodes: Vec<Vec<u8>> }`.


## Friend Mesh Backup API

Optional cooperative backup among friends/devices with rotation.

- friend_mesh_plan(data_size: u64, mesh_config: &FriendMeshConfig) -> FriendBackupPlan
  - `FriendMeshConfig { mesh_id: Key, members: Vec<FriendMeshMember>, replication_factor, rotation_schedule }`
  - Returns `FriendBackupPlan { total_shards, shard_size, assignments: Vec<FriendBackupAssignment> }`.


## Virtual Disk API

Every entity (individual, group, organization, channel) can have two virtual disks: private (encrypted) and public (website). This API provides file system operations over the DHT with FEC protection.

### Core Virtual Disk Operations

- disk_create(entity_id: Key, disk_type: DiskType, config: DiskConfig) -> Result<DiskHandle>
  - `DiskType = { Private, Website }`  
  - `DiskConfig { fec_params: FecParams, encryption: EncryptionConfig, cache_policy: CachePolicy }`
  - Creates virtual disk root and initializes metadata

- disk_mount(entity_id: Key, disk_type: DiskType) -> Result<DiskHandle>
  - Mounts existing virtual disk for operations

- disk_write(handle: DiskHandle, path: &str, content: &[u8], metadata: FileMetadata) -> Result<WriteReceipt>
  - Writes file to path with automatic FEC sealing and DHT distribution
  - `FileMetadata { mime_type, permissions, created_at, tags }`

- disk_read(handle: DiskHandle, path: &str) -> Result<Vec<u8>>
  - Reads file, reconstructing from FEC shards if needed

- disk_list(handle: DiskHandle, path: &str, recursive: bool) -> Result<Vec<FileEntry>>
  - Lists directory contents with metadata
  - `FileEntry { path, size, modified_at, file_type, permissions }`

- disk_delete(handle: DiskHandle, path: &str) -> Result<()>
  - Marks file as deleted and schedules shard cleanup

- disk_sync(handle: DiskHandle) -> Result<SyncStatus>
  - Forces synchronization of pending changes to DHT
  - Returns `SyncStatus { pending_writes, conflicts, last_sync }`

### Website Publishing Operations

- website_set_home(handle: DiskHandle, markdown_content: &str, assets: Vec<Asset>) -> Result<()>
  - Sets `home.md` as website entry point with linked assets
  - `Asset { path, content, mime_type }` for images, CSS, etc.

- website_publish(entity_id: Key, website_root: Key) -> Result<PublishReceipt>  
  - Updates entity's IdentityPacket with new website_root
  - Makes website publicly accessible via four-word address

- website_get_manifest(website_root: Key) -> Result<WebsiteManifest>
  - Retrieves website structure and asset references
  - `WebsiteManifest { home_md_key, assets: Vec<AssetRef>, navigation, metadata }`

### Collaborative Operations

- disk_share(handle: DiskHandle, path: &str, permissions: Permissions, members: Vec<Key>) -> Result<ShareToken>
  - Shares file/directory with specific members
  - `Permissions { read, write, admin }` with role-based access

- disk_collaborate(handle: DiskHandle, path: &str, session_id: SessionId) -> Result<CollabSession>
  - Initiates real-time collaborative editing session
  - Returns conflict-free replicated data type (CRDT) session

- disk_resolve_conflict(handle: DiskHandle, conflict: FileConflict, resolution: ConflictResolution) -> Result<()>
  - Resolves file conflicts using specified strategy
  - `ConflictResolution = { TakeLocal, TakeRemote, Merge(strategy), Manual(content) }`

### Advanced Operations

- disk_snapshot(handle: DiskHandle, name: &str) -> Result<SnapshotId>
  - Creates immutable snapshot of current disk state

- disk_restore(handle: DiskHandle, snapshot_id: SnapshotId) -> Result<()>
  - Restores disk to previous snapshot state

- disk_encrypt_for_group(handle: DiskHandle, group_id: Key, mls_key: &[u8]) -> Result<()>
  - Re-encrypts disk content for group access using MLS derived keys

## Virtual Disks and Websites

Every entity (individual, group, organization, channel) can expose two logical disks:

1) Private Disk (entity-scoped, group-encrypted)
   - Root Key: `disk_root = compute_key("disk", entity_id.as_bytes())`
   - Organization: content addressed by path → object key mapping using `ContainerManifestV1` for each root object.
   - Encryption: MLS or group ML-DSA derived symmetric keys; objects are sealed and sharded with FEC `(k,m,shard_size)` across DHT, with optional member-local caches.
   - Access: membership governed; members reconstruct via DHT + local caches.

2) Website Disk (public)
   - Root Key: `website_root` in `IdentityPacketV1` or `compute_key("website", entity_id.as_bytes())` if not set.
   - Convention: `home.md` is the entry file (Markdown-only web). Assets referenced by relative paths resolve to `assets/` keyed objects in the same container or sibling keys.
   - Publishing: write manifests and assets to DHT under context keys, set/refresh `website_root` on identity.
   - Browsing: agents fetch `IdentityPacketV1`, read `website_root`, fetch `ContainerManifestV1` at root, then fetch `home.md` and linked assets.

Addressing Examples
- Individual disk: `disk_root = blake3("disk" || ID)` where `ID = blake3(words)`.
- Group disk: same construction with the group’s `id` from `GroupIdentityPacketV1`.
- Channel disk: derive channel key: `channel_id = compute_key("channel", group_id.as_bytes())` then `disk_root = compute_key("disk", channel_id.as_bytes())`.


## Messaging API (High-Level Service)

The MessagingService coordinates storage, transport, and encryption for direct and group messaging and calls.

Types
- `FourWordAddress` — identity handle (string form of four words)
- `ChannelId`, `ThreadId`, `MessageId` — logical identifiers
- `MessageContent` — rich content (text, reactions, attachments)
- `EncryptedMessage`, `RichMessage`, `DeliveryReceipt`, `DeliveryStatus`

Construction
- new(identity: FourWordAddress, dht_client: DhtClient) -> Result<MessagingService>
  - Wires persistence, PQC key-exchange, transport, and events.

Send & Receive
- send_message(recipients: Vec<FourWordAddress>, content: MessageContent, channel_id: ChannelId, options: SendOptions) -> Result<(MessageId, DeliveryReceipt)>
  - Encrypts per recipient and sends via transport (DHT + direct), stores locally first.

- MessagingService::send_message_to_channel(channel_id: ChannelId, content: MessageContent, options: SendOptions) -> Result<(MessageId, DeliveryReceipt)>
  - Sends message to all members of a channel by resolving recipients from channel membership.
  - Internally calls `send_message()` with resolved recipient list from `channel_recipients()`.

- channel_recipients(channel_id: &ChannelId) -> Result<Vec<FourWordAddress>>
  - Helper function to resolve channel members to their four-word addresses.
  - Loads channel, maps member user_ids to FourWordAddress for messaging.

- subscribe_messages(channel_filter: Option<ChannelId>) -> Receiver<ReceivedMessage>
  - Async stream of inbound messages (decrypted and persisted before delivery).

- get_message_status(message_id: MessageId) -> Result<DeliveryStatus>
- get_message(message_id: MessageId) -> Result<RichMessage>
- mark_user_online(user: FourWordAddress) -> Result<()>
- mark_delivered(message_id: MessageId, recipient: FourWordAddress) -> Result<()>
- process_message_queue() -> Result<()>
- encrypt_message(recipient, channel_id, content) -> Result<EncryptedMessage>
- decrypt_message(encrypted) -> Result<RichMessage>

Realtime A/V Calls
- The messaging/webrtc bridge supports:
  - Direct 1:1 audio/video/screen-share over WebRTC with QUIC transport.
  - Group calls by creating an MLS-secured session; members receive dynamic group endpoints from `GroupForwardsV1`.
  - Signaling exchanged as messages; media flows are direct peer-to-peer when possible.


## Agent Decision Trees

### When to Use Which API

**For Identity Management:**
- New user? → `identity_claim()` + `identity_publish_endpoints_signed()`  
- User connecting from new device? → `device_publish_forward_signed()`
- Need to find user? → `identity_fetch()` + four-word address resolution

**For Messaging:**
- 1:1 chat? → `MessagingService::send_message()` with single recipient
- Group chat? → Group API first, then `MessagingService` with group context  
- File attachment? → Virtual Disk API to store, then send reference via messaging
- Need offline delivery? → Messages automatically queued in DHT

**For Real-Time Communication:**  
- Voice/video call? → Real-Time Media API `call_initiate()`
- Screen sharing? → `media_toggle_screen_share()` during active call
- Group conference? → `group_call_create()` within existing group
- Recording needed? → `call_record()` with participant consent

**For File Storage:**
- Private group files? → Virtual Disk API with `Private` disk type
- Public website? → Virtual Disk API with `Website` disk type  
- Need backup? → Friend Mesh Backup API for redundancy
- Large files? → Storage Control API for optimal shard placement

### API Interaction Patterns

**Pattern 1: User Onboarding Flow**
```
identity_claim() → identity_publish_endpoints_signed() → 
device_publish_forward_signed() → MessagingService::new()
```

**Pattern 2: Group Creation with Storage**  
```
group_identity_create() → group_identity_publish() → 
disk_create(Private) → group_forwards_put()
```

**Pattern 3: Collaborative Document Editing**
```
disk_mount() → disk_collaborate() → Real-Time Media API (optional voice) →
disk_sync() → disk_snapshot() (for versioning)
```

**Pattern 4: Public Website Publishing**
```
disk_create(Website) → website_set_home() → 
website_publish() → identity_publish_endpoints_signed()
```

## Common Patterns

### Best Practices for Agents

**Security First:**
- Always validate four-word addresses before computing keys
- Use canonical signing bytes for identity and group operations  
- Never persist plaintext keys - use secure storage
- Verify signatures on all critical operations

**Error Handling:**
- All APIs return `Result<T, E>` - handle errors explicitly
- Use structured error types for debugging
- Implement retry logic for network operations
- Log structured events for observability

**Performance Optimization:**
- Cache identity lookups locally with TTL
- Use quorum=1 for best-effort reads, quorum=majority for critical writes
- Batch multiple operations when possible
- Use friend mesh backup for frequently accessed group content

**Network Efficiency:**
- Reuse QUIC connections where possible
- Use appropriate stream classes for telemetry
- Enable compression for large content transfers
- Monitor call quality and adjust media settings dynamically

### Troubleshooting Guide

**Common Issues:**

1. **Identity claim fails:**
   - Check four-word validation against FWN dictionary
   - Verify ML-DSA signature over canonical bytes
   - Ensure words are properly joined with '-'

2. **Group operations fail:**  
   - Verify membership_root matches sorted member IDs
   - Check group signature against canonical message
   - Ensure all members have valid identity packets

3. **File operations slow:**
   - Check FEC parameters (k, m values)
   - Verify shard placement across trusted nodes
   - Consider local caching for frequently accessed content

4. **Call quality issues:**
   - Monitor `call_get_stats()` for packet loss/latency
   - Try `media_adjust_quality(Auto)` for adaptive streaming
   - Check if `call_enable_noise_cancellation()` helps

## Example: Building "Communitas"

Communitas is a large-scale, P2P collaboration app blending WhatsApp (messaging/calls), Dropbox (storage/sync), Slack (channels/threads), and a new Markdown-based web. It is phishing-resistant (four-word networking) and AI-friendly (structured APIs and explicit semantics).

Core Features
- Identity: users and groups claim four-word addresses; groups carry membership roots and published forwards.
- Messaging: 1:1 and group threads with reactions, attachments, and threads.
- Calls: direct audio/video/screen-share with group calls via MLS sessions.
- Storage: end-to-end encrypted “virtual disks” per entity (user/group/channel) with DHT + local caches and FEC-sealed containers.
- Web: every entity can publish a public Markdown site (`home.md`) at its website disk root.

High-Level Flows
1) User Onboarding
   - Generate ML-DSA keypair; select four words; call `identity_claim()` with signature over words.
   - Publish device forwards (`device_publish_forward_signed`) and endpoints (`identity_publish_endpoints_signed`).

2) Creating a Group
   - Select group words; gather initial members (`MemberRef { member_id, member_pk }`).
   - Call `group_identity_create()` and then `group_identity_publish()`.
   - Store `GroupForwardsV1` to advertise callable members.

3) Private Disk Setup (Group)
   - Compute `disk_root = compute_key("disk", group_id.as_bytes())`.
   - Create a root `ContainerManifestV1` with FEC parameters and encrypted `sealed_meta` (MLS key).
   - Place shards with `place_shards(object_id, k+m)` and upload to DHT; optionally seed local caches.

4) Public Website
   - Compute or fetch `website_root`; create a container with `home.md` and assets.
   - Write container manifest under `compute_key("manifest", object_root)` and set `website_root` in identity.
   - Resolution: clients fetch identity → `website_root` → manifest → fetch `home.md` and linked assets.

5) Messaging and Calls
   - For 1:1: create or join `ChannelId` (derived from pair’s IDs), call `send_message()` and listen on `subscribe_messages()`.
   - For groups: derive `ChannelId` from group id; agents retrieve `GroupForwardsV1` to locate members and initiate MLS-secured calls; media flows over WebRTC/QUIC.

6) Friend Mesh Backup (Optional)
   - Maintain resilient copies by planning with `friend_mesh_plan()`; rotate shard assignments on schedule.

Sample Pseudocode (Agent)
```rust
// 1) Claim identity
let words = ["river".into(), "spark".into(), "honest".into(), "lion".into()];
let (pk, sk) = mldsa_generate();
let sig = mldsa_sign(&sk, words.join("-"));
identity_claim(words.clone(), PubKey::new(pk.clone()), Sig::new(sig)).await?;

// 2) Publish endpoints and forwards
let endpoints = vec![NetworkEndpoint { ipv4: Some(("203.0.113.10".into(), 443)), ipv6: None, fw4: None, fw6: None }];
let ep_sig = sign_endpoints(&sk, &id_key, &pk, &endpoints);
identity_publish_endpoints_signed(id_key.clone(), endpoints, ep_sig).await?;
device_publish_forward_signed(id_key.clone(), Forward::quic("203.0.113.10:443"), delegated_sig).await?;

// 3) Create group and publish forwards
let (g_pkt, g_kp) = group_identity_create(group_words, members)?;
group_identity_publish(g_pkt.clone()).await?;
group_forwards_put(&GroupForwardsV1 { v: 1, endpoints: endpoints_for_members, proof: None }, &g_pkt.id.as_bytes()[..], &policy).await?;

// 4) Store website container
let manifest = ContainerManifestV1 { v: 1, object: website_root, fec: FecParams { k: 8, m: 4, shard_size: 65536 }, assets: vec![home_md_key, css_key], sealed_meta: None };
container_manifest_put(&manifest, &policy).await?;

// 5) Messaging
let svc = MessagingService::new(my_fw_address, dht).await?;
let (_id, receipt) = svc.send_message(vec![peer_fw], MessageContent::Text("Hi".into()), channel_id, SendOptions::default()).await?;
```


## Comprehensive Usage Examples

### Identity Website Root Update

```rust
use saorsa_core::api::*;
use saorsa_core::quantum_crypto::{MlDsa65, MlDsaOperations};

// Update an identity's website root
let id_key = Key::from([1u8; 32]);
let website_root = Key::from([2u8; 32]);
let ml = MlDsa65::new();
let (pk, sk) = ml.generate_keypair().unwrap();

// Build canonical message
let mut msg = Vec::new();
msg.extend_from_slice(CANONICAL_IDENTITY_WEBSITE_ROOT);
msg.extend_from_slice(id_key.as_bytes());
msg.extend_from_slice(pk.as_bytes());
let website_root_cbor = serde_cbor::to_vec(&website_root).unwrap();
msg.extend_from_slice(&website_root_cbor);

// Sign and update
let sig = ml.sign(&sk, &msg).unwrap();
identity_set_website_root(id_key, website_root, Sig::new(sig.as_bytes().to_vec())).await?;
```

### Group Membership Update

```rust
use saorsa_core::api::*;

// Update group membership
let group_id = Key::from([1u8; 32]);
let new_members = vec![
    MemberRef {
        member_id: Key::from([2u8; 32]),
        member_pk: vec![1, 2, 3],
    }
];

// Get canonical signing bytes
let membership_root = compute_membership_root(&new_members);
let sign_bytes = group_identity_canonical_sign_bytes(&group_id, &membership_root);

// Sign with group key
let ml = MlDsa65::new();
let group_pk = vec![4, 5, 6]; // From group creation
let group_sk = ml.generate_keypair().unwrap().1; // In practice, use stored key
let sig = ml.sign(&group_sk, &sign_bytes).unwrap();

// Update membership
group_identity_update_members_signed(
    group_id,
    new_members,
    group_pk,
    Sig::new(sig.as_bytes().to_vec())
).await?;
```

### Virtual Disk Operations

```rust
use saorsa_core::virtual_disk::*;

// Create and use a virtual disk
let entity_id = Key::from([1u8; 32]);
let config = DiskConfig::default();

// Create disk
let handle = disk_create(entity_id, DiskType::Private, config).await?;

// Write file
let content = b"Hello, Virtual Disk!";
let metadata = FileMetadata::default();
disk_write(&handle, "hello.txt", content, metadata).await?;

// Read file
let read_content = disk_read(&handle, "hello.txt").await?;
assert_eq!(read_content, content);

// List directory
let files = disk_list(&handle, ".", false).await?;
println!("Files: {:?}", files);

// Sync changes
let sync_status = disk_sync(&handle).await?;
println!("Sync status: {:?}", sync_status);
```

### Website Publishing

```rust
use saorsa_core::virtual_disk::*;

// Create and publish a website
let entity_id = Key::from([1u8; 32]);
let handle = disk_create(entity_id.clone(), DiskType::Website, DiskConfig::default()).await?;

// Set home page with assets
let markdown = "# Welcome\n\nThis is my website.";
let assets = vec![
    Asset {
        path: "style.css".to_string(),
        content: b"body { font-family: sans-serif; }".to_vec(),
        mime_type: "text/css".to_string(),
    }
];

website_set_home(&handle, markdown, assets).await?;

// Publish website
let website_root = Key::from([2u8; 32]);
let receipt = website_publish(entity_id, website_root).await?;
println!("Website published: {:?}", receipt);
```

### Channel Messaging

```rust
use saorsa_core::messaging::service::*;
use saorsa_core::messaging::types::*;

// Send message to channel
let channel_id = ChannelId::new();
let content = MessageContent::Text("Hello, channel!".to_string());
let options = SendOptions::default();

// Send to all channel members
let messaging = MessagingService::new(four_word_address, dht_client).await?;
let (message_id, receipt) = messaging.send_message_to_channel(
    channel_id,
    content,
    options
).await?;

// Get channel recipients
let recipients = channel_recipients(&channel_id).await?;
println!("Channel has {} recipients", recipients.len());
```

### Group Member Management

```rust
use saorsa_core::api::*;

// Add member to group
let group_id = Key::from([1u8; 32]);
let new_member = MemberRef {
    member_id: Key::from([2u8; 32]),
    member_pk: vec![1, 2, 3],
};

// Sign with group key (simplified)
let group_pk = vec![4, 5, 6];
let group_sig = Sig::new(vec![7, 8, 9]); // In practice, compute proper signature

group_member_add(group_id, new_member, group_pk, group_sig).await?;

// Remove member
let member_to_remove = Key::from([2u8; 32]);
group_member_remove(group_id, member_to_remove, group_pk, group_sig).await?;
```

### Group Epoch Bump

```rust
use saorsa_core::api::*;

// Bump group epoch
let group_id = Key::from([1u8; 32]);
let proof = Some(vec![1, 2, 3]); // Optional proof data
let group_pk = vec![4, 5, 6];
let group_sig = Sig::new(vec![7, 8, 9]); // Proper signature required

group_epoch_bump(group_id, proof, group_pk, group_sig).await?;
```

## Anti-Phishing and Name Safety

- Four-word addresses are validated against the FWN dictionary and encoding. Because words map through a checksum-bearing scheme, close-word collisions are minimized and detectable.
- Display of endpoints and identities defaults to four-word forms (FW4/FW6) where possible.
- Agents should treat any UI string not derived from four-word encodings as untrusted.


## Error Handling and Telemetry

- All APIs return explicit `Result<T, E>`; production code never panics. Errors include descriptive messages and can carry machine-parsable codes.
- `tracing` emits JSON-structured events for: DHT puts/gets, auth failures, timeouts, stream class usage, and message delivery outcomes.

### Extended Error Types

The following error variants have been added to support new API functionality:

**Identity Errors:**
- `InvalidSignature` - Signature verification failed
- `InvalidCanonicalBytes` - Canonical message format invalid
- `MembershipConflict` - Group membership operation conflict
- `MissingGroupKey` - Required group key not found
- `WebsiteRootUpdateRefused` - Website root update rejected

**Usage Examples:**
```rust
use saorsa_core::error::{P2PError, IdentityError};

// Handle identity-specific errors
match result {
    Err(P2PError::Identity(IdentityError::InvalidSignature)) => {
        // Handle signature verification failure
        log::warn!("Signature verification failed for identity operation");
    }
    Err(P2PError::Identity(IdentityError::WebsiteRootUpdateRefused)) => {
        // Handle website root update rejection
        log::error!("Website root update was refused");
    }
    // ... other error handling
}
```


## Security Notes

- Identity auth: ML-DSA-65 signatures; signatures over canonical content prevent malleability.
- Content encryption: PQC-friendly symmetric crypto (ChaCha20-Poly1305 via saorsa-pqc). Group content can use MLS session keys.
- Sharding: FEC `(k,m,shard_size)` improves resiliency; shard placement uses trust-weighted selection; repairs planned via `repair_request()` and optional friend-mesh rotation.
- Keys and secrets must never be persisted in plaintext. Use secure storage and zeroization where applicable.


## Compatibility and Versioning

- All top-level records are versioned (`v: u8`).
- New fields are added in a backwards-compatible manner. Unknown fields must be ignored by agents.
- Wire-compatibility is ensured through CBOR encoding of canonical records and explicit signature bytes.


## Quick Reference (Calls)

- Identity: `identity_claim`, `identity_fetch`, `identity_publish_endpoints_signed`, `identity_set_website_root`, `device_publish_forward`, `device_publish_forward_signed`, `device_subscribe`, `group_identity_canonical_sign_bytes`.
- Groups: `group_identity_create`, `group_identity_publish`, `group_identity_fetch`, `group_identity_update_members_signed`, `group_member_add`, `group_member_remove`, `group_epoch_bump`, `group_forwards_put`, `group_forwards_fetch`, `group_put`, `group_fetch`.
- DHT: `dht_put`, `dht_get`, `dht_watch`, `set_dht_instance`.
- Virtual Disk: `disk_create`, `disk_mount`, `disk_write`, `disk_read`, `disk_list`, `disk_delete`, `disk_sync`, `website_set_home`, `website_publish`, `website_get_manifest`, `disk_share`, `disk_collaborate`, `disk_resolve_conflict`, `disk_snapshot`, `disk_restore`, `disk_encrypt_for_group`.
- Messaging: `MessagingService::new`, `send_message`, `send_message_to_channel`, `channel_recipients`, `subscribe_messages`, `get_message_status`, `get_message`, `mark_user_online`, `mark_delivered`, `process_message_queue`, `encrypt_message`, `decrypt_message`.
- Routing & Trust: `record_interaction`, `eigen_trust_epoch`, `route_next_hop`.
- Transport: `quic_connect`, `quic_open`.
- Storage Control: `place_shards`, `provider_advertise_space`, `repair_request`.
- Friend Mesh: `friend_mesh_plan`.


## Implementation Notes for Agents

- Always validate four-word inputs before computing keys.
- Use canonical signing bytes as described for identities, endpoints, and groups.
- For websites, prefer immutable content addresses in manifests; update manifests atomically and then update `website_root` to point to the new object root.
- For large files, use `ContainerManifestV1` + chunked/FEC-sealed storage; place shards via `place_shards` and cache locally for fast group reads.
- For calls, prefer the MessagingService call flows; only reach for raw QUIC when building bespoke transports.