Failures and schema artifacts
@azohra/meteo.core defines a closed vocabulary for upstream failure, the
zod schema primitives that capability configs share, and the one renderer
behind each capability’s published JSON Schema artifacts. They are defined
in
failures.ts,
schema.ts,
and
schema-artifacts.ts.
The failure vocabulary
Section titled “The failure vocabulary”When an upstream fails, the wire carries a reason code from a closed
vocabulary. UPSTREAM_FAILURE_REASONS declares exactly four codes.
| Reason | Meaning |
|---|---|
upstream_error | The upstream failed: an error response, or a network refusal. |
timeout | The request ran out of time or was aborted. |
rate_limited | The upstream refused for rate. |
contract_break | The upstream answered, but not in the shape the contract promises. |
The vocabulary splits into two types. UpstreamFailureReason is all four
codes, which is what the wire may carry. UpstreamErrorReason excludes
contract_break. It is the set an UpstreamError may be thrown with,
because contract_break is only ever the mapper’s verdict and is never
thrown.
UpstreamErroris the error transports throw when they know why an upstream failed. It carries areason(default"upstream_error") alongside the human message.unavailableReasonForError(error)maps any thrown value onto the wire’s reason codes. AnUpstreamErrorkeeps its own reason. AnErrornamedTimeoutErrororAbortErrorbecomestimeout. ATypeErrorbecomesupstream_error, becausefetchrejects network refusals asTypeError. Anything else iscontract_break.
import { UpstreamError, unavailableReasonForError } from "@azohra/meteo.core";
try { throw new UpstreamError("provider returned 429", "rate_limited");} catch (error) { const reason = unavailableReasonForError(error); // "rate_limited"}The reason code is all that travels. Words, retries, and presentation are up to the consumer.
“Closed” applies to what a transport may report. A capability’s wire may
extend the vocabulary with its own failures. Station’s
UNAVAILABLE_REASONS is these four codes plus not_configured, a config
verdict no upstream ever produced, as
its wire contract documents.
Schema primitives
Section titled “Schema primitives”These zod building blocks in
schema.ts
recur in capability configs.
ianaTimeZoneis a string thatIntl.DateTimeFormataccepts as a time zone. Anything else fails withnot an IANA time zone.httpUrlis a parseable URL whose protocol ishttp:orhttps:.positionFieldsholds the position-claim fields that station configs spread in:elevationM(finite),latitude(−90 to 90), andlongitude(−180 inclusive to 180 exclusive). Exactly 180 is rejected, so every position has one canonical longitude. The Tempest adapter normalizes a payload’s 180 to −180 before validating. All three fields are nullish, so a config that claims no position stays null.
Schema artifacts
Section titled “Schema artifacts”Each capability that publishes wire documents also publishes JSON Schema
for them, committed under its own schema/ directory
(briefing,
station),
and this module is the one renderer behind those files. A consumer needs
only that convention. The API below exists for the packages’ own schema
emission, and a consumer of briefing or station never calls it.
SchemaArtifactdeclares one artifact:fileName,title, the zodschemait is generated from, and an optionaldescription.ExampleArtifactdeclares an example wire document committed beside the schemas. It is validated against its schema before writing, so a committed example can never drift from its contract.schemaArtifactJson(artifact)produces the artifact’s JSON Schema document exactly as shipped. The zod schema is converted to JSON Schema draft 2020-12 and wrapped with$schema, thetitle, thedescriptionwhen present, and an$idofhttps://meteo.azohra.com/schema/<fileName>.renderJsonArtifact(value)andrenderSchemaArtifact(artifact)produce the exact shipped bytes, which are two-space-indented JSON with a trailing newline.
The conversion deliberately runs with zod’s io: "input", so a
published schema never carries additionalProperties: false. Wire readers
ignore unknown keys, which is how the contracts evolve. A schema that
rejected unknown keys would contradict the wire’s own semantics.
Every committed schema is generated from its zod authority and ships with its package. The zod schemas and their parse guards remain the behavioural truth.