yacen-core 0.3.9

Core library for yacen, simplifying client development
Documentation
syntax = "proto3";

package yacen_api.v2_2;
option go_package = "yacen_api.v2_2";

import "google/protobuf/timestamp.proto";

// --------------------------------------------------------- //
// region Authentication via gRPC Metadata
//
// All requests and responses in this API are cryptographically authenticated
// using Ed25519 signatures passed through gRPC metadata headers.
//
// Client behavior (on every request):
// - Serialize the request body using protobuf encoding.
// - Sign the serialized body using Ed25519 private key.
// - Encode both the signature and public key using base64.
// - Attach them to gRPC metadata headers:
//   - "signature": base64(Ed25519 signature)
//   - "pubkey":    base64(PublicKey[32])
//
// Server behavior (on request):
// - Extract "pubkey" and "signature" from metadata headers.
// - Verify that the signature matches the serialized protobuf request body.
//
// Response behavior:
// - Server must also include its own signature and public key
//   in the response metadata using the same "signature" and "pubkey" headers.
//
// This mechanism ensures message integrity, authenticity, and
// supports stateless identity verification without sessions or tokens.
//
// Example client-side implementation is based on:
// - tonic::Request
// - prost::Message
// - ed25519_dalek::Signer / Verifier
//
// See: `sign_request` and `verify_response` in Rust for reference.
//
// --------------------------------------------------------- //
// Service: Yacen
//
// All RPCs in this service require the client to sign the full request message
// and include their public key and signature in the gRPC metadata.
// See authentication notes above.

service Yacen {
  // Room Base
  rpc CreateRoom (CreateRoomReq) returns (CreateRoomRes);
  rpc GetRoomInfo (GetRoomInfoReq) returns (GetRoomInfoRes);
  rpc UpdateRoomInfo (UpdateRoomInfoReq) returns (UpdateRoomInfoRes);
  rpc DeleteRoom (DeleteRoomReq) returns (DeleteRoomRes);

  // Non-Members and upper
  rpc RequestJoinRoom (RequestJoinRoomReq) returns (RequestJoinRoomRes);
  rpc GetJoinRequestStatus (GetJoinRequestStatusReq) returns (GetJoinRequestStatusRes);

  // Members and upper
  rpc SendMessage (SendMessageReq) returns (SendMessageRes);
  rpc GetMessages (GetMessageReq) returns (stream GetMessageRes);
  rpc UploadFile (stream UploadFileReq) returns (UploadFileRes);
  rpc DownloadFile (DownloadFileReq) returns (stream DownloadFileRes);
  
  // Extended Rights
  rpc ApproveJoinRequest (ApproveJoinRequestReq) returns (ApproveJoinRequestRes);
  rpc GiveExtendedRights (GiveExtendedRightsReq) returns (GiveExtendedRightsRes);
  rpc RemoveExtendedRights (RemoveExtendedRightsReq) returns (RemoveExtendedRightsRes);
}
// --------------------------------------------------------- //
// region Security

message MessageUniqueID {
  bytes nonce = 1; // bytes[24]
  google.protobuf.Timestamp timestamp = 2;
}

message Ed25519Signature {
  bytes signature = 1; // 64 bytes ed25519 signature
  string public_key = 2;
}

// --------------------------------------------------------- //
// region Room

enum RoomType {
  ROOM_TYPE_COMMON = 0;
  ROOM_TYPE_CHANNEL = 1;
  reserved 2 to 5;
}

message RoomInfoPublic {
  bytes encrypted_room_name = 1; // bytes(enc(AES_256_GCM, room_name))
  bytes encrypted_room_description = 2; // bytes(enc(AES_256_GCM, room_description))
  RoomType room_type = 3; // RoomType enum members
  reserved 4 to 6;
}

message RoomInfoPrivate {
  repeated string extended_rights_public_keys = 1; // same key fmt as in meta ( base64(bytes[32]) ); default only owner
  repeated string allowed_public_keys = 2; // same key fmt as in meta ( base64(bytes[32]) ); default only owner
  repeated string pending_join_requests = 3; // default empty
  reserved 4 to 6;
}

// --------------------------------------------------------- //
// region CreateRoom

message CreateRoomReq {
  RoomInfoPublic public_info = 1;
  MessageUniqueID muid = 5;
}

message CreateRoomRes {
  string room_id = 1; // hex( bytes[32] )
  MessageUniqueID muid = 5;
}

// --------------------------------------------------------- //
// region RequestJoinRoom

message RequestJoinRoomReq {
  string room_id = 1; // hex( bytes[32] )
  string ecies_public_key = 2; // base64( bytes_pubkey )
  MessageUniqueID muid = 5;
}

