Protobuf API Reference
Complete reference for all CitadelMesh Protobuf message types
Overview
CitadelMesh uses Protocol Buffers (Protobuf) for all internal communication. This provides:
- Type safety: Strongly typed messages across languages
- Performance: 10x smaller and faster than JSON
- Versioning: Built-in schema evolution
- Language agnostic: Python ↔ .NET ↔ TypeScript seamlessly
All Protobuf schemas are located in: proto/citadel/v1/
Schema Files
events.proto - Event Messages
Security Events:
message SecurityIncident {
string incident_id = 1;
string location = 2;
string description = 3;
IncidentSeverity severity = 4;
google.protobuf.Timestamp timestamp = 5;
IncidentStatus status = 6;
string assigned_to = 7;
}
enum IncidentSeverity {
SEVERITY_UNSPECIFIED = 0;
LOW = 1;
MEDIUM = 2;
HIGH = 3;
CRITICAL = 4;
}
enum IncidentStatus {
STATUS_UNSPECIFIED = 0;
OPEN = 1;
INVESTIGATING = 2;
RESOLVED = 3;
CLOSED = 4;
}
HVAC Events:
message HVACEvent {
string zone_id = 1;
double temperature_f = 2;
double setpoint_f = 3;
HVACMode mode = 4;
google.protobuf.Timestamp timestamp = 5;
}
enum HVACMode {
MODE_UNSPECIFIED = 0;
OFF = 1;
HEATING = 2;
COOLING = 3;
AUTO = 4;
}
Occupancy Events:
message OccupancyEvent {
string zone_id = 1;
int32 occupant_count = 2;
bool is_occupied = 3;
google.protobuf.Timestamp timestamp = 4;
}
commands.proto - Control Commands
Door Control:
message DoorCommand {
string door_id = 1;
DoorAction action = 2;
int32 duration_seconds = 3;
string reason = 4;
string requested_by = 5;
google.protobuf.Timestamp timestamp = 6;
}
enum DoorAction {
ACTION_UNSPECIFIED = 0;
UNLOCK = 1;
LOCK = 2;
STATUS_QUERY = 3;
}
HVAC Control:
message HVACCommand {
string zone_id = 1;
double setpoint_f = 2;
HVACMode mode = 3;
string reason = 4;
string requested_by = 5;
google.protobuf.Timestamp timestamp = 6;
}
telemetry.proto - System Metrics
message AgentHealth {
string agent_id = 1;
AgentStatus status = 2;
google.protobuf.Timestamp last_heartbeat = 3;
int32 events_processed = 4;
double cpu_usage_percent = 5;
int64 memory_usage_bytes = 6;
}
enum AgentStatus {
STATUS_UNSPECIFIED = 0;
HEALTHY = 1;
DEGRADED = 2;
UNHEALTHY = 3;
OFFLINE = 4;
}
Usage Examples
Python
Import generated code:
from citadel.v1 import events_pb2, commands_pb2
from google.protobuf.timestamp_pb2 import Timestamp
Create a security incident:
incident = events_pb2.SecurityIncident(
incident_id="INC-2025-001",
location="Lobby Main Door",
description="Unauthorized access attempt",
severity=events_pb2.IncidentSeverity.MEDIUM,
timestamp=Timestamp().GetCurrentTime(),
status=events_pb2.IncidentStatus.OPEN
)
# Serialize to bytes
data = incident.SerializeToString()
# Deserialize from bytes
incident2 = events_pb2.SecurityIncident()
incident2.ParseFromString(data)
Create a door command:
command = commands_pb2.DoorCommand(
door_id="DOOR_LOBBY_01",
action=commands_pb2.DoorAction.UNLOCK,
duration_seconds=30,
reason="Authorized by security officer",
requested_by="security-agent",
timestamp=Timestamp().GetCurrentTime()
)
TypeScript
Import generated code:
import { SecurityIncident, IncidentSeverity, IncidentStatus } from './generated/events';
import { Timestamp } from 'google-protobuf/google/protobuf/timestamp_pb';
Create a security incident:
const incident = new SecurityIncident({
incidentId: 'INC-2025-001',
location: 'Lobby Main Door',
description: 'Unauthorized access attempt',
severity: IncidentSeverity.MEDIUM,
timestamp: Timestamp.fromDate(new Date()),
status: IncidentStatus.OPEN
});
// Serialize to bytes
const bytes = incident.serialize();
// Deserialize from bytes
const incident2 = SecurityIncident.deserialize(bytes);
.NET (C#)
Import generated code:
using Citadel.V1;
using Google.Protobuf.WellKnownTypes;
Create a security incident:
var incident = new SecurityIncident
{
IncidentId = "INC-2025-001",
Location = "Lobby Main Door",
Description = "Unauthorized access attempt",
Severity = IncidentSeverity.Medium,
Timestamp = Timestamp.FromDateTime(DateTime.UtcNow),
Status = IncidentStatus.Open
};
// Serialize to bytes
byte[] data = incident.ToByteArray();
// Deserialize from bytes
var incident2 = SecurityIncident.Parser.ParseFrom(data);
Schema Evolution Rules
Backward Compatible Changes ✅
Safe to add:
- New message types
- New fields (always assign new field numbers)
- New enum values
// Version 1
message DoorCommand {
string door_id = 1;
DoorAction action = 2;
}
// Version 2 (backward compatible)
message DoorCommand {
string door_id = 1;
DoorAction action = 2;
string reason = 3; // NEW: Optional field
int32 duration_seconds = 4; // NEW: Optional field
}
Breaking Changes ❌
Never do:
- Change field numbers
- Change field types
- Remove required fields
- Rename message types
// BAD: Breaking change
message DoorCommand {
string door_id = 1;
int32 action = 2; // Changed from enum to int32 ❌
}
CloudEvents Integration
All Protobuf messages are wrapped in CloudEvents envelopes:
{
"specversion": "1.0",
"type": "citadel.security.incident",
"source": "spiffe://citadel.mesh/security-agent",
"id": "a7b3c9d4-e8f2-4a5b-9c7d-1e3f5a8b2c6d",
"time": "2025-10-01T14:23:45Z",
"datacontenttype": "application/protobuf",
"data": "<base64-encoded SecurityIncident>"
}
Python example:
from cloudevents.http import CloudEvent
from citadel.v1 import events_pb2
import base64
# Create Protobuf message
incident = events_pb2.SecurityIncident(...)
# Wrap in CloudEvent
event = CloudEvent({
"type": "citadel.security.incident",
"source": "spiffe://citadel.mesh/security-agent",
"datacontenttype": "application/protobuf",
"data": base64.b64encode(incident.SerializeToString()).decode()
})
Code Generation
Python
# Install tools
pip install grpcio-tools
# Generate code
python -m grpc_tools.protoc \
--python_out=src/generated \
--grpc_python_out=src/generated \
--proto_path=proto \
proto/citadel/v1/*.proto
Generated files:
events_pb2.py- Message typesevents_pb2_grpc.py- gRPC services (if defined)
TypeScript
# Install tools
npm install --save-dev @bufbuild/protoc-gen-es
# Generate code
npx protoc \
--es_out=src/generated \
--es_opt=target=ts \
--proto_path=proto \
proto/citadel/v1/*.proto
Generated files:
events_pb.ts- Message types and serialization
.NET (C#)
Add to .csproj:
<ItemGroup>
<Protobuf Include="proto/citadel/v1/*.proto" GrpcServices="Client" />
<PackageReference Include="Grpc.Tools" Version="2.62.0" PrivateAssets="All" />
<PackageReference Include="Google.Protobuf" Version="3.26.0" />
</ItemGroup>
Generated automatically during build:
Events.cs- Message typesEventsGrpc.cs- gRPC services (if defined)
Validation
Field Constraints
Use buf for validation:
# buf.yaml
version: v1
lint:
use:
- DEFAULT
enum_zero_value_suffix: _UNSPECIFIED
rpc_allow_same_request_response: false
Runtime Validation
Python with Pydantic:
from pydantic import BaseModel, validator
class DoorCommandModel(BaseModel):
door_id: str
action: int
duration_seconds: int
@validator('duration_seconds')
def validate_duration(cls, v):
if v < 0 or v > 300:
raise ValueError('duration must be 0-300 seconds')
return v
See Also
🏰 Use Protobuf for type-safe, efficient communication across CitadelMesh.
Last updated: October 2025