# Evidence Bundle Emit Operation
#
# Terminal op in a recipe DAG that assembles a signed, content-addressable
# Evidence Bundle (RO-Crate 1.1 profile) from upstream outputs + RunRecords.
# Thin DAG-time wrapper around folia.bundle.build.build_bundle().
#
# Ticket: .tickets/impl/op-evidence-bundle-emit/
# Spec:   docs/spec/EVIDENCE_BUNDLE.md, docs/spec/BUNDLE_CLI.md
# Tie-in: UC-045 advisory recipes, op-fm-inference's RunRecord

id: evidence_bundle_emit
name: Evidence Bundle Emit
description: >
  Assemble a signed Evidence Bundle (RO-Crate 1.1 ZIP) from upstream DAG
  outputs + per-op RunRecords. Synthesizes a ProvenanceRecord from the
  recipe's executed transforms, writes outputs + provenance.yaml to a
  staging directory, then calls folia.bundle.build.build_bundle().

  The op is typically the terminal step in a recipe; it returns the
  bundle path + content-addressable bundle ID for downstream registration
  (catalog publish, transparency log, etc.).

version: 0.1.0
category: provenance
type: layers-to-bundle
default_implementation: native

inputs:
  - name: outputs
    type: layer_list
    description: >
      Ordered list of upstream layer references whose data + run_records
      flow into the bundle. Each layer's typed result (PredictionResult,
      EmbeddingResult, raster, vector) contributes a ProvenanceTransform
      entry; if the result carries a RunRecord, the model + input hashes
      are pulled directly. Raw source layers contribute ProvenanceInput
      entries.
    required: true

  - name: spec_path
    type: file
    format: yaml
    description: >
      Path to the folia.yaml that produced these outputs. Used as the
      bundle's spec URI. Defaults to the recipe's own file when invoked
      inside a DAG.
    required: false

requires: {}  # structural — consumes arbitrary upstream artifacts

outputs:
  - name: bundle
    type: file
    format: zip
    # bundle artifact — no concept slug (provenance container, not a phenomenon)
    description: >
      Path to the assembled Evidence Bundle ZIP. The bundle is also
      content-addressable by its bundle_id (sha256 of the canonical
      manifest); see folia.bundle.manifest.compute_bundle_id().

  - name: bundle_id
    type: string
    description: >
      sha256:<hex> of the canonical bundle manifest. Cite this in
      downstream registrations / catalogs.

params:
  out_dir:
    type: string
    description: >
      Directory where the bundle ZIP is written. Defaults to
      `bundles/<bundle_id>.zip` relative to the recipe's run directory.

  issuer_id:
    type: string
    description: >
      Issuer identity for the bundle (e.g. an ORCID, a DID, or a Folia
      tenant ID). Overrides the `issuer` field in the recipe spec.

  license:
    type: string
    default: CDLA-Permissive-2.0
    description: >
      SPDX identifier for the bundle's license. Defaults to the recipe's
      `license:` field; this param overrides it.

  confidentiality:
    type: string
    default: public
    description: >
      Confidentiality classification (public, confidential, restricted).
      Surfaced in the manifest; consumers may use it to gate access.

  predecessor_bundle:
    type: string
    description: >
      Bundle ID of a predecessor bundle this run extends or supersedes.
      Encoded in the manifest's lineage.

  sign:
    type: boolean
    default: false
    description: >
      Sign the bundle with the configured signing key (env var
      FOLIA_BUNDLE_SIGNING_KEY). When false, the bundle is built but
      unsigned. KMS-backed signing is deferred (see ticket US8).

  log:
    type: boolean
    default: false
    description: >
      Log the bundle hash to the transparency log (folia.bundle.log_client).
      Requires a log endpoint to be configured; defaults to off in v1.

  include_renders:
    type: boolean
    default: false
    description: >
      Include rendered preview imagery (PNG / map tiles) in the bundle.
      Increases bundle size; defaults to off.

  methodology_refs:
    type: list
    items: string
    description: >
      Free-form list of methodology references (paper DOIs, ADR slugs,
      spec anchors) recorded in the bundle's PROV-O graph.

execution:
  realtime_max_km2: 100000          # bundle assembly is O(outputs) not O(area)
  cost_per_km2: 0.0                 # negligible
  time_per_km2_sec: 0.0
  memory_profile: low
  profile:
    cpu: low
    memory: low
    io: medium

cache_policy:
  regional_precompute: []
  ttl_days: 0                       # bundles are run-specific; never cache
  invalidate_on: []

examples:
  - name: Terminal op for fire-scar recipe
    description: >
      Bundle the burn-scar mask + cross-validation from upstream ops.
    inputs:
      outputs:
        - "$burn_scar_inference.output"
        - "$cross_validate.output"
    params:
      methodology_refs:
        - "doi:10.1109/IGARSS52108.2023.10282336"
      sign: true

# backends: audited 2026-08-14 (defect 50). A key means a runtime that DISPATCHES this op —
# folia-engine `dispatch_op` (products/sdk/folia-engine/src/lib.rs), a `registerOp`/OP_TABLE
# entry in packages/compute, `_BUILTIN_OP_MAP` in folia/compute.py, or a backend manifest
# (folia/backends/*/backend.yaml).
backends:
  python:
    function: geo.evidence_bundle.emit
    dispatch: folia/compute.py _BUILTIN_OP_MAP