message RequestJoinRoomRes {
  string join_request_id = 1;
  MessageUniqueID muid = 5;
}

// --------------------------------------------------------- //
// region ApproveJoinRequest

message ApproveJoinRequestReq {
  string join_request_id = 1;
  string ecies_encrypted_room_key = 2;
  MessageUniqueID muid = 5;
}

message ApproveJoinRequestRes {
  MessageUniqueID muid = 5;
}

// --------------------------------------------------------- //
// region GetJoinRequestStatus

message GetJoinRequestStatusReq {
  string join_request_id = 1;
  MessageUniqueID muid = 5;
}

enum JoinRequestStatus {
  JOIN_REQUEST_STATUS_DENIED = 0;
  JOIN_REQUEST_STATUS_PENDING = 1;
  JOIN_REQUEST_STATUS_APPROVED = 2;
}

message GetJoinRequestStatusRes {
  JoinRequestStatus status = 1;
  optional string ecies_encrypted_room_key = 2;
  MessageUniqueID muid = 5;
}

// --------------------------------------------------------- //
// region GetRoomInfo

message GetRoomInfoReq {
  string room_id = 1; // hex( bytes[32] )
  MessageUniqueID muid = 5;
}

message GetRoomInfoRes {
  RoomInfoPublic public_info = 1;
  optional RoomInfoPrivate private_info = 2; // only if sender has extended rights
  MessageUniqueID muid = 5;
}

// --------------------------------------------------------- //
// region UpdateRoomInfo

message UpdateRoomInfoReq {
  string room_id = 1;
  RoomInfoPublic public_info = 2;
  MessageUniqueID muid = 5;
}

message UpdateRoomInfoRes {
  MessageUniqueID muid = 5;
}

// --------------------------------------------------------- //
// region DeleteRoom

message DeleteRoomReq {
  string room_id = 1; // hex( bytes[32] )
  MessageUniqueID muid = 5;
}

message DeleteRoomRes {
  MessageUniqueID muid = 5;
}

// --------------------------------------------------------- //
// region GiveExtendedRights

message GiveExtendedRightsReq { // only user with extended rights could do it
  repeated string target_pubkeys = 1;
  MessageUniqueID muid = 5;
}

message GiveExtendedRightsRes {
  MessageUniqueID muid = 5;
}

// --------------------------------------------------------- //
// region RemoveExtendedRights

message RemoveExtendedRightsReq { // only user with extended rights could do it
  repeated string target_pubkeys = 1;
  MessageUniqueID muid = 5;
}

message RemoveExtendedRightsRes {
  MessageUniqueID muid = 5;
}

// --------------------------------------------------------- //
// region Message

message Message {
  oneof payload {
    bytes encrypted_text = 1;
    bytes encrypted_file_id = 2; // 
  }
  MessageUniqueID muid = 5;
}

// --------------------------------------------------------- //
// region SendMessages

message SendMessageReq {
  string room_id = 1;
  Message message = 2;
  Ed25519Signature signature = 3; // 64 bytes ed25519 signature of encoded Message protobuf-object
} // Here MUID is included in message field. Server should check MUID located in Message

message SendMessageRes {
  MessageUniqueID muid = 5;
}

// --------------------------------------------------------- //
// region GetMessage

message GetMessageReq {
  string room_id = 1;
  MessageUniqueID muid = 5;
}

message GetMessageRes {
  Message message = 1; // Here is MUID which is has original date and nonce from sender to match the signature
  Ed25519Signature signature = 2; // 64 bytes ed25519 signature of encoded Message protobuf-object
  MessageUniqueID muid = 5; // Here is another MUID but it has actual date and new nonce. It belongs to server verification
}

// --------------------------------------------------------- //
// region File

message FileChunk {
  int32 chunk_id = 1;
  int32 chunk_count = 2;
  bytes encrypted_data = 3;
  reserved 4;
  MessageUniqueID muid = 5;
}

// --------------------------------------------------------- //
// region UploadFile

message UploadFileReq {
  string room_id = 1;
  FileChunk chunk = 2;
  Ed25519Signature chunk_signature = 3; // signature of FileChunk 
}

message UploadFileRes {
  string file_id = 1; // hex( bytes[32] )
  google.protobuf.Timestamp expires_at = 2;
  MessageUniqueID muid = 5;
}

// --------------------------------------------------------- //
// region DownloadFile

message DownloadFileReq {
  string file_id = 1;
  MessageUniqueID muid = 5;
}

message DownloadFileRes {
  FileChunk chunk = 1; // Here is MUID which is has original date and nonce from sender to match the signature
  Ed25519Signature chunk_signature = 2;
  MessageUniqueID muid = 5; // Here is another MUID but it has actual date and new nonce. It belongs to server verification
}

// --------------------------------------------------------- //