{
  "version": 1,
  "transport": {
    "httpsOnly": true,
    "tlsPin": "required",
    "defaultTimeoutMs": 15000,
    "maxBodyBytes": 33554432,
    "accept": "application/json",
    "contentType": "application/json when a body is present"
  },
  "envelope": {
    "wire": ["ok", "data", "error", "code"],
    "success": "ok true; data is the payload; error and code omitted",
    "error": "ok false; error message; code and data omitted when unused",
    "errorText": "diagnostic only; not an SDK compatibility surface",
    "codeContract": "machine-readable code is contractual when present; invalid_direction is the direction-error code",
    "clientUnwrap": "Agent returns data when ok; otherwise AgentError(message, status, code, data)",
    "streamException": "GET /api/v1/console/stream/{ticket} success is 101 Switching Protocols, not this envelope"
  },
  "omission": {
    "direction": {
      "omitted": "resolves to to_eve",
      "emptyString": "resolves to to_eve",
      "explicitToEve": "to_eve",
      "explicitFromEve": "from_eve",
      "wireDistinct": true,
      "invalid": "400 invalid_direction; auto/both/push/pull are not request values",
      "fromEveIsNotImport": true,
      "planIdentityScope": "opaque and direction-scoped; do not mix to_eve and from_eve identities"
    },
    "node": {
      "omitted": "all nodes",
      "emptyString": "all nodes",
      "named": "that IaC node key",
      "wireDistinct": true
    },
    "prune": {
      "omitted": "Go bool zero = false; extras are not deleted",
      "explicitFalse": "same semantic as omitted, distinct on the wire",
      "explicitTrue": "delete extra live objects on to_eve",
      "wireDistinct": true
    },
    "plan_identity": {
      "omitted": "recompute the live plan",
      "present": "opaque token from the last plan of the same direction",
      "mismatch": "409 plan_stale"
    },
    "wipe": {
      "omittedOnDestroy": "server pointer nil means wipe nodes (true)",
      "explicitFalse": "destroy lab without wiping nodes",
      "wireDistinct": true
    },
    "replace": {
      "omitted": "Go bool zero = false; existing managed lab returns 409 lab_exists",
      "explicitTrue": "stop/wipe/delete then recreate"
    },
    "refresh": {
      "omitted": "Go bool zero = false; inspect may use the session cache",
      "explicitTrue": "bypass inspect cache"
    },
    "stopmode": {
      "omitted": "lifecycle.DefaultStopMode (3, Vue auto)",
      "explicitZero": "graceful stop (0); distinct from omission",
      "values": "0=graceful 1=poweroff 2=hibernate 3=auto",
      "wireDistinct": true
    }
  },
  "unknownFields": {
    "login": "reject (encoding/json DisallowUnknownFields)",
    "project": "ignore (json.Decoder.Decode)",
    "authoring": "ignore",
    "console": "ignore",
    "logout": "unread; Agent sends {}"
  },
  "loadPayload": {
    "clientsShouldOmit": ["yaml", "files", "state"],
    "serverDoesNotRejectExtras": true,
    "note": "LOAD topology is read-only observation; desired-state files are not required on the wire"
  },
  "outOfScope": {
    "browserSession": "POST /api/v1/browser-session is on the Go mux and in docs/http-api.md. It is not in AGENT_OPS. Intentionally omitted from this SDK spec.",
    "browserBootstrap": "GET /browser/{token} is Vue bootstrap, not an Agent JSON op",
    "vueProxy": "non-/api/v1 reverse proxy to native EVE",
    "vscodeFs": "VS Code filesystem",
    "mcp": "MCP confirm/sanitize/cockpit",
    "pullPersistence": "client writing from_eve yaml is not a separate HTTP op",
    "nativeEve": "https://127.0.0.1 native REST is not a client API"
  },
  "publication": {
    "status": "pre-public",
    "afterPublication": "Once API v1 is published, v1 is append-only. Existing valid v1 calls and their semantics must never be changed incompatibly. v1 may gain new endpoints, capabilities, and backward-compatible optional fields. A breaking semantic or wire change requires a new API version."
  },
  "sdkSurface": {
    "direction": "Generated clients should expose Direction = to_eve | from_eve. The HTTP wire remains a free string so invalid values still produce 400 invalid_direction."
  },
  "operations": {
    "getHealth": {
      "agentOp": "health",
      "kind": "read",
      "auth": false,
      "authReplay": false,
      "timeoutMs": 15000,
      "unknownFields": "n/a",
      "decoder": "none"
    },
    "login": {
      "agentOp": "login",
      "kind": "session",
      "auth": false,
      "authReplay": false,
      "timeoutMs": 15000,
      "unknownFields": "reject",
      "decoder": "login",
      "httpsRequired": true
    },
    "logout": {
      "agentOp": "logout",
      "kind": "session",
      "auth": true,
      "authReplay": false,
      "timeoutMs": 15000,
      "unknownFields": "unread",
      "decoder": "none"
    },
    "getSession": {
      "agentOp": "session",
      "kind": "read",
      "auth": true,
      "authReplay": true,
      "timeoutMs": 15000,
      "unknownFields": "n/a",
      "decoder": "none"
    },
    "getCapabilities": {
      "agentOp": "capabilities",
      "kind": "read",
      "auth": true,
      "authReplay": true,
      "timeoutMs": 15000,
      "unknownFields": "n/a",
      "decoder": "none"
    },
    "listTemplates": {
      "agentOp": "templates",
      "kind": "read",
      "auth": true,
      "authReplay": true,
      "timeoutMs": 15000,
      "unknownFields": "n/a",
      "decoder": "none",
      "query": { "provisioned": "only the string true filters; omitted means all" }
    },
    "getTemplate": {
      "agentOp": "template",
      "kind": "read",
      "auth": true,
      "authReplay": true,
      "timeoutMs": 15000,
      "unknownFields": "n/a",
      "decoder": "none"
    },
    "listTemplateImages": {
      "agentOp": "templateImages",
      "kind": "read",
      "auth": true,
      "authReplay": true,
      "timeoutMs": 15000,
      "unknownFields": "n/a",
      "decoder": "none"
    },
    "listTemplateAttributes": {
      "agentOp": "templateAttributes",
      "kind": "read",
      "auth": true,
      "authReplay": true,
      "timeoutMs": 15000,
      "unknownFields": "n/a",
      "decoder": "none"
    },
    "listNetworkTypes": {
      "agentOp": "networkTypes",
      "kind": "read",
      "auth": true,
      "authReplay": true,
      "timeoutMs": 15000,
      "unknownFields": "n/a",
      "decoder": "none"
    },
    "listIcons": {
      "agentOp": "icons",
      "kind": "read",
      "auth": true,
      "authReplay": true,
      "timeoutMs": 15000,
      "unknownFields": "n/a",
      "decoder": "none"
    },
    "completeLinkInterfaces": {
      "agentOp": "linkCompletions",
      "kind": "read",
      "auth": true,
      "authReplay": true,
      "timeoutMs": 15000,
      "unknownFields": "ignore",
      "decoder": "authoring"
    },
    "previewInterfaces": {
      "agentOp": "interfaces",
      "kind": "read",
      "auth": true,
      "authReplay": true,
      "timeoutMs": 15000,
      "unknownFields": "ignore",
      "decoder": "authoring"
    },
    "validateProject": {
      "agentOp": "validate",
      "kind": "read",
      "auth": true,
      "authReplay": true,
      "timeoutMs": 15000,
      "unknownFields": "ignore",
      "decoder": "project"
    },
    "importProject": {
      "agentOp": "import",
      "kind": "mutation",
      "auth": true,
      "authReplay": false,
      "timeoutMs": 120000,
      "unknownFields": "ignore",
      "decoder": "project",
      "requiredFields": ["lab"],
      "note": "Clones source_lab into a managed working copy. Does not mutate source_lab. from_eve is not this operation."
    },
    "deployProject": {
      "agentOp": "deploy",
      "kind": "mutation",
      "auth": true,
      "authReplay": false,
      "timeoutMs": 300000,
      "unknownFields": "ignore",
      "decoder": "project"
    },
    "planProject": {
      "agentOp": "plan",
      "kind": "read",
      "auth": true,
      "authReplay": true,
      "timeoutMs": 180000,
      "unknownFields": "ignore",
      "decoder": "project",
      "note": "Dry-run. Omitted direction is to_eve. Never writes Local files or EVE."
    },
    "reconcileProject": {
      "agentOp": "reconcile",
      "kind": "mutation",
      "auth": true,
      "authReplay": false,
      "timeoutMs": 300000,
      "unknownFields": "ignore",
      "decoder": "project",
      "note": "to_eve mutates EVE. from_eve updates Local from the managed lab with no mutating EVE writes. from_eve is not Import."
    },
    "destroyProject": {
      "agentOp": "destroy",
      "kind": "mutation",
      "auth": true,
      "authReplay": false,
      "timeoutMs": 180000,
      "unknownFields": "ignore",
      "decoder": "project"
    },
    "getProjectStatus": {
      "agentOp": "status",
      "kind": "read",
      "auth": true,
      "authReplay": true,
      "timeoutMs": 15000,
      "unknownFields": "ignore",
      "decoder": "project"
    },
    "inspectProject": {
      "agentOp": "inspect",
      "kind": "read",
      "auth": true,
      "authReplay": true,
      "timeoutMs": 120000,
      "unknownFields": "ignore",
      "decoder": "project",
      "note": "Observation, not desired state."
    },
    "openProject": {
      "agentOp": "open",
      "kind": "read",
      "auth": true,
      "authReplay": true,
      "timeoutMs": 30000,
      "unknownFields": "ignore",
      "decoder": "project"
    },
    "listProjectConsoles": {
      "agentOp": "consoles",
      "kind": "read",
      "auth": true,
      "authReplay": true,
      "timeoutMs": 30000,
      "unknownFields": "ignore",
      "decoder": "project"
    },
    "execProject": {
      "agentOp": "exec",
      "kind": "mutation",
      "auth": true,
      "authReplay": false,
      "timeoutMs": 180000,
      "unknownFields": "ignore",
      "decoder": "project",
      "requiredFields": ["action"],
      "note": "action is start|stop|wipe. Omitted or empty node means all nodes. Success data is BulkResult with stable lowercase keys. Omitted stopmode is 3; explicit 0 is graceful."
    },
    "execConsole": {
      "agentOp": "consoleExec",
      "kind": "mutation",
      "auth": true,
      "authReplay": false,
      "timeoutMs": 15000,
      "unknownFields": "ignore",
      "decoder": "console"
    },
    "execConsoleMany": {
      "agentOp": "consoleExecMany",
      "kind": "mutation",
      "auth": true,
      "authReplay": false,
      "timeoutMs": 15000,
      "unknownFields": "ignore",
      "decoder": "console"
    },
    "attachConsole": {
      "agentOp": "consoleAttach",
      "kind": "mutation",
      "auth": true,
      "authReplay": false,
      "timeoutMs": 30000,
      "unknownFields": "ignore",
      "decoder": "console",
      "transport": "eve-telnet"
    },
    "streamConsole": {
      "agentOp": "consoleStream",
      "kind": "stream",
      "auth": true,
      "authReplay": false,
      "timeoutMs": 15000,
      "unknownFields": "n/a",
      "decoder": "none",
      "upgrade": "eve-telnet",
      "successStatus": 101,
      "ticket": "64-char lowercase hex; one-time; 30s TTL"
    }
  }
}
