Sabline 8.6.0

Velaris is now Sabline

This project was called Velaris from 1.0 to 8.5.0. From 8.6.0 it is called Sabline.

Why #

The name belongs to an unrelated company in the same market — velaris.io, which sells an agent product with an MCP server. Two things with one name in one market is a problem for whoever meets the second one, and the company was there first and is funded. The name was given up rather than contested.

Nothing about the language, the format, the guarantees or the threat model changed with the name. 8.6.0 renames and nothing else.

What you have to change: nothing, in 8.x #

The rename is additive. STABILITY.md's rule 1 says a break ships only in a major version, and a rename that stopped a command, an import or a committed file from working would be a break. So every old name still works, each saying once on stderr that it has changed, and each goes no sooner than 9.0.

What you wroteStill works in 8.xWrite instead
velaris program.velyes, with a noticesabline program.vel
npx velaris ...yes, with a noticenpx sabline ...
import velarisyes, with a notice and a DeprecationWarningimport sabline
from velaris.budget import Budgetyesfrom sabline.budget import ...
except velaris.VelarisErroryes — it is SablineError under the old nameexcept sabline.SablineError
python -m velaris_mcpyes, with a noticepython -m sabline_mcp
%load_ext velaris_magicyes, with a notice%load_ext sabline_magic
VELARIS_TOKEN, VELARIS_PROOF_TIMEOUT, any VELARIS_*yes, when the SABLINE_* name is not setSABLINE_*
a committed velaris.capabilitiesyes, read when there is no sabline.capabilities beside itrename the file
velaris.toml, velaris.lockyes, same rulerename them
a velaris.audit/1 / velaris.receipt/1 / velaris.capabilities/1 documentyes, read as the sabline.* format of the same versionnothing; Sabline writes sabline.* from 8.6
a Statement of the velaris-lang.dev or GitHub Pages predicate typeyes, verified as the same typenothing; new Statements name sabline.dev

Two names for one thing, set to different values, is an error rather than a guess: SABLINE_TOKEN=a VELARIS_TOKEN=b stops and says so, because a guess there decides what a run is allowed to do.

sabline and velaris are the same command, sabline and velaris are the same Python module object, and SablineError and VelarisError are the same class — not copies, so nothing can drift apart.

Every published address, and where it now points #

The packages #

WasIsWhat happens to the old one
PyPI velaris-langPyPI sabline-langa final release that depends on sabline-lang and prints the rename notice; earlier versions stay exactly where they are
npm velaris-langnpm sabline-langthe same, and marked deprecated with npm deprecate
PyPI/npm velaris (the bare name, a placeholder)PyPI/npm sablinekept, pointing at sabline-lang
MCP registry io.github.gowrishankar-infra/velarisio.github.gowrishankar-infra/sablinethe old server keeps its published versions and is marked deprecated
VS Code gowrishankar-infra.velarisgowrishankar-infra.sablinea Marketplace extension id cannot be renamed, so the old one gets a final version whose README says to install Sabline

Nothing published under the old name is deleted, yanked or moved. A pin to velaris-lang==8.5.0 resolves to the same file it always did, with the same digest and the same signature — that is the rule this project has kept since 3.4 and is not breaking now.

The repositories #

WasIs
gowrishankar-infra/velaris-langgowrishankar-infra/sabline-lang
gowrishankar-infra/velaris-specgowrishankar-infra/sabline-spec
gowrishankar-infra/velaris-kitgowrishankar-infra/sabline-kit
gowrishankar-infra/velaris-canarygowrishankar-infra/sabline-canary

Each was renamed in place, so GitHub redirects the old URL — the web page, git clone, and uses: gowrishankar-infra/velaris-lang@<commit> in a workflow. A pin by commit keeps naming the same commit. The redirect lasts only as long as nobody creates a repository at the old name, and nobody will.

The site #

AddressNow
velaris-lang.dev/...301 to sabline.dev/..., path for path
gowrishankar-infra.github.io/sabline-lang/...301 to sabline.dev/...
gowrishankar-infra.github.io/velaris-lang/...404 — this one could not be kept
sabline.devthe site

velaris-lang.dev is kept and will go on redirecting, so an error printed by 8.3 to 8.5 still leads a reader to the card.

The one address the rename broke. A GitHub Pages site is served at <owner>.github.io/<repo>, so renaming the repository moved it: gowrishankar-infra.github.io/velaris-lang/... answers 404, and the reference: line in every error and refusal printed by 8.0 to 8.2.1 points there. The only way to serve that path again is a repository called velaris-lang, and creating one would end GitHub's redirect from every old repository URL — git clone, every link, and every workflow that says uses: gowrishankar-infra/velaris-lang@<commit>. Those are worth more than one address, so it was left broken rather than traded for them. A reader who meets an 8.0-to-8.2.1 error can read the card at https://sabline.dev/llms.txt, and upgrading fixes the line.

This does not affect the predicate type named at that address. A predicate type is a name, not a page: nothing is fetched from it to verify a Statement, and sabline verify reads the name as it always did. Every attestation and receipt signed by 4.2 to 8.2.1 still verifies.

The predicate types #

An in-toto predicate type is a name, and this project has named its two types at three addresses. Every Statement ever signed still verifies, because a reader takes all three as the same type:

Written bycapability/v1receipt/v1
4.2 – 8.2.1https://gowrishankar-infra.github.io/velaris-lang/capability/v1.../receipt/v1 (from 8.1)
8.3 – 8.5https://velaris-lang.dev/capability/v1https://velaris-lang.dev/receipt/v1
8.6 onhttps://sabline.dev/capability/v1https://sabline.dev/receipt/v1

sabline verify, sabline receipts diff, sabline replay and the OPA policy read all three. A verifier outside Sabline that pins one type name — cosign's --type, the Kyverno policy — takes the name the Statement actually carries; the Kyverno policy in policies/ shows how.

velaris.dev was never this project's domain. It is registered to someone else, no release ever wrote a type under it, and a Statement naming one is refused like any other type Sabline does not define. Neither is velaris.io.

Security contact #

security@velaris-lang.dev still reaches the maintainer. New reports should go to security@sabline.dev; SECURITY.md says so.

What is not renamed #

  • .vel stays the file extension. It is name-neutral, and changing it would break every program that exists.
  • The eight published advisories keep their text and their GHSA ids. An advisory records what was wrong with a release that was called Velaris, and its affected package really is velaris-lang on PyPI.
  • The CHANGELOG before 8.6.0 keeps the old name throughout. It is a record of what happened.
  • The documentation of 8.3, 8.4 and 8.5 under /8.3/, /8.4/ and /8.5/ is left as those releases published it, at the address they were published at. Its links redirect.
  • Git history, which is why every file was moved with git mv.

How it was done #

scripts/rename.py, committed, so the diff is reviewable as a set of rules rather than as 27,000 changed lines. The same script, run with no arguments, is the drift test: it fails on any occurrence of the old name that the rules do not account for, and check_rename.py runs it in CI beside the cases that prove every alias in the table above still works.