syntax = "proto3"; package stats.v1; option go_package = "github.com/bergabruh/stats-gateway/gen/stats/v1;statsv1"; service SpeedStatus { // RecentResults streams the last N samples for given filter. rpc RecentResults(Filter) returns (stream Sample); // Aggregate returns histogram for a time range. rpc Aggregate(Range) returns (Histogram); // Tunnel is a bidirectional stream for authenticated clients. // Auth: Bearer JWT (HS256) в gRPC metadata "authorization: Bearer ". // Server validates: signature, exp, scope=="tunnel", optional revocation list. rpc Tunnel(stream Frame) returns (stream Frame); // RecordSpeedTest ingests a single speedtest sample from an edge node. rpc RecordSpeedTest(RecordSpeedTestRequest) returns (RecordSpeedTestResponse); } message Filter { string node = 1; // "fl" | "pl1" | "" (all) int32 limit = 2; // 1..1000 string since = 3; // RFC3339, optional } message Sample { string node = 1; string timestamp = 2; // RFC3339 double http_latency_ms = 3; double tcp_rtt_ms = 4; double dns_resolve_ms = 5; double tls_handshake_ms = 6; int64 throughput_kbps = 7; } message Range { string node = 1; string since = 2; string until = 3; } message Histogram { repeated Bucket buckets = 1; } message Bucket { double upper_ms = 1; int64 count = 2; } message Frame { // Control message. First frame from client must be HELLO with target. enum Kind { UNKNOWN = 0; HELLO = 1; DATA = 2; CLOSE = 3; } Kind kind = 1; string target = 2; // "ip:port" — only used in HELLO bytes payload = 3; // raw TCP bytes bytes padding = 4; // random padding для frame-length obfuscation } message RecordSpeedTestRequest { // Unix epoch seconds. Required. int64 timestamp = 1; // Node identifier: "fl" or "pl1". Required. string node = 2; // ISO-2 country code resolved from client IP at the edge node. "XX" if unknown. string country = 3; // Mbps. >= 0. double dl_mbps = 4; // Mbps. >= 0. double ul_mbps = 5; // Milliseconds. >= 0. double ping_ms = 6; // Milliseconds. >= 0. double jitter_ms = 7; } message RecordSpeedTestResponse { // Server-assigned monotonic ID for the inserted row. int64 id = 1; }