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 old
  • SchemasRemoved — Schemas present in old but not new
  • SchemasChanged — Schemas with different hashes
  • CapabilitiesAdded/Removed — Changed capabilities
  • EndpointsChanged — 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 copy

SchemaDescriptor

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 = mySmallSchema

SchemaEndpoints

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

StatusDescription
startingInstance is starting up
healthyInstance is healthy and serving traffic
degradedInstance is operational but impaired
unhealthyInstance is not healthy
drainingInstance is draining connections before shutdown
stoppingInstance is shutting down

Instance Roles

RoleDescription
primaryProduction instance
canaryCanary deployment for testing
blueBlue side of blue-green deployment
greenGreen side of blue-green deployment
shadowShadow 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?

On this page