Core Protobuf contracts (generic, reusable message types) shared across Feather gRPC services — packaged for both .NET and PHP.
This repository is the single source of truth for the low-level, domain-agnostic contracts used across Feather. The Protobuf schema in proto/feather/core/v1/core.proto is compiled into:
- a .NET library published as the
Feather.ContractsNuGet package, - a PHP package (
feather/contracts) with generated message, client and RoadRunner server classes undergen/php/, and - a Protobuf module published to the Buf Schema Registry (
buf.build/feathertools/core).
It is designed to be consumed in three ways:
- As a .NET dependency in the
Feather.Grpclibrary, providing the core message types. - As a PHP dependency in the PHP contracts library, providing the same core types.
- Directly in other
.protofiles, by depending on the BSR modulebuf.build/feathertools/coreand referencing thefeather.core.v1types.
All messages live in the feather.core.v1 package (proto/feather/core/v1/core.proto):
| Message | Purpose |
|---|---|
Error |
Structured error with a name and message. |
CorrelationId |
Request/trace correlation identifier. |
Timestamp |
Unix timestamp in milliseconds. |
Spot |
A zone + bucket location pair. |
Instance |
A single instance identifier. |
Box |
An Instance bound to a Spot. |
SerializedForChunking |
Wrapper (bytes content) for chunking large payloads in streaming gRPC calls. |
Generated namespaces (derived by Buf managed mode from the feather.core.v1 package):
- .NET:
Feather.Core.V1 - PHP:
Feather\Core\V1(messages) andFeather\Core\V1\GPBMetadata(metadata)
dotnet add package Feather.Contractsopen Feather.Core.V1
let error = Error(Name = "NotFound", Message = "Instance not found")Not published to Packagist — consume it as a git VCS repository. Add the repository to your composer.json:
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/FeatherTools/grpc.contract.core.git"
}
]
}Then require it (use the tag/branch you need):
composer require feather/contracts:dev-mainuse Feather\Core\V1\Error;
$error = (new Error())->setName('NotFound')->setMessage('Instance not found');Add the BSR module as a dependency in your buf.yaml:
version: v2
deps:
- buf.build/feathertools/coreThen import and reference the feather.core.v1 types:
syntax = "proto3";
import "feather/core/v1/core.proto";
message Envelope {
feather.core.v1.CorrelationId correlation_id = 1;
feather.core.v1.Error error = 2;
}dotnet tool restore
dotnet tool run paket install
./build.sh
composer installThe build is driven by FAKE via build.sh:
./build.sh # default target
./build.sh -t tests no-lint # run tests
./build.sh -t publish no-lint # pack & publish the NuGet packageCommon flags: no-lint, no-clean to skip the respective steps.
proto/feather/core/v1/core.proto is the source of truth. After editing it:
-
Lint the schema:
buf lint
-
.NET classes are generated automatically at build time by
Grpc.Tools(seeContracts.csproj) — just run./build.sh. -
PHP classes (and the C# reference output) are regenerated with Buf using the remote plugins in
buf.gen.yaml:buf generate
This produces PHP message, client and RoadRunner server classes under
gen/php/(namespaceFeather\Core\V1) and the C# undergen/csharp/; both are committed to the repository.buf buildonly compiles the schema to an in-memory image; usebuf generateto emit code.Before opening a PR, run
buf generateand commit the regeneratedgen/files so they stay in sync with the schema in git. -
Publish the module to the Buf Schema Registry:
buf registry login # first time only buf push # publishes buf.build/feathertools/core
- File name:
lower_snake_case; messages:UpperCamelCase; fields:lower_snake_case; enum values:UPPER_SNAKE_CASE. - Keep types generic and domain-agnostic — this library holds only reusable primitives.
- Enforced by Buf's
STANDARDlint rule set (seebuf.yaml).
proto/feather/core/v1/core.proto # Source-of-truth Protobuf schema
buf.yaml # Buf module (buf.build/feathertools/core), lint & breaking config
buf.gen.yaml # Buf code generation (managed mode, remote plugins)
Contracts.csproj # .NET package (Feather.Contracts), compiles gen/csharp
composer.json # PHP package (feather/contracts), autoloads gen/php
gen/csharp/ # Generated C# classes (committed, compiled by Contracts.csproj)
gen/php/ # Generated PHP classes (committed, autoloaded by composer)
build/ # FAKE build project (F#)
.github/workflows/ # CI: net-tests, php-tests, proto-lint, net-publish, bsr-publish, pr-check
Publishing the NuGet package is triggered by pushing a semver tag (MAJOR.MINOR.PATCH), which runs the .NET Publish workflow. Update CHANGELOG.md and the <Version> in Contracts.csproj before tagging. Publish the Protobuf module to the BSR with buf push.
