Australian National University · API Governance Rules

Australian National University API Rules

Spectral linting rules defining API design standards and conventions for Australian National University.

13 Rules error 10 warn 3
View Rules File View on GitHub

Rule Categories

anu

Rules

error
anu-info-operator-declared
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.
$.paths[*][get,post,put,patch,delete].responses[?(@property != '204')]
error
anu-operation-id-required
Every operation needs a stable operationId for client generation.
$.paths[*][get,post,put,patch,delete]
error
anu-operation-tagged
Every operation must carry at least one tag so the surface can be split and navigated.
$.paths[*][get,post,put,patch,delete].tags
warn
anu-parameter-described
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.
$.paths[*][get,post,put,patch,delete].parameters[*]
error
anu-parameter-bounded
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.
$.paths[*][get,post,put,patch,delete].parameters[*]
error
anu-deprecated-needs-successor
The legacy QRNG endpoint is deprecated with no sunset date. Any operation marked deprecated must at minimum describe what replaces it.
$.paths[*][get,post,put,patch,delete][?(@.deprecated == true)]
error
anu-contact-is-institutional
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.
$.paths[*][get,post,put,patch,delete]

Spectral Ruleset

Raw ↑
# 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