syntax = "proto3"; package broadannounce.v1; option go_package = "git3.techno-world.net/lrosales/broad-announce/gen/go/broadannounce/v1;broadannouncev1"; // Ingest is the gRPC service for first-party, high-volume alert sources. // It runs on a dedicated port (default :9090) inside the tenant's VPC; // external webhook sources continue to use HTTP POST on :8800. service Ingest { // StreamAlerts is a bidirectional stream: the client sends zero or more // Alerts, the server sends exactly one Ack for each Alert received. // // Flow: // 1. Client opens stream (auth metadata required on the call) // 2. Client streams Alerts; server processes each concurrently // 3. Server streams back Acks as they are ready (order not guaranteed) // 4. Client reads Acks and adjusts send rate accordingly // // Backpressure: if the server's in-flight buffer (256 msgs) fills up, // it sends Error.RATE_LIMITED with retry_after_ms > 0. The client MUST // honour that delay before resuming. rpc StreamAlerts(stream Alert) returns (stream Ack); } // Alert is what a first-party service sends to BroadAnnounce. message Alert { string company_id = 1; // required; maps to sources.company_id string source_id = 2; // required; maps to sources.source_id string severity = 3; // "info" | "warning" | "critical" | "inminent_colapse" string category = 4; // arbitrary category tag string title = 5; // pre-localized alert title string body = 6; // pre-localized alert body map data = 7; // arbitrary key-value metadata string dedupe_key = 8; // opaque string; if set, dedupe applies within the window int64 client_ts_ms = 9; // Unix-ms timestamp set by the client; used for skew detection } // Ack is what the server sends back after processing an Alert. message Ack { // alert_id is an opaque server-assigned identifier for the alert. // It may be empty if the alert was rejected before NATS publish. string alert_id = 1; // dedupe_key echoes back the client's dedupe_key. string dedupe_key = 2; // dedupe_count is 1 on first arrival; >1 when the server collapsed a // burst of identical dedupe_keys within the dedupe window. uint32 dedupe_count = 3; // accepted_at_ms is the server-side Unix-ms timestamp at which the alert // was accepted (i.e. after all protection layers passed). int64 accepted_at_ms = 4; // result is the processing outcome. oneof result { Ok ok = 10; // alert accepted Error error = 11; // alert rejected or rate-limited } } // Ok is returned when an Alert was accepted. message Ok {} // Error is returned when an Alert was rejected. message Error { // Code classifies the error so the client can act programmatically. enum Code { UNKNOWN = 0; // catch-all; include message UNAUTHENTICATED = 1; // API key missing or invalid RATE_LIMITED = 2; // per-source or per-company rate limit hit INVALID = 3; // schema validation failed;修复 check message INTERNAL = 4; // server-side error; do not retry immediately } Code code = 1; string message = 2; // human-readable; never parse this // retry_after_ms is non-zero when Code == RATE_LIMITED. // The client MUST wait at least this long before sending the next message. // A value of 0 means "do not retry" (permanent failure). int32 retry_after_ms = 3; }