> ## Documentation Index
> Fetch the complete documentation index at: https://docs.scanoss.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Assign a finding to an actor (also serves as defer/reassign)



## OpenAPI

````yaml /api-reference/earnie/triage-openapi.json post /v1/findings/{findingId}/actions/assign
openapi: 3.0.3
info:
  title: Earnie Findings API
  description: List and read findings, triage them, and review resolutions.
  version: 1.0.0
servers:
  - url: https://{tenant}.earnie.dev
    description: Your Earnie deployment
    variables:
      tenant:
        default: your-company
        description: >-
          Your organization's Earnie address, as shown in your browser when you
          sign in.
security:
  - bearerAuth: []
paths:
  /v1/findings/{findingId}/actions/assign:
    post:
      tags:
        - findings
      summary: Assign a finding to an actor (also serves as defer/reassign)
      operationId: PostV1FindingActionsAssign
      parameters:
        - name: findingId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AssignFindingRequest'
      responses:
        '200':
          description: Finding after assignment
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Finding'
        '400':
          description: Invalid request body or transition
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Not authenticated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Insufficient permissions (findings:write required)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Finding not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: >-
            `version_conflict`: refetch and retry. `finding_scan_only`: the
            finding exists only in a pull request scan and cannot be triaged
            until it reaches the default branch.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    AssignFindingRequest:
      type: object
      required:
        - assigned_to_actor_kind
        - assigned_to_actor_id
        - expected_version
      properties:
        assigned_to_actor_kind:
          type: string
          enum:
            - user
            - apikey
        assigned_to_actor_id:
          type: string
          format: uuid
        justification:
          type: string
        expected_version:
          type: integer
          format: int32
    Finding:
      type: object
      required:
        - id
        - org_id
        - project_id
        - domain_slug
        - title
        - evidence
        - produced_by
        - state
        - domain
        - severity
        - suppressed
        - version
        - created_at
        - updated_at
        - purpose
        - export_signals
      properties:
        id:
          type: string
          format: uuid
        org_id:
          type: string
          format: uuid
        project_id:
          type: string
          format: uuid
        domain_slug:
          type: string
        title:
          type: string
        evidence:
          $ref: '#/components/schemas/Evidence'
        location:
          $ref: '#/components/schemas/FindingLocation'
          nullable: true
        produced_by:
          $ref: '#/components/schemas/ActorRef'
        producer_kind:
          $ref: '#/components/schemas/ProducerKind'
          nullable: true
          description: Which producer last observed this finding.
        producer_ref:
          type: string
          nullable: true
          description: Human-readable provenance reference (e.g. Null when not set.
        state:
          type: string
          enum:
            - open
            - assigned
            - resolved
            - superseded_by_rule
            - reopened
        domain:
          type: string
          enum:
            - oss
            - crypto
            - ai
            - deps
            - provenance
        severity:
          type: string
          enum:
            - critical
            - high
            - medium
            - low
            - info
            - none
        previous_severity:
          type: string
          enum:
            - critical
            - high
            - medium
            - low
            - info
            - none
          nullable: true
          description: >-
            The severity this finding carried before the most recent re-scan
            changed it. `severity` is recomputed and overwritten on every
            re-scan, so without this the previous value is simply gone. Null
            means no re-scan has ever moved this finding's severity — it is not
            "unknown", and it must not be read as "was previously none".
        previous_severity_scan_run_id:
          type: string
          format: uuid
          nullable: true
          description: >-
            The scan run this finding was last observed at while it still
            carried `previous_severity`, so a client can state the whole fact —
            "was critical at scan <id>" — instead of an unattributable claim.
            Null when no transition has been recorded, and also when the earlier
            observation predates scan-run tracking: a set `previous_severity`
            with a null scan run is a real transition whose scan cannot be
            named.
        severity_change_reason:
          nullable: true
          allOf:
            - $ref: '#/components/schemas/SeverityChangeReason'
          description: >-
            Which direction the recorded transition went, and the only field
            that distinguishes a downgrade from a raise. Null when no transition
            has been recorded.
        suppressed:
          type: boolean
        version:
          type: integer
          format: int32
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        enrichments:
          $ref: '#/components/schemas/FindingEnrichment'
          description: Canonical PURL-keyed enrichments attached at read time.
        resolution_id:
          type: string
          format: uuid
          nullable: true
          description: >-
            ID of the resolution that currently explains this finding's resolved
            state. Null when the finding is open, reopened, or superseded by a
            rule. Set on resolve; cleared to null on reopen, supersede, or
            revert. Consumers can use this to fetch the full resolution record
            in one query rather than replaying audit events.
        scan_only:
          type: boolean
          description: >-
            True when the finding was read from a pull request scan's own result
            set and no standing project finding carries its id: the pull request
            introduced it and it has not reached the default branch. It can
            still be resolved, reopened and approved: the decision is kept by
            identity and applies when the finding reaches the default branch.
            Assign, suppress and create-rule answer 409 `finding_scan_only`
            until it does. Absent or false everywhere else.
        pending_resolution:
          $ref: '#/components/schemas/PendingResolution'
        purpose:
          allOf:
            - $ref: '#/components/schemas/CryptoPurpose'
          nullable: true
          description: >-
            Per-finding crypto purpose. Present for crypto findings and null for
            other finding domains.
        export_signals:
          type: array
          items:
            $ref: '#/components/schemas/FindingExportSignal'
          description: >-
            Per-finding Export Signals for the current regime, current-vintage
            rows first. Rows computed under a superseded regime version are
            still returned, marked `vintage: retired`; they are never dropped,
            because a regime bump would otherwise empty this array for every
            project that has not re-scanned. Other finding domains return an
            empty array.
    Error:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: string
        message:
          type: string
    Evidence:
      oneOf:
        - $ref: '#/components/schemas/OssDiffEvidence'
        - $ref: '#/components/schemas/ReachabilityPathEvidence'
        - $ref: '#/components/schemas/CryptoReachabilityEvidence'
        - $ref: '#/components/schemas/MetadataCardEvidence'
        - $ref: '#/components/schemas/DependencyEvidence'
        - $ref: '#/components/schemas/AIUsageEvidence'
      discriminator:
        propertyName: kind
        mapping:
          oss-diff: '#/components/schemas/OssDiffEvidence'
          reachability-path: '#/components/schemas/ReachabilityPathEvidence'
          crypto-reachability: '#/components/schemas/CryptoReachabilityEvidence'
          metadata-card: '#/components/schemas/MetadataCardEvidence'
          dependency: '#/components/schemas/DependencyEvidence'
          ai-usage: '#/components/schemas/AIUsageEvidence'
    FindingLocation:
      type: object
      properties:
        purl:
          type: string
          nullable: true
        path:
          type: string
          nullable: true
        line:
          type: integer
          format: int32
          nullable: true
        end_line:
          type: integer
          format: int32
          nullable: true
    ActorRef:
      type: object
      required:
        - kind
        - id
      properties:
        kind:
          type: string
          enum:
            - user
            - apikey
            - worker
            - agent
        id:
          type: string
          format: uuid
    ProducerKind:
      type: string
      description: >-
        Which kind of producer last observed and emitted this finding. Nullable
        during the migration window (existing rows have no producer_kind). repo
        = connected repository full scan; upload = user-uploaded archive audit;
        pr_ci = PR/CI diff scan (partial coverage); agent = autonomous AI agent
        (working set).
      enum:
        - repo
        - upload
        - pr_ci
        - agent
    SeverityChangeReason:
      type: string
      enum:
        - rescan_lowered
        - rescan_raised
      description: >-
        What a re-scan observed when a finding's effective severity moved:
        `rescan_lowered` — this scan's effective severity ranks below the stored
        one; `rescan_raised` — it ranks above. Both name an observation, never a
        cause. A lowered severity is most often a reachability regression (a
        truncated traversal, a language the producer stopped resolving, a
        producer version walking fewer edges), but that is indistinguishable
        from a genuine improvement at the point the value is written, so the
        field does not claim to know which happened.
    FindingEnrichment:
      type: object
      description: >-
        Purl-keyed enrichment layer attached at read time. Contains component
        metadata, license, vulnerability, and available geoprovenance data.
        Declared-dependency and export-control evidence are produced by scanners
        and are not optional PURL enrichments. Never stored in findings rows.
      properties:
        component:
          $ref: '#/components/schemas/ComponentEnrichment'
        license:
          $ref: '#/components/schemas/LicenseEnrichment'
        vulnerabilities:
          type: array
          items:
            $ref: '#/components/schemas/VulnerabilityEnrichment'
          description: >-
            Array of vulnerability entries. Empty array means no known CVEs;
            omitted means not yet resolved.
        geoprovenance:
          nullable: true
          allOf:
            - $ref: '#/components/schemas/GeoprovenanceEnrichment'
          description: >-
            Stored geoprovenance data for this component. Null means no data is
            available. Geoprovenance is not a public optional scan enrichment.
        model:
          nullable: true
          allOf:
            - $ref: '#/components/schemas/ModelEnrichment'
          description: >-
            ai-identity-api layer for an identified-model finding, resolved by
            the exact (purl, manifest_version) pair the finding's own evidence
            names. Null means the finding names no such pair, the pair has not
            been fetched yet, or the fetch degraded (a bundle-vintage mismatch,
            a not-found response, or a network error all leave this null rather
            than failing the read). Deliberately separate from `license` — an
            OSS license policy or facet must never read a model's license.
        remediation:
          allOf:
            - $ref: '#/components/schemas/RemediationAssessment'
          description: >-
            Remediation for this finding's exact purl@version, joined at read
            time. Absent when no source is configured or it has no entry.
    PendingResolution:
      type: object
      description: >-
        A resolve decision taken on a finding a pull request introduced
        (`scan_only`). It is kept by the finding's identity and becomes the
        resolution it describes when that identity first reaches the default
        branch. Until then the pull request reads the finding as resolved, and
        out of its gate when `suppresses` is true. Present only on a `scan_only`
        finding that carries one.
      required:
        - reason_slug
        - reason_display_name
        - justification
        - status
        - suppresses
        - decided_by
        - decided_at
      properties:
        reason_slug:
          type: string
        reason_display_name:
          type: string
        justification:
          type: string
        status:
          type: string
          enum:
            - pending_review
            - confirmed
          description: The status the resolution takes when it applies.
        suppresses:
          type: boolean
          description: Whether the reason takes the finding out of the pull request gate.
        decided_by:
          $ref: '#/components/schemas/ActorRef'
        decided_by_display:
          type: string
          description: The deciding user's email or API key name, when known.
        decided_at:
          type: string
          format: date-time
    CryptoPurpose:
      type: string
      enum:
        - confidentiality
        - excluded
        - support
        - unknown
      description: >-
        Purpose class of the detected cryptographic mechanism under EAR
        Technical Note 1. Derived from algorithmPrimitive only; it is not a
        claim about the data protected by the mechanism.
    FindingExportSignal:
      type: object
      required:
        - regime
        - regime_version
        - test
        - state
        - vintage
      properties:
        regime:
          type: string
          description: Export-control regime identifier (for example, ear).
        regime_version:
          type: string
          description: Version of the cited regime dataset.
        vintage:
          $ref: '#/components/schemas/ExportSignalVintage'
        test:
          type: string
          description: >-
            Stable regime test identifier. New TN 2.c evidence uses
            `ear.tn2c_described_algorithm`. `ear.pqc_present` is a deprecated
            one-release alias retained only for evidence written before the
            rename; producers must not emit it for new evidence.
        state:
          $ref: '#/components/schemas/ExportSignalState'
        provenance_ref:
          type: string
          nullable: true
          description: Citation or other typed dataset reference for the signal.
    OssDiffEvidence:
      type: object
      required:
        - kind
        - local_file
        - local_line_start
        - local_line_end
        - oss_file
        - oss_line_start
        - oss_line_end
        - purl
        - match_percent
        - algorithm
      properties:
        kind:
          type: string
          enum:
            - oss-diff
        local_file:
          type: string
        local_line_start:
          type: integer
        local_line_end:
          type: integer
        oss_file:
          type: string
          description: >-
            CRC64 source hash of the matched OSS file; the content-fetch key,
            not a path.
        oss_file_path:
          type: string
          description: >-
            Relative path of the matched file within the OSS component (empty
            for findings scanned before this was captured).
        oss_line_start:
          type: integer
        oss_line_end:
          type: integer
        spans:
          type: array
          description: >-
            All matched line ranges, in order. A snippet may match several
            discontiguous spans; the scalar local_line_*/oss_line_* fields
            mirror spans[0]. Empty for a whole-file match or findings from
            before multi-span capture.
          items:
            type: object
            required:
              - local_line_start
              - local_line_end
              - oss_line_start
              - oss_line_end
            properties:
              local_line_start:
                type: integer
              local_line_end:
                type: integer
              oss_line_start:
                type: integer
              oss_line_end:
                type: integer
        purl:
          type: string
        match_percent:
          type: number
          format: double
        match_type:
          type: string
          enum:
            - file
            - snippet
          description: >-
            SCANOSS match kind — "file" for a full-file fingerprint match (line
            ranges are 0/absent, the whole file matched), "snippet" for a
            partial line-range match. Absent on findings emitted before this
            field was captured.
        algorithm:
          type: string
    ReachabilityPathEvidence:
      type: object
      required:
        - kind
        - algorithm
        - purl
        - call_chain
      properties:
        kind:
          type: string
          enum:
            - reachability-path
        algorithm:
          type: string
        purl:
          type: string
        call_chain:
          type: array
          items:
            $ref: '#/components/schemas/CallChainEntry'
    CryptoReachabilityEvidence:
      type: object
      required:
        - kind
        - occurrence_key
        - rule_key
        - source_range
        - source
        - reachability
        - asset
        - rules
        - producer
      properties:
        kind:
          type: string
          enum:
            - crypto-reachability
        occurrence_key:
          type: string
        rule_key:
          type: string
        source_range:
          $ref: '#/components/schemas/CryptoSourceRange'
        matched_text:
          type: string
          description: >-
            The exact code the producer matched at source_range, retained
            verbatim. It is the only renderable code for an occurrence whose
            file is not among the scanned files — a dependency-sourced one,
            whose call site lives in the dependency's own resolved source.
            Absent when the producer reported no match text; consumers MUST then
            say the code is unavailable rather than render an empty pane.
        matched_symbol:
          type: string
          description: >-
            Fully qualified symbol from the producer's matched_operation. Absent
            on evidence written before symbol capture.
        source:
          type: string
          enum:
            - direct
            - dependency
        purl:
          type: string
          description: >-
            The component the occurrence is attributed to. Always present for
            dependency-sourced evidence; present for direct evidence when the
            matched rule is backed by a published package (the library whose API
            the first-party code is calling), absent otherwise.
        module:
          type: string
          description: >-
            The dependency's raw, ecosystem-native module identifier as the
            producer reported it (Maven's `groupId:artifactId`, a Go module
            path, a crate name). Present only for dependency-sourced evidence.
            Stored separately from `purl` because the resolved-source read keys
            on it directly: deriving it back out of a composed `purl@version`
            would be a lossy inverse, and a wrong key silently reads nothing.
        module_version:
          type: string
          description: >-
            The dependency version exactly as the producer reported it, kept
            beside `module` for the same reason — the composed `purl` cannot be
            split back into the two halves reliably. Present only for
            dependency-sourced evidence.
        reachability:
          type: string
          enum:
            - reachable
            - unreachable
            - unknown
        base_severity:
          type: string
          enum:
            - info
            - low
            - medium
            - high
          description: >-
            The intrinsic risk Earnie's algorithm-risk table assigned to the
            asset, before reachability escalation — so an escalated severity can
            explain its derivation. Capped at high: critical is only ever earned
            by escalation. Absent on evidence written before this field existed;
            the next scan fills it in.
        assessed:
          type: boolean
          description: >-
            Whether a curated risk table actually decided base_severity. False
            means the unassessed fallback — nobody has assessed this asset — and
            an unassessed finding never escalates on reachability, so severity
            equals base_severity. It is what lets a reader tell "medium because
            the table says so" from "medium because nobody looked". Absent on
            evidence written before this field existed.
        pqc_status:
          type: string
          enum:
            - safe
            - vulnerable
            - unassessed
            - not_applicable
          description: >-
            The post-quantum verdict, assessed from the algorithm family on any
            asset type that carries one — including certificates and protocols,
            which carry the longest-lead migration work. `vulnerable` is
            Shor-relevant (the classical asymmetric families); `not_applicable`
            is a hash, symmetric cipher, MAC or KDF, which Shor has no structure
            to attack; `unassessed` is an absent or uncurated family and is
            never asserted safe. Replaces the quantum_safe boolean, which had to
            express three ideas with two values.
        risk_table_version:
          type: string
          description: >-
            The curation vintage of the Earnie-owned risk tables that judged
            this finding (e.g. `nist-2026-08`). Severity is scan-anchored: a
            finding assessed last release was assessed by rows the running
            process no longer holds, so the vintage travels with the verdict
            instead of living only in release notes. Absent on evidence written
            before the stamp existed.
        current_risk_table_version:
          type: string
          description: >-
            The risk-table vintage shipping now. Paired with
            `risk_table_version` so a reader can state the whole fact —
            "assessed under nist-2026-08, current nist-2026-11" — without a
            second lookup. Derived on every read, never stored.
        risk_table_vintage:
          type: string
          enum:
            - current
            - retired
          description: >-
            Whether this finding's severity, `assessed` flag and `pqc_status`
            came from the risk tables shipping today (`current`) or from a
            superseded vintage (`retired`). Derived on every read from the two
            fields above — never a stored column, because a stored answer would
            freeze a comparison whose right operand moves with the release and
            would keep reading `current` for exactly the findings a reassessment
            must catch. A retired verdict is still auditable: it was correct
            under the tables that produced it, and the reassessment job brings
            it forward without a re-scan.
        export_regime_version:
          type: string
          description: >-
            The export-control regime identity this finding's export signals
            were computed from, as the COMPOSED value (`ear-2026-08`) rather
            than the bare vintage. Composed because the vintage alone does not
            say which regime stated the test, and a second regime's rows (EU
            dual-use, Wassenaar) would be indistinguishable from EAR's. Paired
            with `risk_table_version` it completes the provenance of the
            finding: which table judged its severity, and which regime dataset
            answered its export tests. Absent on evidence written before the
            stamp existed; the next scan fills it in.
        assessed_family:
          type: string
          description: >-
            The canonical algorithm family the curated tables actually resolved
            this occurrence to — not the producer's spelling, which
            `asset.algorithm` carries verbatim. It is what lets a reader tell
            "judged as `rsa`" from "the producer wrote RSA and nothing matched",
            and what stops a later alias edit from answering a question with a
            family this finding was never judged as. Absent when the family is
            uncurated — the same distinction `assessed` draws, applied to the
            family rather than to the severity.
        deprecation_horizon:
          type: integer
          description: >-
            The calendar year a cited migration deadline falls on — 2030 for the
            CNSA 2.0 retirement of the classical asymmetric algorithms — and
            absent when no published document sets one. INFORMATIONAL, and NEVER
            a severity. It takes no part in reachability escalation and never
            moves `base_severity` or `severity`. A client MUST render it as the
            deadline it is and MUST NOT render it as an alarm, a risk level, or
            anything adjacent to the severity: RSA-2048 and P-256 are correctly
            `low` today and have a deadline, and a UI that folds the deadline
            into the severity is how a risk table starts crying wolf about
            cryptography that is currently fine.
        unknown_reason:
          type: string
          description: >-
            Why reachability is unknown. `traversal_truncated`: a depth limit
            cut every route before a root. `unresolved_dispatch`: every route to
            the finding crosses a call the producer linked by method name alone,
            so its call_chains show how the crypto MAY run, not that it does;
            each step's entry_resolution says which hops were guessed.
            `dependency_without_source`: no call chain reaches the finding, and
            every route through the dependency graph to its library crosses a
            dependency the producer parsed without source (types only), so the
            calls inside it could not be walked; dependency_provenance marks
            that step `without_source`.
          enum:
            - unsupported_language
            - missing_anchor
            - traversal_truncated
            - analysis_failed
            - unresolved_dispatch
            - dependency_without_source
        asset:
          $ref: '#/components/schemas/CryptoAssetEvidence'
        implementation:
          $ref: '#/components/schemas/CryptoImplementationEvidence'
        rules:
          type: array
          items:
            $ref: '#/components/schemas/CryptoRuleEvidence'
        producer:
          $ref: '#/components/schemas/CryptoProducerEvidence'
        resolved_params:
          type: array
          description: >-
            Terminal crypto-call arguments, including static values where the
            producer resolved them. Absent on older evidence.
          items:
            $ref: '#/components/schemas/CryptoResolvedParameter'
        call_chains:
          type: array
          maxItems: 20
          description: >-
            Retained root-to-crypto paths, capped at ingest to the shortest
            distinct ones. NOT required: absent means the caller asked for a
            summary view and the chains were not loaded, while an empty array
            means the producer found none. A required array cannot express that
            difference. Use call_chains_total to tell how many existed. maxItems
            binds evidence written since the cap; findings stored before it can
            still carry up to the producer's own 128 until their project is
            re-scanned, so a strict client should validate leniently rather than
            reject.
          items:
            $ref: '#/components/schemas/CryptoCallChain'
        call_chains_total:
          type: integer
          description: >-
            How many call chains the producer reported, before the ingest cap.
            Absent on evidence written before the cap existed, which readers
            MUST treat as unknown rather than as zero.
        call_chains_truncated:
          type: boolean
          description: >-
            True when fewer chains are stored than the producer reported.
            Consumers rendering a trace MUST say so rather than present the
            retained paths as the whole story.
        call_chain_steps_dropped:
          type: integer
          description: >-
            Total frames removed across all stored chains by the per-chain step
            cap.
        call_paths_total:
          type: integer
          format: int64
          description: >-
            How many distinct routes, from a chain root to the finding, the
            producer's call graph holds. A route is a function sequence, so
            chains that differ only in a call-site line count once. Unlike
            call_chains_total it counts routes the producer never exported, so
            it is the number to compare the shown chains against. Saturates at
            the largest int64 and is then a lower bound. Absent when the
            producer does not report it (crypto-finder 0.32.0 and earlier) or
            the finding has no route.
        call_paths_kept:
          type: integer
          format: int64
          description: >-
            How many of call_paths_total the producer exported as chains, before
            the ingest cap. Absent exactly when call_paths_total is.
        route_evidence:
          type: string
          description: >-
            How strongly the producer resolved the finding's best route, the one
            its verdict rests on. `direct`: every call on it is statically
            resolved. `dispatch`: it needs at least one interface or runtime
            dispatch hop but no call matched by method name alone; the finding
            still reads reachable, and each step's entry_resolution marks the
            dispatch hop. `name_only`: every route crosses a call matched by
            method name alone, so reachability is `unknown` with reason
            `unresolved_dispatch`. Absent when the producer does not report it
            (crypto-finder 0.32.0 and earlier), and on a dependency finding
            proven only by a dependency's cached entry index.
          enum:
            - direct
            - dispatch
            - name_only
        no_callers_only:
          type: boolean
          description: >-
            True when every route to the finding starts at application code
            nothing in the application calls (chain root_kind `no_callers`). The
            finding reads reachable, on weaker evidence: whether that code ever
            runs is not established. Absent when false, and when the producer
            does not report it.
        dependency_provenance:
          $ref: '#/components/schemas/CryptoDependencyProvenance'
    MetadataCardEvidence:
      type: object
      description: >-
        A model file's identification outcome. `status` selects the shape of
        `detail`: identified carries ModelIdentifiedDetail, unidentified
        ModelUnidentifiedDetail, too_large ModelTooLargeDetail, lfs_pointer
        ModelLFSPointerDetail and matching_unavailable
        ModelMatchingUnavailableDetail. The server never emits any other
        pairing.
      required:
        - kind
        - location
        - status
        - detail
        - sha256
      properties:
        kind:
          type: string
          enum:
            - metadata-card
        location:
          $ref: '#/components/schemas/ModelLocation'
        status:
          type: string
          enum:
            - identified
            - unidentified
            - too_large
            - lfs_pointer
            - matching_unavailable
        detail:
          oneOf:
            - $ref: '#/components/schemas/ModelIdentifiedDetail'
            - $ref: '#/components/schemas/ModelUnidentifiedDetail'
            - $ref: '#/components/schemas/ModelTooLargeDetail'
            - $ref: '#/components/schemas/ModelLFSPointerDetail'
            - $ref: '#/components/schemas/ModelMatchingUnavailableDetail'
        sha256:
          type: string
          description: >-
            Content identity of the model file, synthesized for a sharded
            snapshot's index manifest.
        size_bytes:
          type: integer
          format: int64
        fingerprint_version:
          type: string
        shards:
          type: array
          description: Set only for a sharded snapshot.
          items:
            $ref: '#/components/schemas/ModelShard'
    DependencyEvidence:
      type: object
      required:
        - kind
        - purl
        - declarations
      properties:
        kind:
          type: string
          enum:
            - dependency
        purl:
          type: string
          description: >-
            purl@version for a resolved pin, or the base purl (no @version) when
            the declaration is an unresolved range/constraint.
        declarations:
          type: array
          items:
            $ref: '#/components/schemas/DependencyDeclaration'
          description: All manifest declarations aggregated for this finding.
    AIUsageEvidence:
      type: object
      description: >-
        An AI usage detected in source code or a manifest. It marks one line of
        one file. `detection_type` selects the shape of `detail`: sdk_usage
        carries AISDKUsageDetail, manifest_dep AIManifestDepDetail, agent
        AIAgentDetail, tool AIToolDetail, embedding AIEmbeddingDetail,
        vector_store AIVectorStoreDetail and dataset AIDatasetDetail. The server
        never emits any other pairing.
      required:
        - kind
        - location
        - detection_type
        - detail
        - confidence
      properties:
        kind:
          type: string
          enum:
            - ai-usage
        location:
          $ref: '#/components/schemas/AIUsageLocation'
        line_text:
          type: string
          description: >-
            The source line as the producer read it, truncated to 500
            characters. Absent when the producer could not read the line.
        detection_type:
          type: string
          enum:
            - sdk_usage
            - manifest_dep
            - agent
            - tool
            - embedding
            - vector_store
            - dataset
        detail:
          oneOf:
            - $ref: '#/components/schemas/AISDKUsageDetail'
            - $ref: '#/components/schemas/AIManifestDepDetail'
            - $ref: '#/components/schemas/AIAgentDetail'
            - $ref: '#/components/schemas/AIToolDetail'
            - $ref: '#/components/schemas/AIEmbeddingDetail'
            - $ref: '#/components/schemas/AIVectorStoreDetail'
            - $ref: '#/components/schemas/AIDatasetDetail'
        confidence:
          type: number
          format: double
          minimum: 0
          maximum: 1
    ComponentEnrichment:
      type: object
      description: Release and lifecycle metadata for the matched component version.
      properties:
        release_date:
          type: string
          format: date-time
          nullable: true
        latest_release_date:
          type: string
          format: date-time
          nullable: true
        age_days:
          type: integer
          nullable: true
          minimum: 0
        versions_behind:
          type: integer
          nullable: true
          minimum: 0
        status:
          type: string
          nullable: true
    LicenseEnrichment:
      type: object
      description: License data sourced from scan-time scanoss-go match data.
      properties:
        spdx_id:
          type: string
          nullable: true
          description: SPDX license identifier (e.g. "MIT", "Apache-2.0").
        name:
          type: string
          nullable: true
          description: Human-readable license name.
        url:
          type: string
          nullable: true
          description: License text URL.
        copyleft:
          type: boolean
          nullable: true
          description: True if the license has copyleft obligations.
        category:
          type: string
          enum:
            - permissive
            - copyleft-weak
            - copyleft-strong
            - proprietary
            - public-domain
            - unknown
          description: >-
            License risk category derived from a curated SPDX-to-category map
            (ScanCode LicenseDB, CC-BY-4.0). Always populated ("unknown"
            fallback), optional in the contract for backward compatibility.
        dual_licensed:
          type: boolean
          nullable: true
          description: >-
            True when the upstream license statement contains multiple
            alternatives.
        source:
          type: string
          description: Source of the license data (e.g. "scanoss-go", "mock").
    VulnerabilityEnrichment:
      type: object
      description: >-
        Vulnerability entry from scanoss.api v3. fixed_versions contains only
        explicit upstream fix boundaries; Earnie never infers one.
      required:
        - fixed_versions
        - cwe
        - kev
        - known_ransomware
      properties:
        cve_id:
          type: string
          nullable: true
          description: CVE identifier (e.g. "CVE-2021-44228").
        cvss_score:
          type: number
          nullable: true
          description: CVSS base score 0.0–10.0.
        cvss_vector:
          type: string
          nullable: true
          description: CVSS vector string.
        epss_score:
          type: number
          nullable: true
          description: EPSS probability 0.0–1.0.
        epss_percentile:
          type: number
          nullable: true
          description: EPSS percentile 0.0–100.0.
        severity:
          type: string
          nullable: true
          enum:
            - critical
            - high
            - medium
            - low
            - none
          description: Vulnerability severity level.
        source:
          type: string
          description: >-
            Data source identifier. Names every source that reported the CVE
            when there are several, sorted and comma-joined ("NVD, OSV").
        kev:
          type: boolean
          description: >-
            True when the CVE is in the CISA Known Exploited Vulnerabilities
            catalog.
        known_ransomware:
          type: boolean
          description: >-
            True when CISA associates the CVE with known ransomware campaign
            use.
        published:
          type: string
          format: date-time
          nullable: true
          description: Advisory publication timestamp.
        modified:
          type: string
          format: date-time
          nullable: true
          description: Advisory last-modified timestamp.
        fixed_versions:
          type: array
          items:
            type: string
          description: >-
            Deterministic, naturally sorted explicit fix versions reported by
            scanoss.api. Always present; empty when no authoritative fix is
            available.
        cwe:
          type: array
          items:
            type: string
          description: >-
            CWE identifiers this vulnerability is classified under, in canonical
            `CWE-<n>` form. A vulnerability may carry several weaknesses, so
            this is a list, never a scalar. Always present, empty when the
            producer classified nothing. Do not build a consumer that assumes
            values.
    GeoprovenanceEnrichment:
      type: object
      description: >-
        Geoprovenance data for a component — country codes inferred from the
        component's origin data. Populated by the GeoprovenanceEnricher phase.
        The countries field is reserved in this schema; it may be empty in v1 if
        the upstream API does not yet provide country-level data.
      required:
        - countries
        - locations
      properties:
        countries:
          type: array
          items:
            type: string
          description: >-
            ISO-3166 alpha-2 country codes inferred from the component's origin
            data. May be an empty array if the upstream geoprovenance API does
            not return country-level data for this component.
        locations:
          type: array
          items:
            $ref: '#/components/schemas/GeoprovenanceLocation'
          description: Weighted country-of-origin values returned by SCANOSS.
    ModelEnrichment:
      type: object
      description: >-
        ai-identity-api layer for one identified model, resolved by the exact
        (purl, manifest_version) pair — never joined by purl alone, since the
        same purl re-matched against a newer bundle is a different vintage's
        data.
      required:
        - derivation
        - datasets
        - bias
        - curation
        - model_card
        - shards
      properties:
        name:
          type: string
          nullable: true
        author:
          type: string
          nullable: true
        architecture:
          type: string
          nullable: true
        model_type:
          type: string
          nullable: true
        parameter_count:
          type: integer
          format: int64
          nullable: true
        quantization:
          type: string
          nullable: true
        license:
          type: string
          nullable: true
          description: >-
            The MODEL's own license — deliberately not the same field as
            FindingEnrichment.license, so an OSS license policy or facet can
            never read it.
        organization:
          type: string
          nullable: true
        source:
          type: string
          nullable: true
        considerations:
          $ref: '#/components/schemas/ModelConsiderations'
        derivation:
          $ref: '#/components/schemas/ModelDerivation'
        datasets:
          type: array
          items:
            type: string
        bias:
          type: array
          items:
            type: string
        curation:
          $ref: '#/components/schemas/ModelCuration'
        model_card:
          $ref: '#/components/schemas/ModelCard'
        modality:
          type: string
          nullable: true
        shards:
          type: array
          items:
            $ref: '#/components/schemas/ModelEnrichmentShard'
        info_code:
          type: string
          nullable: true
          description: >-
            ai-identity-api's own per-item outcome (e.g. COMPONENT_NOT_FOUND)
            when the answer is not a plain full match.
        info_message:
          type: string
          nullable: true
    RemediationAssessment:
      type: object
      description: >-
        What to do about this exact component version, joined at read time from
        the configured remediation source. An enrichment, never stored in
        findings rows, and may be absent: absence means no source is configured,
        the source has no entry, or the source failed. `coverage: not_covered`
        means the source has not assessed this component, never that it is
        healthy; such an assessment carries no priority, action or signals. It
        carries no composite, dimension or weighted score by design.
      required:
        - purl
        - version
        - coverage
        - signals
        - confidence
        - confidence_reasons
        - assessed_at
        - source
      properties:
        purl:
          type: string
          description: Base purl without version (e.g. "pkg:npm/request").
        version:
          type: string
        coverage:
          type: string
          enum:
            - assessed
            - not_covered
        priority:
          type: string
          enum:
            - fix_now
            - plan
            - monitor
            - healthy
          description: >-
            Qualitative band chosen by the source, never computed by Earnie.
            Present exactly when coverage is `assessed`.
        action:
          $ref: '#/components/schemas/RemediationAction'
        signals:
          type: array
          items:
            $ref: '#/components/schemas/RemediationSignal'
          description: >-
            Verifiable facts behind the priority, one dimension each. Empty when
            not_covered.
        confidence:
          type: number
          minimum: 0
          maximum: 1
          description: The source's confidence in the assessment.
        confidence_reasons:
          type: array
          items:
            type: string
          description: Why confidence is below 1, e.g. "replacement not assessed".
        assessed_at:
          type: string
          format: date-time
          description: Timestamp of the oldest input the source used.
        source:
          $ref: '#/components/schemas/RemediationProvenance'
    ExportSignalVintage:
      type: string
      enum:
        - current
        - retired
      description: >-
        Whether the signal was computed under the regime version Earnie ships
        today (`current`) or under a superseded one (`retired`). Derived on read
        by comparing the row's `regime_version` against the shipped version,
        never stored: a stored flag would keep reading `current` after the
        version moved. A `retired` signal is still evidence and is still
        returned, but it is never a fact about the current regime — re-scan the
        project to refresh it.
    ExportSignalState:
      type: string
      enum:
        - met
        - not_met
        - unknown
        - not_evaluated
      description: >-
        Result of one export-control test. `unknown` means occurrence evidence
        exists but cannot decide the test at occurrence scope; `not_evaluated`
        means the occurrence carries no evidence applicable to that test.
    CallChainEntry:
      type: object
      required:
        - file
        - line
        - function
      properties:
        file:
          type: string
        line:
          type: integer
        function:
          type: string
        signature:
          type: string
          description: Canonical function signature retained from the callgraph producer.
        call_site_line:
          type: integer
          minimum: 1
          description: >-
            The invocation line within this frame: the call to the next frame,
            or the matched crypto invocation for the terminal frame. Absent on
            evidence written before call-site capture.
        argument_expression:
          type: string
          minLength: 1
          description: >-
            The producer-retained argument expression passed from this frame to
            the next frame. Absent on terminal frames, older evidence, or when
            the producer retained no renderable argument for the edge.
        resolved_value:
          type: string
          minLength: 1
          description: >-
            The statically resolved value of argument_expression. Absent when
            the producer could not resolve the edge argument.
        library:
          $ref: '#/components/schemas/CallChainLibrary'
        entry_resolution:
          type: string
          minLength: 1
          description: >-
            How the producer resolved the call that arrives at this frame:
            `exact` when the callee is certain, or a dispatch kind (for example
            `interface_dispatch`) when the analysis could not narrow the
            receiver and considered every compatible implementation. A dispatch
            hop is indicative, not proven. The set of kinds is the producer's
            and may grow, so a client treats an unknown value as not exact.
            Absent on the first frame of a chain, on evidence from producers
            that do not report it, and on the frame after a truncation gap,
            whose caller is no longer shown.
        entry_declared_type:
          type: string
          minLength: 1
          description: >-
            The static type a dispatch hop was resolved over. Absent when
            entry_resolution is absent or exact.
    CryptoSourceRange:
      type: object
      required:
        - file
        - start_line
        - end_line
      properties:
        file:
          type: string
        start_line:
          type: integer
        end_line:
          type: integer
        start_column:
          type: integer
        end_column:
          type: integer
    CryptoAssetEvidence:
      type: object
      description: >-
        One cryptographic asset, discriminated by `type`. At most one of
        `algorithm_properties`, `protocol_properties`, `certificate_properties`
        and `material_properties` is present, and it is the one matching `type`;
        an asset of a `type` the server does not model carries none. A fact that
        is a coherent question for one asset type alone lives in that type's
        object and is structurally absent everywhere else: a certificate has no
        cipher mode and key material has no protocol version, so a client MUST
        read a fact from its own object rather than assuming a sibling applies.
        `type`, `algorithm` and `algorithm_name` stay at this level because they
        are the asset's identity rather than one type's property. The
        `*_properties` names follow CycloneDX `cryptoProperties`, which is also
        why the algorithm object is not called `algorithm`: that name is already
        the family spelling.
      properties:
        type:
          type: string
        algorithm:
          type: string
        algorithm_name:
          type: string
        primitive:
          type: string
          deprecated: true
          description: Replaced by `algorithm_properties.primitive`. Kept for one release.
        mode:
          type: string
          deprecated: true
          description: Replaced by `algorithm_properties.mode`. Kept for one release.
        padding:
          type: string
          deprecated: true
          description: Replaced by `algorithm_properties.padding`. Kept for one release.
        key_size:
          type: integer
          deprecated: true
          description: >-
            Typed key length in bits; never parsed from
            algorithmParameterSetIdentifier. Replaced by
            `algorithm_properties.key_size`. Kept for one release. It was never
            key material's own size: a related-crypto-material asset reports
            that as `material_properties.size`, and the two are not
            commensurable, so a client MUST NOT compare a 256-bit symmetric key
            against an RSA modulus threshold.
        protocol_type:
          type: string
          deprecated: true
          description: Replaced by `protocol_properties.type`. Kept for one release.
        protocol_version:
          type: string
          deprecated: true
          description: Replaced by `protocol_properties.version`. Kept for one release.
        oid:
          type: string
        algorithm_properties:
          allOf:
            - $ref: '#/components/schemas/CryptoAlgorithmProperties'
          description: Present only when `type` is `algorithm`.
        protocol_properties:
          allOf:
            - $ref: '#/components/schemas/CryptoProtocolProperties'
          description: Present only when `type` is `protocol`.
        certificate_properties:
          allOf:
            - $ref: '#/components/schemas/CryptoCertificateProperties'
          description: Present only when `type` is `certificate`.
        material_properties:
          allOf:
            - $ref: '#/components/schemas/CryptoRelatedMaterialProperties'
          description: Present only when `type` is `related-crypto-material`.
        metadata:
          type: object
          deprecated: true
          description: >-
            The producer's own keys that no reader consumed, verbatim, kept for
            forensics. Every key a client used to read from here now has a typed
            home: the four `*_properties` objects, or `implementation` on the
            enclosing evidence for `library`, `api` and `provider`. Kept for one
            release, and its contents are not a contract: a key leaves it the
            moment the server types that fact.
          additionalProperties:
            type: string
    CryptoImplementationEvidence:
      type: object
      description: >-
        What PROVIDES the crypto, as opposed to what the crypto is. It sits
        beside `purl` and `module` on the evidence rather than inside `asset`
        because "Bouncy Castle" is not a property of AES the way a cipher mode
        is. Absent on evidence written before this object existed.
      properties:
        library:
          type: string
          description: The providing library, e.g. `Bouncy Castle` or `JCA/JCE`.
        api:
          type: string
          description: The call surface the producer's rule matched.
        provider:
          type: string
          description: The runtime provider name, e.g. `BC`.
    CryptoRuleEvidence:
      type: object
      required:
        - id
      properties:
        id:
          type: string
        message:
          type: string
        version:
          type: string
    CryptoProducerEvidence:
      type: object
      properties:
        tool_name:
          type: string
        tool_version:
          type: string
        rules_source:
          type: string
        rules_name:
          type: string
        rules_version:
          type: string
        rules_checksum_sha256:
          type: string
        finding_id:
          type: string
          description: Producer artifact join key only; never part of finding identity.
    CryptoResolvedParameter:
      type: object
      required:
        - index
        - type
        - expression
      properties:
        index:
          type: integer
          minimum: 0
        type:
          type: string
        expression:
          type: string
        resolved_value:
          type: string
          description: >-
            Statically resolved value; absent when analysis could not resolve
            it.
    CryptoCallChain:
      type: object
      required:
        - root
        - depth
        - complete
        - truncated
        - steps
      properties:
        root:
          $ref: '#/components/schemas/CallChainEntry'
        depth:
          type: integer
        complete:
          type: boolean
        truncated:
          type: boolean
        root_kind:
          type: string
          description: >-
            What the chain's first frame is. `main`: the program's main.
            `framework_entry`: a function a framework invokes (an override of a
            type outside the application, or a request-mapping, scheduling or
            listener annotation). `no_callers`: application code nothing in the
            application calls. `depth_limit`: a depth limit stopped the walk
            here, so the chain does not reach a real root. Absent when the
            producer does not report it (crypto-finder 0.32.0 and earlier).
          enum:
            - main
            - framework_entry
            - no_callers
            - depth_limit
        dependency_path:
          type: array
          description: >-
            The libraries this chain passes through, in call order, from the
            first library the application calls into to the one holding the
            crypto call (app -> A -> B reads [A, B]). Derived from the frames'
            `library` on every read, never stored. Consecutive frames of one
            library count once; a route that leaves a library and returns lists
            it again. Empty for a first-party chain. On a truncated chain it
            covers the frames that were kept.
          items:
            $ref: '#/components/schemas/CallChainLibrary'
        steps:
          type: array
          maxItems: 24
          description: >-
            Frames from entry point to crypto call. Capped at ingest: a chain
            longer than this keeps both ends and drops from the middle, because
            a trace that loses its sink is wrong rather than short. The edge
            data on the frame before the gap (call_site_line,
            argument_expression) and on the frame after it (entry_resolution) is
            cleared, because it described a call between frames that are no
            longer adjacent. maxItems binds evidence written since the cap; rows
            stored before it can still exceed this until their project is
            re-scanned, so a strict client should validate leniently rather than
            reject. Such a chain reports truncated: true.
          items:
            $ref: '#/components/schemas/CallChainEntry'
    CryptoDependencyProvenance:
      type: object
      description: >-
        How the scanned application depends on the library holding a dependency
        finding, from the producer's resolved dependency graph. Present only on
        dependency-sourced evidence, and absent when the producer does not
        report it (crypto-finder 0.32.0 and earlier). This is the DECLARED path,
        not a call path. A call chain's dependency_path follows calls and can
        cross libraries the declarations do not (app -> tika-core ->
        tika-parsers -> bcprov by calls, app -> tika-parsers -> bcprov by
        declarations); the two answer different questions and are both served.
      properties:
        relationship:
          type: string
          description: >-
            `direct`: the application declares the library itself. `transitive`:
            it arrives through another dependency. Absent when the producer gave
            a value outside this set.
          enum:
            - direct
            - transitive
        path:
          type: array
          description: >-
            The shortest path through the dependency graph, from the library the
            application declares to the one holding the finding, app excluded
            (app -> A -> B reads [A, B]; a direct dependency reads [B]). Absent
            when the producer gave none, or a step that names no library.
          items:
            $ref: '#/components/schemas/CryptoDependencyStep'
    ModelLocation:
      type: object
      description: The model file, or the shard index manifest for a sharded snapshot.
      required:
        - path
      properties:
        path:
          type: string
    ModelIdentifiedDetail:
      type: object
      required:
        - purl
        - matched_via
      properties:
        purl:
          type: string
          description: Typically pkg:huggingface/<org>/<name>.
        name:
          type: string
          description: Derived from purl when the producer left it empty.
        matched_via:
          type: string
          enum:
            - sha256
            - md5
            - header_sha256
            - manifest_sha256
            - tlsh
            - filename
            - composite
          description: filename means a match by file name alone, with no other signal.
        matched_signals:
          type: array
          description: Populated only when matched_via is composite.
          items:
            type: string
        confidence_band:
          type: string
          enum:
            - high
            - medium
            - low
          description: >-
            The server's own band, shown as text and never turned into a
            percentage. Absent for an offline guess.
        near_ties:
          type: array
          items:
            $ref: '#/components/schemas/ModelNearTie'
        near_tie_resolution:
          type: string
          enum:
            - elected
            - kept
        bundle_manifest_version:
          type: string
          description: >-
            Present only for a server match. Its absence is the only proof the
            offline fallback answered instead.
        matcher_version:
          type: string
    ModelUnidentifiedDetail:
      type: object
      properties:
        candidate_purls:
          type: array
          items:
            type: string
        error:
          type: string
          description: The tool's own error text (ai-finder-pro misses[].error).
    ModelTooLargeDetail:
      type: object
      required:
        - cap_mb
      properties:
        cap_mb:
          type: integer
          description: The limit the model's own size_bytes was measured against.
    ModelLFSPointerDetail:
      type: object
      description: Set only when the pointer text parsed.
      properties:
        pointer_oid:
          type: string
        pointer_size:
          type: integer
          format: int64
    ModelMatchingUnavailableDetail:
      type: object
      required:
        - reason
      properties:
        reason:
          type: string
          enum:
            - no_key
            - offline
            - auth
            - rate_limited
    ModelShard:
      type: object
      description: >-
        One file of a sharded snapshot, named by the index manifest
        ModelLocation.path points at.
      required:
        - filename
        - sha256
        - size_bytes
      properties:
        filename:
          type: string
        sha256:
          type: string
        size_bytes:
          type: integer
          format: int64
    DependencyDeclaration:
      type: object
      description: >-
        One manifest declaration of a dependency. Multiple declarations for the
        same purl@version (e.g. declared in several manifests) are aggregated
        into DependencyEvidence.declarations rather than emitting several
        findings.
      required:
        - manifest_path
        - line
      properties:
        manifest_path:
          type: string
          description: Path of the manifest file the declaration was found in.
        line:
          type: integer
          description: >-
            1-based line number of the declaration within the manifest. 0 is a
            first-class sentinel meaning the parser could not map this
            declaration to a specific line — it MUST NOT be treated as an error
            and consumers MUST degrade gracefully.
        declared_text:
          type: string
          nullable: true
          description: The raw declaration text as extracted from the manifest.
        scope:
          type: string
          nullable: true
          description: >-
            Runtime classification as reported by the manifest parser (e.g.
            "dev", "test", "optional", or the default/production scope). This is
            metadata, not graph depth.
        requirement:
          type: string
          nullable: true
          description: >-
            The raw declared version constraint (e.g. "^1.2.0", "v1.62.0").
            Preserved even when the finding's identity collapses to a
            version-less base purl for unresolved ranges.
    AIUsageLocation:
      type: object
      description: The one line an AI usage marks.
      required:
        - path
      properties:
        path:
          type: string
          description: File path relative to the scanned tree.
        line:
          type: integer
          minimum: 1
          description: >-
            1-based line. Absent when the producer could not place the detection
            on a line, which it does for some manifest formats (package.json).
    AISDKUsageDetail:
      type: object
      required:
        - sdk
        - import_statement
      properties:
        sdk:
          type: string
        import_statement:
          type: string
        version:
          type: string
    AIManifestDepDetail:
      type: object
      required:
        - name
        - version
        - manifest_file
      properties:
        name:
          type: string
        version:
          type: string
          description: The declared version or constraint, verbatim. May be empty.
        manifest_file:
          type: string
    AIAgentDetail:
      type: object
      required:
        - framework
      properties:
        framework:
          type: string
        agent_type:
          type: string
    AIToolDetail:
      type: object
      required:
        - name
      properties:
        name:
          type: string
        description:
          type: string
    AIEmbeddingDetail:
      type: object
      required:
        - provider
      properties:
        provider:
          type: string
        model:
          type: string
    AIVectorStoreDetail:
      type: object
      required:
        - provider
      properties:
        provider:
          type: string
    AIDatasetDetail:
      type: object
      required:
        - source
      properties:
        source:
          type: string
        name:
          type: string
        split:
          type: string
    GeoprovenanceLocation:
      type: object
      required:
        - country
        - percentage
      properties:
        country:
          type: string
        percentage:
          type: number
          format: double
    ModelConsiderations:
      type: object
      description: >-
        What the model's publisher says about its ethical, fairness and
        environmental impact.
      required:
        - ethical_considerations
        - fairness_assessments
        - environmental_considerations
      properties:
        ethical_considerations:
          type: array
          items:
            type: string
        fairness_assessments:
          type: array
          items:
            type: string
        environmental_considerations:
          type: array
          items:
            type: string
        source:
          type: string
          nullable: true
    ModelDerivation:
      type: object
      description: One identified model's lineage.
      required:
        - is_adapter
        - parents
      properties:
        transform_kind:
          type: string
          nullable: true
        parents:
          type: array
          items:
            type: string
        is_adapter:
          type: boolean
        adapter_type:
          type: string
          nullable: true
        evidence_source:
          type: string
          nullable: true
        source:
          type: string
          nullable: true
    ModelCuration:
      type: object
      description: Audit/curation status of a model's training data.
      properties:
        audit_status:
          type: string
          nullable: true
        declared_license:
          type: string
          nullable: true
        source:
          type: string
          nullable: true
    ModelCard:
      type: object
      required:
        - structured
      properties:
        structured:
          $ref: '#/components/schemas/ModelCardStructured'
        source:
          type: string
          nullable: true
    ModelEnrichmentShard:
      type: object
      description: One weight file of the model as published upstream.
      required:
        - filename
        - sha256
        - size_bytes
      properties:
        filename:
          type: string
        sha256:
          type: string
        size_bytes:
          type: integer
          format: int64
    RemediationAction:
      type: object
      description: The one step the source recommends. Absent when it recommends none.
      required:
        - kind
        - upgrade_pain
        - summary
      properties:
        kind:
          type: string
          enum:
            - upgrade
            - replace
            - remove
        target_version:
          type: string
          description: Version to upgrade to. Absent when there is none.
        replacement_purl:
          type: string
          description: A specific replacement package. Absent when the source names none.
        upgrade_pain:
          type: string
          enum:
            - none
            - low
            - medium
            - high
            - unknown
          description: >-
            Expected effort of the change; `unknown` when the source did not
            assess it.
        summary:
          type: string
    RemediationSignal:
      type: object
      description: >-
        One verifiable fact on one dimension. A license signal states the
        license's nature, never a verdict; the verdict stays with Earnie's
        policy engine.
      required:
        - dimension
        - kind
        - effect
        - fact
        - evidence
      properties:
        dimension:
          type: string
          enum:
            - vulnerability
            - health
            - currency
            - license
            - integrity
        kind:
          type: string
          description: Source-defined signal kind within the dimension (e.g. "deprecated").
        effect:
          type: string
          enum:
            - blocking
            - concern
            - info
        fact:
          type: string
        evidence:
          type: array
          items:
            $ref: '#/components/schemas/RemediationEvidence'
    RemediationProvenance:
      type: object
      required:
        - provider
        - version
      properties:
        provider:
          type: string
          description: Who produced the assessment (e.g. "earnie-fixture").
        version:
          type: string
    CallChainLibrary:
      type: object
      required:
        - module
      description: >-
        The dependency a call-chain frame belongs to, as the scanner stamped it.
        Absent on first-party frames. `purl` is the identity; `module` and
        `version` are the ecosystem's own spelling.
      properties:
        module:
          type: string
        version:
          type: string
          minLength: 1
        purl:
          type: string
          minLength: 1
    CryptoAlgorithmProperties:
      type: object
      description: >-
        Facts that are coherent questions only for an `algorithm` asset.
        Measured over 2,659 real assets, `primitive` is `other` on every
        non-algorithm asset and the algorithm family is absent from every one of
        them, so these are not shared axes carrying a dummy value.
      properties:
        primitive:
          type: string
        mode:
          type: string
        padding:
          type: string
        block_size:
          type: integer
        hash_function:
          type: string
        parameter_set_identifier:
          type: string
        iterations:
          type: integer
        crypto_function:
          type: string
          description: >-
            What the occurrence does with the algorithm (encrypt, sign, digest).
            One fact the producer spells with two keys, reported once here.
        elliptic_curve:
          type: string
          description: >-
            The curve, in CycloneDX's family-qualified spelling
            (`secg/secp256k1`, `nist/P-256`). 579 rules in the shipped ruleset
            emit one, so an elliptic-curve algorithm without this field was not
            asked, it simply has no curve.
          example: secg/secp256k1
        key_size:
          type: integer
          description: >-
            The algorithm's key parameter in bits: the resolved call-site
            literal where one exists, else the producer's typed key length, and
            only for the primitives whose key length is key bits. A key
            derivation function's length is a derived-output size and is
            deliberately absent rather than reported here.
    CryptoProtocolProperties:
      type: object
      description: Facts that are coherent questions only for a `protocol` asset.
      properties:
        type:
          type: string
        name:
          type: string
          description: >-
            The protocol's own name, and the only fact separating SSL from TLS:
            the producer models SSLv3 as type `tls` with name `SSL`. A client
            testing for SSL MUST read this rather than `type`.
        version:
          type: string
    CryptoCertificateProperties:
      type: object
      description: Facts that are coherent questions only for a `certificate` asset.
      properties:
        type:
          type: string
        format:
          type: string
        serial_number:
          type: string
    CryptoRelatedMaterialProperties:
      type: object
      description: >-
        Facts about a key, secret, seed, salt, IV or nonce. There is no
        primitive here because the producer reports `other` for every one of
        these assets: the asset type is the discriminant, and there is no
        further axis to narrow on.
      properties:
        type:
          type: string
        size:
          type: integer
          description: >-
            This material's own size in bits, whatever the material is, a
            nonce's 96 included. It is NOT a key-size threshold input: a policy
            asking "under 2048 bits" MUST NOT read it for non-key material.
        algorithm:
          type: string
          description: >-
            The algorithm this material belongs to, the producer's spelling. It
            is the only algorithm identity a material asset carries.
        format:
          type: string
        algorithm_family:
          type: string
          description: >-
            The family the material's algorithm belongs to, where the producer
            names one separately: a BLS12-381 key is of family BLS. Present when
            `algorithm` alone is too specific to compare.
          example: BLS
        elliptic_curve:
          type: string
          description: >-
            The curve this key is on, family-qualified. 94 of the curve-emitting
            rules put a curve on a private key rather than on an algorithm.
          example: nist/P-256
        origin:
          type: string
          description: >-
            How the material came to exist: generated, derived, loaded,
            imported. It separates a key the code minted from one it read off
            disk.
          example: generated
    CryptoDependencyStep:
      type: object
      required:
        - module
      description: >-
        One library on a declared dependency path. `purl` is the identity;
        `module` and `version` are the ecosystem's own spelling, and `module` is
        empty only when the producer gave a purl alone.
      properties:
        module:
          type: string
        version:
          type: string
          minLength: 1
        purl:
          type: string
          minLength: 1
        without_source:
          type: boolean
          description: >-
            True when the producer parsed this library without source (types
            only), so it holds no call edges of its own and a route through it
            cannot be walked. Absent when false.
    ModelNearTie:
      type: object
      description: >-
        A candidate the matcher could not separate from the winner. purl is
        absent when the candidate itself has none.
      required:
        - sha256
        - relation
      properties:
        purl:
          type: string
        sha256:
          type: string
        relation:
          type: string
          enum:
            - near_tie
            - score_tie
            - weight_identical
    ModelCardStructured:
      type: object
      description: Parsed subset of a model's model card.
      required:
        - authors
        - ethical_considerations
      properties:
        intended_use:
          type: string
          nullable: true
        technical_limitations:
          type: string
          nullable: true
        ethical_considerations:
          type: array
          items:
            type: string
        authors:
          type: array
          items:
            type: string
        paper_url:
          type: string
          nullable: true
    RemediationEvidence:
      type: object
      required:
        - label
      properties:
        label:
          type: string
        url:
          type: string
          description: >-
            Where the fact can be checked. Absent when the evidence has no
            public link.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        An Earnie API key, sent as `Authorization: Bearer sk_earnie_...`. Create
        one under Settings > API keys. The key's scopes decide which operations
        it may call.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.