CarbonFarm · OpenAPI Overlay 1.0.0

API Evangelist enhancements for the CarbonFarm CMS content API

12 actions 12 updates documentation extends openapi/carbonfarm-cms-openapi.json
Generated by API Evangelist Written by API Evangelist tooling for CarbonFarm's API. It is a proposal applied on top of the contract, not a document CarbonFarm publishes.
View Overlay File View on GitHub Overlay Specification

What the actions change

descriptionx-apievangelist-gaptitlex-apievangelist-provenancex-apievangelist-surfacesecurityDirectusErrorcontent

Targets 11

$.servers
$.info
$
$.components.securitySchemes.KeyAuth
$.components.securitySchemes.Auth
$.components.schemas
$.paths['/items/post'].get.responses['401']
$.paths['/items/post'].get
$.paths['/auth/password/request'].post
$.paths['/auth/password/reset'].post
$.paths['/auth/login'].post

OpenAPI Overlay

Raw ↑
overlay: 1.0.0
info:
  title: API Evangelist enhancements for the CarbonFarm CMS content API
  version: 1.0.0
extends: openapi/carbonfarm-cms-openapi.json
x-generated: '2026-08-17'
x-method: generated
x-source: >-
  Enhancements derived from this pass over https://cms.int.carbonfarm.app/server/specs/oas. The
  harvested spec in openapi/_original/ is never mutated; every correction below is expressed as an
  overlay action so the provider's own document stays byte-faithful.
actions:
# ---------------------------------------------------------------------------
# The single most consequential defect: servers[0].url has no scheme. Directus
# emits the bare host, so the document is not resolvable by a generator or an
# agent as published.
# ---------------------------------------------------------------------------
- target: $.servers
  description: >-
    Replace the schemeless server entry ("cms.int.carbonfarm.app", emitted by Directus 10.10.7)
    with the resolvable absolute URL observed to serve this API.
  update:
  - url: https://cms.int.carbonfarm.app
    description: CarbonFarm CMS (Directus 10.10.7). Verified live 2026-08-17.
- target: $.info
  description: Title the document for what it actually is, and record provenance and ownership.
  update:
    title: CarbonFarm CMS Content API
    description: >-
      Directus-generated contract for the headless CMS that serves carbonfarm.tech's news posts
      and image assets. Auto-generated from the live schema at /server/specs/oas — it is not a
      published developer contract, carries no versioning commitment, and can change without
      notice when the Directus instance or its collections change. This is NOT CarbonFarm's rice
      MRV product API; that surface sits behind an Auth0 organization login and publishes no
      contract.
    x-apievangelist-provenance:
      harvested_from: https://cms.int.carbonfarm.app/server/specs/oas
      harvested: '2026-08-17'
      http_status: 200
      generator: Directus 10.10.7 (dynamic specification)
      ownership_evidence: >-
        servers[] names the fetch host; /server/info reports project_name "CarbonFarm CMS"; the
        host is a subdomain of carbonfarm.app, which also serves web-login and portal; and
        carbonfarm.tech loads its post images from cms.int.carbonfarm.app/assets/.
    x-apievangelist-surface: internal-infrastructure
- target: $
  description: >-
    Declare the security requirement globally. The document defines KeyAuth and Auth but sets no
    top-level `security`, so the spec reads as though every operation were public — it is not:
    data reads return 403 anonymously.
  update:
    security:
    - Auth: []
    - KeyAuth: []
- target: $.components.securitySchemes.KeyAuth
  description: Warn that this scheme puts a credential in the query string.
  update:
    description: >-
      Directus static access token passed as the `access_token` QUERY parameter. Discouraged — a
      token in a query string is captured by access logs, proxies and Referer headers. Prefer the
      Auth (Authorization header) scheme.
- target: $.components.securitySchemes.Auth
  update:
    description: 'Bearer token in the Authorization header: `Authorization: Bearer <token>`.'
# ---------------------------------------------------------------------------
# Error contract. The generated document declares 4xx status codes with no
# schema at all, so a consumer cannot tell what an error body looks like.
# ---------------------------------------------------------------------------
- target: $.components.schemas
  description: >-
    Add the Directus error envelope observed on live responses, so 4xx responses can reference a
    real schema instead of an empty declaration.
  update:
    DirectusError:
      type: object
      description: >-
        Error envelope returned by every Directus 4xx/5xx response. NOT RFC 9457 — there is no
        application/problem+json, no type URI, and no title/status/detail members. Branch on
        errors[].extensions.code.
      properties:
        errors:
          type: array
          items:
            type: object
            properties:
              message: {type: string}
              extensions:
                type: object
                properties:
                  code:
                    type: string
                    description: Stable machine-readable error code.
                    enum: [FORBIDDEN, INVALID_CREDENTIALS, INVALID_PAYLOAD, ROUTE_NOT_FOUND]
                  reason:
                    type: string
                    description: Present on INVALID_PAYLOAD; names the failing constraint.
                  path:
                    type: string
                    description: Present on ROUTE_NOT_FOUND; echoes the requested path.
- target: $.paths['/items/post'].get.responses['401']
  description: Attach the observed error schema to the declared 401.
  update:
    description: >-
      Unauthorized — missing, expired or invalid token. Anonymous requests to this operation
      return 403 FORBIDDEN rather than 401, because the public role exists but holds no read
      permission on the collection.
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/DirectusError'
- target: $.paths['/items/post'].get
  description: Record the anonymous-access finding and the undeclared caching behaviour.
  update:
    x-apievangelist-observed:
      anonymous_status: 403
      anonymous_code: FORBIDDEN
      etag: 'weak ETags are returned at runtime but are not declared in this document'
# ---------------------------------------------------------------------------
# Gaps recorded rather than silently fixed.
# ---------------------------------------------------------------------------
- target: $.paths['/auth/password/request'].post
  description: Flag that no success response is declared.
  update:
    x-apievangelist-gap: >-
      Declares 401 as its ONLY response. No 2xx is documented, so the success contract for the
      password-request flow is unspecified.
- target: $.paths['/auth/password/reset'].post
  update:
    x-apievangelist-gap: >-
      Declares 401 as its ONLY response. No 2xx is documented.
- target: $.paths['/auth/login'].post
  update:
    x-apievangelist-gap: >-
      Declares only 200. A login endpoint with no documented failure response — a consumer cannot
      tell from the contract what a bad credential returns.
- target: $.info
  description: Record the checks this document does not satisfy, for the provider-facing report.
  update:
    x-apievangelist-findings:
      servers_schemeless: true
      global_security_absent: true
      error_schemas_declared: 0
      operations_missing_4xx: [login, logout, ping]
      rfc9457: false
      idempotency: false
      rate_limit_headers: false
      versioning_scheme: none
      etag_declared_in_spec: false