{
  "openapi": "3.1.0",
  "info": {
    "title": "Pi Daemon additive session API",
    "version": "1.0.0",
    "description": "Authenticated REST session lifecycle, bounded SHA-256 blob/session file transfer, WebSocket Pi RPC, and upstream Agent Client Protocol attachment. The existing owner-only Unix NDJSON protocol remains additive and equivalent at the logical-session layer."
  },
  "servers": [
    {
      "url": "http://127.0.0.1:7463/v1",
      "description": "Default loopback listener; the implementation may also expose the same HTTP routes over a Unix socket."
    }
  ],
  "security": [
    {
      "serviceBearer": []
    }
  ],
  "paths": {
    "/capabilities": {
      "get": {
        "operationId": "getCapabilities",
        "summary": "Negotiate API, transport, RPC, isolation, and authentication capabilities",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          }
        ],
        "responses": {
          "200": {
            "description": "Current host capabilities",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/capabilitiesEnvelope"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/session": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "listSessions",
        "summary": "List logical sessions without secret environment values",
        "parameters": [
          {
            "$ref": "#/components/parameters/PageCursor"
          },
          {
            "$ref": "#/components/parameters/PageLimit"
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": "array",
              "items": {
                "enum": [
                  "opening",
                  "idle",
                  "running",
                  "failed",
                  "closing"
                ]
              },
              "maxItems": 5
            },
            "style": "form",
            "explode": false
          }
        ],
        "responses": {
          "200": {
            "description": "One stable page ordered by session ID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/sessionListEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "post": {
        "operationId": "createSession",
        "summary": "Create one logical Pi runtime from a CLI-equivalent session specification",
        "description": "The server allocates the canonical session ID before returning a bounded retained ticket. Raw env values are memory-only and must never appear in the ticket, logs, metrics, manifests, journals, or session resource.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/WaitForTerminal"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "./session-api.schema.json#/$defs/sessionCreateRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Creation durably admitted or joined by idempotency key",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/ticketEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unsupported"
          },
          "429": {
            "$ref": "#/components/responses/Capacity"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/session/{sessionRef}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SessionRef"
        },
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "getSession",
        "summary": "Get a session by canonical ID or unique exact name",
        "responses": {
          "200": {
            "description": "Current session resource and attach links",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/sessionEnvelope"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      },
      "put": {
        "operationId": "replaceSessionSpec",
        "summary": "Replace a session specification with optimistic generation and revision checks",
        "description": "A cwd, target, agentDir, environment, resource, settings, or isolation change replaces the runtime and increments generation. In-place name or supported Pi state changes increment revision only. Busy replacements fail rather than racing a live turn.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          },
          {
            "$ref": "#/components/parameters/WaitForTerminal"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "./session-api.schema.json#/$defs/sessionUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Update admitted or joined",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/ticketEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unsupported"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      },
      "delete": {
        "operationId": "deleteSession",
        "summary": "Close a session and optionally delete retained artifacts",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          },
          {
            "name": "retainArtifacts",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": true
            }
          },
          {
            "$ref": "#/components/parameters/WaitForTerminal"
          }
        ],
        "responses": {
          "202": {
            "description": "Close admitted or joined",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/ticketEnvelope"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/session/{sessionRef}/blob": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SessionRef"
        },
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "post": {
        "operationId": "reserveSessionBlob",
        "summary": "Durably reserve one bounded opaque upload for an exact session generation",
        "description": "Declares untrusted name/MIME, exact byte size and lowercase SHA-256. The response is a durable idempotent ticket; no content, path or filesystem authority is accepted.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/WaitForTerminal"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "./session-api.schema.json#/$defs/blobReservationRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Mutation durably admitted or joined",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/ticketEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unsupported"
          },
          "429": {
            "$ref": "#/components/responses/Capacity"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/session/{sessionRef}/blob/{blobId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SessionRef"
        },
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/BlobId"
        },
        {
          "$ref": "#/components/parameters/Generation"
        }
      ],
      "get": {
        "operationId": "getSessionBlob",
        "summary": "Inspect bounded blob metadata without content",
        "responses": {
          "200": {
            "description": "Bounded blob metadata; content is never embedded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/blobTransferEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unsupported"
          },
          "429": {
            "$ref": "#/components/responses/Capacity"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      },
      "delete": {
        "operationId": "deleteSessionBlob",
        "summary": "Durably delete an unreferenced blob alias and prune its backing object when unused",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/WaitForTerminal"
          }
        ],
        "responses": {
          "202": {
            "description": "Mutation durably admitted or joined",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/ticketEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unsupported"
          },
          "429": {
            "$ref": "#/components/responses/Capacity"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/session/{sessionRef}/blob/{blobId}/content": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SessionRef"
        },
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/BlobId"
        },
        {
          "$ref": "#/components/parameters/Generation"
        }
      ],
      "put": {
        "operationId": "uploadSessionBlobContent",
        "summary": "Stream and verify reserved opaque content",
        "description": "Content-Length, actual bytes and SHA-256 must match the reservation. The same idempotency key can safely retry an interrupted reserved upload; settled or quarantined content is never blindly replaced.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/octet-stream": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Bounded blob metadata; content is never embedded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/blobTransferEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unsupported"
          },
          "429": {
            "$ref": "#/components/responses/Capacity"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      },
      "get": {
        "operationId": "downloadSessionBlobContent",
        "summary": "Download available non-quarantined opaque content",
        "responses": {
          "200": {
            "description": "Bounded opaque content download; declared MIME remains untrusted metadata",
            "headers": {
              "Digest": {
                "description": "Verified SHA-256 digest",
                "schema": {
                  "type": "string"
                }
              },
              "X-Pi-Untrusted-Media-Type": {
                "description": "Untrusted client-declared media type; never used as Content-Type",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unsupported"
          },
          "429": {
            "$ref": "#/components/responses/Capacity"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/session/{sessionRef}/file": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SessionRef"
        },
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "post": {
        "operationId": "materializeSessionBlob",
        "summary": "Durably create a daemon-chosen session upload reference",
        "description": "The body accepts only an authorized blob ID and exact generation. The daemon chooses uploads/<fileId> inside its owner-private session inbox; clients cannot supply cwd-relative or absolute paths.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/WaitForTerminal"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "./session-api.schema.json#/$defs/blobMaterializationRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Mutation durably admitted or joined",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/ticketEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unsupported"
          },
          "429": {
            "$ref": "#/components/responses/Capacity"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/session/{sessionRef}/file/{fileId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SessionRef"
        },
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/FileId"
        },
        {
          "$ref": "#/components/parameters/Generation"
        }
      ],
      "get": {
        "operationId": "getSessionUpload",
        "summary": "Inspect a daemon-owned session upload reference",
        "responses": {
          "200": {
            "description": "Daemon-chosen session upload reference metadata",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/sessionUploadEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unsupported"
          },
          "429": {
            "$ref": "#/components/responses/Capacity"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      },
      "delete": {
        "operationId": "deleteSessionUpload",
        "summary": "Durably delete a session upload reference",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/WaitForTerminal"
          }
        ],
        "responses": {
          "202": {
            "description": "Mutation durably admitted or joined",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/ticketEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unsupported"
          },
          "429": {
            "$ref": "#/components/responses/Capacity"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/session/{sessionRef}/file/{fileId}/content": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SessionRef"
        },
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/FileId"
        },
        {
          "$ref": "#/components/parameters/Generation"
        }
      ],
      "get": {
        "operationId": "downloadSessionUploadContent",
        "summary": "Download content through an exact session upload reference",
        "responses": {
          "200": {
            "description": "Bounded opaque content download; declared MIME remains untrusted metadata",
            "headers": {
              "Digest": {
                "description": "Verified SHA-256 digest",
                "schema": {
                  "type": "string"
                }
              },
              "X-Pi-Untrusted-Media-Type": {
                "description": "Untrusted client-declared media type; never used as Content-Type",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unsupported"
          },
          "429": {
            "$ref": "#/components/responses/Capacity"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/session/{sessionRef}/rpc": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SessionRef"
        },
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "name": "cursor",
          "in": "query",
          "required": false,
          "description": "Opaque framed-stream cursor scoped to host instance, session ID, and generation.",
          "schema": {
            "type": "string",
            "minLength": 1,
            "maxLength": 1024
          }
        },
        {
          "name": "generation",
          "in": "query",
          "required": false,
          "description": "Expected daemon session generation; stale values fail before upgrade.",
          "schema": {
            "type": "integer",
            "minimum": 0
          }
        },
        {
          "name": "hydrate",
          "in": "query",
          "required": false,
          "description": "Explicit trusted-service opt-in to reopen a retained durable session without prompting before attach. Omission preserves resident-only RPC behavior.",
          "schema": {
            "type": "boolean",
            "default": false
          }
        },
        {
          "name": "role",
          "in": "query",
          "required": false,
          "description": "Controller is a concurrency lease, not an authorization boundary; every attachment uses the same service bearer.",
          "schema": {
            "enum": [
              "observer",
              "controller"
            ],
            "default": "observer"
          }
        }
      ],
      "get": {
        "operationId": "attachPiRpc",
        "summary": "Upgrade to a raw or framed Pi RPC WebSocket attachment",
        "description": "Offer Sec-WebSocket-Protocol pi-rpc.v1 for live-only upstream Pi message shapes or pi-daemon-rpc.v1 for atomic snapshot, bounded replay, host identity, generation, and cursors. Trusted service clients may explicitly hydrate retained durable sessions without prompting; ordinary attaches remain resident-only. Responses are sent only to the issuing connection; AgentSession events fan out to all readers. Reject unacknowledged command replay after disconnect.",
        "parameters": [
          {
            "name": "Sec-WebSocket-Protocol",
            "in": "header",
            "required": true,
            "schema": {
              "enum": [
                "pi-rpc.v1",
                "pi-daemon-rpc.v1"
              ]
            }
          }
        ],
        "responses": {
          "101": {
            "description": "WebSocket protocol selected and attachment established"
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "426": {
            "$ref": "#/components/responses/UpgradeRequired"
          },
          "429": {
            "$ref": "#/components/responses/Capacity"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-websocket-client-message": {
          "oneOf": [
            {
              "$ref": "./session-api.schema.json#/$defs/piRpcCommand"
            },
            {
              "$ref": "./session-api.schema.json#/$defs/rpcCommandFrame"
            },
            {
              "$ref": "./session-api.schema.json#/$defs/rpcExtensionUiResponseFrame"
            },
            {
              "$ref": "./session-api.schema.json#/$defs/rpcControlFrame"
            }
          ]
        },
        "x-websocket-server-message": {
          "oneOf": [
            {
              "$ref": "./session-api.schema.json#/$defs/piRpcResponse"
            },
            {
              "$ref": "./session-api.schema.json#/$defs/piRpcEvent"
            },
            {
              "$ref": "./session-api.schema.json#/$defs/rpcResponseFrame"
            },
            {
              "$ref": "./session-api.schema.json#/$defs/rpcEventFrame"
            },
            {
              "$ref": "./session-api.schema.json#/$defs/rpcAttachReadyFrame"
            },
            {
              "$ref": "./session-api.schema.json#/$defs/rpcReplayGapFrame"
            },
            {
              "$ref": "./session-api.schema.json#/$defs/rpcControlFrame"
            }
          ]
        }
      }
    },
    "/session/{sessionRef}/apc": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SessionRef"
        },
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "attachAgentClientProtocol",
        "summary": "Upgrade to upstream Agent Client Protocol JSON-RPC 2.0",
        "description": "The v1 route is intentionally spelled /apc to preserve the operator contract, while the payload protocol is upstream ACP (Agent Client Protocol). This is one authenticated WebSocket transport for the existing logical session, not a distinct session owner or token domain.",
        "parameters": [
          {
            "name": "Sec-WebSocket-Protocol",
            "in": "header",
            "required": true,
            "schema": {
              "const": "agent-client-protocol.v1"
            }
          }
        ],
        "responses": {
          "101": {
            "description": "ACP JSON-RPC WebSocket established"
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "426": {
            "$ref": "#/components/responses/UpgradeRequired"
          },
          "429": {
            "$ref": "#/components/responses/Capacity"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-websocket-message": {
          "$ref": "./session-api.schema.json#/$defs/jsonRpcMessage"
        },
        "x-upstream-protocol": "Agent Client Protocol JSON-RPC 2.0"
      }
    },
    "/schedule": {
      "get": {
        "operationId": "listSchedules",
        "summary": "List durable schedules, optionally resolved by exact session reference",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "name": "session",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 256
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Schedule list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/scheduleListEnvelope"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/schedule/status": {
      "get": {
        "operationId": "getScheduleStatus",
        "summary": "Get content-free schedule status and next wake",
        "responses": {
          "200": {
            "description": "Schedule status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/scheduleStatusEnvelope"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/schedule/{scheduleId}": {
      "parameters": [
        {
          "name": "scheduleId",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$"
          }
        },
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "getSchedule",
        "responses": {
          "200": {
            "description": "Schedule and ETag",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/scheduleResourceEnvelope"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "post": {
        "operationId": "createSchedule",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Schedule created"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      },
      "put": {
        "operationId": "updateSchedule",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Schedule updated"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          }
        }
      },
      "delete": {
        "operationId": "deleteSchedule",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "Schedule deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          }
        }
      }
    },
    "/schedule/{scheduleId}/enable": {
      "post": {
        "operationId": "enableSchedule",
        "parameters": [
          {
            "name": "scheduleId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "Schedule enabled"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          }
        }
      }
    },
    "/schedule/{scheduleId}/disable": {
      "post": {
        "operationId": "disableSchedule",
        "parameters": [
          {
            "name": "scheduleId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "Schedule disabled"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          }
        }
      }
    },
    "/dashboard/capabilities": {
      "get": {
        "operationId": "getDashboardServiceCapabilities",
        "summary": "Negotiate neutral inventory, preview, ownership/export, lease, and TUI service capabilities",
        "responses": {
          "200": {
            "description": "Authenticated neutral Dash service capabilities",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/dashboardServiceCapabilitiesEnvelope"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/dashboard/diagnostics": {
      "get": {
        "operationId": "getDashboardServiceDiagnostics",
        "summary": "Read bounded allowlisted daemon policy and request-failure events",
        "description": "Server-to-server endpoint for the Dash BFF. Raw logs, prompts, model output, paths, credentials, environment values, and bearer material are never returned.",
        "responses": {
          "200": {
            "description": "Browser-safe diagnostics snapshot",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/dashboardDiagnosticsEnvelope"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        }
      }
    },
    "/dashboard/inventory": {
      "get": {
        "operationId": "listDashboardInventory",
        "summary": "List bounded preview-only managed and external Pi sessions",
        "parameters": [
          {
            "$ref": "#/components/parameters/PageCursor"
          },
          {
            "$ref": "#/components/parameters/PageLimit"
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 1024
            }
          },
          {
            "name": "sourceKind",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "runtime",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "unread",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "modifiedAfter",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stable opaque-cursor inventory page without canonical paths",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/dashboardInventoryEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/dashboard/inventory/{inventoryId}": {
      "parameters": [
        {
          "name": "inventoryId",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256
          }
        }
      ],
      "get": {
        "operationId": "getDashboardInventoryInfo",
        "summary": "Get authenticated source, ownership, runtime and diagnostics metadata",
        "responses": {
          "200": {
            "description": "Full safe inventory information; may include canonical source path",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/dashboardSessionInfoEnvelope"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/dashboard/inventory/{inventoryId}/transcript": {
      "parameters": [
        {
          "name": "inventoryId",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256
          }
        }
      ],
      "get": {
        "operationId": "getDashboardInventoryTranscript",
        "summary": "Return a bounded transcript or truthful source-unavailable empty state without runtime hydration",
        "parameters": [
          {
            "$ref": "#/components/parameters/PageCursor"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "direction",
            "in": "query",
            "schema": {
              "enum": [
                "older",
                "newer"
              ]
            }
          },
          {
            "name": "leafId",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 256
            }
          },
          {
            "name": "fingerprint",
            "in": "query",
            "schema": {
              "$ref": "./dashboard-api.schema.json#/$defs/fingerprint"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Identity-matched preview resource with availability, freshness, quarantine and observer-attach truth; unprojectable rows return records=[]",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/dashboardTranscriptEnvelope"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          }
        }
      }
    },
    "/dashboard/inventory/{inventoryId}/activate": {
      "parameters": [
        {
          "name": "inventoryId",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256
          }
        },
        {
          "$ref": "#/components/parameters/IdempotencyKey"
        }
      ],
      "post": {
        "operationId": "activateDashboardInventorySession",
        "summary": "Durably admit preview-only, reuse, direct co-opt, or fork/import activation",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "./dashboard-api.schema.json#/$defs/activationRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Durable activation ticket",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/dashboardActivationEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "429": {
            "$ref": "#/components/responses/Capacity"
          }
        }
      }
    },
    "/dashboard/activation/{ticketId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/TicketId"
        }
      ],
      "get": {
        "operationId": "getDashboardActivationTicket",
        "summary": "Inspect a durable activation ticket",
        "responses": {
          "200": {
            "description": "Activation ticket",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/dashboardActivationEnvelope"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/dashboard/session/{sessionRef}/export": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SessionRef"
        },
        {
          "$ref": "#/components/parameters/IdempotencyKey"
        }
      ],
      "post": {
        "operationId": "exportDashboardSession",
        "summary": "Durably export as new or guarded append-to-origin",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "./dashboard-api.schema.json#/$defs/exportRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Durable export ticket",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/dashboardExportEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          }
        }
      }
    },
    "/dashboard/export/{ticketId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/TicketId"
        }
      ],
      "get": {
        "operationId": "getDashboardExportTicket",
        "summary": "Inspect a durable export ticket",
        "responses": {
          "200": {
            "description": "Export ticket",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/dashboardExportEnvelope"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/dashboard/session/{sessionRef}/lease": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SessionRef"
        }
      ],
      "post": {
        "operationId": "renewDashboardOwnershipLease",
        "summary": "Renew the exact active cooperative ownership lease",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "./dashboard-api.schema.json#/$defs/dashboardLeaseRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Renewed lease",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/dashboardLeaseEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/dashboard/session/{sessionRef}/tui": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SessionRef"
        }
      ],
      "get": {
        "operationId": "attachDashboardTuiChannel",
        "summary": "Capability-gated server-side TUI channel",
        "x-websocket-subprotocol": "pi-daemon-tui.v1",
        "responses": {
          "101": {
            "description": "Authenticated TUI WebSocket attachment"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "426": {
            "$ref": "#/components/responses/UpgradeRequired"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          }
        }
      }
    },
    "/ticket": {
      "get": {
        "operationId": "getTicketByIdempotency",
        "summary": "Read a retained mutation ticket by idempotency scope",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "method",
            "in": "query",
            "required": true,
            "schema": {
              "enum": [
                "POST",
                "PUT",
                "DELETE",
                "WAKE"
              ]
            }
          },
          {
            "name": "target",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 4096
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current ticket for the exact method, canonical target, and idempotency key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/ticketEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/ticket/{ticketId}/reconcile": {
      "post": {
        "operationId": "reconcileTicket",
        "summary": "Explicitly resolve an indeterminate ticket after inspecting retained Pi entries",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "name": "ticketId",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "./session-api.schema.json#/$defs/identifier"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "requestId",
                  "state",
                  "evidence"
                ],
                "properties": {
                  "requestId": {
                    "$ref": "./session-api.schema.json#/$defs/identifier"
                  },
                  "state": {
                    "enum": [
                      "succeeded",
                      "failed"
                    ]
                  },
                  "error": {
                    "$ref": "./session-api.schema.json#/$defs/apiError"
                  },
                  "evidence": {
                    "type": "object",
                    "required": [
                      "piEntryIds"
                    ],
                    "properties": {
                      "piEntryIds": {
                        "type": "array",
                        "minItems": 1,
                        "maxItems": 256,
                        "items": {
                          "$ref": "./session-api.schema.json#/$defs/identifier"
                        }
                      }
                    },
                    "additionalProperties": false
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reconciled terminal ticket",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/ticketEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/ticket/{ticketId}": {
      "get": {
        "operationId": "getTicket",
        "summary": "Read a retained mutation ticket",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "name": "ticketId",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "./session-api.schema.json#/$defs/identifier"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current queued, running, terminal, or indeterminate state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./session-api.schema.json#/$defs/ticketEnvelope"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/dashboard/session-drafts": {
      "post": {
        "operationId": "createServiceDashboardSessionDraft",
        "summary": "Persist a validated no-runtime Dashboard session draft",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "./dashboard-session-draft.schema.json#/$defs/createRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Durable draft resource",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "./session-api.schema.json#/$defs/apiEnvelopeBase"
                    },
                    {
                      "type": "object",
                      "required": [
                        "data"
                      ],
                      "properties": {
                        "ok": {
                          "const": true
                        },
                        "data": {
                          "$ref": "./dashboard-session-draft.schema.json#/$defs/resource"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/Capacity"
          }
        }
      }
    },
    "/dashboard/session-drafts/{draftId}": {
      "parameters": [
        {
          "name": "draftId",
          "in": "path",
          "required": true,
          "description": "Opaque dashboard session draft ID",
          "schema": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
          }
        }
      ],
      "get": {
        "operationId": "getServiceDashboardSessionDraft",
        "summary": "Inspect a no-runtime Dashboard session draft",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          }
        ],
        "responses": {
          "200": {
            "description": "Draft resource",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "./session-api.schema.json#/$defs/apiEnvelopeBase"
                    },
                    {
                      "type": "object",
                      "required": [
                        "data"
                      ],
                      "properties": {
                        "ok": {
                          "const": true
                        },
                        "data": {
                          "$ref": "./dashboard-session-draft.schema.json#/$defs/resource"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "operationId": "cancelServiceDashboardSessionDraft",
        "summary": "Cancel a draft with optimistic revision and durable truth",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "./dashboard-session-draft.schema.json#/$defs/cancelRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cancelled or cancellation-indeterminate draft",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "./session-api.schema.json#/$defs/apiEnvelopeBase"
                    },
                    {
                      "type": "object",
                      "required": [
                        "data"
                      ],
                      "properties": {
                        "ok": {
                          "const": true
                        },
                        "data": {
                          "$ref": "./dashboard-session-draft.schema.json#/$defs/resource"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          }
        }
      }
    },
    "/dashboard/session-drafts/{draftId}/send": {
      "parameters": [
        {
          "name": "draftId",
          "in": "path",
          "required": true,
          "description": "Opaque dashboard session draft ID",
          "schema": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
          }
        }
      ],
      "post": {
        "operationId": "sendServiceDashboardSessionDraft",
        "summary": "Admit one exact-once first message through the injected materializer",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "./dashboard-session-draft.schema.json#/$defs/sendRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Durable first-send ticket",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "./session-api.schema.json#/$defs/apiEnvelopeBase"
                    },
                    {
                      "type": "object",
                      "required": [
                        "data"
                      ],
                      "properties": {
                        "ok": {
                          "const": true
                        },
                        "data": {
                          "$ref": "./dashboard-session-draft.schema.json#/$defs/sendTicket"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/dashboard/session-draft-send/{ticketId}": {
      "parameters": [
        {
          "name": "ticketId",
          "in": "path",
          "required": true,
          "description": "Durable dashboard first-send ticket ID",
          "schema": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
          }
        }
      ],
      "get": {
        "operationId": "getServiceDashboardSessionDraftSend",
        "summary": "Inspect first-send terminal or indeterminate truth",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          }
        ],
        "responses": {
          "200": {
            "description": "Current first-send ticket",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "./session-api.schema.json#/$defs/apiEnvelopeBase"
                    },
                    {
                      "type": "object",
                      "required": [
                        "data"
                      ],
                      "properties": {
                        "ok": {
                          "const": true
                        },
                        "data": {
                          "$ref": "./dashboard-session-draft.schema.json#/$defs/sendTicket"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "serviceBearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "opaque",
        "description": "One server-wide bearer for the complete HTTP/WebSocket API trust domain. It is not a per-session credential."
      }
    },
    "parameters": {
      "RequestId": {
        "name": "X-Request-Id",
        "in": "header",
        "required": false,
        "description": "Optional caller correlation ID. If a mutating JSON body also carries requestId, the values must match. The server generates one when absent.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128
        }
      },
      "SessionRef": {
        "name": "sessionRef",
        "in": "path",
        "required": true,
        "description": "URL-encoded canonical ID or unique exact session name. Ambiguity is a conflict, never first-match selection.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 512
        }
      },
      "WaitForTerminal": {
        "name": "waitForTerminal",
        "in": "query",
        "required": false,
        "description": "Convenience barrier: hold the ticket envelope until terminal instead of returning immediately after admission.",
        "schema": {
          "type": "boolean",
          "default": false
        }
      },
      "IfMatch": {
        "name": "If-Match",
        "in": "header",
        "required": true,
        "description": "Strong ETag returned by GET, derived from immutable session ID and revision without secret material.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256
        }
      },
      "PageCursor": {
        "name": "cursor",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 1024
        }
      },
      "PageLimit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 50
        }
      },
      "Generation": {
        "name": "generation",
        "in": "query",
        "required": true,
        "description": "Exact daemon session generation owning the blob or upload reference.",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      "BlobId": {
        "name": "blobId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^blob-[A-Za-z0-9_-]{43}$"
        }
      },
      "FileId": {
        "name": "fileId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^file-[A-Za-z0-9_-]{43}$"
        }
      }
    },
    "headers": {
      "Location": {
        "description": "Ticket or canonical session resource URL",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 4096
        }
      },
      "ETag": {
        "description": "Strong session revision validator",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256
        }
      }
    },
    "responses": {
      "InvalidRequest": {
        "description": "Malformed or semantically invalid request",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "./session-api.schema.json#/$defs/apiErrorEnvelope"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid service bearer; response never identifies sessions",
        "headers": {
          "WWW-Authenticate": {
            "schema": {
              "type": "string",
              "const": "Bearer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "./session-api.schema.json#/$defs/apiErrorEnvelope"
            }
          }
        }
      },
      "NotFound": {
        "description": "Session or ticket not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "./session-api.schema.json#/$defs/apiErrorEnvelope"
            }
          }
        }
      },
      "Conflict": {
        "description": "Name ambiguity, generation, idempotency, controller, or busy-state conflict",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "./session-api.schema.json#/$defs/apiErrorEnvelope"
            }
          }
        }
      },
      "PreconditionFailed": {
        "description": "ETag, expected revision, or expected generation does not match",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "./session-api.schema.json#/$defs/apiErrorEnvelope"
            }
          }
        }
      },
      "TooLarge": {
        "description": "Request body, environment, prompt, or frame exceeds a configured bound",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "./session-api.schema.json#/$defs/apiErrorEnvelope"
            }
          }
        }
      },
      "Unsupported": {
        "description": "Known Pi option, resource, isolation mode, or protocol feature is unsupported",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "./session-api.schema.json#/$defs/apiErrorEnvelope"
            }
          }
        }
      },
      "Capacity": {
        "description": "Connection, session, queue, ticket, or outbound capacity reached",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "./session-api.schema.json#/$defs/apiErrorEnvelope"
            }
          }
        }
      },
      "UpgradeRequired": {
        "description": "WebSocket upgrade or supported subprotocol required",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "./session-api.schema.json#/$defs/apiErrorEnvelope"
            }
          }
        }
      },
      "NotImplemented": {
        "description": "Capability is known but unavailable in this host configuration",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "./session-api.schema.json#/$defs/apiErrorEnvelope"
            }
          }
        }
      },
      "Unavailable": {
        "description": "Host not ready, draining, or temporarily unable to admit the operation",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "./session-api.schema.json#/$defs/apiErrorEnvelope"
            }
          }
        }
      }
    }
  }
}
