{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://oosl.org/schema/give-back-1.json",
  "title": "Give Back Declaration",
  "description": "An annual statement of what an entity's software is built on, what it gave back, and why it considers that appropriate. DRAFT 0.1 - the shape is expected to change.",
  "type": "object",
  "required": ["format", "entity", "period", "published", "reliance", "contributions", "rationale"],
  "additionalProperties": true,
  "properties": {
    "format": {
      "description": "Format identifier and version. Lets a crawler know how to read the rest.",
      "type": "string",
      "const": "give-back/0.1"
    },
    "entity": {
      "description": "Licence s.3.2(a). Who is declaring, and how to reach them.",
      "type": "object",
      "required": ["name", "contact"],
      "properties": {
        "name":    { "type": "string", "description": "Legal name of the declaring entity." },
        "url":     { "type": "string", "format": "uri" },
        "contact": { "type": "string", "description": "mailto: or https: URI." },
        "covers":  {
          "type": "array",
          "description": "Optional. Affiliates covered by this declaration. One declaration may cover a whole group.",
          "items": { "type": "string" }
        }
      }
    },
    "period": {
      "description": "Licence s.3.2(b). Any twelve months you choose; align it to your financial year.",
      "type": "object",
      "required": ["start", "end"],
      "properties": {
        "start": { "type": "string", "format": "date" },
        "end":   { "type": "string", "format": "date" }
      }
    },
    "published": { "type": "string", "format": "date", "description": "Licence s.3.2(f)." },
    "previous": {
      "type": "string", "format": "uri",
      "description": "Optional. URI of the prior period's declaration, so a crawler can build a series."
    },

    "reliance": {
      "description": "Licence s.3.2(c). What you are standing on. NOTE: only publicly registered components are ever counted. See the privacy rules.",
      "type": "object",
      "required": ["component_count", "method"],
      "properties": {
        "component_count": {
          "type": "integer", "minimum": 0,
          "description": "Count of distinct publicly registered components relied on, transitively."
        },
        "method": {
          "type": "string",
          "description": "How the number was arrived at, in plain words. A reader needs this to know what it means."
        },
        "ecosystems": {
          "type": "array",
          "description": "Optional breakdown by package ecosystem.",
          "items": {
            "type": "object",
            "required": ["name", "count"],
            "properties": {
              "name":  { "type": "string", "examples": ["npm", "pypi", "cargo", "maven", "nuget", "go"] },
              "count": { "type": "integer", "minimum": 0 }
            }
          }
        },
        "maintainers": {
          "description": "The column SBOM does not have. Bands, never names of individuals.",
          "type": "object",
          "properties": {
            "identified":      { "type": "integer", "minimum": 0 },
            "for_profit":      { "type": "integer", "minimum": 0 },
            "not_for_profit":  { "type": "integer", "minimum": 0 },
            "unincorporated":  { "type": "integer", "minimum": 0 },
            "unknown":         { "type": "integer", "minimum": 0 },
            "profile_published": { "type": "integer", "minimum": 0,
              "description": "How many resolved to a published maintainer profile." }
          }
        },
        "fragility": {
          "description": "Optional but the most useful thing in the document.",
          "type": "object",
          "properties": {
            "single_maintainer":  { "type": "integer", "minimum": 0 },
            "unpaid_maintainer":  { "type": "integer", "minimum": 0 },
            "no_release_18m":     { "type": "integer", "minimum": 0 },
            "no_commit_18m":      { "type": "integer", "minimum": 0 },
            "archived":           { "type": "integer", "minimum": 0 }
          }
        },
        "notable": {
          "description": "Optional. Specific components worth naming, typically the fragile ones. A declaration naming eleven things well beats one listing four hundred.",
          "type": "array",
          "items": {
            "type": "object",
            "required": ["purl"],
            "properties": {
              "purl":       { "type": "string", "description": "Package URL, e.g. pkg:npm/lodash@4.17.21" },
              "maintainer": { "type": "string", "format": "uri", "description": "URI of their maintainer profile, if any." },
              "flags":      { "type": "array", "items": { "type": "string",
                              "enum": ["single-maintainer", "unpaid", "unmaintained", "archived", "no-profile", "critical-path"] } },
              "note":       { "type": "string" }
            }
          }
        },
        "components": {
          "description": "Optional full enumeration. Most declarations should link to an SBOM instead of inlining one.",
          "type": "array",
          "items": { "type": "string", "description": "Package URL." }
        },
        "sbom": {
          "type": "string", "format": "uri",
          "description": "Optional. Link to a CycloneDX or SPDX document, if you publish one."
        }
      }
    },

    "contributions": {
      "description": "Licence s.3.2(d). What you gave. An empty list is valid and fully compliant.",
      "type": "object",
      "required": ["items"],
      "properties": {
        "monetary_total": {
          "type": "object",
          "properties": {
            "currency": { "type": "string", "description": "ISO 4217." },
            "amount":   { "type": "number", "minimum": 0 }
          }
        },
        "staff_hours": { "type": "number", "minimum": 0 },
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "required": ["kind", "recipient"],
            "properties": {
              "kind": { "type": "string",
                "enum": ["money", "code", "triage", "documentation", "infrastructure",
                         "security-review", "staff-time", "employment", "other"] },
              "recipient":  { "type": "string", "description": "Project, foundation or maintainer." },
              "recipient_profile": { "type": "string", "format": "uri" },
              "purl":       { "type": "string" },
              "amount":     { "type": "number", "minimum": 0 },
              "currency":   { "type": "string" },
              "hours":      { "type": "number", "minimum": 0 },
              "recurring":  { "type": "boolean" },
              "note":       { "type": "string" }
            }
          }
        }
      }
    },

    "rationale": {
      "description": "Licence s.3.2(e). Written by you. Nobody scores it. There is no minimum length and no required tone; there is only the fact that it is public.",
      "type": "string"
    },

    "omissions": {
      "description": "Licence s.6.2. If you withheld a detail because publishing it would be unlawful or unsafe, say so here. You never have to say what, or how much.",
      "type": "array",
      "items": {
        "type": "object",
        "required": ["field", "reason"],
        "properties": {
          "field":  { "type": "string", "description": "Which part of the declaration, e.g. reliance.notable" },
          "reason": { "type": "string", "enum": ["legal", "security"] },
          "note":   { "type": "string" }
        }
      }
    },

    "software": {
      "description": "Optional. Covered software you distribute, if any. Most declarants are only licensees; some are both.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name":    { "type": "string" },
          "url":     { "type": "string", "format": "uri" },
          "profile": { "type": "string", "format": "uri" }
        }
      }
    }
  }
}
