Skip to main content

gRPC API Overview

All internal service-to-service communication in the Platform-Kernel uses gRPC / Protocol Buffers. The REST endpoints you call from your module code are translated by the API Gateway into gRPC calls directed at the appropriate core service. Module code never calls gRPC directly — it uses the TypeScript SDK or the REST API.

This reference documents the gRPC contracts so that:

  • Platform engineers can understand the internal service boundaries.
  • Advanced module authors can call services directly from backend sidecars.
  • Infrastructure teams can configure mTLS, deadlines, and circuit breakers with accurate RPC names.

Proto Packages — Catalogue

Proto packageDomain Scope
platform.iam.v1Identity, Access Management, and Tenants
platform.billing.v1Subscriptions, Billing, and Metering
platform.data.v1Unified Data Layer API
platform.events.v1Asynchronous Event Bus schemas
platform.module_registry.v1Module lifecycle and tenant routing
platform.integration_hub.v1Third-party integrations
platform.common.v1Shared types (e.g. Pagination)

Proto File Locations

All proto files live under .dev/kernel/proto/:

proto/platform/
├── iam/v1/
│ ├── iam_service.proto # Service definitions (3 services, 10 RPCs)
│ └── iam_messages.proto # Request/Response messages
├── billing/v1/
│ ├── billing_service.proto # Service definitions (1 service, 14 RPCs)
│ └── billing_messages.proto # Request/Response messages + enums
├── data/v1/
│ └── data.proto # DataLayerService (5 RPCs)
├── events/v1/
│ ├── events.proto # Event envelope definition
│ └── schemas/v1/
│ ├── auth.proto # Auth domain event schemas
│ ├── common.proto # Shared event fields
│ ├── module.proto # Module domain event schemas
│ └── money.proto # Money domain event schemas
├── module_registry/v1/
│ └── module_registry_service.proto
├── integration_hub/v1/
│ ├── integration_hub_service.proto
│ └── integration_hub_messages.proto
└── common/v1/
└── pagination.proto # PaginationRequest + PaginationMeta

Naming Convention — Proto Packages

ElementPatternExample
Packageplatform.<domain>.v<N>platform.iam.v1
ServicePascalCase + Service suffixIamService
RPCPascalCase verb — CRUD: Create, Retrieve, List, Update, DeleteCreateUser, ListPlans
Message<RpcName>Request / <RpcName>ResponseCreateUserRequest
EnumSCREAMING_SNAKE_CASE, prefixed with type nameSUBSCRIPTION_STATUS_ACTIVE
Fieldsnake_casetenant_id, created_at
Filesnake_caseiam_service.proto, billing_messages.proto

CRUD verb convention: The platform uses Retrieve (not Get) for single- resource fetch and List for paginated collections, following Google API Design Guide semantics. Action endpoints use imperative names: CancelSubscription, HandleWebhook, CheckLimit.


Go Package Convention

Generated Go code is placed in gen/go/ and follows this import path pattern:

kernel.internal/platform-kernel/gen/go/platform/<domain>/v<N>;<domain>v<N>
Proto packageGo package identifier
platform.iam.v1iamv1
platform.billing.v1billingv1
platform.data.v1datav1
platform.events.v1eventsv1
platform.module_registry.v1module_registryv1
platform.integration_hub.v1integration_hubv1
platform.common.v1commonv1

The go_package option is set identically in every .proto file:

option go_package = "kernel.internal/platform-kernel/gen/go/platform/<domain>/v1;<domain>v1";

Example usage in a Go service:

import (
// Import path uses slashes (must match the structure in gen/go)
"kernel.internal/platform-kernel/gen/go/platform/iam/v1"
)

func handle() {
// Package identifier has no slashes (the suffix declared in go_package)
req := &iamv1.CreateUserRequest{
}
}

buf.yaml — Lint and Breaking Change Policy

Located at .dev/kernel/buf.yaml:

version: v2
modules:
- path: proto
lint:
use:
- STANDARD
breaking:
use:
- WIRE_JSON
except:
- FIELD_SAME_ONEOF
ConfigurationValueRationale
lint.useSTANDARDEnforces buf's full standard lint ruleset: naming conventions, comment requirements, import style
breaking.useWIRE_JSONStricter than FILE — catches field number reuse, type changes, JSON name changes, and removed fields
breaking.exceptFIELD_SAME_ONEOFAllows adding new optional fields to existing messages; new consumers see defaults, old consumers ignore unknown fields

Why WIRE_JSON: Event Bus schemas (platform.events.v1) are consumed by multiple modules simultaneously. Any wire-breaking change would cause data loss (serialization mismatch). WIRE_JSON prevents this at CI time.


