UseArazzo Validator
In developmentEvery violation against the Arazzo specification, with the location that caused it.
@usearazzo/validator is a validator and linter for Arazzo Specification documents. It performs semantic validation and semantic linting, with JSON Schema validation available opt-in, and returns diagnostics compatible with the Language Server Protocol and VS Code.
Not yet published. There is no @usearazzo/validator package on npm today. It is developed inside the arazzo-toolkit monorepo and will be installable once its API stabilizes. The API described below is the library as it exists there, and it may change without notice. Follow Discussions to hear when it ships.
Supported versions:
- ✓ Arazzo 1.0.0, 1.0.1
Availability
For now the Validator runs from a checkout of the arazzo-toolkit monorepo, where it is developed. It is not on npm yet, so there is no install command to give you; once it publishes, that becomes a single line.
Validating Arazzo Documents
Two functions cover every input shape: validateURI for file paths and URLs, and the lower-level validate for an in-memory TextDocument.
From a file
import { validateURI, DiagnosticSeverity } from '@usearazzo/validator';
const diagnostics = await validateURI('/path/to/arazzo.yaml');
From a URL
import { validateURI } from '@usearazzo/validator';
const diagnostics = await validateURI('https://example.com/arazzo.yaml');
From an in-memory document
When you already have document content in memory, use validate with createTextDocument:
import { validate, createTextDocument } from '@usearazzo/validator';
const content = `
arazzo: '1.0.1'
info:
title: My Workflow
version: '1.0.0'
sourceDescriptions:
- name: myApi
type: openapi
url: https://example.com/openapi.json
workflows:
- workflowId: myWorkflow
steps:
- stepId: step1
operationId: myApi.getUsers
`;
const textDocument = createTextDocument('file:///path/to/arazzo.yaml', content);
const diagnostics = await validate(textDocument);
Every diagnostic is LSP-compatible, so it carries a precise range, a severity, and a numeric code, the same shape a VS Code extension would render inline. Illustrative shape, not the literal output of a specific document:
arazzo.yaml 3:3-3:9 error Info Object should always have a 'version' 9:24-9:33 error operationId 'myApi.getUsers' could not be resolved ✖ 2 problems (2 errors)
Validation Options
Customizing language service context
Both functions accept an optional context parameter:
import { validateURI } from '@usearazzo/validator';
const diagnostics = await validateURI('/path/to/arazzo.yaml', {
validationContext: {
jsonSchemaValidation: true, // Opt in to JSON Schema validation (default: false)
semanticValidation: true, // Perform semantic validation (default: true)
referenceValidation: true, // Validate references (default: true)
semanticLinting: true, // Apply linting rules (default: true)
betterAjvErrors: true, // Use improved error messages (default: true)
},
parseContext: {
fileAllowList: ['*'], // Glob patterns for allowed files (default: ['*'])
arazzo: {
sourceDescriptionsResolution: true, // Resolve source descriptions (default: true)
},
},
});
jsonSchemaValidation is off by default. Turning it on adds structural checks from the Arazzo JSON Schema, which mostly catch malformed Reusable Object references. The cost is duplicate output, because the linting rules already report many of the same problems.
referenceValidation checks that local $ref pointers in workflow.inputs and components.inputs point at something that exists.
Relative sourceDescriptions[].url entries need a baseURI to resolve against. validateURI works one out from the file location. validate cannot, because its TextDocument may only exist in memory, so pass baseURI yourself.
Customizing URI resolution
validateURI canonicalizes its input into an absolute URI before anything else, so a relative path, an absolute path, and any legal form of a file: URI all land on the same location. That is what makes relative references inside the document, such as sourceDescriptions[].url: ./openapi.yaml, resolve the same way no matter how you named the file.
To fetch the document it reuses the file and HTTP resolvers from @usearazzo/parser, which sets the HTTP resolver to a 15 second timeout, 5 redirects, and no credentials. A third parameter overrides that. Note that resolverOpts is not a fixed set of options: its entries are merged onto the resolver instance, so the keys worth setting are the resolver's own properties, which for the HTTP resolver are timeout, redirects, withCredentials, and cache.
import { validateURI } from '@usearazzo/validator';
const diagnostics = await validateURI('https://example.com/arazzo.yaml', {}, {
resolverOpts: {
timeout: 10000, // HTTP timeout in milliseconds
},
});
Security Considerations
Two allow lists gate file access, at different layers. The resolver behind validateURI only reads paths matching its patterns, which by default admit local .json, .yaml, and .yml files and nothing else. parseContext.fileAllowList gates what the language service may open while it resolves source descriptions during semantic linting, and defaults to ['*'], which matches anything. sourceDescriptionsResolution is also on by default, so external documents named in the Arazzo document are fetched and parsed.
When validating untrusted documents, restrict file access:
const diagnostics = await validateURI('/path/to/arazzo.yaml', {
parseContext: {
fileAllowList: [], // Disable file access
arazzo: {
sourceDescriptionsResolution: false, // Disable source description resolution
},
},
});
Working with Diagnostics
Both validation functions return an array of Diagnostic objects compatible with VS Code and the Language Server Protocol.
import { validateURI, DiagnosticSeverity } from '@usearazzo/validator';
const diagnostics = await validateURI('/path/to/arazzo.yaml');
const errors = diagnostics.filter((d) => d.severity === DiagnosticSeverity.Error);
const warnings = diagnostics.filter((d) => d.severity === DiagnosticSeverity.Warning);
const isValid = errors.length === 0;
Rest of the Toolkit
Runner
Executes the workflows you validate here, interpreting the same Arazzo semantics.
Explore RunnerCLI
Will put this library behind a command, so validation runs from a terminal instead of your own code.
Explore CLIUnder the hood, the Validator uses @usearazzo/parser to load and resolve referenced files.
Frequently Asked Questions
Can I install the Validator today?
Not from npm. @usearazzo/validator has not been published yet and is under heavy development inside the arazzo-toolkit monorepo. It will publish once its API stabilizes.
Is the Validator free?
Yes. @usearazzo/validator is free, open-source, and licensed under Apache 2.0, and it will stay that way once published.
What does it check?
Semantic validation against the Arazzo specification, semantic linting, and reference validation, which checks that local $ref pointers inside workflow.inputs and components.inputs resolve to a target that exists. JSON Schema (AJV) validation is available on top of that, opt-in.
Which Arazzo versions does it support?
Arazzo 1.0.0 and 1.0.1. Arazzo 1.1.0 is not yet supported.
Is it safe to run on documents I don't fully trust?
By default the validator can read any local file and will fetch external source descriptions referenced by the document. When validating untrusted input, set fileAllowList: [] and sourceDescriptionsResolution: false to disable both.