Skip to content

Manifest

The manifest is deterministic JSON describing the application shape Anvil compiled.

Generated Go is for runtime. The manifest is for tooling: OpenAPI, testbeds, linting, Starlark rules, route audits, docs, and CI diff checks.

Terminal window
anvil manifest .

anvil manifest scans the project and compiles the manifest. It does not run built-in manifest rules or Starlark rules. Use anvil lint when you want rule diagnostics.

The command accepts the same project directory, profile flag, and package pattern overrides as generate.

During package loading, the command overlays a small generated-package stub so imports of the configured generated package can resolve. The command does not write generated Go files.

The schema identifier is:

"anvil.manifest.v1"

Top-level structure:

{
"schema": "anvil.manifest.v1",
"endpoints": [],
"http": {
"groups": [],
"routes": []
},
"grpc": {},
"graphql": {},
"queue": {}
}

The http, grpc, graphql, and queue protocol sections are always present when Anvil writes the manifest through the CLI. Empty protocol subsections omit their empty lists, so a project with no gRPC services receives "grpc": {} instead of "grpc": {"services": []}.

Type references use:

{
"package": "example.com/portal/project",
"name": "ProjectDTO",
"pointer": false,
"provider": ""
}

Fields:

  • package: Go import path when known
  • name: Go type name
  • pointer: true when the compiled type is a pointer
  • provider: named provider value, such as read, when the source field uses inject:"read"; empty for the default provider

Source references use:

{"file": "api/projects.go", "line": 19}

Anvil uses source references for diagnostics, Starlark rule output, OpenAPI traceability, and testbed provenance.

HTTP group entries contain:

{
"name": "Admin",
"type": {"package": "example.com/portal/api", "name": "Admin"},
"path": "/admin",
"fullPath": "/api/admin",
"middleware": [{"package": "example.com/portal/auth", "name": "AdminOnly"}],
"graphqlMiddleware": [{"package": "example.com/portal/auth", "name": "GraphQLTrace"}],
"grpcMiddleware": [{"package": "example.com/portal/auth", "name": "RPCTrace"}],
"queueMiddleware": [{"package": "example.com/portal/auth", "name": "QueueTrace"}],
"children": [{"package": "example.com/portal/api", "name": "Projects"}],
"source": {"file": "api/admin.go", "line": 8}
}

path is the group’s declared path. fullPath is the inherited path after parent groups are applied.

Group middleware is stored by protocol:

  • middleware: HTTP and WebSocket middleware.
  • graphqlMiddleware: GraphQL middleware inherited by GraphQL endpoints.
  • grpcMiddleware: gRPC middleware inherited by gRPC services.
  • queueMiddleware: Queue middleware inherited by queue jobs.

The compiler keeps these chains separate. HTTP middleware is never recorded as GraphQL, gRPC, or queue middleware just because the endpoints share the same group.

HTTP route entries contain:

{
"method": "GET",
"webSocket": false,
"path": "/projects/:projectId",
"controller": "Projects",
"endpoint": "Get",
"operationId": "Projects.Get",
"request": {"package": "example.com/portal/project", "name": "GetProjectRequest"},
"response": {"package": "example.com/portal/project", "name": "ProjectDTO"},
"validateRequest": true,
"params": [{"name": "projectId"}],
"bindings": [{"field": "ProjectID", "source": "param", "key": "projectId"}],
"fields": [{"field": "ProjectID", "source": "param", "key": "projectId", "schema": "string"}],
"validations": [{"field": "ProjectID", "key": "projectId", "kind": "string", "rule": "uuid"}],
"middleware": [{"package": "example.com/portal/auth", "name": "ReadPolicy"}],
"source": {"file": "api/projects.go", "line": 19}
}

Important fields:

  • operationId is Controller.Endpoint and is unique within the HTTP surface.
  • params are extracted from :name path segments.
  • bindings describe generated request assignments.
  • fields describe request fields for schema generation.
  • validations describe generated validation rules.
  • middleware includes route and inherited group middleware.
  • webSocket marks sdk.WS routes.

Validation entries expose the generated rule:

{
"field": "Email",
"key": "email",
"kind": "string",
"rule": "email"
}

Supported rule names include:

  • required
  • email
  • uuid
  • url
  • oneof
  • regex
  • eqfield
  • nefield
  • len
  • min
  • max
  • gt
  • gte
  • lt
  • lte

Numeric rules use value. String rules use text. Cross-field rules use fieldRef and keyRef.

gRPC service entries expose service name, type, inherited gRPC middleware, method list, stream kind, request type, response type, and source:

{
"name": "ProjectService",
"type": {"package": "example.com/portal/rpc", "name": "ProjectService"},
"middleware": [{"package": "example.com/portal/auth", "name": "RPCTrace"}],
"methods": [
{
"name": "GetProject",
"kind": "unary",
"request": {"package": "example.com/portal/rpc", "name": "GetProjectRequest"},
"response": {"package": "example.com/portal/rpc", "name": "ProjectResponse"},
"source": {"file": "rpc/projects.go", "line": 21}
}
],
"source": {"file": "rpc/projects.go", "line": 8}
}

GraphQL endpoints expose name, path, type, handler, optional subscription handler, inherited GraphQL middleware, and source.

Queue jobs expose name, queue name, type, handler, inherited queue middleware, and source.

Manifest output is sorted by stable source-derived keys. A clean repository can run the same command twice and receive byte-identical JSON when source code and configuration did not change.

Use manifest diffs in CI to catch accidental API shape changes.