Spectral linting rules defining API design standards and conventions for Australian National University.
13 Ruleserror 10warn 3
Generated by API Evangelist
Written by API Evangelist tooling for Australian National University's APIs. It is a starting point, not a ruleset Australian National University publishes or enforces.
Every contract in a university repository must declare who operates the thing it describes. A university is a federation of buyers; without x-operator an artifact is silently credited to the institution.
$.info
error
anu-info-operator-is-institution
Only institution-operated surfaces belong in this repository as saved contracts. A tenant relationship is recorded in apis.yml, not saved as a spec here.
$.info.x-operator
error
anu-server-under-anu-domain
Every server URL must sit under anu.edu.au. A host outside it is a vendor's, and a vendor's contract does not belong in this repository.
$.servers[*].url
error
anu-provenance-declared
ANU publishes no OpenAPI. Every document here is derived or probed by API Evangelist and must say so, or it reads as something ANU published.
$.info.x-provenance
error
anu-ambiguous-200-documented
Two of ANU's three surfaces return HTTP 200 for failures — the legacy QRNG endpoint returns a plain-text rate-limit refusal, and OAI-PMH returns protocol errors inside a 200 envelope. Any operation on those surfaces must document the 200 response so a client is warned not to trust the status code.
$.paths[*][get,post,put,patch,delete].responses
warn
anu-response-has-content-type
Because status is not a reliable success signal on ANU surfaces, Content-Type is the discriminator. Every documented response must declare its content.
Numeric parameters on ANU surfaces are range-limited by the service. Declare the schema so the bound is machine-readable rather than documented in a sentence.
info.contact must resolve to an anu.edu.au address. A vendor contact address is the clearest single signal that a contract has been misattributed to the institution.
$.info.contact
warn
anu-security-declared-or-explicitly-open
ANU has one keyed surface and two open ones. Both cases must be explicit — an absent security block is indistinguishable from an undocumented one.
# authorship: generated by API Evangelist tooling. Stamped 2026-08-19.
# An unmarked file is NOT assumed to be ours.
x-method: generated
# x-operator: institution — these rules govern ANU-operated surfaces only.
# ANU publishes no governance ruleset of its own. This ruleset was written by
# API Evangelist against the three institution-operated surfaces profiled in
# this repository, and it deliberately encodes the two failure modes the probe
# found rather than a generic style guide: a status code that does not mean
# success, and an unversioned, unlabelled contract.
#
# Spectral 6.x. Reference from a .spectral.yml via `extends:`. Built-in
# functions only (pattern, truthy, falsy, defined, schema, length).
formats:
- oas3
rules:
# --- OPERATOR ATTRIBUTION ---------------------------------------------------
anu-info-operator-declared:
description: >-
Every contract in a university repository must declare who operates the thing it
describes. A university is a federation of buyers; without x-operator an artifact
is silently credited to the institution.
message: info.x-operator MUST be declared (institution | tenant | vendor)
severity: error
given: $.info
then:
field: x-operator
function: truthy
anu-info-operator-is-institution:
description: >-
Only institution-operated surfaces belong in this repository as saved contracts.
A tenant relationship is recorded in apis.yml, not saved as a spec here.
message: info.x-operator MUST be "institution" for a contract saved under all/anu/openapi/
severity: error
given: $.info.x-operator
then:
function: pattern
functionOptions:
match: "^institution$"
anu-server-under-anu-domain:
description: >-
Every server URL must sit under anu.edu.au. A host outside it is a vendor's, and a
vendor's contract does not belong in this repository.
message: servers[].url MUST be under anu.edu.au
severity: error
given: $.servers[*].url
then:
function: pattern
functionOptions:
match: "^https://[A-Za-z0-9.-]*anu\\.edu\\.au"
anu-provenance-declared:
description: >-
ANU publishes no OpenAPI. Every document here is derived or probed by API Evangelist
and must say so, or it reads as something ANU published.
message: info.x-provenance.method MUST be declared (derived | probed | searched | generated)
severity: error
given: $.info.x-provenance
then:
field: method
function: truthy
# --- THE STATUS-CODE TRAP ---------------------------------------------------
anu-ambiguous-200-documented:
description: >-
Two of ANU's three surfaces return HTTP 200 for failures — the legacy QRNG endpoint
returns a plain-text rate-limit refusal, and OAI-PMH returns protocol errors inside a
200 envelope. Any operation on those surfaces must document the 200 response so a
client is warned not to trust the status code.
message: Operations MUST document a 200 response describing what a 200 actually means
severity: error
given: $.paths[*][get,post,put,patch,delete].responses
then:
field: '200'
function: truthy
anu-response-has-content-type:
description: >-
Because status is not a reliable success signal on ANU surfaces, Content-Type is the
discriminator. Every documented response must declare its content.
message: Responses MUST declare content so callers can branch on media type
severity: warn
given: $.paths[*][get,post,put,patch,delete].responses[?(@property != '204')]
then:
field: content
function: truthy
# --- CONTRACT HYGIENE -------------------------------------------------------
anu-operation-id-required:
description: Every operation needs a stable operationId for client generation.
message: operationId MUST be present
severity: error
given: $.paths[*][get,post,put,patch,delete]
then:
field: operationId
function: truthy
anu-operation-tagged:
description: Every operation must carry at least one tag so the surface can be split and navigated.
message: Operations MUST be tagged
severity: error
given: $.paths[*][get,post,put,patch,delete].tags
then:
function: length
functionOptions:
min: 1
anu-parameter-described:
description: >-
ANU's parameters carry hard numeric bounds (length 1-1024, size 1-10) that are only
discoverable from prose today. Every parameter must be described.
message: Parameters MUST have a description
severity: warn
given: $.paths[*][get,post,put,patch,delete].parameters[*]
then:
field: description
function: truthy
anu-parameter-bounded:
description: >-
Numeric parameters on ANU surfaces are range-limited by the service. Declare the
schema so the bound is machine-readable rather than documented in a sentence.
message: Parameters MUST declare a schema
severity: error
given: $.paths[*][get,post,put,patch,delete].parameters[*]
then:
field: schema
function: truthy
anu-deprecated-needs-successor:
description: >-
The legacy QRNG endpoint is deprecated with no sunset date. Any operation marked
deprecated must at minimum describe what replaces it.
message: A deprecated operation MUST carry a description naming its replacement
severity: error
given: $.paths[*][get,post,put,patch,delete][?(@.deprecated == true)]
then:
field: description
function: truthy
anu-contact-is-institutional:
description: >-
info.contact must resolve to an anu.edu.au address. A vendor contact address is the
clearest single signal that a contract has been misattributed to the institution.
message: info.contact.email MUST be an anu.edu.au address
severity: error
given: $.info.contact
then:
field: email
function: pattern
functionOptions:
match: "@[A-Za-z0-9.-]*anu\\.edu\\.au$"
anu-security-declared-or-explicitly-open:
description: >-
ANU has one keyed surface and two open ones. Both cases must be explicit — an absent
security block is indistinguishable from an undocumented one.
message: A security scheme SHOULD be declared, or the operation described as open
severity: warn
given: $.paths[*][get,post,put,patch,delete]
then:
field: description
function: truthy
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.