{
  "openapi": "3.1.0",
  "info": {
    "title": "RightFlow Coordination API",
    "version": "0.1.0",
    "description": "RightFlow coordinates what should happen next among independent actors (humans, AI agents, robots, services).\n\n**Core principle: Assignment is not authority.**\nRightOS answers: What may this actor do?\nRightFlow answers: What should happen next?\nYour system answers: How will it actually be done?\n\nProposals (assign / reassign / swap) update coordination state only. `requiredRights` are a read-only gate against RightOS tokens on accept — they do not mint rights. Re-verify RightOS before real execution when policy requires.\n\n**Visibility ≠ necessity:** Organization-wide `list_*` endpoints are integrator/admin capabilities. Autonomous actors and AI should prefer `get_*`, scoped filters (e.g. `actorId`), and relationship lookups—not org-wide discovery as the default path. List APIs are retained.\n\n**Coordination tempo:** Shared coordination state should change relatively slowly. Prefer coarse, infrequent `progress` signals; keep high-frequency telemetry and internal execution detail local to the execution system.\n\nPair with `@i-s3/rightflow-mcp` and optional A2A-style peer messaging; keep `@i-s3/rightos-mcp` for rights. Do not collapse into one central agent.\n\nMonetary concepts (price, bid, pay, reward) are intentionally excluded. RightFlow does not dispatch vehicles, control robots, or mediate transport contracts.\n\nAuth: same organization API key as RightOS (`Authorization: Bearer rk_live_...` or `x-rightos-key`). Hosted v0.1 uses one organization API key. Cross-organization authority federation is not available yet.\n\nRate limits (approx.): 180 req/min per IP; 120 req/min per organization; 60 write req/min per organization. Exceeded → HTTP 429 `rate_limited` with `Retry-After`.\n\nThin client: /sdk/rightflow.ts"
  },
  "servers": [{ "url": "/", "description": "Same origin as RightOS" }],
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Organization API key (rk_live_...)"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": { "type": "string" },
          "message": { "type": "string" }
        }
      },
      "FlowActor": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "organizationId": { "type": "string" },
          "capabilities": {
            "type": "array",
            "items": { "type": "string" },
            "description": "Capability tokens, e.g. carry.light — no actor class enum"
          },
          "active": { "type": "boolean" },
          "createdAt": { "type": "string", "format": "date-time" },
          "updatedAt": { "type": "string", "format": "date-time" }
        }
      },
      "FlowTask": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "organizationId": { "type": "string" },
          "title": { "type": "string" },
          "description": { "type": "string" },
          "state": {
            "type": "string",
            "enum": [
              "open",
              "assigned",
              "in_progress",
              "completed",
              "failed",
              "cancelled"
            ]
          },
          "requiredCapabilities": {
            "type": "array",
            "items": { "type": "string" }
          },
          "requiredRights": {
            "type": "array",
            "items": { "type": "string" },
            "description": "RightOS token IDs checked on proposal accept (read-only gate)"
          },
          "dependencyIds": {
            "type": "array",
            "items": { "type": "string" }
          },
          "assignedActorId": { "type": "string" },
          "scheduledStartAt": { "type": "string", "format": "date-time" },
          "scheduledEndAt": { "type": "string", "format": "date-time" },
          "spatialRequirement": { "type": "object" },
          "progressPercent": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "description": "Coarse coordination signal 0–100. Not continuous telemetry."
          },
          "metadata": {
            "type": "object",
            "description": "Extension bag. Monetary keys are rejected."
          },
          "createdAt": { "type": "string", "format": "date-time" },
          "updatedAt": { "type": "string", "format": "date-time" }
        }
      },
      "FlowProposal": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "organizationId": { "type": "string" },
          "kind": {
            "type": "string",
            "enum": ["assignment", "reassignment", "swap"]
          },
          "state": {
            "type": "string",
            "enum": ["proposed", "accepted", "rejected", "invalidated"]
          },
          "taskId": { "type": "string" },
          "toActorId": { "type": "string" },
          "fromActorId": { "type": "string" },
          "assignments": { "type": "array" },
          "createdAt": { "type": "string", "format": "date-time" },
          "resolvedAt": { "type": "string", "format": "date-time" }
        }
      }
    }
  },
  "security": [{ "ApiKey": [] }],
  "paths": {
    "/api/rightflow/tasks": {
      "post": {
        "summary": "Create a FlowTask in open state",
        "operationId": "createTask",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["title"],
                "properties": {
                  "title": { "type": "string" },
                  "description": { "type": "string" },
                  "requiredCapabilities": {
                    "type": "array",
                    "items": { "type": "string" }
                  },
                  "requiredRights": {
                    "type": "array",
                    "items": { "type": "string" }
                  },
                  "dependencyIds": {
                    "type": "array",
                    "items": { "type": "string" }
                  },
                  "scheduledStartAt": { "type": "string", "format": "date-time" },
                  "scheduledEndAt": { "type": "string", "format": "date-time" },
                  "spatialRequirement": { "type": "object" },
                  "metadata": { "type": "object" }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": { "task": { "$ref": "#/components/schemas/FlowTask" } }
                }
              }
            }
          },
          "400": { "description": "invalid_request" },
          "409": { "description": "dependency_cycle | dependency_not_found" }
        }
      },
      "get": {
        "summary": "List tasks (integrator/admin; prefer get + actorId filter for actors)",
        "description": "Organization-wide listing is an integrator/admin capability. Autonomous actors should prefer GET /tasks/{taskId} or filter with actorId. Visibility does not imply every decision needs the full list.",
        "operationId": "listTasks",
        "parameters": [
          {
            "name": "state",
            "in": "query",
            "schema": { "type": "string" },
            "description": "Optional state filter"
          },
          {
            "name": "actorId",
            "in": "query",
            "schema": { "type": "string" },
            "description": "Prefer scoping to an assigned actor when listing for operational use"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tasks": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/FlowTask" }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/rightflow/tasks/{taskId}": {
      "get": {
        "summary": "Get a task",
        "operationId": "getTask",
        "parameters": [
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": { "description": "OK" },
          "404": { "description": "task_not_found" }
        }
      }
    },
    "/api/rightflow/tasks/{taskId}/transitions": {
      "post": {
        "summary": "Apply execution-state transition (start|progress|complete|fail|cancel)",
        "description": "Coordination transitions. Prefer coarse, infrequent progressPercent updates; keep high-frequency telemetry in the execution system (Coordination Tempo).",
        "operationId": "applyTransition",
        "parameters": [
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["action"],
                "properties": {
                  "action": {
                    "type": "string",
                    "enum": ["start", "progress", "complete", "fail", "cancel"]
                  },
                  "progressPercent": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Optional coarse progress 0–100. Not for continuous telemetry."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "OK" },
          "409": {
            "description": "invalid_transition | dependency_incomplete"
          }
        }
      }
    },
    "/api/rightflow/tasks/{taskId}/suggest-candidates": {
      "post": {
        "summary": "Reference who-next ranking (multi-signal; no auto-proposal)",
        "description": "Ranks candidate actors using coarse availability plus request-scoped softSignals (nearZone, busy). Soft signals are never persisted. engineId heuristic.v0 is a reference scorer only — not the sole optimizer; callers may rank externally and POST proposals. Prefer scoped actorIds (Principle §13). Does not create or accept proposals; re-check rights on accept/start.",
        "operationId": "suggestCandidates",
        "parameters": [
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "actorIds": {
                    "type": "array",
                    "items": { "type": "string" },
                    "description": "Prefer scoped candidates; omit only for integrator/admin org-wide rank."
                  },
                  "softSignals": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "object",
                      "properties": {
                        "nearZone": { "type": "string" },
                        "busy": { "type": "boolean" }
                      }
                    },
                    "description": "Request-scoped only; not continuous telemetry."
                  },
                  "engineId": {
                    "type": "string",
                    "description": "Optional label; default heuristic.v0"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Ranked candidates + draftProposal inputs (optional)" },
          "404": { "description": "task_not_found" },
          "409": { "description": "invalid_transition (task not assignable)" }
        }
      }
    },
    "/api/rightflow/actors": {
      "get": {
        "summary": "List actors (integrator/admin)",
        "description": "Organization-wide actor listing is an integrator/admin capability. Prefer getActor for normal lookups.",
        "operationId": "listActors",
        "responses": { "200": { "description": "OK" } }
      }
    },
    "/api/rightflow/actors/{actorId}": {
      "put": {
        "summary": "Upsert actor capabilities (idempotent)",
        "operationId": "upsertActor",
        "parameters": [
          {
            "name": "actorId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["capabilities"],
                "properties": {
                  "capabilities": {
                    "type": "array",
                    "items": { "type": "string" }
                  },
                  "active": { "type": "boolean" },
                  "availability": {
                    "type": "string",
                    "enum": ["available", "waiting", "unavailable"],
                    "description": "Coarse coordination fact (not high-frequency telemetry). waiting = volunteering for work."
                  }
                }
              }
            }
          }
        },
        "responses": { "200": { "description": "OK" } }
      },
      "get": {
        "summary": "Get actor",
        "operationId": "getActor",
        "parameters": [
          {
            "name": "actorId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": { "description": "OK" },
          "404": { "description": "actor_not_found" }
        }
      }
    },
    "/api/rightflow/proposals": {
      "post": {
        "summary": "Create assignment, reassignment, or swap proposal",
        "operationId": "createProposal",
        "description": "Neutral coordination language only. No bid/auction/pay.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["kind"],
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": ["assignment", "reassignment", "swap"]
                  },
                  "taskId": { "type": "string" },
                  "toActorId": { "type": "string" },
                  "fromActorId": { "type": "string" },
                  "assignments": {
                    "type": "array",
                    "minItems": 2,
                    "maxItems": 2,
                    "items": {
                      "type": "object",
                      "required": ["taskId", "fromActorId", "toActorId"],
                      "properties": {
                        "taskId": { "type": "string" },
                        "fromActorId": { "type": "string" },
                        "toActorId": { "type": "string" }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": { "description": "Created" },
          "409": { "description": "proposal_precondition_failed" }
        }
      },
      "get": {
        "summary": "List proposals (integrator/admin; prefer taskId filter)",
        "description": "Organization-wide proposal listing is an integrator/admin capability. Prefer filtering by taskId when resolving a specific interaction.",
        "operationId": "listProposals",
        "parameters": [
          {
            "name": "taskId",
            "in": "query",
            "schema": { "type": "string" }
          },
          {
            "name": "state",
            "in": "query",
            "schema": { "type": "string" }
          }
        ],
        "responses": { "200": { "description": "OK" } }
      }
    },
    "/api/rightflow/proposals/{proposalId}/accept": {
      "post": {
        "summary": "Accept proposal (capability + RightOS rights gate)",
        "operationId": "acceptProposal",
        "parameters": [
          {
            "name": "proposalId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": { "description": "Accepted; assignment committed in RightFlow" },
          "409": {
            "description": "capability_mismatch | required_right_unavailable | proposal_precondition_failed | ..."
          }
        }
      }
    },
    "/api/rightflow/proposals/{proposalId}/reject": {
      "post": {
        "summary": "Reject proposal",
        "operationId": "rejectProposal",
        "parameters": [
          {
            "name": "proposalId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": { "200": { "description": "Rejected" } }
      }
    },
    "/api/rightflow/safety-events": {
      "post": {
        "summary": "Record a post-hoc safety event and optionally reconcile tasks (L2)",
        "description": "Immediate safety action must already have happened in the execution system. RightFlow only audits and repairs coordination state. Does not control motors or e-stop.",
        "operationId": "recordSafetyEvent",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["kind", "source", "reconcileAction"],
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "e_stop",
                      "clinical_interrupt",
                      "collision_avoidance",
                      "device_interlock",
                      "other"
                    ]
                  },
                  "source": {
                    "type": "string",
                    "description": "Execution system identifier"
                  },
                  "taskIds": {
                    "type": "array",
                    "items": { "type": "string" }
                  },
                  "actorId": { "type": "string" },
                  "note": { "type": "string" },
                  "reconcileAction": {
                    "type": "string",
                    "enum": ["none", "fail_tasks", "cancel_tasks"]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": { "description": "Safety event recorded" },
          "400": { "description": "Invalid request" },
          "404": { "description": "Task not found" }
        }
      }
    },
    "/api/rightflow/lab/attempt-execute": {
      "post": {
        "summary": "Facility Handoff Lab — execution simulator (L1)",
        "description": "Wraps the reference execution adapter: re-checks requiredRights for an assigned task. Not a motion controller. Used by /software/rightflow/lab.",
        "operationId": "labAttemptExecute",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["taskId"],
                "properties": {
                  "taskId": { "type": "string" },
                  "reconcileStale": {
                    "type": "boolean",
                    "description": "If true and rights fail, mark task failed"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "{ result: ExecutionAttempt }" },
          "400": { "description": "invalid_request" },
          "404": { "description": "task_not_found" }
        }
      }
    }
  }
}
