{
  "manifest_version": "1.0.0",
  "service": {
    "name": "elyreon-arsenal",
    "version": "0.1.0",
    "public_base_url": null,
    "cost_visibility": "Every product below carries status, billing_mode and a DERIVED purchasable flag. A product with purchasable=false executes and meters, but cannot be charged: it is not for sale yet."
  },
  "catalog": {
    "catalog_version": "1.0.0",
    "schema_version": "arsenal.catalog/1",
    "generated_at": "2026-11-13T18:10:00Z",
    "currency": "USD",
    "price_unit": "minor_units"
  },
  "endpoints": {
    "catalog": {
      "method": "GET",
      "path": "/v1/catalog",
      "auth": "none",
      "returns": "this document's products[]"
    },
    "product": {
      "method": "GET",
      "path": "/v1/products/{product_id}",
      "auth": "none",
      "returns": "the full catalog entry: input_schema, output_schema, pricing, resources, errors"
    },
    "execute": {
      "method": "POST",
      "path": "/v1/products/{product_id}/execute",
      "auth": "credential",
      "body": "the product's input_schema",
      "returns": "success document (see responses.success)"
    },
    "mcp": {
      "method": "POST",
      "path": "/mcp",
      "transport": "JSON-RPC 2.0 over HTTP",
      "protocol": "2024-11-05",
      "auth": "credential",
      "methods": [
        "initialize",
        "tools/list",
        "tools/call",
        "ping"
      ]
    },
    "health": {
      "method": "GET",
      "path": "/v1/health",
      "auth": "none"
    }
  },
  "auth": {
    "schemes": [
      {
        "type": "api_key",
        "header": "X-Arsenal-Key"
      },
      {
        "type": "bearer",
        "header": "Authorization",
        "format": "Bearer <key>"
      }
    ],
    "scope_rule": "the credential must carry every scope listed in product.auth.scopes",
    "refusals": {
      "missing_or_unknown_credential": {
        "status": 401,
        "code": "unauthorized"
      },
      "missing_scope": {
        "status": 403,
        "code": "forbidden_scope"
      }
    }
  },
  "metering": {
    "unit": "call",
    "charged_rule": "min(pricing.list_price_minor, pricing.ceiling_minor, tenant.policy.ceiling_per_call_minor)",
    "usage_fields": [
      "upstream_calls",
      "rows_returned",
      "duration_ms",
      "metered_units"
    ],
    "response_headers": {
      "x-arsenal-request-id": "the request this document answers",
      "x-arsenal-receipt-id": "the settlement record, when the call succeeded",
      "x-arsenal-charged-minor": "minor units charged, as an integer string",
      "x-arsenal-simulated": "true when no money moved"
    }
  },
  "idempotency": {
    "header": "Idempotency-Key",
    "mcp_argument": "__idempotency_key",
    "required": "every charged call; a call without one is refused rather than executed unprotected",
    "binding": "the key is bound to a digest of the request body",
    "replay": "a repeat with the same key and body returns the recorded outcome with replayed:true and settles nothing",
    "conflict": {
      "status": 409,
      "code": "idempotency_conflict"
    }
  },
  "responses": {
    "success": {
      "fields": [
        "ok",
        "product_id",
        "product_version",
        "request_id",
        "idempotency_key",
        "tenant_id",
        "result",
        "usage",
        "receipt",
        "replayed"
      ],
      "note": "result validates against the product's output_schema; a result is never returned without a receipt"
    },
    "failure": {
      "fields": [
        "ok",
        "problem",
        "request_id"
      ],
      "problem": {
        "fields": [
          "type",
          "title",
          "status",
          "code",
          "detail",
          "retryable",
          "errors",
          "release_failure"
        ],
        "codes": "each product's catalog entry lists the codes it can return"
      }
    }
  },
  "receipt": {
    "fields": [
      "receipt_id",
      "issued_at",
      "tenant_id",
      "product_id",
      "product_version",
      "request_id",
      "idempotency_key",
      "authorization_id",
      "commerce_backend",
      "simulated",
      "charged_minor",
      "currency",
      "price_model",
      "metered_units",
      "usage",
      "digest",
      "signature"
    ],
    "digest": "sha256 over the sorted-key JSON of every field except digest; recomputable by the holder without the gateway",
    "simulated_semantics": "simulated:true means no money moved. A test-mode receipt is a metering record, never a payment.",
    "signature": "null when the backend does not sign; a signature is present only when a real commerce backend produced it"
  },
  "purchasable_semantics": {
    "definition": "status === 'AVAILABLE' && billing_mode === 'live' && pricing.approved === true",
    "stored": false,
    "note": "derived on every read, so no stored flag can disagree with the catalog"
  },
  "products": [
    {
      "product_id": "elyreon.research.structured",
      "version": "1.0.0",
      "title": "ELYREON Research — structured, source-backed findings",
      "summary": "Answers a bounded research question about a company, industry or named subject from ELYREON's own licensed datasets and SEC index intelligence. Every finding carries an evidence receipt (endpoint, request digest, retrieved_at, rows examined, freshness). Parts of the question the data cannot answer are returned under unanswered, never invented.",
      "capability": "research.synthesis.source_backed",
      "status": "AVAILABLE",
      "billing_mode": "live",
      "purchasable": true,
      "executable": true,
      "price": {
        "model": "per_call",
        "unit": "call",
        "list_price_minor": 500,
        "ceiling_minor": 1500,
        "currency": "USD",
        "approved": true
      },
      "scopes": [
        "arsenal.research.read"
      ],
      "docs": "docs/products/research.md"
    },
    {
      "product_id": "elyreon.signals.detect",
      "version": "1.0.0",
      "title": "ELYREON Signals — reproducible change detection on live datasets",
      "summary": "Runs named detectors over ELYREON's own SEC index and dataset lakes and returns the changes worth acting on. Each signal is reproducible: the detector, its parameters and a digest of its inputs are returned so a third party can re-run the calculation.",
      "capability": "signals.change_detection",
      "status": "AVAILABLE",
      "billing_mode": "live",
      "purchasable": true,
      "executable": true,
      "price": {
        "model": "per_call",
        "unit": "call",
        "list_price_minor": 150,
        "ceiling_minor": 600,
        "currency": "USD",
        "approved": true
      },
      "scopes": [
        "arsenal.signals.read"
      ],
      "docs": "docs/products/signals.md"
    },
    {
      "product_id": "elyreon.verification.claims",
      "version": "1.0.0",
      "title": "ELYREON Verification — claim checking against owned evidence",
      "summary": "Checks structured claims (a dataset, a column, an operator, an expected value) against ELYREON's own datasets and returns verified, contradicted, insufficient evidence or invalid input, with the rows examined as evidence.",
      "capability": "verification.claim_check",
      "status": "AVAILABLE",
      "billing_mode": "live",
      "purchasable": true,
      "executable": true,
      "price": {
        "model": "per_call",
        "unit": "call",
        "list_price_minor": 100,
        "ceiling_minor": 400,
        "currency": "USD",
        "approved": true
      },
      "scopes": [
        "arsenal.verification.read"
      ],
      "docs": "docs/products/verification.md"
    },
    {
      "product_id": "elyreon.workflow.diagnose",
      "version": "1.0.0",
      "title": "ELYREON Workflow Diagnostics — bounded agent-facing autopsy",
      "summary": "Runs the existing ELYRAON Workflow Autopsy engine over a bounded workflow export or canonical execution-event log and returns normalised findings. The engine is the shipped one; this product adds a schema, resource bounds, redaction reporting and a receipt, not a second diagnostic engine.",
      "capability": "workflow.diagnose",
      "status": "AVAILABLE",
      "billing_mode": "live",
      "purchasable": true,
      "executable": true,
      "price": {
        "model": "per_call",
        "unit": "call",
        "list_price_minor": 250,
        "ceiling_minor": 900,
        "currency": "USD",
        "approved": true
      },
      "scopes": [
        "arsenal.workflow.read"
      ],
      "docs": "docs/products/workflow.md"
    },
    {
      "product_id": "elyreon.dataset.quality",
      "version": "1.0.0",
      "title": "ELYREON Dataset Quality — validation, schema, duplicates, privacy warnings",
      "summary": "Returns the Foundry's own blocking and non-blocking quality checks for a dataset, a 0-100 score derived from them, duplicate detection, and privacy-sensitive column warnings. Reuses the existing Foundry quality engine and the dataset-doctor check semantics; it is not a second processing engine.",
      "capability": "dataset.quality_report",
      "status": "AVAILABLE",
      "billing_mode": "live",
      "purchasable": true,
      "executable": true,
      "price": {
        "model": "per_call",
        "unit": "call",
        "list_price_minor": 75,
        "ceiling_minor": 300,
        "currency": "USD",
        "approved": true
      },
      "scopes": [
        "arsenal.dataset.read"
      ],
      "docs": "docs/products/dataset_quality.md"
    }
  ]
}