Schema Manifest
Core data structures for describing service API contracts
The Schema Manifest is the central data structure in FARP. It describes all API contracts exposed by a service instance, including schemas, capabilities, endpoints, routing rules, authentication, and change tracking metadata.
SchemaManifest
A SchemaManifest is a JSON document that fully describes a service instance's API surface:
type SchemaManifest struct {
Version string `json:"version"` // Protocol version (semver)
ServiceName string `json:"service_name"` // Logical service name
ServiceVersion string `json:"service_version"` // Service version (semver)
InstanceID string `json:"instance_id"` // Unique instance identifier
Instance *InstanceMetadata `json:"instance,omitempty"` // Instance metadata
Schemas []SchemaDescriptor `json:"schemas"` // Schema descriptors
Capabilities []string `json:"capabilities"` // Supported protocols
Endpoints SchemaEndpoints `json:"endpoints"` // Introspection URLs
Routing RoutingConfig `json:"routing"` // Gateway routing config
Auth AuthConfig `json:"auth,omitempty"` // Authentication config
Webhook WebhookConfig `json:"webhook,omitempty"` // Bidirectional communication
Hints *ServiceHints `json:"hints,omitempty"` // Operational hints
UpdatedAt int64 `json:"updated_at"` // Unix timestamp
Checksum string `json:"checksum"` // SHA256 of all schemas
}Creating a Manifest
manifest := farp.NewManifest("user-service", "v1.2.3", "instance-abc123")
// Configure endpoints
manifest.Endpoints.Health = "/health"
manifest.Endpoints.Metrics = "/metrics"
manifest.Endpoints.OpenAPI = "/openapi.json"
// Add capabilities
manifest.AddCapability("rest")
manifest.AddCapability("grpc")
manifest.AddCapability("websocket")
// Add schemas (see SchemaDescriptor below)
manifest.AddSchema(openAPIDescriptor)
manifest.AddSchema(grpcDescriptor)Validation
FARP validates manifests for correctness before registration:
err := manifest.Validate()Validation checks:
- Protocol version compatibility
- Required fields:
service_name,instance_id,endpoints.health - Schema descriptor validity (type, spec version, location, hash)
- Routing configuration consistency
- Checksum integrity (if present)
Change Detection
Manifests support efficient change detection through checksums:
// Update checksum after modifying schemas
err := manifest.UpdateChecksum()
// Compare two manifests
diff := farp.DiffManifests(oldManifest, newManifest)
if diff.HasChanges() {
fmt.Printf("Added: %d, Removed: %d, Changed: %d\n",
len(diff.SchemasAdded),
len(diff.SchemasRemoved),
len(diff.SchemasChanged))
}The ManifestDiff provides:
SchemasAdded— Schemas present in new but not oldSchemasRemoved— Schemas present in old but not newSchemasChanged— Schemas with different hashesCapabilitiesAdded/Removed— Changed capabilitiesEndpointsChanged— Whether endpoints changed
Serialization
// Serialize to JSON
data, err := manifest.ToJSON()
// Serialize to pretty JSON
data, err := manifest.ToPrettyJSON()
// Deserialize from JSON
manifest, err := farp.FromJSON(data)Cloning
clone := manifest.Clone() // Deep copySchemaDescriptor
A SchemaDescriptor describes a single API schema/contract:
type SchemaDescriptor struct {
Type SchemaType `json:"type"` // Schema type
SpecVersion string `json:"spec_version"` // Spec version
Location SchemaLocation `json:"location"` // How to retrieve
ContentType string `json:"content_type"` // MIME type
InlineSchema any `json:"inline_schema,omitempty"` // Inline schema
Hash string `json:"hash"` // SHA256 checksum
Size int64 `json:"size"` // Size in bytes
Compatibility *SchemaCompatibility `json:"compatibility,omitempty"`
Metadata *ProtocolMetadata `json:"metadata,omitempty"`
}Example
descriptor := farp.SchemaDescriptor{
Type: farp.SchemaTypeOpenAPI,
SpecVersion: "3.1.0",
ContentType: "application/json",
Location: farp.SchemaLocation{
Type: farp.LocationTypeHTTP,
URL: "http://user-service:8080/openapi.json",
},
Hash: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
Size: 8192,
}SchemaLocation
Describes where and how to fetch a schema. Three strategies are supported:
type SchemaLocation struct {
Type LocationType `json:"type"`
URL string `json:"url,omitempty"` // For HTTP
RegistryPath string `json:"registry_path,omitempty"` // For Registry
Headers map[string]string `json:"headers,omitempty"` // Auth headers
}HTTP Location
Gateway fetches the schema from a service HTTP endpoint:
location := farp.SchemaLocation{
Type: farp.LocationTypeHTTP,
URL: "http://user-service:8080/openapi.json",
Headers: map[string]string{
"Authorization": "Bearer token",
},
}Registry Location
Gateway fetches the schema from a backend KV store:
location := farp.SchemaLocation{
Type: farp.LocationTypeRegistry,
RegistryPath: "/schemas/user-service/v1/openapi",
}Inline Location
Schema is embedded directly in the manifest (recommended for schemas < 100KB):
location := farp.SchemaLocation{
Type: farp.LocationTypeInline,
}
descriptor.InlineSchema = mySmallSchemaSchemaEndpoints
Provides URLs for service introspection:
type SchemaEndpoints struct {
Health string `json:"health"` // Required
Metrics string `json:"metrics,omitempty"` // Prometheus metrics
OpenAPI string `json:"openapi,omitempty"` // OpenAPI spec
AsyncAPI string `json:"asyncapi,omitempty"` // AsyncAPI spec
GRPCReflection bool `json:"grpc_reflection,omitempty"` // gRPC reflection enabled
GraphQL string `json:"graphql,omitempty"` // GraphQL endpoint
}The health endpoint is required. Manifests will fail validation without it.
Example
manifest.Endpoints = farp.SchemaEndpoints{
Health: "/health",
Metrics: "/metrics",
OpenAPI: "/openapi.json",
AsyncAPI: "/asyncapi.json",
GRPCReflection: true,
GraphQL: "/graphql",
}InstanceMetadata
Optional metadata about the service instance for load balancing and deployment control:
type InstanceMetadata struct {
Address string `json:"address"` // host:port
Region string `json:"region,omitempty"`
Zone string `json:"zone,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
Weight int `json:"weight,omitempty"` // 0-100
Status InstanceStatus `json:"status"`
Role InstanceRole `json:"role,omitempty"`
Deployment *DeploymentMetadata `json:"deployment,omitempty"`
StartedAt int64 `json:"started_at"`
}Instance Status Values
| Status | Description |
|---|---|
starting | Instance is starting up |
healthy | Instance is healthy and serving traffic |
degraded | Instance is operational but impaired |
unhealthy | Instance is not healthy |
draining | Instance is draining connections before shutdown |
stopping | Instance is shutting down |
Instance Roles
| Role | Description |
|---|---|
primary | Production instance |
canary | Canary deployment for testing |
blue | Blue side of blue-green deployment |
green | Green side of blue-green deployment |
shadow | Shadow traffic instance |
Deployment Metadata
type DeploymentMetadata struct {
DeploymentID string `json:"deployment_id"`
Strategy DeploymentStrategy `json:"strategy"`
TrafficPercent int `json:"traffic_percent,omitempty"` // 0-100
Stage string `json:"stage,omitempty"`
DeployedAt int64 `json:"deployed_at"`
}Deployment strategies: rolling, canary, blue_green, shadow, recreate
Full Manifest Example
{
"version": "1.0.0",
"service_name": "user-service",
"service_version": "v1.2.3",
"instance_id": "user-service-abc123",
"instance": {
"address": "10.0.1.5:8080",
"region": "us-east-1",
"weight": 100,
"status": "healthy",
"role": "primary",
"started_at": 1698765432
},
"schemas": [
{
"type": "openapi",
"spec_version": "3.1.0",
"content_type": "application/json",
"location": {
"type": "http",
"url": "http://user-service:8080/openapi.json"
},
"hash": "a1b2c3d4e5f6...",
"size": 8192
}
],
"capabilities": ["rest", "websocket"],
"endpoints": {
"health": "/health",
"metrics": "/metrics",
"openapi": "/openapi.json"
},
"routing": {
"strategy": "service",
"strip_prefix": true,
"priority": 50
},
"updated_at": 1698765432,
"checksum": "e3b0c44298fc..."
}How is this guide?