# Enigma SFU
Generic in-memory SFU core for managing rooms, participants, tracks, and subscriptions. It focuses on deterministic state only; media forwarding and signaling transports are left to adapters you plug in.
## Highlights
- Pure in-memory state machine with validated identifiers
- Room, participant, track, and subscription management with event hooks
- No hard participant or track caps; callers enforce policy
- Transport adapter trait to bridge WebRTC or any media layer later
## Quickstart
```rust
use enigma_sfu::{ParticipantId, ParticipantMeta, RoomId, Sfu, TrackKind, VecEventSink};
fn main() -> Result<(), enigma_sfu::SfuError> {
let sink = VecEventSink::new();
let sfu = Sfu::new(sink);
let room = RoomId::new("demo")?;
let alice = ParticipantId::new("alice")?;
let bob = ParticipantId::new("bob")?;
sfu.create_room(room.clone(), 0)?;
sfu.join(room.clone(), alice.clone(), ParticipantMeta::default(), 1)?;
sfu.join(room.clone(), bob.clone(), ParticipantMeta::default(), 2)?;
let track = sfu.publish_track(room.clone(), alice.clone(), TrackKind::Audio, None, 3)?;
sfu.subscribe(room.clone(), bob.clone(), track.clone())?;
sfu.unsubscribe(room.clone(), bob.clone(), track)?;
sfu.leave(room.clone(), bob)?;
sfu.leave(room, alice)?;
Ok(())
}
```
## Events and adapters
Use `EventSink` to capture room events (for logging, metrics, or async dispatch). Implement `SfuTransportAdapter` to react when tracks are published or subscriptions change so a media stack can wire transports.
## Compatibility
Legacy types and engine wrappers remain available for callers that relied on earlier interfaces, but the core API is `Sfu`, `RoomId`/`ParticipantId`/`TrackId`, and the event-driven state machine shown above.