Skip to content

Manifest Model

This page is the exhaustive reference for Shoehorn’s native manifest schema, schemaVersion: 1. Use it when you need the full object model for .shoehorn/manifest.yml, not just a quick-start example.

Shoehorn looks for manifests in these common locations:

  • .shoehorn/manifest.yml
  • .shoehorn/**/*.yml
  • .shoehorn/**/*.yaml
  • catalog-info.yaml for Backstage compatibility
FieldRequiredTypeNotes
schemaVersionYesintegerMust be 1
annotationsNoobjectString key-value metadata
integrationsNoobjectChangelog, runbooks, licenses
descriptionNostringTop-level description
serviceYesobjectCore entity identity
ownerYes*arrayAt least one owner, except catalog-source
lifecycleNostringLifecycle stage
tagsNoarrayLowercase kebab-case tags
linksNoarrayExternal links
interfacesNoobjectHTTP and gRPC metadata
relationsNoarrayEntity relationships
extrasNoarraySlack channels, discovery pointers, custom extras
docsNoobjectDocumentation paths
schemaVersion: 1
annotations:
github.com/project-slug: acme/payment-api
pagerduty.com/service-id: P123456
integrations:
changelog:
path: CHANGELOG.md
runbooks:
- title: Payment API incident response
path: docs/runbooks/payment-api.md
severity: critical
licenses:
- title: Stripe API
vendor: Stripe
purchased: "2026-01-15"
expires: "2027-01-14"
seats: 1
cost: "$2000/year"
contract: STRIPE-2026
notes: Auto-renews unless canceled
description: Handles payment authorization, capture, and refunds.
service:
id: payment-api
name: Payment API
type: service
tier: gold
description: Public-facing payments backend
members:
- payments-oncall@example.com
- payments-techlead@example.com
owner:
- type: team
id: payments-team
- type: manager
id: jane@example.com
lifecycle: production
tags:
- payments
- critical
- pci
links:
- name: Repository
url: https://github.com/acme/payment-api
icon: GitHub
- name: Grafana
url: https://grafana.example.com/d/payment-api
icon: Grafana
interfaces:
http:
baseUrl: https://api.example.com/payments
openapi: docs/openapi.yaml
version: v1
auth:
type: oauth2
rateLimits:
requestsPerMinute: 600
requestsPerHour: 10000
graphql:
endpoint: /graphql
schema: schema/payment-api.graphql
grpc:
package: acme.payments.v1
proto: proto/payment.proto
services:
- PaymentService
- RefundService
protos:
- proto/payment.proto
- proto/refund.proto
relations:
- type: depends_on
target: database:payments-db
notes: Primary OLTP database
- type: publishes_to
target: topic:payment-events
- type: part_of
target: system:payments-platform
extras:
- type: slackchannel
target: "#payments"
- type: catalog-discovery-file
target: .shoehorn/manifest.yml
docs:
readme:
path: README.md

The service block defines the entity’s identity and type.

FieldRequiredTypeNotes
idYesstringLowercase kebab-case, unique within the tenant
nameYesstringHuman-readable display name
typeYesstringEntity type
tierNostringImportance or criticality tier
descriptionNostringAlternative to top-level description
membersNoarrayEmail addresses, mainly for team entities

Supported service.type values:

  • api
  • service
  • frontend
  • database
  • library
  • team
  • extras
  • system
  • resource
  • catalog-source
  • domain

Supported service.tier values:

  • platinum
  • gold
  • silver
  • bronze
  • critical
  • high
  • medium
  • low

owner is an array of owner references. Each item has the same shape:

FieldRequiredTypeNotes
typeYesstringOwner role or owner kind
idYesstringTeam slug, email address, or other identifier

Common owner types:

  • team
  • user
  • productOwner
  • designer
  • stakeholder
  • support
  • manager

owner is required for every entity except catalog-source.

annotations is a free-form string map for metadata that does not belong in the structured model.

Example:

annotations:
github.com/project-slug: acme/payment-api
backstage.io/techdocs-ref: dir:.

integrations groups optional metadata about changelogs, runbooks, and commercial licenses.

FieldRequiredTypeNotes
pathNostringPath relative to repository root
FieldRequiredTypeNotes
titleYesstringDisplay name
pathNostringPath relative to repository root
severityNostringcritical, high, medium, low
FieldRequiredTypeNotes
titleYesstringLicense or contract name
vendorNostringVendor name
purchasedNostringISO date string
expiresNostringISO date string
seatsNointegerMinimum value 1
costNostringHuman-readable cost
contractNostringContract identifier
notesNostringFree-form notes

Supported lifecycle values:

  • production
  • staging
  • development
  • deprecated
  • experimental

tags must be lowercase kebab-case strings.

Example:

tags:
- payments
- internal-api

Each link object has this shape:

FieldRequiredTypeNotes
nameYesstringDisplay label
urlYesstringMust start with http:// or https://
iconNostringOptional icon name

interfaces exposes API and protocol metadata.

FieldRequiredTypeNotes
baseUrlNostringBase URL for the HTTP API
openapiNostringFile path or URL
versionNostringVersion label, for example v1
auth.typeNostringoauth2, apikey, none
rateLimits.requestsPerMinuteNointegerRequests per minute
rateLimits.requestsPerHourNointegerRequests per hour
rateLimits.requestsPerDayNointegerRequests per day
graphql.endpointNostringPath or URL
graphql.schemaNostringPath or URL
FieldRequiredTypeNotes
packageNostringgRPC package name
protoNostringSingle proto path or URL
servicesNoarrayService names
protosNoarrayMultiple proto paths or URLs

Each relation object has this shape:

FieldRequiredTypeNotes
typeYesstringRelation type
targetYesstring<type>:<identifier>
notesNostringExtra context

Supported relation types:

  • depends_on
  • publishes_to
  • consumes_api
  • provides_api
  • deployed_to
  • calls
  • reads_from
  • writes_to
  • subscribes_to
  • uses
  • via
  • part_of

Supported relation target prefixes:

  • service:
  • database:
  • topic:
  • team:
  • channel:
  • link:
  • oncall:
  • system:
  • resource:

extras is for metadata that does not fit the main model but still belongs on the entity.

FieldRequiredTypeNotes
typeYesstringExtra type
targetYesstringValue for that extra

Supported extra types:

  • slackchannel
  • teamLinks
  • custom
  • catalog-discovery-url
  • catalog-discovery-file

The docs block currently supports README discovery:

FieldRequiredTypeNotes
readme.pathYesstringPath relative to repository root
  • description can live at the top level or inside service.description.
  • docs.readme.path, integrations.changelog.path, and integrations.runbooks[].path are relative to the repository root.
  • Backstage catalog-info.yaml files can be imported, but Shoehorn’s native manifest model is the schema on this page.