{
  "task": "implement_source",
  "source_id": "demo",
  "protocol": "1",
  "language": "python",
  "topology": "standalone_gateway",
  "upstream": {
    "base_url_env": "DEMO_BASE_URL",
    "fixtures_dir": "testdata/upstream",
    "auth": "none",
    "notes": "所有上游字段只能来自 fixture 或官方文档，禁止猜测"
  },
  "required_pages": [
    "home.feed",
    "search",
    "detail",
    "player"
  ],
  "endpoints": {
    "search": { "upstream": "/search", "method": "GET" },
    "detail": { "upstream": "/item/{id}", "method": "GET" },
    "episodes": { "upstream": "/item/{id}/episodes", "method": "GET" },
    "play": { "upstream": "/item/{id}/play", "method": "POST" }
  },
  "endpoints": {
    "ui": "/v1/demo/ui_test.php",
    "feed": "/v1/demo/feed_test.php"
  },
  "decryptors": [
    { "id": "builtin:cenc-ctr", "algorithms": ["cenc-ctr"], "abi": 1 }
  ],
  "ui": {
    "home_tabs": [
      { "key": "home", "title": "精选", "channel": "home" },
      { "key": "series", "title": "连载", "channel": "series", "category_tag": "示例分类" }
    ],
    "labels": {
      "play": "播放",
      "play_full": "观看完整剧集 · 全{count}集",
      "detail.hot_label": "热度",
      "search.type_fallback": "内容"
    }
  },
  "auth": {
    "required": false,
    "methods": ["form"],
    "login": {
      "title": "示例登录",
      "description": "凭证只保存在服务端。",
      "method": "form",
      "submit_label": "登录",
      "fields": [
        { "key": "username", "label": "账号", "type": "text", "required": true },
        { "key": "password", "label": "密码", "type": "password", "required": true }
      ],
      "success_fields": ["user_id", "name", "avatar", "credentials"]
    }
  },
  "media": {
    "kind": "plain_mp4",
    "range": true,
    "notes": "asset 必须支持 Range；上游 URL 不能直接下发"
  },
  "acceptance": [
    "GET /v1/sources 返回 protocol=1",
    "GET /ui 只返回封闭页面类型，并遵守 X-Client-Pages",
    "空搜索返回 code 0 且 items 为空",
    "未知 detail 返回 40400",
    "play 至少返回一条 stream",
    "asset 对 bytes=0-255 返回 206 且包含 Content-Range",
    "未实现的可选能力返回 50100"
  ],
  "constraints": [
    "never expose upstream URLs; tokens/cookies may only appear in the login credentials object and must never be logged",
    "use sample data in tests, never production identifiers",
    "preserve 64-bit ids as strings",
    "every upstream call has a timeout",
    "do not invent page types or upstream constants",
    "do not modify the Flutter client"
  ],
  "deliverables": [
    "source service code",
    "testdata/upstream fixtures",
    "mapping unit tests",
    "endpoint self-check output",
    "not-implemented list"
  ]
}
