Documentation for v2.6.1. Read the latest, v2.12.0.
Start
Glossary
Every term the documentation uses, defined once. Chapters link here on the first use of a term;
the vocabulary itself is kept in CONTEXT.md in the repository.
Who is who#
- Sanshain
- The registry itself: the server that stores, splits and distributes API specifications. Where a longer name is needed, Sanshain Service.
- Producer
-
A system that publishes an API spec to Sanshain. On the wire it is named by
producername. A role, not an entity type: one system is usually a Producer and a Consumer at once. - Consumer
-
A system that requires endpoints from a Producer and is recorded as depending on them. Named by
consumername. - System
-
A Producer or Consumer seen as one thing: the
serviceNameof asanshain.yaml. The catalog push and the node panel speak of systems because they do not care which role the build plays. - Tooling (client)
-
Software that speaks HTTP to Sanshain on a Producer's or Consumer's behalf: the Maven plugin,
the cargo subcommand, the Go, JavaScript and Conan clients, or plain
curl. Tooling acts for a system; it is never a domain entity itself. - Actor
- The authenticated caller behind a request, as the audit log records it. A version's "provided by" is the actor of its last provide, except that a byte-identical promotion keeps the snapshot's provider.
- Role
-
A fixed, named bundle of permissions held instance-wide (
admin,releaser, ...). The set of roles is part of the product. - Permission
-
One thing an actor may do; what every authorisation check tests. For example
release_gais the permission that publishing a GA version needs. - Releaser
-
The role that holds
release_ga: publishing a GA version, retiring a protocol family and cutting a sanshain-branch need it. Admins and root hold it implicitly. - Maintainer
- An actor responsible for a named set of Producers, with powers over those and no others: delete one of their versions, retire a family, manage the Producer's webhooks.
- Root
-
An account whose authority comes from configuration rather than from stored grants, so it cannot
be revoked from inside Sanshain.
SANSHAIN_ROOT_USERS, when set, alone names the root accounts; otherwise the initial admin (INITIAL_ADMIN_USERNAME, defaultroot) is root. Holds every permission. - Approval
- A locally registered user cannot log in until an administrator approves the account, unless the administrator switched on auto-approve on the admin page.
Versions#
- Version
-
The Producer-declared identity of a spec:
MAJOR.MINOR.PATCH, read from the spec file itself (info.version; for proto a mandatory// sanshain-version:comment). Sanshain never assigns one.v2and2.1are accepted and stored as2.0.0and2.1.0. - Version line
- The ordered set of versions one Producer has published for one API type. Diffing, compatibility checks and cleanup happen within a single line; a Producer's OpenAPI and proto lines evolve independently.
- Stability
- Which of exactly two states a stored version is in, snapshot or GA. Declared by the caller on every provide; how the caller decides is the tooling's business (the ga switch), never Sanshain's.
- Snapshot
- A version in its mutable state: re-providing it overwrites it (last writer wins, every overwrite audited), it is never compatibility-checked, and it expires once neither provided nor required for the snapshot window.
- GA
- A version in its immutable state. Re-providing identical content is a no-op; different content is rejected with a proposed next version. A GA permanently claims its number: no snapshot may ever exist for it again, and cleanup never removes it.
- Promotion
-
The GA provide of a number that existed as a snapshot. The entry becomes GA in place and the
snapshot content is gone. The response says
"promoted": true. - Proposed version
-
The
proposed_versionfield of a409that refused a provide: the next free number of the line, bumped by what actually changed (breaking: major, additive: minor, shape-identical: patch). Set it in the spec file and republish. - Breaking change
- A change the compatibility classifier flags between two documents of one line: a removed endpoint, parameter, property, message or rpc, a type change, a new required field. A GA version that is breaking relative to the highest GA below it must bump the major.
- Deprecation
-
A per-element marker in the spec (
deprecated: true,option deprecated = true;,[deprecated = true]). Removing an element that was deprecated in the previous GA is not breaking. - Retire
-
A provide call with
retired: trueand no body: the Producer no longer provides that API family. It clears the family's capability tag, closes its trunk pins and releases its message contracts; versions and existing pins stay. Needs the releaser role or a maintainer grant. - Snapshot expiry
-
A snapshot that is neither provided nor required for
snapshot_max_age_days(default 30,0disables) is cleaned up. Use keeps it alive. GA never expires. - Instance version
-
Sanshain's own build version, answered by
GET /version. Always qualified, to keep it apart from spec versions.
Publishing and requiring#
- Provide
-
A Producer's submission of a complete spec for one version of one API type, with a declared
stability (
POST /provide,/provide/asyncapi,/provide/grpc). Because it is complete, an endpoint absent from it is absent from that version's API. - Snippet
- The part of a spec Sanshain cuts out for one endpoint: one OpenAPI operation with the schemas it references, one AsyncAPI channel with its messages, one proto service with one rpc and the messages it needs.
- Require
-
A Consumer's request for specific endpoints at its pin (
GET /require,/require/asyncapi,/require/grpc). A successful require also records the dependency; a failed one records nothing. - Bundle
-
POST /require-bundle: several endpoints of one Producer at one pin, answered as a single merged document with one copy of each shared schema. If any endpoint is absent the whole bundle fails and names the missing ones. - Pin
-
A Consumer's exact version choice for one dependency, written in its own configuration. No
ranges, no
latest, no default: what a Consumer builds against changes only when someone edits the pin. - Resolution
- Answering "what is this endpoint at this pin?". The line holds one entry per version, snapshot or GA; that entry answers, and there is no fallback to any other version. Every resolution ends in exactly one of three states: served, absent or unknown.
- Served
-
Resolution state: the pinned version exists and contains the endpoint. The
X-Sanshain-Stabilityheader says whether GA or snapshot answered. - Absent
-
Resolution state,
410 Gone: the pinned version exists and deliberately does not include this endpoint. A definitive no. - Unknown
-
Resolution state,
404 Not Found: the Producer, or the pinned version in either stability, does not exist. A configuration error on the Consumer's side, answered immediately. - Dry run
-
dry_run: trueon a provide, require or bundle: the full validation runs and nothing is stored, not even the Producer. Made for pull-request pipelines. - Idempotent no-op
-
Re-providing byte-identical content (after line endings are normalised to LF and a leading BOM
is removed) stores nothing and answers
changesall zero. CI re-runs never fight. - ETag
-
Every require answer carries an
ETag; sending it back asIf-None-Matchyields304 Not Modifiedwhen the content is unchanged. A GA pin never changes; a snapshot pin can, and the ETag is what detects it. - Sanshain-Warning
- A response header, one line per warning, on a call that succeeded but could not be recorded the way it was declared: an unknown tag, trunk and tag together, a catalog push that recorded nothing. Clients print it and fail on it only in strict mode.
- Strict mode
-
A client setting (
strict: trueinsanshain.yamlor the client's flag): missing configuration and anySanshain-Warningfail the build instead of printing a warning. - Message contract (AsyncAPI)
-
On a GA provide, every named
publishmessage registers a contract keyed by channel and message name, owned by the first Producer to publish it. The owner may widen it; another Producer may co-publish only an identical payload schema. - Harvested subscription
-
An AsyncAPI
subscribe(2.x) orreceive(3.x) operation in a provided document becomes a version-less consumer edge in the graph, resolved against the channel's message contract. No hand-written require is needed for it. - Validator
-
POST /validateand the form on the landing page: the provide-side checks (version extraction, splitting) on any document, without authentication and without storing anything.
The graph#
- Dependency graph
-
What Sanshain knows about who pins which version of which endpoint, drawn as a live SVG on
/graph.htmland answered as JSON byGET /report. - Outdated
- A dependency whose pin is below the latest GA of its line. A display state only: being outdated changes nothing about what is served.
- Snapshot-pinned
- A dependency served from a snapshot because its pin has no GA. It flags building against overwritable content; such a pin may even be ahead of the latest GA.
- Superseded
-
A snapshot below the latest GA of its line. The producers page marks it
superseded by X ga, and a pin to it counts as outdated. - Stream
-
Where a build belongs: plain calls record dev activity,
trunk: truemarks the trunk stream,tag: "<branch>"marks a sanshain-branch. Streams never change version rules or what is served; they only decide which graph records the call. - Dev graph
-
The default view: everything ever provided or required, snapshots included, thinned by the
dependency window (
dependency_max_age_days, default 30). - Trunk
- The stream of your default-branch CI. A trunk provide stamps the version as "trunk's current version"; a trunk require maintains the main graph's pin set, last write per endpoint wins.
- Main graph
- The trunk stream's view: every Producer at its trunk version, edges from trunk pins. What trunk is, deterministic after every trunk build.
- Trunk TTL
-
Trunk entries not refreshed within
trunk_max_age_days(default 90) leave the main graph; they are highlighted as stale once they pass half the window. History keeps them. - Sanshain-branch
-
A named copy of a graph at a chosen instant: the release cut. Created by a releaser from trunk
or from another branch, updated by tagged builds, diffable against main or other branches.
main,devandtrunkare reserved names. - Tag
-
The
tagparameter of a provide, require or bundle: the call updates the named sanshain-branch instead of trunk. Branches are never auto-created; an unknown tag records the call in the dev graph only and answers aSanshain-Warning. - Release cut
-
Creating a sanshain-branch:
POST /admin/brancheswith a name, optionally a source branch and anas_ofinstant. A past instant repairs a forgotten cut. - Timeline
- Trunk and branch writes are append-only, so the main graph and every branch can be rendered as they were at any past instant. The slider's markers are the instants the graph changed.
- Peripheral resource
-
Something outside Sanshain a system depends on (a database, bucket, queue), known only by its
Backstage ref
resource:<namespace>/<name>from the system's owncatalog-info.yaml. One node per ref, shared by every system that names it. - Catalog push
-
PUT /catalog/{systemname}with the system's Backstagecatalog-info.yaml, once per build. Sanshain reads the Component named like the system and of it the periphery and the catalog context; everything else is ignored. - Catalog context
- What the catalog push records besides the periphery: the system's owner, description, source location and links. Shown on the graph's node panel and on the Producer and Consumer pages. One present-day fact per system, not tracked per stream.
- Report scope
-
?scope=dev(default),main[@instant]or<branch>[@instant]on/reportand its variants: which graph a report describes. - Audit timeline
-
The log of every provide, require and administrative action, with a diff viewer and filters by
date, action, service and stream. For holders of the
view_auditpermission: the admin and viewer roles.
Credentials and integrations#
- Session
-
What
POST /auth/loginanswers and what the web UI sends: a token that expires with the session (7 days). Sessions can mint API tokens; API tokens cannot. - API token
-
A long-lived credential (
san_+ 64 hex characters) owned by one user, minted on the account page or withPOST /auth/tokens, shown once, with a mandatory expiry. What CI, scripts and AI clients send asAuthorization: Bearer. - Token scope
-
Decided when a token is minted, immutable afterwards.
fullmay do everything its owner may;read_onlymay read reports, versions, the update streams and the MCP endpoint, and is refused with403on every route that changes the catalog. - Webhook
-
A signed
POSTSanshain sends to a registered URL for every fact it records and every provide it rejects:version.published,provide.rejected,version.deprecated,dependency.recorded,branch.cut,catalog.recorded. Registered globally by an administrator, or per Producer and Consumer on their pages. - MCP
-
The Model Context Protocol endpoint
POST /mcp: seven read-only tools that let an AI assistant list and describe services, find an endpoint, read a spec, walk the graph, diff and blame versions. API tokens only, 60 calls per minute per token, 64 KiB per answer. - Developer mode
-
A local-only switch that bypasses authentication. It needs both the admin setting (or
SANSHAIN_DEV_MODE) and theALLOW_INSECURE_DEV_MODE=truesafety gate, and fails closed otherwise.
Checked against v2.6.0.