{
  "title": "FDA supplier and follow-up watchlist",
  "description": "Monitor FDA warning letters and response or closeout changes for supplier review. Bounded public windows, literal matches and saved comparisons. No compliance verdicts or letter-body scraping.",
  "type": "object",
  "schemaVersion": 1,
  "properties": {
    "sortBy": {
      "title": "Which FDA update window?",
      "type": "string",
      "editor": "select",
      "enum": [
        "postedDate",
        "letterIssueDate",
        "responsePostedDate",
        "closeoutPostedDate"
      ],
      "enumTitles": [
        "Recently posted warning letters",
        "Recently issued warning letters",
        "Recently posted response links",
        "Recently posted closeout links"
      ],
      "default": "postedDate",
      "description": "Descending publisher date, with company name as the second requested sort. Response and closeout sorting still returns warning-letter rows with distinct follow-up links; blanks can follow dated entries.",
      "sectionCaption": "1 - Choose the update window",
      "sectionDescription": "One public FDA table request, after honoring its robots crawl delay. No accounts, keys or per-letter crawling."
    },
    "maxSourceRecords": {
      "title": "Source window size",
      "type": "integer",
      "default": 25,
      "prefill": 25,
      "minimum": 1,
      "maximum": 100,
      "description": "Read the first 1-100 records in the chosen date order. Company and keyword filters apply only within this window. A missing match is not a clean supplier assessment."
    },
    "companyNames": {
      "title": "Supplier or company names",
      "type": "array",
      "editor": "stringList",
      "default": [],
      "description": "Optional literal, case-insensitive substrings; at least one must match the published company name. Up to 30 values of 120 characters. No fuzzy entity matching."
    },
    "keywords": {
      "title": "Subject or issuing-office keywords",
      "type": "array",
      "editor": "stringList",
      "default": [],
      "description": "Optional literal, case-insensitive terms across company, subject and issuing office. Any keyword matches; when supplier names are also given, both groups must match. Up to 30 terms."
    },
    "maxResults": {
      "title": "Maximum saved letter observations",
      "type": "integer",
      "default": 10,
      "prefill": 10,
      "minimum": 1,
      "maximum": 1000,
      "description": "Confirmed dataset rows only. A result cap can leave matching source rows unsaved. Unchanged rows skipped by onlyChanges do not consume this limit.",
      "sectionCaption": "2 - Save results and compare changes"
    },
    "comparePrevious": {
      "title": "Compare with saved observations",
      "type": "boolean",
      "default": false,
      "description": "First saved observations are new; later runs show changed or unchanged fields and previous values. Only confirmed saved rows advance history."
    },
    "onlyChanges": {
      "title": "Save only new or changed observations",
      "type": "boolean",
      "default": false,
      "description": "Also enables comparisons. An unchanged run can legitimately save zero rows. A row leaving this bounded window is never reported as removed or resolved."
    },
    "snapshotName": {
      "title": "Comparison namespace",
      "type": "string",
      "editor": "textfield",
      "default": "default",
      "description": "1-80 letters, numbers, underscores or hyphens. The sort, source-window size and normalized filters are also part of the history scope. Use one sequential writer per scope."
    },
    "stateStoreName": {
      "title": "Named history store",
      "type": "string",
      "editor": "textfield",
      "default": "maydit-fda-warning-letter-history",
      "description": "3-63 letters, numbers or hyphens. Used only for comparisons. Choose a dedicated store for each workflow when isolation is needed."
    },
    "maxRunSeconds": {
      "title": "Run budget in seconds",
      "type": "integer",
      "default": 240,
      "minimum": 30,
      "maximum": 900,
      "description": "Includes the publisher crawl delay, currently 30 seconds, and requests/history. Use at least 90 seconds of platform timeout. The Actor reserves 25 seconds before that platform deadline; a 30-second own budget may expire before results.",
      "sectionCaption": "3 - Time and source limits",
      "sectionDescription": "No retries or bypass after access/rate failures. Responses are capped at2MiB; errors are recorded in SUMMARY and never emitted as paid rows."
    }
  }
}
