Rename the project to Echo (was fedserv)
Rebrand the daemon and workspace: the binary is now `echo`, every crate is `echo-*` (`echo-api` and the module crates), Rust imports use `echo_*`, the gRPC proto is `proto/echo.proto` with package `echo.v1`, and the log filter, gossip peer-name default, and on-disk store default (`echo.db.jsonl`) follow. Docs updated throughout. No behaviour change; crate directories and the config schema are untouched.
This commit is contained in:
parent
e7037572e5
commit
993f5b2eea
159 changed files with 660 additions and 660 deletions
|
|
@ -1,157 +0,0 @@
|
|||
// Directory replication API: lets a website (e.g. a Django backend) mirror the
|
||||
// account/channel directory this node owns, without touching IRC at all.
|
||||
//
|
||||
// Deliberately excludes anything credential-shaped (password hashes, SCRAM
|
||||
// verifiers, TLS cert fingerprints) — a subscriber gets identity and metadata
|
||||
// only, never a way to authenticate as an account. Channel events are the
|
||||
// events already scoped Local to this node (see Scope in engine/db.rs), so a
|
||||
// website only ever sees its own network's channels, matching what gossip
|
||||
// federates.
|
||||
syntax = "proto3";
|
||||
package fedserv.v1;
|
||||
|
||||
service Directory {
|
||||
// One-shot full read of current state, for a subscriber's initial load.
|
||||
rpc Snapshot(SnapshotRequest) returns (SnapshotResponse);
|
||||
|
||||
// Live feed of directory changes from the moment of the call onward. A
|
||||
// dropped stream should be followed by a fresh Snapshot (this is at-least-
|
||||
// once delivery, not a resumable cursor) — appliers should be idempotent,
|
||||
// keyed by account/channel name.
|
||||
rpc Subscribe(SubscribeRequest) returns (stream ReplicationEvent);
|
||||
}
|
||||
|
||||
message SnapshotRequest {}
|
||||
|
||||
message AccountRecord {
|
||||
string name = 1;
|
||||
string email = 2; // empty = none on file
|
||||
bool verified = 3;
|
||||
uint64 registered_at = 4; // unix seconds
|
||||
string home = 5; // origin node sid that first registered it
|
||||
}
|
||||
|
||||
message ChannelRecord {
|
||||
string name = 1;
|
||||
string founder = 2; // account name
|
||||
uint64 registered_at = 3;
|
||||
string description = 4;
|
||||
}
|
||||
|
||||
message SnapshotResponse {
|
||||
repeated AccountRecord accounts = 1;
|
||||
repeated ChannelRecord channels = 2;
|
||||
}
|
||||
|
||||
message SubscribeRequest {}
|
||||
|
||||
// The gossip envelope (origin/seq/lamport) is carried alongside the payload so
|
||||
// a subscriber can log/dedupe by (origin, seq) if it wants to, even though the
|
||||
// stream itself is not resumable by cursor in this version.
|
||||
message ReplicationEvent {
|
||||
string origin = 1;
|
||||
uint64 seq = 2;
|
||||
uint64 lamport = 3;
|
||||
|
||||
oneof kind {
|
||||
AccountRegistered account_registered = 10;
|
||||
AccountEmailSet account_email_set = 11;
|
||||
AccountVerified account_verified = 12;
|
||||
AccountDropped account_dropped = 13;
|
||||
NickGrouped nick_grouped = 14;
|
||||
NickUngrouped nick_ungrouped = 15;
|
||||
ChannelRegistered channel_registered = 20;
|
||||
ChannelDropped channel_dropped = 21;
|
||||
ChannelFounderSet channel_founder_set = 22;
|
||||
ChannelDescSet channel_desc_set = 23;
|
||||
}
|
||||
}
|
||||
|
||||
message AccountRegistered {
|
||||
string name = 1;
|
||||
string email = 2;
|
||||
bool verified = 3;
|
||||
uint64 registered_at = 4;
|
||||
string home = 5;
|
||||
}
|
||||
message AccountEmailSet { string account = 1; string email = 2; }
|
||||
message AccountVerified { string account = 1; }
|
||||
message AccountDropped { string account = 1; }
|
||||
message NickGrouped { string nick = 1; string account = 2; }
|
||||
message NickUngrouped { string nick = 1; }
|
||||
message ChannelRegistered { string name = 1; string founder = 2; uint64 registered_at = 3; }
|
||||
message ChannelDropped { string name = 1; }
|
||||
message ChannelFounderSet { string name = 1; string founder = 2; }
|
||||
message ChannelDescSet { string name = 1; string description = 2; }
|
||||
|
||||
// Account authority API: the write side, for a trusted caller (e.g. a website's
|
||||
// own backend, already having done its own login/session check) to manage
|
||||
// accounts the same way an IRC user does through NickServ — registration,
|
||||
// credentials, grouping, and forced logout. The bearer token IS the
|
||||
// authorization: unlike the NickServ commands these mirror, most calls here do
|
||||
// NOT re-check the account's own password (the caller is trusted, the same
|
||||
// model as an admin-level override) — Register and Authenticate are the two
|
||||
// exceptions, since the password is the actual input/question there.
|
||||
// A write committed here replicates to every other fedserv node exactly like
|
||||
// an IRC-originated one does — gossip doesn't know or care where it came from.
|
||||
service Accounts {
|
||||
rpc Register(RegisterRequest) returns (AccountReply);
|
||||
// Create-or-update an account from pre-derived SCRAM verifiers instead of a
|
||||
// plaintext password. For bulk backfill from an authority (e.g. a website)
|
||||
// that stores verifiers, not passwords. scram512 may be empty.
|
||||
rpc Provision(ProvisionRequest) returns (AccountReply);
|
||||
rpc Authenticate(AuthenticateRequest) returns (AuthenticateReply);
|
||||
rpc SetPassword(SetPasswordRequest) returns (AccountReply);
|
||||
rpc SetEmail(SetEmailRequest) returns (AccountReply);
|
||||
rpc Confirm(ConfirmRequest) returns (AccountReply);
|
||||
rpc Drop(DropRequest) returns (AccountReply);
|
||||
rpc ForceLogout(ForceLogoutRequest) returns (ForceLogoutReply);
|
||||
rpc GroupNick(GroupNickRequest) returns (AccountReply);
|
||||
rpc UngroupNick(UngroupNickRequest) returns (AccountReply);
|
||||
}
|
||||
|
||||
enum Status {
|
||||
OK = 0;
|
||||
ALREADY_EXISTS = 1;
|
||||
NOT_FOUND = 2;
|
||||
RATE_LIMITED = 3;
|
||||
INVALID = 4; // bad password/code/input, or a name-shaped invariant violation
|
||||
INTERNAL = 5;
|
||||
}
|
||||
|
||||
message AccountReply {
|
||||
Status status = 1;
|
||||
string message = 2; // human-readable detail, safe to show a user
|
||||
}
|
||||
|
||||
message RegisterRequest { string name = 1; string password = 2; string email = 3; }
|
||||
message ProvisionRequest { string name = 1; string scram256 = 2; string scram512 = 3; string email = 4; }
|
||||
|
||||
message AuthenticateRequest { string name = 1; string password = 2; }
|
||||
message AuthenticateReply {
|
||||
Status status = 1;
|
||||
string account = 2; // canonical account name (resolves a grouped-nick alias)
|
||||
}
|
||||
|
||||
message SetPasswordRequest { string account = 1; string password = 2; }
|
||||
message SetEmailRequest { string account = 1; string email = 2; } // empty = clear
|
||||
message ConfirmRequest { string account = 1; string code = 2; }
|
||||
message DropRequest { string account = 1; }
|
||||
|
||||
message ForceLogoutRequest { string account = 1; }
|
||||
message ForceLogoutReply { Status status = 1; uint32 sessions_cleared = 2; }
|
||||
|
||||
message GroupNickRequest { string nick = 1; string account = 2; }
|
||||
message UngroupNickRequest { string nick = 1; }
|
||||
|
||||
// Stats API: a flat, namespaced counter map any service contributes to
|
||||
// (e.g. "nickserv.command", "botserv.kick", "channels.total"). Read-only.
|
||||
service Stats {
|
||||
rpc Get(StatsRequest) returns (StatsResponse);
|
||||
}
|
||||
|
||||
message StatsRequest {}
|
||||
message StatsResponse {
|
||||
map<string, uint64> counters = 1;
|
||||
uint64 collected_at = 2; // unix seconds when this snapshot was taken
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue