{
  "openapi": "3.1.0",
  "info": {
    "title": "AI LearnOS Public & Protocol API",
    "version": "0.1.0",
    "description": "Authoritative OpenAPI 3.1 contract for AI Capability OS (AI LearnOS). Covers Public Verification, Share Grants, Enterprise Verification Standard (EVS), Billing, Learning Runtime, Opportunity Matching, and Organization Cohorts."
  },
  "servers": [
    {
      "url": "http://localhost:3000",
      "description": "Local Development Server"
    }
  ],
  "paths": {
    "/api/verify/{id}": {
      "get": {
        "summary": "Resolve Public Verification ID",
        "description": "Public, unauthenticated resolution of an issued credential, passport claim, or proof-of-skill. Returns issuer metadata, revocation status, evidence summary, and protocol version.",
        "operationId": "resolveVerification",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The opaque public verification ID (e.g. pvi_...)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Verification details successfully resolved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerificationResolution"
                }
              }
            }
          },
          "400": {
            "description": "Missing verification ID parameter.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Verification ID not found or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/share": {
      "get": {
        "summary": "Resolve Scoped Share Grant",
        "description": "Public resolution of a scoped learner passport share grant. Atomically increments view count and enforces time expiration and maximum view limits.",
        "operationId": "resolveShareGrant",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The share grant ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Share grant successfully resolved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResolvedShareGrant"
                }
              }
            }
          },
          "400": {
            "description": "Missing share ID query parameter.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Share grant expired, revoked, or max views exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create Scoped Share Grant",
        "description": "Authenticated learner generates a privacy-preserving, time-bounded or view-bounded share grant for their skill passport.",
        "operationId": "createShareGrant",
        "security": [{ "SessionAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateShareGrantRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Share grant created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateShareGrantResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/evs": {
      "post": {
        "summary": "Issue Enterprise Verification ID",
        "description": "Learner issues a fixed-scope Enterprise Verification Standard (EVS) ID for a specific enterprise organization.",
        "operationId": "issueEvs",
        "security": [{ "SessionAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IssueEvsRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "EVS ID successfully issued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IssueEvsResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/evs/resolve": {
      "post": {
        "summary": "Resolve Enterprise Verification ID",
        "description": "Enterprise organization verifies an employee or candidate's EVS token. Unconditionally logs verification access.",
        "operationId": "resolveEvs",
        "security": [{ "SessionAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResolveEvsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "EVS verified and scoped skills returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResolveEvsResponse"
                }
              }
            }
          },
          "403": {
            "description": "Unauthorized organization or insufficient role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "EVS ID not found or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/evs/revoke": {
      "post": {
        "summary": "Revoke Enterprise Verification ID",
        "description": "Learner immediately revokes an issued EVS token.",
        "operationId": "revokeEvs",
        "security": [{ "SessionAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["evsId"],
                "properties": {
                  "evsId": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "EVS successfully revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": { "type": "boolean" },
                    "evs": { "$ref": "#/components/schemas/EnterpriseVerificationRecord" }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/billing/plans": {
      "get": {
        "summary": "List Active Billing Plans",
        "description": "Public catalog of subscription plans and one-time credit packs with pricing in integer minor units.",
        "operationId": "listBillingPlans",
        "responses": {
          "200": {
            "description": "List of active plans.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "plans": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PlanCatalogItem"
                      }
                    }
                  },
                  "required": ["plans"]
                }
              }
            }
          }
        }
      }
    },
    "/api/billing/checkout": {
      "post": {
        "summary": "Create Checkout Session",
        "description": "Initiates payment checkout for a subscription or credit pack. Routes currency automatically (TWD -> NewebPay, non-TWD -> PayPal).",
        "operationId": "createCheckout",
        "security": [{ "SessionAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckoutRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Checkout session created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/network/leaderboard": {
      "get": {
        "summary": "Get Leaderboard Rankings",
        "description": "Public capability rankings across Free and Premium zones.",
        "operationId": "getLeaderboard",
        "parameters": [
          {
            "name": "zone",
            "in": "query",
            "required": false,
            "description": "Leaderboard zone (free | premium)",
            "schema": {
              "type": "string",
              "enum": ["free", "premium"],
              "default": "free"
            }
          },
          {
            "name": "skillNodeId",
            "in": "query",
            "required": false,
            "description": "Filter rankings by specific skill node ID",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of entries (1-100)",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Leaderboard entries.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "entries": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LeaderboardEntry"
                      }
                    }
                  },
                  "required": ["entries"]
                }
              }
            }
          }
        }
      }
    },
    "/api/network/teams": {
      "get": {
        "summary": "List Team Rankings",
        "description": "Lists collaborative team rankings within a leaderboard zone.",
        "operationId": "listTeams",
        "parameters": [
          {
            "name": "zone",
            "in": "query",
            "required": false,
            "schema": { "type": "string", "enum": ["free", "premium"], "default": "free" }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": { "type": "integer", "default": 20 }
          }
        ],
        "responses": {
          "200": {
            "description": "Team rankings.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "teams": { "type": "array", "items": { "$ref": "#/components/schemas/TeamRankingEntry" } }
                  },
                  "required": ["teams"]
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Manage Team Membership",
        "description": "Create, join, or leave a collaborative team.",
        "operationId": "manageTeam",
        "security": [{ "SessionAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TeamActionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Team operation successful.",
            "content": {
              "application/json": {
                "schema": { "type": "object", "properties": { "team": { "type": "object" } } }
              }
            }
          }
        }
      }
    },
    "/api/network/matches": {
      "get": {
        "summary": "List Opportunity Matches",
        "description": "Recomputes and returns privacy-preserving matched opportunities for the learner.",
        "operationId": "listMatches",
        "security": [{ "SessionAuth": [] }],
        "responses": {
          "200": {
            "description": "List of opportunity matches.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "matches": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/OpportunityMatch" }
                    }
                  },
                  "required": ["matches"]
                }
              }
            }
          }
        }
      }
    },
    "/api/network/matches/{id}/release": {
      "post": {
        "summary": "Release Opportunity Match Profile",
        "description": "Learner explicitly consents to reveal their verified identity and passport to the matched opportunity company.",
        "operationId": "releaseMatch",
        "security": [{ "SessionAuth": [] }],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "Match released.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "match": { "$ref": "#/components/schemas/OpportunityMatch" }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/org/opportunity-api-keys": {
      "get": {
        "summary": "List Opportunity Integration Keys",
        "description": "Lists non-secret metadata for an enterprise organization's machine credentials. Requires organization owner authority.",
        "operationId": "listOpportunityApiKeys",
        "security": [{ "SessionAuth": [] }],
        "parameters": [{
          "name": "organizationId",
          "in": "query",
          "required": true,
          "schema": { "type": "string" }
        }],
        "responses": {
          "200": {
            "description": "Non-secret API key metadata.",
            "content": { "application/json": { "schema": {
              "type": "object",
              "required": ["apiKeys"],
              "properties": { "apiKeys": { "type": "array", "items": { "$ref": "#/components/schemas/OpportunityApiKey" } } }
            } } }
          }
        }
      },
      "post": {
        "summary": "Create Opportunity Integration Key",
        "description": "Creates an expiring outcomes:write bearer credential. The token is returned exactly once and is never persisted in recoverable form.",
        "operationId": "createOpportunityApiKey",
        "security": [{ "SessionAuth": [] }],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateOpportunityApiKeyRequest" } } }
        },
        "responses": {
          "201": {
            "description": "Credential created; copy token immediately.",
            "headers": { "Cache-Control": { "schema": { "type": "string", "const": "no-store" } } },
            "content": { "application/json": { "schema": {
              "type": "object",
              "required": ["apiKey", "token"],
              "properties": {
                "apiKey": { "$ref": "#/components/schemas/OpportunityApiKey" },
                "token": { "type": "string", "pattern": "^isk_v1_" }
              }
            } } }
          }
        }
      }
    },
    "/api/org/opportunity-api-keys/{id}": {
      "delete": {
        "summary": "Revoke Opportunity Integration Key",
        "operationId": "revokeOpportunityApiKey",
        "security": [{ "SessionAuth": [] }],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "organizationId", "in": "query", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Credential revoked immediately." } }
      }
    },
    "/api/opportunities/outcomes": {
      "get": {
        "summary": "List Pending Opportunity Outcomes",
        "description": "Lists reports awaiting the authenticated learner's accept/decline decision.",
        "operationId": "listPendingOpportunityOutcomes",
        "security": [{ "SessionAuth": [] }],
        "responses": { "200": { "description": "Pending learner outcome inbox." } }
      },
      "post": {
        "summary": "Report or Decide an Opportunity Outcome",
        "description": "Providers may report only against their own released match. Reports become Passport evidence only after the learner accepts. M2M credentials support report actions only.",
        "operationId": "updateOpportunityOutcome",
        "security": [{ "SessionAuth": [] }, { "OpportunityApiKey": [] }],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OpportunityOutcomeAction" } } }
        },
        "responses": {
          "200": { "description": "Learner decision recorded." },
          "201": { "description": "Provider report recorded; awaiting learner decision." },
          "401": { "description": "Missing, invalid, expired or revoked credential." },
          "403": { "description": "Organization does not own the released opportunity match." },
          "429": { "description": "Per-IP or per-key rate limit exceeded." }
        }
      }
    },
    "/api/student-verification": {
      "post": {
        "summary": "Create Student Email Verification Session",
        "description": "Generates a cryptographic single-use verification token and pre-filled mailto: challenge link.",
        "operationId": "createStudentVerification",
        "security": [{ "SessionAuth": [] }],
        "responses": {
          "201": {
            "description": "Session created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StudentVerificationSessionResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (5 requests/hour or 10 requests/day).",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          }
        }
      }
    },
    "/api/student-verification/{id}/status": {
      "get": {
        "summary": "Get Student Verification Status",
        "description": "Polls verification status for a student verification session owned by the authenticated learner.",
        "operationId": "getStudentVerificationStatus",
        "security": [{ "SessionAuth": [] }],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "Session status.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StudentVerificationStatusResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/student-verification/{id}/cancel": {
      "post": {
        "summary": "Cancel Student Verification Session",
        "description": "Explicitly cancels an active pending student verification session.",
        "operationId": "cancelStudentVerification",
        "security": [{ "SessionAuth": [] }],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "Session cancelled.",
            "content": {
              "application/json": {
                "schema": { "type": "object", "properties": { "success": { "type": "boolean" } } }
              }
            }
          }
        }
      }
    },
    "/api/student-verification/{id}/retry": {
      "post": {
        "summary": "Retry Student Verification Session",
        "description": "Cancels prior session and returns a fresh mailto: link.",
        "operationId": "retryStudentVerification",
        "security": [{ "SessionAuth": [] }],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "201": {
            "description": "Fresh session created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StudentVerificationSessionResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/lms/login": {
      "get": {
        "summary": "Begin an LTI 1.3 OIDC Launch",
        "description": "Requires an existing IdeaStone session, creates user-bound one-time state and nonce, and redirects only to the authorization endpoint stored in the matching LMS registration.",
        "operationId": "beginLtiLogin",
        "security": [{ "SessionAuth": [] }],
        "parameters": [
          {
            "name": "iss",
            "in": "query",
            "required": true,
            "schema": { "type": "string", "format": "uri", "maxLength": 2048 }
          },
          {
            "name": "login_hint",
            "in": "query",
            "required": true,
            "schema": { "type": "string", "minLength": 1, "maxLength": 255 }
          },
          {
            "name": "target_link_uri",
            "in": "query",
            "required": true,
            "description": "Must exactly match the registered IdeaStone /api/lms/launch URL.",
            "schema": { "type": "string", "format": "uri", "maxLength": 2048 }
          },
          {
            "name": "client_id",
            "in": "query",
            "schema": { "type": "string", "minLength": 1, "maxLength": 255 }
          },
          {
            "name": "lti_deployment_id",
            "in": "query",
            "schema": { "type": "string", "minLength": 1, "maxLength": 255 }
          },
          {
            "name": "lti_message_hint",
            "in": "query",
            "schema": { "type": "string", "minLength": 1, "maxLength": 255 }
          }
        ],
        "responses": {
          "302": { "description": "Redirect to the fixed registered platform authorization endpoint." },
          "400": { "description": "Malformed initiation or unregistered target link URI." },
          "401": { "description": "An IdeaStone session is required before initiation." },
          "404": { "description": "No unique active LTI registration matched." },
          "429": { "description": "Per-account federated-login limit exceeded." },
          "503": { "description": "The matching LTI registration is incomplete or unsafe." }
        }
      }
    },
    "/api/lms/launch": {
      "post": {
        "summary": "Verify and Resolve an LTI 1.3 Resource Link Launch",
        "description": "Verifies an RS256 assertion against the registration's fixed JWKS URL, atomically consumes user-bound state/nonce, resolves a pre-linked assignment and identity, and writes a success audit event. This endpoint does not create an IdeaStone session.",
        "operationId": "resolveLtiLaunch",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": ["state", "id_token"],
                "properties": {
                  "state": { "type": "string", "minLength": 32, "maxLength": 512 },
                  "id_token": { "type": "string", "description": "Platform-signed LTI 1.3 JWT." }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verified, organization-scoped assignment launch.",
            "headers": {
              "Cache-Control": {
                "schema": { "type": "string", "const": "no-store" }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["courseId", "organizationId", "externalRole", "assignmentLinkId"],
                  "properties": {
                    "courseId": { "type": "string" },
                    "organizationId": { "type": "string" },
                    "externalRole": { "type": "string", "enum": ["learner", "instructor", "admin"] },
                    "assignmentLinkId": { "type": "string" }
                  }
                }
              }
            }
          },
          "400": { "description": "Missing or malformed form fields." },
          "401": { "description": "Invalid signature, registered key, or required LTI claim." },
          "403": { "description": "Expired/replayed state, identity mismatch, or assignment scope mismatch." },
          "404": { "description": "Registered connection was not found or is inactive." },
          "415": { "description": "Content-Type must be application/x-www-form-urlencoded." },
          "429": { "description": "Per-IP federated-launch limit exceeded." },
          "503": { "description": "Registered configuration or JWKS endpoint is temporarily unavailable." }
        }
      }
    },
    "/api/org/cohorts": {
      "get": {
        "summary": "List Organization Cohorts",
        "description": "Lists all cohorts in the organization.",
        "operationId": "listOrgCohorts",
        "security": [{ "SessionAuth": [] }],
        "parameters": [
          {
            "name": "orgId",
            "in": "query",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "List of cohorts.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "cohorts": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/CohortRecord" }
                    }
                  },
                  "required": ["cohorts"]
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create Organization Cohort",
        "description": "Manager creates a learner cohort.",
        "operationId": "createOrgCohort",
        "security": [{ "SessionAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCohortRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Cohort created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "cohort": { "$ref": "#/components/schemas/CohortRecord" }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/org/workforce-report": {
      "get": {
        "summary": "List Workforce Reports",
        "description": "Lists generated workforce reports for an organization.",
        "operationId": "listWorkforceReports",
        "security": [{ "SessionAuth": [] }],
        "parameters": [
          {
            "name": "orgId",
            "in": "query",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "List of reports.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "reports": { "type": "array", "items": { "type": "object" } },
                    "enabled": { "type": "boolean" }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Generate Workforce Report",
        "description": "Triggers skill intelligence analysis for an organization.",
        "operationId": "generateWorkforceReport",
        "security": [{ "SessionAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["orgId"],
                "properties": { "orgId": { "type": "string" } }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Report generated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "report": { "type": "object" }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/activities/{id}/assistance": {
      "post": {
        "summary": "Request Tutor Assistance",
        "description": "Requests scaffolding assistance during an activity with support-debt accounting.",
        "operationId": "requestAssistance",
        "security": [{ "SessionAuth": [] }],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssistanceRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Assistance event.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "event": { "type": "object" }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/activities/{id}/attempts": {
      "post": {
        "summary": "Record Activity Answer Attempt",
        "description": "Records answer attempt, evaluates mastery against student model, and performs diagnostic checks.",
        "operationId": "recordAttempt",
        "security": [{ "SessionAuth": [] }],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RecordAttemptRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Attempt recorded and evaluated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecordAttemptResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/sources": {
      "get": {
        "summary": "List Uploaded Sources",
        "description": "Lists source documents uploaded by the authenticated user.",
        "operationId": "listSources",
        "security": [{ "SessionAuth": [] }],
        "responses": {
          "200": {
            "description": "List of sources.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "documents": { "type": "array", "items": { "$ref": "#/components/schemas/SourceDocument" } }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Upload and Ingest Source Document",
        "description": "Uploads PDF/EPUB/DOCX/MD/URL file with provenance chunking.",
        "operationId": "uploadSource",
        "security": [{ "SessionAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["file", "sourceType"],
                "properties": {
                  "file": { "type": "string", "format": "binary" },
                  "sourceType": {
                    "type": "string",
                    "enum": ["pdf", "epub", "docx", "md", "url", "audio_transcript"]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Source ingested.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "document": { "$ref": "#/components/schemas/SourceDocument" }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/compile": {
      "get": {
        "summary": "List Compilation Jobs",
        "description": "Lists compilation jobs for the authenticated creator.",
        "operationId": "listCompileJobs",
        "security": [{ "SessionAuth": [] }],
        "responses": {
          "200": {
            "description": "List of jobs.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jobs": { "type": "array", "items": { "$ref": "#/components/schemas/CompileJob" } }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Dispatch Course Compilation",
        "description": "Dispatches compilation workflow for an ingested source document.",
        "operationId": "dispatchCompileJob",
        "security": [{ "SessionAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["documentId"],
                "properties": { "documentId": { "type": "string" } }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Compile job dispatched.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "job": { "$ref": "#/components/schemas/CompileJob" }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/admin/modules/{slug}/recompile": {
      "post": {
        "summary": "Generate a Reviewable Module Recompilation Candidate",
        "description": "Admin-only, paid specialist Module-engineering route. The response is schema-bound and review-required; this operation never edits source, deploys a Module, or mutates a published course.",
        "operationId": "recompileModuleCandidate",
        "security": [{ "SessionAuth": [] }],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Exact slug from the deployed Module catalog.",
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ModuleRecompileRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Schema-valid candidate generated; human review remains required.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ModuleRecompileResponse" }
              }
            }
          },
          "400": { "description": "Malformed request or props outside the Module schema.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } },
          "401": { "description": "No authenticated session.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } },
          "402": { "description": "Insufficient Premium points or configured budget.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } },
          "403": { "description": "Authenticated caller is not an administrator.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } },
          "404": { "description": "Module slug is not present in the deployed catalog.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } },
          "429": { "description": "Paid-compute admission limit exceeded.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } },
          "502": { "description": "Provider output failed the Module contract.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } },
          "503": { "description": "Module engineering policy or provider route unavailable.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "SessionAuth": {
        "type": "apiKey",
        "in": "cookie",
        "name": "better-auth.session_token",
        "description": "Better-Auth HTTP-only session cookie."
      },
      "OpportunityApiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "isk_v1",
        "description": "Expiring organization-scoped key with outcomes:write only."
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": { "type": "string" },
          "message": { "type": "string" },
          "status": { "type": "string" }
        }
      },
      "VerificationResolution": {
        "type": "object",
        "required": ["protocolVersion", "status", "verifiedAt"],
        "properties": {
          "protocolVersion": { "type": "string", "example": "0.1" },
          "status": {
            "type": "string",
            "enum": ["valid", "revoked", "expired", "not_found"]
          },
          "verificationId": { "type": "string" },
          "credentialId": { "type": "string" },
          "skillNodeId": { "type": "string" },
          "skillName": { "type": "string" },
          "levelClaimed": { "type": "string" },
          "kind": { "type": "string" },
          "issuedAt": { "type": "string", "format": "date-time" },
          "expiresAt": { "type": "string", "format": "date-time", "nullable": true },
          "revokedAt": { "type": "string", "format": "date-time", "nullable": true },
          "revokeReason": { "type": "string", "nullable": true },
          "issuer": {
            "type": "object",
            "nullable": true,
            "properties": {
              "id": { "type": "string" },
              "displayName": { "type": "string" },
              "authorityStatus": { "type": "string", "nullable": true }
            }
          },
          "evidenceSummary": {
            "type": "object",
            "properties": {
              "count": { "type": "integer" },
              "lastAt": { "type": "string", "format": "date-time" },
              "topSource": { "type": "string" }
            }
          },
          "verifiedAt": { "type": "string", "format": "date-time" }
        }
      },
      "CreateShareGrantRequest": {
        "type": "object",
        "required": ["expiresAt"],
        "properties": {
          "scope": {
            "type": "object",
            "properties": {
              "fullPassport": { "type": "boolean", "default": true },
              "skillNodeIds": { "type": "array", "items": { "type": "string" } }
            }
          },
          "expiresAt": { "type": "string", "format": "date-time" },
          "maxViews": { "type": "integer", "nullable": true, "minimum": 1 }
        }
      },
      "CreateShareGrantResponse": {
        "type": "object",
        "required": ["grant"],
        "properties": {
          "grant": {
            "type": "object",
            "properties": {
              "id": { "type": "string" },
              "userId": { "type": "string" },
              "scope": { "type": "object" },
              "expiresAt": { "type": "string", "format": "date-time" },
              "maxViews": { "type": "integer", "nullable": true },
              "viewCount": { "type": "integer" },
              "createdAt": { "type": "string", "format": "date-time" }
            }
          }
        }
      },
      "ResolvedShareGrant": {
        "type": "object",
        "required": ["grantId", "learner", "scope", "skills", "expiresAt", "viewsRemaining"],
        "properties": {
          "grantId": { "type": "string" },
          "learner": {
            "type": "object",
            "properties": {
              "displayName": { "type": "string" },
              "avatarUrl": { "type": "string", "nullable": true }
            }
          },
          "scope": { "type": "object" },
          "skills": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "skillNodeId": { "type": "string" },
                "name": { "type": "string" },
                "level": { "type": "string" },
                "evidenceCount": { "type": "integer" },
                "lastVerifiedAt": { "type": "string", "format": "date-time" }
              }
            }
          },
          "expiresAt": { "type": "string", "format": "date-time" },
          "viewsRemaining": { "type": "integer", "nullable": true }
        }
      },
      "IssueEvsRequest": {
        "type": "object",
        "required": ["orgId", "skillNodeIds"],
        "properties": {
          "orgId": { "type": "string" },
          "skillNodeIds": { "type": "array", "items": { "type": "string" }, "minItems": 1 }
        }
      },
      "IssueEvsResponse": {
        "type": "object",
        "required": ["evs"],
        "properties": {
          "evs": {
            "$ref": "#/components/schemas/EnterpriseVerificationRecord"
          }
        }
      },
      "EnterpriseVerificationRecord": {
        "type": "object",
        "required": ["id", "userId", "organizationId", "scopedSkillNodeIds", "createdAt"],
        "properties": {
          "id": { "type": "string" },
          "userId": { "type": "string" },
          "organizationId": { "type": "string" },
          "scopedSkillNodeIds": { "type": "array", "items": { "type": "string" } },
          "revokedAt": { "type": "string", "format": "date-time", "nullable": true },
          "createdAt": { "type": "string", "format": "date-time" }
        }
      },
      "ResolveEvsRequest": {
        "type": "object",
        "required": ["evsId", "orgId"],
        "properties": {
          "evsId": { "type": "string" },
          "orgId": { "type": "string" }
        }
      },
      "ResolveEvsResponse": {
        "type": "object",
        "required": ["valid", "evsId", "learnerId", "organizationId", "evsVersion", "issuer", "scopedSkills", "resolvedAt"],
        "properties": {
          "valid": { "type": "boolean" },
          "evsId": { "type": "string" },
          "learnerId": { "type": "string" },
          "organizationId": { "type": "string" },
          "evsVersion": {
            "type": "string",
            "description": "Protocol version of the resolution payload.",
            "enum": ["1.0"]
          },
          "issuer": {
            "type": "object",
            "nullable": true,
            "description": "Top-level credential issuer; null when the credential has no issuer.",
            "required": ["displayName", "tier"],
            "properties": {
              "displayName": { "type": "string" },
              "tier": { "type": "string", "enum": ["platform", "accredited", "community"] }
            }
          },
          "scopedSkills": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "skillNodeId",
                "skillName",
                "level",
                "historicalPeakLevel",
                "evidenceSummary",
                "confidenceBand",
                "lastVerifiedAt",
                "credentialValidity"
              ],
              "properties": {
                "skillNodeId": { "type": "string" },
                "skillName": { "type": "string" },
                "level": { "type": "string", "description": "Current SkillMasteryLevel." },
                "historicalPeakLevel": {
                  "type": "string",
                  "description": "Highest SkillMasteryLevel ever attained for this skill."
                },
                "evidenceSummary": {
                  "type": "object",
                  "properties": {
                    "count": { "type": "integer" },
                    "lastAt": { "type": "string", "format": "date-time" },
                    "topSource": { "type": "string" }
                  }
                },
                "confidenceBand": {
                  "type": "string",
                  "description": "Derived from evidence_confidence: < 0.4 = low, < 0.7 = medium, >= 0.7 = high.",
                  "enum": ["low", "medium", "high"]
                },
                "lastVerifiedAt": {
                  "type": "string",
                  "format": "date-time",
                  "nullable": true,
                  "description": "From learner_skill_state.last_verified_at; null when never verified."
                },
                "credentialValidity": {
                  "type": "boolean",
                  "description": "True iff an active non-revoked proof-of-skill credential exists for this skill."
                }
              }
            }
          },
          "resolvedAt": { "type": "string", "format": "date-time" }
        }
      },
      "PlanCatalogItem": {
        "type": "object",
        "required": ["key", "kind", "displayNameKey", "priceMinor", "currency", "isActive"],
        "properties": {
          "key": { "type": "string" },
          "kind": { "type": "string", "enum": ["subscription", "credit_pack"] },
          "displayNameKey": { "type": "string" },
          "priceMinor": { "type": "integer", "description": "Price in minor units (e.g. 33000 = 330.00 TWD)" },
          "currency": { "type": "string", "example": "TWD" },
          "monthlyPoints": { "type": "integer", "nullable": true },
          "pointsGrant": { "type": "integer", "nullable": true },
          "isActive": { "type": "boolean" }
        }
      },
      "CheckoutRequest": {
        "type": "object",
        "required": ["productKey"],
        "properties": {
          "productKey": { "type": "string" },
          "successUrl": { "type": "string", "format": "uri" },
          "cancelUrl": { "type": "string", "format": "uri" }
        }
      },
      "CheckoutResponse": {
        "type": "object",
        "properties": {
          "provider": { "type": "string", "enum": ["newebpay", "paypal"] },
          "actionUrl": { "type": "string" },
          "formParams": { "type": "object" },
          "checkoutUrl": { "type": "string" },
          "orderId": { "type": "string" }
        }
      },
      "LeaderboardEntry": {
        "type": "object",
        "required": ["rank", "userId", "displayName", "zone", "totalMasteryPoints", "skillsMastered"],
        "properties": {
          "rank": { "type": "integer" },
          "userId": { "type": "string" },
          "displayName": { "type": "string" },
          "zone": { "type": "string", "enum": ["free", "premium"] },
          "totalMasteryPoints": { "type": "integer" },
          "skillsMastered": { "type": "integer" },
          "topSkill": { "type": "string", "nullable": true }
        }
      },
      "TeamRankingEntry": {
        "type": "object",
        "required": ["rank", "teamId", "teamName", "memberCount", "totalPoints"],
        "properties": {
          "rank": { "type": "integer" },
          "teamId": { "type": "string" },
          "teamName": { "type": "string" },
          "memberCount": { "type": "integer" },
          "totalPoints": { "type": "integer" }
        }
      },
      "TeamActionRequest": {
        "type": "object",
        "required": ["action"],
        "properties": {
          "action": { "type": "string", "enum": ["create", "join", "leave"] },
          "name": { "type": "string" },
          "teamId": { "type": "string" }
        }
      },
      "OpportunityMatch": {
        "type": "object",
        "required": ["id", "companyName", "roleTitle", "matchScore", "matchedSkills", "status"],
        "properties": {
          "id": { "type": "string" },
          "companyName": { "type": "string" },
          "roleTitle": { "type": "string" },
          "matchScore": { "type": "number" },
          "matchedSkills": { "type": "array", "items": { "type": "string" } },
          "status": { "type": "string", "enum": ["pending_learner_release", "released"] },
          "releasedAt": { "type": "string", "format": "date-time", "nullable": true }
        }
      },
      "OpportunityApiKey": {
        "type": "object",
        "required": ["id", "organizationId", "label", "keyPrefix", "scopes", "createdAt", "expiresAt"],
        "properties": {
          "id": { "type": "string" },
          "organizationId": { "type": "string" },
          "label": { "type": "string" },
          "keyPrefix": { "type": "string" },
          "scopes": { "type": "array", "items": { "type": "string", "enum": ["outcomes:write"] } },
          "createdAt": { "type": "string", "format": "date-time" },
          "expiresAt": { "type": "string", "format": "date-time", "nullable": true },
          "lastUsedAt": { "type": "string", "format": "date-time", "nullable": true },
          "revokedAt": { "type": "string", "format": "date-time", "nullable": true }
        }
      },
      "CreateOpportunityApiKeyRequest": {
        "type": "object",
        "required": ["organizationId", "label"],
        "properties": {
          "organizationId": { "type": "string" },
          "label": { "type": "string", "minLength": 2, "maxLength": 80 },
          "expiresInDays": { "type": "integer", "minimum": 1, "maximum": 365, "default": 90 }
        }
      },
      "OpportunityOutcomeAction": {
        "oneOf": [
          {
            "type": "object",
            "required": ["action", "opportunityId", "userId", "outcomeKind"],
            "properties": {
              "action": { "const": "report" },
              "opportunityId": { "type": "string" },
              "userId": { "type": "string" },
              "organizationId": { "type": "string", "description": "Required for session reports; ignored only when absent for M2M reports." },
              "outcomeKind": { "type": "string", "enum": ["completed", "partially_completed", "withdrew", "not_selected", "ongoing"] },
              "observedCapabilities": { "type": "array", "maxItems": 50, "items": { "type": "object" } },
              "narrative": { "type": "string", "maxLength": 4000 }
            }
          },
          {
            "type": "object",
            "required": ["action", "outcomeId"],
            "properties": {
              "action": { "type": "string", "enum": ["accept", "decline"] },
              "outcomeId": { "type": "string" }
            }
          }
        ]
      },
      "StudentVerificationSessionResponse": {
        "type": "object",
        "required": ["id", "mailtoUrl", "expiresAt"],
        "properties": {
          "id": { "type": "string" },
          "mailtoUrl": { "type": "string" },
          "expiresAt": { "type": "string", "format": "date-time" }
        }
      },
      "StudentVerificationStatusResponse": {
        "type": "object",
        "required": ["sessionId", "status", "expiresAt"],
        "properties": {
          "sessionId": { "type": "string" },
          "status": { "type": "string", "enum": ["pending", "verified", "failed", "cancelled", "expired"] },
          "expiresAt": { "type": "string", "format": "date-time" },
          "verification": {
            "type": "object",
            "nullable": true,
            "properties": {
              "level": { "type": "string" },
              "institutionName": { "type": "string", "nullable": true },
              "domain": { "type": "string" },
              "verifiedAt": { "type": "string", "format": "date-time" },
              "expiresAt": { "type": "string", "format": "date-time" }
            }
          }
        }
      },
      "CohortRecord": {
        "type": "object",
        "required": ["id", "organizationId", "courseId", "name", "createdAt"],
        "properties": {
          "id": { "type": "string" },
          "organizationId": { "type": "string" },
          "courseId": { "type": "string" },
          "name": { "type": "string" },
          "createdAt": { "type": "string", "format": "date-time" }
        }
      },
      "CreateCohortRequest": {
        "type": "object",
        "required": ["orgId", "courseId", "name"],
        "properties": {
          "orgId": { "type": "string" },
          "courseId": { "type": "string" },
          "name": { "type": "string" }
        }
      },
      "AssistanceRequest": {
        "type": "object",
        "required": ["kind"],
        "properties": {
          "kind": { "type": "string", "enum": ["hint", "explanation", "remediation", "solution"] },
          "attemptId": { "type": "string" },
          "content": { "type": "string" }
        }
      },
      "RecordAttemptRequest": {
        "type": "object",
        "required": ["correct"],
        "properties": {
          "response": { "type": "object" },
          "correct": { "type": "boolean" },
          "score": { "type": "number" }
        }
      },
      "RecordAttemptResponse": {
        "type": "object",
        "required": ["attempt", "evidenceResult"],
        "properties": {
          "attempt": { "type": "object" },
          "evidenceResult": { "type": "object" },
          "diagnosis": { "type": "object", "nullable": true }
        }
      },
      "SourceDocument": {
        "type": "object",
        "required": ["id", "title", "sourceType", "status"],
        "properties": {
          "id": { "type": "string" },
          "title": { "type": "string" },
          "sourceType": { "type": "string" },
          "status": { "type": "string" },
          "chunkCount": { "type": "integer" }
        }
      },
      "CompileJob": {
        "type": "object",
        "required": ["id", "status"],
        "properties": {
          "id": { "type": "string" },
          "status": { "type": "string" },
          "courseId": { "type": "string", "nullable": true }
        }
      },
      "ModuleRecompileRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["objective"],
        "properties": {
          "objective": { "type": "string", "minLength": 20, "maxLength": 4000 },
          "currentProps": {
            "type": "object",
            "description": "Preview overrides; keys and values are validated against the selected Module's generated prop schema."
          },
          "locale": {
            "type": "string",
            "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})?$",
            "default": "en"
          }
        }
      },
      "ModuleRecompileCandidate": {
        "type": "object",
        "additionalProperties": false,
        "required": ["summary", "previewProps", "changes", "requiresCodeChange", "implementationPlan", "verificationChecklist", "risks"],
        "properties": {
          "summary": { "type": "string" },
          "previewProps": {
            "type": "object",
            "description": "Complete proposed preview override map, validated against the deployed Module schema."
          },
          "changes": {
            "type": "array",
            "maxItems": 30,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": ["target", "rationale"],
              "properties": {
                "target": { "type": "string" },
                "rationale": { "type": "string" }
              }
            }
          },
          "requiresCodeChange": { "type": "boolean" },
          "implementationPlan": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": ["area", "change", "acceptanceCriteria"],
              "properties": {
                "area": { "type": "string", "enum": ["component", "manifest", "accessibility", "security", "evidence", "tests"] },
                "change": { "type": "string" },
                "acceptanceCriteria": { "type": "string" }
              }
            }
          },
          "verificationChecklist": {
            "type": "array",
            "minItems": 1,
            "maxItems": 20,
            "items": { "type": "string" }
          },
          "risks": {
            "type": "array",
            "maxItems": 12,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": ["risk", "mitigation"],
              "properties": {
                "risk": { "type": "string" },
                "mitigation": { "type": "string" }
              }
            }
          }
        }
      },
      "ModuleRecompileResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": ["candidate", "invocation", "auditRecorded", "deployState"],
        "properties": {
          "candidate": { "$ref": "#/components/schemas/ModuleRecompileCandidate" },
          "invocation": {
            "type": "object",
            "required": ["id", "providerModel", "inputTokens", "outputTokens", "latencyMs", "premiumPointsCharged"],
            "properties": {
              "id": { "type": "string" },
              "providerModel": { "type": "string" },
              "inputTokens": { "type": "integer" },
              "outputTokens": { "type": "integer" },
              "latencyMs": { "type": "integer" },
              "premiumPointsCharged": { "type": "integer" }
            }
          },
          "auditRecorded": { "type": "boolean" },
          "deployState": { "type": "string", "const": "review_required" }
        }
      }
    }
  }
}