buf.gen.yaml — Code Generation Pipeline

Located at .dev/kernel/buf.gen.yaml:

version: v2
managed:
enabled: true
override:
- file_option: go_package_prefix
value: kernel.internal/platform-kernel/gen/go
plugins:
- remote: buf.build/protocolbuffers/go
out: gen/go
opt: paths=source_relative
- remote: buf.build/grpc/go
out: gen/go
opt: paths=source_relative
- remote: buf.build/bufbuild/es:v1.10.0
out: packages/sdk-codegen/src
opt: target=ts
- remote: buf.build/connectrpc/es:v1.4.0
out: packages/sdk-codegen/src
opt: target=ts
- remote: buf.build/bufbuild/validate-go
out: gen/go
opt: paths=source_relative
PluginOutputPurpose
buf.build/protocolbuffers/gogen/go/Go message structs and enums (*.pb.go)
buf.build/grpc/gogen/go/Go gRPC server interfaces and client stubs (*_grpc.pb.go)
buf.build/bufbuild/es:v1.10.0packages/sdk-codegen/src/TypeScript Protobuf-ES message classes
buf.build/connectrpc/es:v1.4.0packages/sdk-codegen/src/TypeScript ConnectRPC client (used by Data Layer frontend SDK)
buf.build/bufbuild/validate-gogen/go/Go field-level validation for event schemas (*.pb.validate.go)

Run code generation:

# From .dev/kernel/
buf generate

Gateway → Service Protocol

The API Gateway translates every incoming REST request into a gRPC call:

[Browser / Module] ── REST (HTTPS) ──► [Envoy Gateway]

JWT validation + rate limit + OpenAPI validation

[Go Gateway Service] ── gRPC (mTLS) ──► [Core Service]

Response ◄──────────────────────────────
LayerProtocolAuthentication
Client → EnvoyHTTPS (TLS 1.3)JWT Bearer token
Envoy → Go GatewayInternal (same pod or service mesh)
Go Gateway → Core ServicegRPC over mTLSmTLS client certificate
Core Service → Core ServicegRPC over mTLSmTLS client certificate

Cross-Cutting Concerns

gRPC Deadlines

ParameterValueEnvironment variable
Default deadline5 secondsGRPC_CALL_TIMEOUT_MS=5000
Timeout behaviourGateway returns 504 Gateway Timeout
PropagationDeadline is propagated from Gateway through all service hops

mTLS

All gRPC connections between services use mutual TLS (mTLS) managed by Istio service mesh. Certificates are issued by HashiCorp Vault and rotated every 90 days.

Circuit Breaker

The Go Gateway Service wraps every gRPC call with sony/gobreaker:

ParameterValue
Failure threshold5 consecutive failures within 30 s → circuit OPEN
Reset timeout30 seconds in OPEN state, then HALF_OPEN
Per-tenant isolationSeparate soft breaker per tenant — one tenant cannot trip the circuit for all

Error Mapping (gRPC → HTTP)

gRPC statusHTTP statusRFC 9457 type
INVALID_ARGUMENT400 Bad Requestproblems/validation-failed
UNAUTHENTICATED401 Unauthorizedproblems/unauthorized
PERMISSION_DENIED403 Forbiddenproblems/forbidden
NOT_FOUND404 Not Foundproblems/not-found
ALREADY_EXISTS409 Conflictproblems/conflict
RESOURCE_EXHAUSTED429 Too Many Requestsproblems/rate-limit-exceeded
INTERNAL500 Internal Server Errorproblems/internal-error
UNAVAILABLE503 Service Unavailableproblems/service-unavailable
DEADLINE_EXCEEDED504 Gateway Timeoutproblems/gateway-timeout

Common Shared Types

PaginationRequest (platform.common.v1)

message PaginationRequest {
int32 limit = 1; // Max items per page (default: 20, max: 100)
string cursor = 2; // Opaque cursor from previous response
}

PaginationMeta (platform.common.v1)

message PaginationMeta {
string cursor = 1; // Cursor for next page
bool has_more = 2; // Whether more pages exist
}

All paginated List* RPCs use these shared types. The cursor is an opaque, base64-encoded string — callers must not parse or construct it.


Service Reference

Service filePhase
IAM Service — IamService, AuthService, TenantHierarchyServiceBatch 34.2
Billing Service — BillingServiceBatch 34.3
Data Layer Service — DataLayerServiceBatch 35.1
Events Service — event schemasBatch 35.2
Module Registry Service — ModuleRegistryServiceBatch 35.3
Integration Hub Service — IntegrationHubServiceBatch 35.4