{
  "openapi": "3.1.1",
  "info": {
    "title": "LegalArxiv Contribution Gateway",
    "version": "0.2.0-pilot",
    "summary": "Private intake for human and machine research contributions",
    "termsOfService": "https://legalarxiv.org/submission-terms",
    "description": "The Contribution Gateway accepts private candidate contributions. A gateway submission is not a publication, endorsement, public archive record, or completed review. Human identity, rights, and AI-use statements are submitter assertions until independently checked. Candidate PDFs are never public: only an authenticated management session may retrieve the current exact object, and only after its immutable safety assessment passes and the server re-verifies its complete fixity. Publication, if approved, is a separate operator-controlled transition into the immutable public archive."
  },
  "servers": [
    {
      "url": "https://legalarxiv.org",
      "description": "Production pilot"
    }
  ],
  "tags": [
    {
      "name": "Human challenges",
      "description": "Short-lived, single-use challenges for same-origin human-web flows. Challenges are abuse controls, not proof of identity."
    },
    {
      "name": "Submission drafts",
      "description": "Private, capability-protected intake and lifecycle operations."
    },
    {
      "name": "Artifacts",
      "description": "Integrity-checked PDF upload into private quarantine."
    }
  ],
  "paths": {
    "/api/v1/submissions/challenge": {
      "post": {
        "tags": ["Human challenges"],
        "operationId": "issueSubmissionChallenge",
        "summary": "Issue a single-use human-web challenge",
        "description": "Requires an allowed same-origin browser request. Create challenges are source-bound. Confirmation challenges additionally require the private management session and are bound to one submission revision and digest. Every challenge expires after ten minutes and may be consumed once; it is not independent identity proof.",
        "parameters": [
          {
            "name": "purpose",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": ["create", "confirm"]
            }
          },
          {
            "name": "submission",
            "in": "query",
            "required": false,
            "description": "Required when purpose is confirm.",
            "schema": { "type": "string", "pattern": "^sub_[A-Za-z0-9_-]{27}$" }
          },
          {
            "name": "revision_id",
            "in": "query",
            "required": false,
            "description": "Required when purpose is confirm.",
            "schema": { "type": "string", "pattern": "^subrev_[A-Za-z0-9_-]{27}$" }
          },
          {
            "name": "revision_sha256",
            "in": "query",
            "required": false,
            "description": "Required when purpose is confirm.",
            "schema": { "$ref": "#/components/schemas/Sha256" }
          }
        ],
        "responses": {
          "200": {
            "description": "Challenge issued",
            "headers": {
              "Cache-Control": {
                "schema": { "type": "string", "const": "private, no-store, max-age=0" }
              }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Challenge" }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Problem" },
          "429": { "$ref": "#/components/responses/Problem" },
          "503": { "$ref": "#/components/responses/Problem" }
        }
      }
    },
    "/api/v1/submissions": {
      "post": {
        "tags": ["Submission drafts"],
        "operationId": "createSubmissionDraft",
        "summary": "Create a private contribution draft",
        "description": "Human-web callers use a same-origin request and a create challenge. Their response reveals a private management capability once. Machine callers use a separately issued machine credential and never receive that human capability; human confirmation is delivered later through an operator-controlled handoff to the named contact. An Idempotency-Key is mandatory and scoped to the caller. Replays report the actual current lifecycle and never reopen stale uploads. No public record is created.",
        "security": [
          { "MachineBearer": [] },
          { "HumanChallenge": [] }
        ],
        "parameters": [
          { "$ref": "#/components/parameters/IdempotencyKey" }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/SubmissionDocument" },
              "examples": {
                "newWorkWithoutPdf": {
                  "summary": "New work metadata draft",
                  "value": {
                    "schema_version": "legalarxiv.submission.v1",
                    "submission_type": "release_candidate",
                    "contribution_kind": "new_work",
                    "intent": "request_publication",
                    "target": {},
                    "identity": {
                      "title": "Auditable evaluation for legal reasoning systems",
                      "abstract": "A bounded empirical study with reproducible evaluation materials.",
                      "work_type": "research_article",
                      "language": "en",
                      "jurisdictions": ["cross-jurisdictional"],
                      "subjects": ["legal AI", "evaluation"],
                      "external_identifiers": []
                    },
                    "research_boundary": {
                      "primary_contribution": "A documented protocol for auditing legal reasoning evaluations.",
                      "scope_boundary": "The study does not measure deployment safety or legal correctness outside the stated corpus.",
                      "material_limitations": ["The source corpus is limited to published appellate decisions."]
                    },
                    "authors": [
                      {
                        "name": "Researcher Name",
                        "position": 1,
                        "corresponding": true,
                        "responsibility_scope": "Study design, source verification, analysis, and final manuscript."
                      }
                    ],
                    "ai_disclosure": {
                      "use_class": "none",
                      "systems": [],
                      "contributions": []
                    },
                    "artifacts": [],
                    "rights": {
                      "authority_basis": "author",
                      "confirmation": true
                    },
                    "contact": {
                      "name": "Researcher Name",
                      "email": "researcher@example.org"
                    },
                    "terms": {
                      "version": "legalarxiv.submission-terms.2026-08-30",
                      "accepted": true
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Private draft created",
            "headers": {
              "Location": {
                "description": "Private status resource",
                "schema": { "type": "string", "format": "uri" }
              },
              "Idempotency-Replayed": {
                "schema": { "type": "string", "const": "false" }
              }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CreateSubmissionResult" }
              }
            }
          },
          "200": {
            "description": "Idempotent replay of the existing private draft",
            "headers": {
              "Idempotency-Replayed": {
                "schema": { "type": "string", "const": "true" }
              }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CreateSubmissionResult" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/Problem" },
          "401": { "$ref": "#/components/responses/Problem" },
          "403": { "$ref": "#/components/responses/Problem" },
          "409": { "$ref": "#/components/responses/Problem" },
          "413": { "$ref": "#/components/responses/Problem" },
          "422": { "$ref": "#/components/responses/Problem" },
          "429": { "$ref": "#/components/responses/Problem" },
          "503": { "$ref": "#/components/responses/Problem" }
        }
      }
    },
    "/api/v1/submissions/{submission}": {
      "parameters": [
        { "$ref": "#/components/parameters/SubmissionId" }
      ],
      "get": {
        "tags": ["Submission drafts"],
        "operationId": "getSubmissionStatus",
        "summary": "Read private submission state",
        "description": "Requires the submission management capability, its submission-bound browser session, or a machine credential that owns the submission and has submission:read. Returns bounded event and decision history. It is intentionally private and non-cacheable.",
        "security": [
          { "SubmissionManagementBearer": [] },
          { "MachineBearer": [] }
        ],
        "responses": {
          "200": {
            "description": "Private workflow state",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/SubmissionStatus" }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Problem" },
          "403": { "$ref": "#/components/responses/Problem" },
          "404": { "$ref": "#/components/responses/Problem" },
          "503": { "$ref": "#/components/responses/Problem" }
        }
      }
    },
    "/api/v1/submissions/{submission}/session": {
      "parameters": [
        { "$ref": "#/components/parameters/SubmissionId" }
      ],
      "post": {
        "tags": ["Human challenges"],
        "operationId": "exchangeSubmissionManagementSession",
        "summary": "Exchange a management fragment for a private browser session",
        "description": "Same-origin browser operation. It validates the lax_s_ management capability, creates a distinct eight-hour server-recorded session token for this submission, sets it in an HttpOnly, Secure, SameSite=Strict cookie, and permits the client to remove the long-lived bearer fragment from the address bar. Opening another submission uses a different cookie name and does not overwrite the first session.",
        "security": [
          { "SubmissionManagementBearer": [] }
        ],
        "responses": {
          "204": { "description": "Private browser session established" },
          "401": { "$ref": "#/components/responses/Problem" },
          "403": { "$ref": "#/components/responses/Problem" },
          "404": { "$ref": "#/components/responses/Problem" },
          "503": { "$ref": "#/components/responses/Problem" }
        }
      }
    },
    "/api/v1/submissions/{submission}/revisions": {
      "parameters": [
        { "$ref": "#/components/parameters/SubmissionId" }
      ],
      "post": {
        "tags": ["Submission drafts"],
        "operationId": "createSubmissionRevision",
        "summary": "Create the next immutable private revision",
        "description": "Creates a complete replacement document as the next revision. It is available while the submission is draft, awaiting human confirmation, or changes requested. The new revision becomes the current draft; a prior seal or human confirmation is never carried forward. An Idempotency-Key is mandatory and scoped to the authorized submission owner. Identical or previously used revision content is rejected. Declared artifacts receive new private upload instructions.",
        "security": [
          { "SubmissionManagementBearer": [] },
          { "MachineBearer": [] }
        ],
        "parameters": [
          { "$ref": "#/components/parameters/IdempotencyKey" }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/SubmissionDocument" }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Next private revision created",
            "headers": {
              "Location": {
                "description": "Private submission status resource",
                "schema": { "type": "string", "format": "uri" }
              },
              "Idempotency-Replayed": {
                "schema": { "type": "string", "const": "false" }
              }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CreateRevisionResult" }
              }
            }
          },
          "200": {
            "description": "Idempotent replay of an existing revision",
            "headers": {
              "Idempotency-Replayed": {
                "schema": { "type": "string", "const": "true" }
              }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CreateRevisionResult" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/Problem" },
          "401": { "$ref": "#/components/responses/Problem" },
          "403": { "$ref": "#/components/responses/Problem" },
          "404": { "$ref": "#/components/responses/Problem" },
          "409": { "$ref": "#/components/responses/Problem" },
          "413": { "$ref": "#/components/responses/Problem" },
          "422": { "$ref": "#/components/responses/Problem" },
          "429": { "$ref": "#/components/responses/Problem" },
          "503": { "$ref": "#/components/responses/Problem" }
        }
      }
    },
    "/api/v1/submissions/{submission}/artifacts/{artifact}": {
      "parameters": [
        { "$ref": "#/components/parameters/SubmissionId" },
        { "$ref": "#/components/parameters/ArtifactId" }
      ],
      "get": {
        "tags": ["Artifacts"],
        "operationId": "downloadSubmissionArtifactForResponsibilityReview",
        "summary": "Retrieve the exact quarantined PDF for named-contact review",
        "description": "Available only through the private management capability or its browser session, and only after the artifact's immutable safety assessment is passed; a machine credential is not accepted. The server full-reads R2 and rechecks byte length, SHA-256, ETag, and PDF signature before returning an attachment. Pending or failed artifacts are denied. The response is private, no-store, sandboxed, and includes X-Content-SHA256.",
        "security": [
          { "SubmissionManagementBearer": [] }
        ],
        "responses": {
          "200": {
            "description": "Integrity-reverified private PDF attachment",
            "headers": {
              "X-Content-SHA256": { "schema": { "$ref": "#/components/schemas/Sha256" } },
              "X-LegalArxiv-Scan-State": { "schema": { "type": "string", "enum": ["pending_manual_scan", "passed", "failed"] } }
            },
            "content": {
              "application/pdf": { "schema": { "type": "string", "format": "binary" } }
            }
          },
          "401": { "$ref": "#/components/responses/Problem" },
          "403": { "$ref": "#/components/responses/Problem" },
          "404": { "$ref": "#/components/responses/Problem" },
          "503": { "$ref": "#/components/responses/Problem" }
        }
      },
      "put": {
        "tags": ["Artifacts"],
        "operationId": "uploadSubmissionArtifact",
        "summary": "Upload one declared PDF to private quarantine",
        "description": "The body must exactly match the declared byte length and SHA-256. Content-Length is required, compressed transfer content is rejected, and the stored object must begin with the PDF signature. A successful upload is quarantined with manual safety screening pending. The PUT response never returns uploaded bytes.",
        "security": [
          { "SubmissionManagementBearer": [] },
          { "MachineBearer": [] }
        ],
        "parameters": [
          {
            "name": "X-Content-SHA256",
            "in": "header",
            "required": true,
            "description": "The exact lowercase declaration, including the sha256: prefix.",
            "schema": { "$ref": "#/components/schemas/Sha256" }
          },
          {
            "name": "Content-Length",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20971520
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/pdf": {
              "schema": {
                "type": "string",
                "format": "binary",
                "maxLength": 20971520
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Upload verified and quarantined, or idempotently replayed",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ArtifactUploadResult" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/Problem" },
          "401": { "$ref": "#/components/responses/Problem" },
          "404": { "$ref": "#/components/responses/Problem" },
          "409": { "$ref": "#/components/responses/Problem" },
          "411": { "$ref": "#/components/responses/Problem" },
          "413": { "$ref": "#/components/responses/Problem" },
          "415": { "$ref": "#/components/responses/Problem" },
          "422": { "$ref": "#/components/responses/Problem" },
          "503": { "$ref": "#/components/responses/Problem" }
        }
      }
    },
    "/api/v1/submissions/{submission}/prepare": {
      "parameters": [
        { "$ref": "#/components/parameters/SubmissionId" }
      ],
      "post": {
        "tags": ["Submission drafts"],
        "operationId": "prepareSubmission",
        "summary": "Seal the current revision for human confirmation",
        "description": "All declared artifacts must already be integrity-checked in quarantine. Sealing makes the current revision immutable and advances the draft to awaiting_human_confirmation. It does not submit the work for review by itself.",
        "security": [
          { "SubmissionManagementBearer": [] },
          { "MachineBearer": [] }
        ],
        "responses": {
          "200": {
            "description": "Revision sealed or idempotently replayed",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/PrepareResult" }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Problem" },
          "404": { "$ref": "#/components/responses/Problem" },
          "409": { "$ref": "#/components/responses/Problem" },
          "503": { "$ref": "#/components/responses/Problem" }
        }
      }
    },
    "/api/v1/submissions/{submission}/confirm": {
      "parameters": [
        { "$ref": "#/components/parameters/SubmissionId" }
      ],
      "post": {
        "tags": ["Submission drafts"],
        "operationId": "confirmSubmissionResponsibility",
        "summary": "Confirm responsibility for a sealed revision",
        "description": "This action is presented to the named contact and does not accept a machine credential. It requires a private, same-origin management session and a single-use challenge bound to the same revision. Machine-originated revisions must first pass immutable artifact safety screening. The request repeats the exact revision id, number, metadata digest, and artifact digest manifest shown for review; any stale value fails. The attestor name and email must match the normalized contact. The resulting identity state is self_asserted_unverified: these controls do not independently prove identity or technically exclude undisclosed automation using the human-web path.",
        "security": [
          {
            "SubmissionManagementBearer": [],
            "HumanChallenge": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ResponsibilityConfirmation" }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Responsibility recorded and submission queued for editorial review",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ConfirmationResult" }
              }
            }
          },
          "200": {
            "description": "Idempotent replay of an existing confirmation",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ConfirmationResult" }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Problem" },
          "403": { "$ref": "#/components/responses/Problem" },
          "404": { "$ref": "#/components/responses/Problem" },
          "409": { "$ref": "#/components/responses/Problem" },
          "422": { "$ref": "#/components/responses/Problem" },
          "503": { "$ref": "#/components/responses/Problem" }
        }
      }
    },
    "/api/v1/submissions/{submission}/withdraw": {
      "parameters": [
        { "$ref": "#/components/parameters/SubmissionId" }
      ],
      "post": {
        "tags": ["Submission drafts"],
        "operationId": "withdrawSubmission",
        "summary": "Withdraw a private submission",
        "description": "Withdraws a submission while its lifecycle permits withdrawal. It does not erase immutable revision, attestation, decision, or event evidence, and it cannot retract an already published archive release.",
        "security": [
          { "SubmissionManagementBearer": [] },
          { "MachineBearer": [] }
        ],
        "responses": {
          "200": {
            "description": "Submission withdrawn or idempotently replayed",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/WithdrawalResult" }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Problem" },
          "404": { "$ref": "#/components/responses/Problem" },
          "409": { "$ref": "#/components/responses/Problem" },
          "503": { "$ref": "#/components/responses/Problem" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "MachineBearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "lax_m_…",
        "description": "Separately issued machine credential. The credential must own the submission for resource operations and carry the documented submission:read or submission:write scope."
      },
      "SubmissionManagementBearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "lax_s_…",
        "description": "High-entropy per-submission human management capability. Human-web creation returns it once; machine creation never does. The browser exchanges the fragment for a short-lived, HttpOnly, same-site session and clears the URL. The original link remains a bearer secret."
      },
      "HumanChallenge": {
        "type": "apiKey",
        "in": "header",
        "name": "X-LegalArxiv-Challenge",
        "description": "A short-lived single-use lax_c_… token from /api/v1/submissions/challenge. Confirmation challenges are source-, submission-, revision-, and digest-bound. They must accompany an allowed same-origin request and are not independent identity proof."
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "description": "Caller-scoped visible ASCII key, 16 to 128 characters. Reuse it only to retry the exact same operation and content.",
        "schema": {
          "type": "string",
          "minLength": 16,
          "maxLength": 128,
          "pattern": "^[\\x21-\\x7e]{16,128}$"
        }
      },
      "SubmissionId": {
        "name": "submission",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^sub_[A-Za-z0-9_-]{27}$"
        }
      },
      "ArtifactId": {
        "name": "artifact",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^subart_[A-Za-z0-9_-]{27}$"
        }
      }
    },
    "responses": {
      "Problem": {
        "description": "RFC 9457-style problem response",
        "content": {
          "application/problem+json": {
            "schema": { "$ref": "#/components/schemas/Problem" }
          }
        }
      }
    },
    "schemas": {
      "Sha256": {
        "type": "string",
        "pattern": "^sha256:[0-9a-f]{64}$",
        "examples": ["sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"]
      },
      "SubmissionState": {
        "type": "string",
        "enum": [
          "draft",
          "awaiting_human_confirmation",
          "submitted",
          "in_review",
          "changes_requested",
          "accepted",
          "declined",
          "withdrawn",
          "publishing",
          "published"
        ]
      },
      "ContributionKind": {
        "type": "string",
        "enum": [
          "new_work",
          "new_version",
          "research_effort",
          "effort_update",
          "fork",
          "evidence",
          "evaluation",
          "correction",
          "replication",
          "review",
          "status_update"
        ]
      },
      "Challenge": {
        "type": "object",
        "additionalProperties": false,
        "required": ["schema_version", "purpose", "token", "expires_at"],
        "properties": {
          "schema_version": { "type": "string", "const": "legalarxiv.submission-challenge.v1" },
          "purpose": { "type": "string", "enum": ["create", "confirm"] },
          "token": {
            "type": "string",
            "pattern": "^lax_c_[A-Za-z0-9_-]{43}$",
            "writeOnly": true
          },
          "expires_at": { "type": "string", "format": "date-time" },
          "binding": {
            "type": "object",
            "additionalProperties": false,
            "required": ["submission_id", "revision_id", "revision_sha256"],
            "properties": {
              "submission_id": { "type": "string" },
              "revision_id": { "type": "string" },
              "revision_sha256": { "$ref": "#/components/schemas/Sha256" }
            },
            "description": "Present only for a confirmation challenge."
          }
        }
      },
      "SubmissionDocument": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schema_version",
          "submission_type",
          "contribution_kind",
          "intent",
          "target",
          "identity",
          "research_boundary",
          "authors",
          "ai_disclosure",
          "artifacts",
          "rights",
          "contact",
          "terms"
        ],
        "properties": {
          "schema_version": { "type": "string", "const": "legalarxiv.submission.v1" },
          "submission_type": {
            "type": "string",
            "enum": ["release_candidate", "graph_contribution"],
            "description": "release_candidate is required for new_work, new_version, research_effort, effort_update, and fork; the remaining contribution kinds are graph_contribution."
          },
          "contribution_kind": { "$ref": "#/components/schemas/ContributionKind" },
          "intent": {
            "type": "string",
            "enum": ["request_publication", "request_review", "share_evidence", "seek_collaborators"]
          },
          "target": { "$ref": "#/components/schemas/SubmissionTarget" },
          "identity": { "$ref": "#/components/schemas/WorkIdentity" },
          "research_boundary": { "$ref": "#/components/schemas/ResearchBoundary" },
          "authors": {
            "type": "array",
            "minItems": 1,
            "maxItems": 200,
            "items": { "$ref": "#/components/schemas/Author" },
            "description": "At least one author must be corresponding. Positions must be contiguous and match array order."
          },
          "ai_disclosure": { "$ref": "#/components/schemas/AIDisclosure" },
          "artifacts": {
            "type": "array",
            "maxItems": 1,
            "items": { "$ref": "#/components/schemas/ArtifactDeclaration" },
            "description": "The pilot accepts at most one PDF. The declaration is metadata only; upload it using the returned upload instruction."
          },
          "rights": { "$ref": "#/components/schemas/RightsAssertion" },
          "contact": { "$ref": "#/components/schemas/Contact" },
          "terms": { "$ref": "#/components/schemas/TermsAcceptance" }
        }
      },
      "SubmissionTarget": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "work_id": { "type": "string", "minLength": 1, "maxLength": 256 },
          "version": { "type": "string", "minLength": 1, "maxLength": 64 },
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Absolute public HTTPS URL without credentials or an explicit port. Private, loopback, local, and internal hosts are rejected."
          }
        },
        "description": "May be empty only for new_work and research_effort. Other kinds must identify the receiving work, version, or public URL."
      },
      "WorkIdentity": {
        "type": "object",
        "additionalProperties": false,
        "required": ["title", "work_type", "language", "jurisdictions", "subjects", "external_identifiers"],
        "properties": {
          "title": { "type": "string", "minLength": 1, "maxLength": 4000 },
          "abstract": { "type": "string", "minLength": 1, "maxLength": 100000 },
          "work_type": { "type": "string", "minLength": 1, "maxLength": 200 },
          "language": { "type": "string", "minLength": 1, "maxLength": 32 },
          "jurisdictions": {
            "type": "array",
            "minItems": 1,
            "maxItems": 50,
            "items": { "type": "string", "minLength": 1, "maxLength": 500 }
          },
          "subjects": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "items": { "type": "string", "minLength": 1, "maxLength": 500 }
          },
          "external_identifiers": {
            "type": "array",
            "maxItems": 20,
            "items": { "$ref": "#/components/schemas/ExternalIdentifier" }
          }
        }
      },
      "ExternalIdentifier": {
        "type": "object",
        "additionalProperties": false,
        "required": ["scheme", "value"],
        "properties": {
          "scheme": { "type": "string", "enum": ["arxiv", "doi", "ssrn", "other"] },
          "value": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "DOI values must be lowercase."
          }
        }
      },
      "ResearchBoundary": {
        "type": "object",
        "additionalProperties": false,
        "required": ["primary_contribution", "scope_boundary", "material_limitations"],
        "properties": {
          "primary_contribution": { "type": "string", "minLength": 1, "maxLength": 20000 },
          "scope_boundary": { "type": "string", "minLength": 1, "maxLength": 20000 },
          "material_limitations": {
            "type": "array",
            "minItems": 1,
            "maxItems": 50,
            "items": { "type": "string", "minLength": 1, "maxLength": 2000 }
          }
        }
      },
      "Author": {
        "type": "object",
        "additionalProperties": false,
        "required": ["name", "position", "corresponding", "responsibility_scope"],
        "properties": {
          "name": { "type": "string", "minLength": 1, "maxLength": 500 },
          "affiliation": { "type": "string", "minLength": 1, "maxLength": 1000 },
          "orcid": { "type": "string", "pattern": "^\\d{4}-\\d{4}-\\d{4}-\\d{3}[\\dX]$" },
          "position": { "type": "integer", "minimum": 1 },
          "corresponding": { "type": "boolean" },
          "responsibility_scope": { "type": "string", "minLength": 1, "maxLength": 2000 }
        }
      },
      "AIDisclosure": {
        "type": "object",
        "additionalProperties": false,
        "required": ["use_class", "systems", "contributions"],
        "properties": {
          "use_class": { "type": "string", "enum": ["none", "assistive", "material"] },
          "systems": {
            "type": "array",
            "maxItems": 50,
            "items": { "$ref": "#/components/schemas/AISystem" }
          },
          "contributions": {
            "type": "array",
            "maxItems": 100,
            "items": { "$ref": "#/components/schemas/AIContribution" }
          }
        },
        "description": "none requires empty systems and contributions. assistive and material require at least one system. material also requires at least one specific contribution. Structural acceptance does not verify the substance of the disclosure."
      },
      "AISystem": {
        "type": "object",
        "additionalProperties": false,
        "required": ["provider", "name", "access_context"],
        "properties": {
          "provider": { "type": "string", "minLength": 1, "maxLength": 500 },
          "name": { "type": "string", "minLength": 1, "maxLength": 500 },
          "version": { "type": "string", "minLength": 1, "maxLength": 500 },
          "access_context": { "type": "string", "enum": ["public", "private", "internal", "unknown"] }
        }
      },
      "AIContribution": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "role",
          "description",
          "targets",
          "human_actions",
          "validation_state",
          "evidence_access",
          "selection_context",
          "known_limitations",
          "responsible_people"
        ],
        "properties": {
          "role": {
            "type": "string",
            "enum": [
              "claim_generation",
              "legal_reasoning",
              "source_retrieval",
              "drafting",
              "coding",
              "data_analysis",
              "counterexample",
              "review",
              "verification",
              "orchestration",
              "other"
            ]
          },
          "description": { "type": "string", "minLength": 1, "maxLength": 20000 },
          "targets": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "items": { "type": "string", "minLength": 1, "maxLength": 1000 }
          },
          "human_actions": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "items": { "type": "string", "minLength": 1, "maxLength": 2000 }
          },
          "validation_state": {
            "type": "string",
            "enum": ["not_evaluated", "submitter_checked", "independently_checked", "reproduced", "disputed"]
          },
          "evidence_access": {
            "type": "string",
            "enum": ["public", "reviewer_only", "withheld", "not_retained"]
          },
          "selection_context": { "type": "string", "minLength": 1, "maxLength": 10000 },
          "known_limitations": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "items": { "type": "string", "minLength": 1, "maxLength": 2000 }
          },
          "responsible_people": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "items": { "type": "string", "minLength": 1, "maxLength": 500 }
          }
        }
      },
      "ArtifactDeclaration": {
        "type": "object",
        "additionalProperties": false,
        "required": ["client_ref", "role", "filename", "media_type", "byte_length", "sha256"],
        "properties": {
          "client_ref": { "type": "string", "minLength": 1, "maxLength": 64 },
          "role": { "type": "string", "enum": ["manuscript", "evidence"] },
          "filename": {
            "type": "string",
            "minLength": 1,
            "maxLength": 180,
            "description": "Plain filename only; slash, backslash, dot, and dot-dot names are rejected."
          },
          "media_type": { "type": "string", "const": "application/pdf" },
          "byte_length": { "type": "integer", "minimum": 1, "maximum": 20971520 },
          "sha256": { "$ref": "#/components/schemas/Sha256" }
        }
      },
      "RightsAssertion": {
        "type": "object",
        "additionalProperties": false,
        "required": ["authority_basis", "confirmation"],
        "properties": {
          "authority_basis": {
            "type": "string",
            "enum": ["author", "authorized_agent", "license", "metadata_only", "other"]
          },
          "license": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2000,
            "description": "Required when authority_basis is license."
          },
          "confirmation": { "type": "boolean", "const": true }
        }
      },
      "Contact": {
        "type": "object",
        "additionalProperties": false,
        "required": ["name", "email"],
        "properties": {
          "name": { "type": "string", "minLength": 1, "maxLength": 500 },
          "email": { "type": "string", "format": "email", "maxLength": 320 }
        }
      },
      "TermsAcceptance": {
        "type": "object",
        "additionalProperties": false,
        "required": ["version", "accepted"],
        "properties": {
          "version": { "type": "string", "const": "legalarxiv.submission-terms.2026-08-30" },
          "accepted": { "type": "boolean", "const": true }
        }
      },
      "CreateSubmissionResult": {
        "type": "object",
        "additionalProperties": false,
        "oneOf": [
          { "required": ["management_token", "manage_url"] },
          { "required": ["human_confirmation"] }
        ],
        "required": [
          "state",
          "submission_id",
          "lifecycle_state",
          "revision",
          "revision_sha256",
          "current_revision",
          "api_url",
          "uploads",
          "notice"
        ],
        "properties": {
          "state": { "type": "string", "enum": ["created", "replayed"] },
          "submission_id": { "type": "string" },
          "lifecycle_state": { "$ref": "#/components/schemas/SubmissionState" },
          "revision": { "type": "integer", "minimum": 1 },
          "revision_sha256": { "$ref": "#/components/schemas/Sha256" },
          "current_revision": { "type": "integer", "minimum": 1 },
          "management_token": {
            "type": "string",
            "pattern": "^lax_s_[A-Za-z0-9_-]{43}$",
            "writeOnly": true,
            "description": "Reveal-on-create bearer capability. Store as a secret."
          },
          "manage_url": {
            "type": "string",
            "format": "uri",
            "writeOnly": true,
            "description": "Private human status URL with the management token in the fragment."
          },
          "human_confirmation": {
            "type": "object",
            "additionalProperties": false,
            "required": ["state", "contact", "notice"],
            "properties": {
              "state": { "type": "string", "const": "operator_delivery_required" },
              "contact": { "type": "string", "description": "Masked contact email." },
              "notice": { "type": "string" }
            },
            "description": "Machine responses never contain a human management capability."
          },
          "api_url": { "type": "string", "format": "uri" },
          "uploads": {
            "type": "array",
            "items": {
              "oneOf": [
                { "$ref": "#/components/schemas/ArtifactUploadInstruction" },
                { "$ref": "#/components/schemas/RevisionUploadInstruction" }
              ]
            }
          },
          "notice": { "type": "string" }
        }
      },
      "ArtifactUploadInstruction": {
        "type": "object",
        "additionalProperties": false,
        "required": ["artifact_id", "client_ref", "state", "method", "url", "authorization", "required_headers", "maximum_bytes"],
        "properties": {
          "artifact_id": { "type": "string" },
          "client_ref": { "type": "string" },
          "state": { "type": "string", "enum": ["awaiting_upload", "quarantined", "rejected"] },
          "method": { "type": "string", "const": "PUT" },
          "url": { "type": "string", "format": "uri" },
          "authorization": { "type": "string", "writeOnly": true },
          "required_headers": {
            "type": "object",
            "additionalProperties": false,
            "required": ["Content-Type", "X-Content-SHA256"],
            "properties": {
              "Content-Type": { "type": "string", "const": "application/pdf" },
              "X-Content-SHA256": { "$ref": "#/components/schemas/Sha256" }
            }
          },
          "maximum_bytes": { "type": "integer", "const": 20971520 }
        }
      },
      "CreateRevisionResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "state",
          "submission_id",
          "lifecycle_state",
          "revision",
          "revision_sha256",
          "current_revision",
          "api_url",
          "manage_url",
          "uploads",
          "requires_human_confirmation",
          "notice"
        ],
        "properties": {
          "state": { "type": "string", "enum": ["created", "replayed"] },
          "submission_id": { "type": "string" },
          "lifecycle_state": { "$ref": "#/components/schemas/SubmissionState" },
          "revision": { "type": "integer", "minimum": 2 },
          "revision_sha256": { "$ref": "#/components/schemas/Sha256" },
          "current_revision": { "type": "integer", "minimum": 1 },
          "api_url": { "type": "string", "format": "uri" },
          "manage_url": {
            "type": "string",
            "format": "uri",
            "description": "Token-free human status URL. Continue to retain the management capability separately."
          },
          "uploads": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/RevisionUploadInstruction" },
            "description": "Empty when an idempotent replay refers to a revision that is no longer the current draft."
          },
          "requires_human_confirmation": { "type": "boolean", "const": true },
          "notice": { "type": "string" }
        }
      },
      "RevisionUploadInstruction": {
        "type": "object",
        "additionalProperties": false,
        "required": ["artifact_id", "client_ref", "state", "method", "url", "authentication", "required_headers", "maximum_bytes"],
        "properties": {
          "artifact_id": { "type": "string" },
          "client_ref": { "type": "string" },
          "state": { "type": "string", "enum": ["awaiting_upload", "quarantined", "rejected"] },
          "method": { "type": "string", "const": "PUT" },
          "url": { "type": "string", "format": "uri" },
          "authentication": {
            "type": "object",
            "additionalProperties": false,
            "required": ["scheme", "credential"],
            "properties": {
              "scheme": { "type": "string", "const": "Bearer" },
              "credential": {
                "type": "string",
                "const": "Reuse the credential that authorized the revision request."
              }
            }
          },
          "required_headers": {
            "type": "object",
            "additionalProperties": false,
            "required": ["Content-Type", "X-Content-SHA256"],
            "properties": {
              "Content-Type": { "type": "string", "const": "application/pdf" },
              "X-Content-SHA256": { "$ref": "#/components/schemas/Sha256" }
            }
          },
          "maximum_bytes": { "type": "integer", "const": 20971520 }
        }
      },
      "ArtifactUploadResult": {
        "type": "object",
        "additionalProperties": false,
        "required": ["state", "artifact_id", "sha256", "scan_state"],
        "properties": {
          "state": { "type": "string", "enum": ["quarantined", "replayed"] },
          "artifact_id": { "type": "string" },
          "sha256": { "$ref": "#/components/schemas/Sha256" },
          "scan_state": { "type": "string", "enum": ["pending_manual_scan", "passed", "failed"] }
        }
      },
      "PrepareResult": {
        "type": "object",
        "additionalProperties": false,
        "required": ["state", "submission_id", "revision", "revision_sha256", "sealed_at"],
        "properties": {
          "state": { "type": "string", "enum": ["prepared", "replayed"] },
          "submission_id": { "type": "string" },
          "revision": { "type": "integer", "minimum": 1 },
          "revision_sha256": { "$ref": "#/components/schemas/Sha256" },
          "sealed_at": { "type": "string", "format": "date-time" }
        }
      },
      "ResponsibilityConfirmation": {
        "type": "object",
        "additionalProperties": false,
        "required": ["attestor_name", "attestor_email", "statement_accepted", "revision_id", "revision_number", "revision_sha256", "artifact_sha256s"],
        "properties": {
          "attestor_name": { "type": "string", "minLength": 1, "maxLength": 500 },
          "attestor_email": { "type": "string", "format": "email", "maxLength": 320 },
          "revision_id": { "type": "string", "pattern": "^subrev_[A-Za-z0-9_-]{27}$" },
          "revision_number": { "type": "integer", "minimum": 1 },
          "revision_sha256": { "$ref": "#/components/schemas/Sha256" },
          "artifact_sha256s": {
            "type": "array",
            "maxItems": 1,
            "items": { "$ref": "#/components/schemas/Sha256" },
            "description": "Exact sorted digest manifest displayed to the attestor."
          },
          "statement_accepted": {
            "type": "boolean",
            "const": true,
            "description": "Confirms responsibility for the sealed revision. This records a self-asserted, unverified identity statement."
          }
        }
      },
      "ConfirmationResult": {
        "type": "object",
        "additionalProperties": false,
        "required": ["state", "submission_id", "submitted_at"],
        "properties": {
          "state": { "type": "string", "enum": ["submitted", "replayed"] },
          "submission_id": { "type": "string" },
          "submitted_at": { "type": "string", "format": "date-time" },
          "revision_sha256": { "$ref": "#/components/schemas/Sha256" }
        }
      },
      "WithdrawalResult": {
        "type": "object",
        "additionalProperties": false,
        "required": ["state", "submission_id", "withdrawn_at"],
        "properties": {
          "state": { "type": "string", "enum": ["withdrawn", "replayed"] },
          "submission_id": { "type": "string" },
          "withdrawn_at": { "type": "string", "format": "date-time" }
        }
      },
      "SubmissionStatus": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schema_version",
          "id",
          "state",
          "submission_type",
          "contribution_kind",
          "title",
          "contact",
          "created_at",
          "updated_at",
          "retention_after",
          "current_revision",
          "confirmation_manifest",
          "artifacts",
          "checks",
          "required_actions",
          "decisions",
          "events",
          "links",
          "notice"
        ],
        "properties": {
          "schema_version": { "type": "string", "const": "legalarxiv.submission-status.v1" },
          "id": { "type": "string" },
          "state": { "$ref": "#/components/schemas/SubmissionState" },
          "submission_type": { "type": "string", "enum": ["release_candidate", "graph_contribution"] },
          "contribution_kind": { "$ref": "#/components/schemas/ContributionKind" },
          "title": { "type": "string" },
          "contact": { "$ref": "#/components/schemas/MaskedContact" },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" },
          "retention_after": {
            "type": "string",
            "format": "date-time",
            "description": "Earliest routine-retention review date, not a promise that immutable accountability evidence will be erased."
          },
          "current_revision": { "$ref": "#/components/schemas/CurrentRevision" },
          "confirmation_manifest": { "$ref": "#/components/schemas/ConfirmationManifest" },
          "artifacts": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/ArtifactStatus" }
          },
          "checks": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/FacetCheck" },
            "description": "Separate, inspectable facets. The gateway intentionally does not compute a composite trust score."
          },
          "required_actions": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/RequiredAction" }
          },
          "decisions": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/EditorialDecision" },
            "maxItems": 20
          },
          "events": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/SubmissionEvent" },
            "maxItems": 100
          },
          "links": { "$ref": "#/components/schemas/SubmissionLinks" },
          "notice": { "type": "string" }
        }
      },
      "MaskedContact": {
        "type": "object",
        "additionalProperties": false,
        "required": ["name", "email"],
        "properties": {
          "name": { "type": "string" },
          "email": { "type": "string", "description": "Masked email address." }
        }
      },
      "CurrentRevision": {
        "type": "object",
        "additionalProperties": false,
        "required": ["id", "number", "sha256", "created_at", "sealed_at", "attested_at", "document"],
        "properties": {
          "id": { "type": "string", "pattern": "^subrev_[A-Za-z0-9_-]{27}$" },
          "number": { "type": "integer", "minimum": 1 },
          "sha256": { "$ref": "#/components/schemas/Sha256" },
          "created_at": { "type": "string", "format": "date-time" },
          "sealed_at": { "type": ["string", "null"], "format": "date-time" },
          "attested_at": { "type": ["string", "null"], "format": "date-time" },
          "document": { "$ref": "#/components/schemas/SubmissionDocument" }
        }
      },
      "ConfirmationManifest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["submission_id", "revision_id", "revision_number", "revision_sha256", "artifact_sha256s", "sealed_at"],
        "properties": {
          "submission_id": { "type": "string" },
          "revision_id": { "type": "string" },
          "revision_number": { "type": "integer", "minimum": 1 },
          "revision_sha256": { "$ref": "#/components/schemas/Sha256" },
          "artifact_sha256s": { "type": "array", "maxItems": 1, "items": { "$ref": "#/components/schemas/Sha256" } },
          "sealed_at": { "type": ["string", "null"], "format": "date-time" }
        }
      },
      "ArtifactStatus": {
        "type": "object",
        "additionalProperties": false,
        "required": ["id", "client_ref", "role", "filename", "media_type", "byte_length", "sha256", "state", "scan_state", "screening", "upload", "download_url"],
        "properties": {
          "id": { "type": "string" },
          "client_ref": { "type": "string" },
          "role": { "type": "string", "enum": ["manuscript", "evidence"] },
          "filename": { "type": "string" },
          "media_type": { "type": "string", "const": "application/pdf" },
          "byte_length": { "type": "integer", "minimum": 1, "maximum": 20971520 },
          "sha256": { "$ref": "#/components/schemas/Sha256" },
          "state": { "type": "string", "enum": ["awaiting_upload", "quarantined", "rejected", "released"] },
          "scan_state": { "type": "string", "enum": ["not_uploaded", "pending_manual_scan", "passed", "failed"] },
          "screening": {
            "type": ["object", "null"],
            "additionalProperties": true,
            "description": "Immutable scanner/operator assessment pinned to artifact digest and R2 object identity, when present."
          },
          "upload": {
            "type": ["object", "null"],
            "additionalProperties": false,
            "required": ["method", "url", "required_headers", "maximum_bytes"],
            "properties": {
              "method": { "type": "string", "const": "PUT" },
              "url": { "type": "string", "format": "uri" },
              "required_headers": { "type": "object", "additionalProperties": { "type": "string" } },
              "maximum_bytes": { "type": "integer", "const": 20971520 }
            },
            "description": "Present only to a management-session caller while the current draft artifact still awaits its exact bytes."
          },
          "download_url": {
            "type": ["string", "null"],
            "format": "uri",
            "description": "Present only to a management-session caller for a current-revision artifact with an immutable passed safety assessment. Pending and failed artifacts are never offered."
          }
        }
      },
      "FacetCheck": {
        "type": "object",
        "additionalProperties": false,
        "required": ["facet", "state", "basis"],
        "properties": {
          "facet": {
            "type": "string",
            "enum": ["identity", "artifact_integrity", "artifact_safety", "rights", "ai_disclosure", "scholarly_evaluation", "preservation"]
          },
          "state": { "type": "string" },
          "basis": { "type": "string" }
        }
      },
      "RequiredAction": {
        "type": "object",
        "additionalProperties": false,
        "required": ["code", "message"],
        "properties": {
          "code": {
            "type": "string",
            "enum": ["upload_artifacts", "replace_artifact", "prepare_revision", "await_artifact_safety", "confirm_responsibility", "submit_revision"]
          },
          "message": { "type": "string" }
        }
      },
      "EditorialDecision": {
        "type": "object",
        "additionalProperties": false,
        "required": ["decision", "rationale", "decided_at"],
        "properties": {
          "decision": { "type": "string", "enum": ["begin_review", "request_changes", "accept", "decline"] },
          "rationale": { "type": "string" },
          "decided_at": { "type": "string", "format": "date-time" }
        }
      },
      "SubmissionEvent": {
        "type": "object",
        "additionalProperties": false,
        "required": ["id", "type", "actor_class", "occurred_at", "detail"],
        "properties": {
          "id": { "type": "string" },
          "type": { "type": "string" },
          "actor_class": { "type": "string", "enum": ["human", "machine", "operator", "system"] },
          "occurred_at": { "type": "string", "format": "date-time" },
          "detail": { "type": "object", "additionalProperties": true }
        }
      },
      "SubmissionLinks": {
        "type": "object",
        "additionalProperties": false,
        "required": ["self", "human"],
        "properties": {
          "self": { "type": "string", "format": "uri" },
          "human": { "type": "string", "format": "uri" }
        }
      },
      "Problem": {
        "type": "object",
        "additionalProperties": false,
        "required": ["type", "title", "status", "code", "request_id"],
        "properties": {
          "type": { "type": "string", "format": "uri" },
          "title": { "type": "string" },
          "status": { "type": "integer", "minimum": 400, "maximum": 599 },
          "code": { "type": "string" },
          "path": { "type": "string", "description": "JSON Pointer-like path for validation failures." },
          "request_id": { "type": "string", "format": "uuid" },
          "errors": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": ["pointer", "detail"],
              "properties": {
                "pointer": { "type": "string", "description": "JSON Pointer-like field path." },
                "detail": { "type": "string" }
              }
            }
          }
        }
      }
    }
  }
}
