# tsafe-collab

Team collaboration service skeleton for [tsafe](https://crates.io/crates/tsafe-cli).

Provides the `CollabRemote` trait and an in-memory stub server for sharing
encrypted vault DEKs (data encryption keys) between team members using
age encryption + Shamir secret sharing for recovery.

## Status: Early / Experimental

The collaboration service protocol and wire format are defined; production
server infrastructure is not yet included. The stub server (for testing) is.

## Key types

- `CollabRemote` — trait for membership directory, DEK delivery, invite flow,
  and recovery-share transport; synchronous HTTP via `ureq` for production
  implementations
- `StubServer` — thread-safe in-memory `CollabRemote` implementation backed
  by `HashMap` state; enforces the membership gate on every call
- `MemberEntry` — team member identified by an age X25519 bech32 public key
- `DekEnvelope` — age-encrypted DEK blob; the server stores it opaquely and
  cannot decrypt it (`schema: "tsafe/collab-dek/v1"`)
- `InviteToken` / `InviteRecord` — TOFU-bound invite flow (ADR-028): an invite
  is bound to a specific invitee pubkey at creation time; `confirm_invite`
  enforces the binding and consumes the token (one-use, 48-hour TTL)
- `split_recovery_key` / `reconstruct_recovery_key` — Shamir N-of-M sharing

## Wire format

Recovery shares produced by `split_recovery_key` are serialized as:

```
[ threshold: u8 ][ blahaj_share_bytes: x || y[0..31] ]
```

The leading threshold byte lets `reconstruct_recovery_key` operate without
the caller tracking the threshold separately. Total per-share size: 33 bytes.
Base64-encode for transport. See `docs/decisions/shamir-crate-selection.md`
(ADR-032) for crate-selection rationale (`blahaj 0.6` as the maintained
successor to `sharks 0.5`).

## Architectural boundary

`tsafe-core` MUST NOT import this crate (ADR-027). The dependency direction is:

```
tsafe-collab  →  (ureq, age, serde, thiserror, uuid, chrono, blahaj)
tsafe-cli     →  tsafe-collab   [feature = "collab"]
```

Add `--features collab` to the CLI build to pull this crate in. The crate
compiles and all tests pass without a live collab-service.

## Security properties

- The server (stub or production) stores only age-encrypted ciphertext — it
  holds no plaintext key material (ADR-027 "Service NEVER holds").
- DEK envelopes are age-encrypted to the recipient's X25519 public key;
  a non-member who obtains the envelope bytes cannot decrypt them.
- `fetch_dek` and `fetch_recovery_share` enforce membership before returning
  any data; the adversarial proof is in
  `tests/non_member_dek_isolation.rs` (D3.4).
