#ifndef CABLE_H #define CABLE_H #include #include #include "keys.h" #include "sleep_feed.h" #define CABLE_KEY_BYTES 32u #define CABLE_CHAT_TEXT_BYTES 768u #define CABLE_CHAT_WIRE_BYTES (4u + 8u + 2u + CABLE_CHAT_TEXT_BYTES) #define CABLE_CHAT_SEAL_BYTES (CABLE_CHAT_WIRE_BYTES + 48u) enum cable_address_scheme { CABLE_ADDRESS_CABAL = 1, CABLE_ADDRESS_CABLE = 2, CABLE_ADDRESS_HYPER = 3 }; typedef struct cable_chat_message { uint64_t timestamp_ms; char text[CABLE_CHAT_TEXT_BYTES + 1u]; size_t text_length; } cable_chat_message_t; /* A Cabal user address is that user's persistent feed public key. A room * address may additionally carry a room moderation/admin key. */ typedef struct cable_room_address { uint8_t key[CABLE_KEY_BYTES]; uint8_t admin_key[CABLE_KEY_BYTES]; enum cable_address_scheme scheme; int has_admin; } cable_room_address_t; /* The schemes share a 32-byte key representation; the caller decides whether * it is a room key or a user feed key. hyper:// is a migration alias only. */ int cable_address_parse(const char *address, uint8_t key[CABLE_KEY_BYTES], enum cable_address_scheme *scheme); int cable_address_format(const uint8_t key[CABLE_KEY_BYTES], enum cable_address_scheme scheme, char *out, size_t capacity); int cable_room_address_parse(const char *address, cable_room_address_t *room); int cable_room_address_format(const cable_room_address_t *room, enum cable_address_scheme scheme, char *out, size_t capacity); int cable_user_address_format(const uint8_t user_feed_key[CABLE_KEY_BYTES], enum cable_address_scheme scheme, char *out, size_t capacity); /* Cabal stores the local writer in a room's storage, so derive a per-room * local feed-key path instead of sharing one global identity across rooms. */ int cable_user_identity_path(const char *home, const uint8_t room_key[CABLE_KEY_BYTES], char *out, size_t capacity); /* Create a Cabal room signing key and persist it in the room directory. */ int cable_room_create(const char *home, uint8_t room_key[CABLE_KEY_BYTES]); /* Store/load the user's local feed secret key. The public key is derived and * checked on load. The file contains only the 64-byte Ed25519 secret key. */ int cable_user_identity_load_or_create(const char *path, sleep_keypair_t *identity); /* Cabal stores messages as JSON blocks in each user's Hypercore feed. These * helpers use the same Hypercore 7.x on-disk tree/signature layout. */ int cable_user_feed_open(const char *home, const uint8_t room_key[CABLE_KEY_BYTES], sleep_keypair_t *identity, sleep_feed_t *feed); int cable_user_feed_append(const char *home, const uint8_t room_key[CABLE_KEY_BYTES], const uint8_t *record, size_t record_length, uint8_t user_key[CABLE_KEY_BYTES]); int cable_user_feed_publish(const char *home, const uint8_t room_key[CABLE_KEY_BYTES], const char *record_type, const char *nick, const char *channel, const char *text, uint8_t user_key[CABLE_KEY_BYTES]); int cable_chat_message_encode(const cable_chat_message_t *message, uint8_t *out, size_t capacity, size_t *written); int cable_chat_message_decode(cable_chat_message_t *message, const uint8_t *input, size_t length); int cable_chat_seal(const uint8_t recipient_ed25519[32], const uint8_t *message, size_t message_length, uint8_t *out, size_t capacity, size_t *written); int cable_chat_open(const sleep_keypair_t *identity, const uint8_t *sealed, size_t sealed_length, uint8_t *out, size_t capacity, size_t *written); #endif