{
  "schemaVersion": 3,
  "package": {
    "name": "@xmobitea/gn-typescript-client",
    "entryPoint": "GNNetwork",
    "installCommand": "npm install @xmobitea/gn-typescript-client",
    "typesEntry": "dist/index.d.ts",
    "runtimeEntry": "dist/index.js"
  },
  "docs": {
    "readingOrderForAi": [
      "docs/AI_CHEATSHEET.md",
      "docs/RULES.md",
      "docs/ai-manifest.json",
      "docs/reference/API_INDEX.md",
      "docs/reference/ERROR_HANDLING.md",
      "docs/reference/CONFIG.md",
      "docs/reference/EVENTS.md",
      "docs/reference/ENUMS.md",
      "docs/COOKBOOK.md"
    ],
    "entryPoints": {
      "cheatsheet": "docs/AI_CHEATSHEET.md",
      "rules": "docs/RULES.md",
      "agentGuide": "AGENTS.md",
      "llmstxtIndex": "llms.txt",
      "fullBundle": "docs/llms-full.txt"
    },
    "reference": {
      "apiIndex": "docs/reference/API_INDEX.md",
      "dtoIndex": "docs/reference/DTO_INDEX.md",
      "dtoDirectory": "docs/reference/dto",
      "enums": "docs/reference/ENUMS.md",
      "config": "docs/reference/CONFIG.md",
      "events": "docs/reference/EVENTS.md",
      "errorHandling": "docs/reference/ERROR_HANDLING.md",
      "permissionRules": "docs/reference/PERMISSION_RULES.md"
    },
    "cookbook": "docs/COOKBOOK.md",
    "guidesDirectory": "docs/guides",
    "guidanceForAiConsumer": [
      "đọc docs/AI_CHEATSHEET.md trước (one-page) để biết file nào cần mở tiếp",
      "đọc docs/RULES.md cho rule cross-cutting (route, permission, self/other-self, socket, error)",
      "tra method signature qua docs/reference/API_<GROUP>.md",
      "tra DTO field qua docs/reference/dto/<DOMAIN>.md hoặc grep DTO_INDEX.md (2506 rows, đừng load full)",
      "tra enum value numeric qua docs/reference/ENUMS.md",
      "scenario end-to-end xem docs/COOKBOOK.md (16 scenarios)",
      "chỉ fall back đọc dist/*.d.ts khi câu hỏi nằm ngoài scope docs",
      "docs/llms-full.txt là generated bundle optional; không dùng làm source thắng khi mâu thuẫn với source docs"
    ]
  },
  "globalRules": {
    "preferAsyncAwait": true,
    "requireInitBeforeAnyApiCall": true,
    "initMethod": "GNNetwork.init(settings)",
    "initStrategy": "once_per_app_session",
    "repeatInitBehavior": "ignored",
    "successCodeCheckOrder": [
      "returnCode",
      "errorCode"
    ],
    "successCodes": {
      "returnCodeOk": 1,
      "errorCodeOk": 1
    },
    "doNotAssumeSuccessIsZero": true,
    "doNotReadSrcForNormalPackageUsage": true,
    "responseFieldAccess": "public_fields_not_getters"
  },
  "returnCodeMeanings": {
    "Ok": "success, sang tầng errorCode để check business",
    "OperationTimeout": "timeout từ SDK hoặc backend; retry với backoff nếu operation idempotent",
    "OperationNotAllow": "secretKey hợp lệ nhưng permission rules không cho phép operation trong target context; check route + flag self/other/server/admin",
    "InternalServerError": "backend exception; có thể retry 1 lần rồi escalate",
    "OperationInvalid": "operation code không tồn tại hoặc không hợp lệ với request type/role",
    "InvalidRequestParameters": "request shape sai; đọc res.invalidMembers",
    "OperationNotAuthorized": "caller chưa auth; refresh token hoặc re-login",
    "MaxCCUReject": "vượt CCU limit; backoff retry",
    "MaxRequestReject": "rate limit; exponential backoff",
    "MaxSizeRequestReject": "payload vượt size; paginate hoặc split",
    "SecretInvalid": "secretKey sai, thiếu, hoặc không khớp game; KHÔNG retry, fix config"
  },
  "routing": {
    "principle": "trust_boundary",
    "client": "code chạy trong app hoặc player client",
    "server": "code chạy trong trusted backend như game server, internal service, worker, cron hoặc webhook backend",
    "admin": "code chạy trong backoffice, dashboard, GM tool, migration tool hoặc vận hành dữ liệu",
    "rules": [
      "không chọn server hoặc admin chỉ vì target không thuộc user hiện tại",
      "không dùng namespace server hoặc admin từ app client chỉ để vượt permission",
      "không suy diễn route chỉ từ việc request có hay không có userId"
    ]
  },
  "permissionRules": {
    "authoritativeDoc": "docs/reference/PERMISSION_RULES.md",
    "externalReference": "https://docs.gearn.net/permissionRules",
    "note": "Backend GearN Server/dashboard là runtime source-of-truth per-operation. Trong repo, dùng docs/reference/PERMISSION_RULES.md và docs/reference/API_<GROUP>.md để lấy operation name và mapping flag; externalReference chỉ là mirror khi cần đối chiếu online.",
    "selfOtherSelfOnlyApplyOnClientRoute": true,
    "flags": {
      "selfEnable": "cho phép thực thi trên chính tài nguyên thuộc user đã authenticate",
      "otherSelfEnable": "cho phép thực thi trên tài nguyên không thuộc user đã authenticate",
      "serverSelfEnable": "cho phép thực thi qua route server",
      "adminSelfEnable": "cho phép thực thi qua route admin"
    },
    "routeToFlagMapping": [
      { "callerNamespace": "GNNetwork.<group>.<method>()",        "route": "client", "target": "self",       "requiredFlag": "selfEnable" },
      { "callerNamespace": "GNNetwork.<group>.<method>(otherId)", "route": "client", "target": "other-self", "requiredFlag": "otherSelfEnable" },
      { "callerNamespace": "GNNetwork.<group>.server.<method>()", "route": "server", "target": "*",          "requiredFlag": "serverSelfEnable" },
      { "callerNamespace": "GNNetwork.<group>.admin.<method>()",  "route": "admin",  "target": "*",          "requiredFlag": "adminSelfEnable" }
    ],
    "configOwnership": {
      "configuredBy": "backend_admin_on_gearn_dashboard",
      "configGranularity": "per secretKey x per operation x per flag",
      "clientCanChange": false,
      "recommendedActionOnOperationNotAllow": [
        "dùng secretKey khác qua GNServerSettings.secretKey",
        "truyền overrideSecretKey per-request",
        "yêu cầu backend admin bật flag cho secret hiện tại trong GearN Dashboard"
      ]
    },
    "selfSemantics": {
      "masterPlayerAndGamePlayer": "target userId trùng userId đã authenticate thành công",
      "characterPlayerInventoryGroup": "entity target thuộc ownership của GamePlayer có userId trùng userId đã authenticate",
      "domainsWithoutClearOwnership": [
        "ContentApi",
        "StoreInventoryApi",
        "MultiplayerApi",
        "CloudScriptApi"
      ]
    },
    "operationNotAllowChecklist": [
      "xác định route đang gọi: client hay .server hay .admin",
      "xác định target self hay other-self theo self-semantics của domain",
      "tra routeToFlagMapping ra flag cần",
      "check secretKey active có flag đó cho operation này không (xem backend dashboard hoặc hỏi admin)",
      "nếu không có: dùng secret khác, overrideSecretKey, hoặc yêu cầu backend admin bật flag trong GearN Dashboard",
      "KHÔNG retry - đây là config fix"
    ],
    "diagnoseWorkflow": "docs/COOKBOOK.md#scenario-16-diagnose-operationnotallow"
  },
  "authAndSocket": {
    "flow": [
      "login hoặc refresh token qua HTTP",
      "sau khi SDK đã có authToken, nếu cần realtime thì gọi GNNetwork.connectSocket()",
      "nếu socket connect khi token đã có trong cache, SDK sẽ tự auth socket",
      "chỉ gọi GNNetwork.sendRequestAuthSocket() khi cần re-auth thủ công"
    ],
    "rules": [
      "không gộp auth socket với auth HTTP",
      "không bắt buộc gọi tay sendRequestAuthSocket sau mọi lần connectSocket",
      "nếu socket connect trước khi token xuất hiện hoặc token vừa đổi và không muốn reconnect thì mới gọi sendRequestAuthSocket"
    ]
  },
  "dashboardSpecialCase": {
    "apiGroup": "DashboardApi",
    "publicWrapperRequestRole": "Client",
    "backendAuthBehavior": "sau loginByAdminAccountAsync thành công, backend middleware resolve secret context và quyền admin riêng từ authToken",
    "emptyPublicNamespaces": [
      "GNNetwork.dashboard.server",
      "GNNetwork.dashboard.admin"
    ]
  },
  "enums": {
    "docPath": "docs/reference/ENUMS.md",
    "list": [
      { "name": "ReturnCode", "anchor": "returncode", "okValue": 1, "role": "transport" },
      { "name": "ErrorCode", "anchor": "errorcode", "okValue": 1, "role": "domain" },
      { "name": "RequestRole", "anchor": "requestrole" },
      { "name": "RequestType", "anchor": "requesttype" },
      { "name": "MessageType", "anchor": "messagetype" },
      { "name": "PostType", "anchor": "posttype" },
      { "name": "LogType", "anchor": "logtype" },
      { "name": "FriendStatus", "anchor": "friendstatus" },
      { "name": "GroupStatus", "anchor": "groupstatus" },
      { "name": "GoogleLoginType", "anchor": "googlelogintype" },
      { "name": "InvalidMemberType", "anchor": "invalidmembertype" },
      { "name": "ItemType", "anchor": "itemtype" },
      { "name": "OwnerType", "anchor": "ownertype" },
      { "name": "PushPlatformType", "anchor": "pushplatformtype" },
      { "name": "MatchmakingMemberStatus", "anchor": "matchmakingmemberstatus" },
      { "name": "MatchmakingTicketStatus", "anchor": "matchmakingticketstatus" },
      { "name": "MatchStatus", "anchor": "matchstatus" },
      { "name": "ExecuteResponseStatus", "anchor": "executeresponsestatus" },
      { "name": "StoreItemType", "anchor": "storeitemtype" },
      { "name": "StoreReceiveType", "anchor": "storereceivetype" },
      { "name": "PermissionDataItem", "anchor": "permissiondataitem" },
      { "name": "FieldDataType", "anchor": "fielddatatype" }
    ]
  },
  "events": {
    "docPath": "docs/reference/EVENTS.md",
    "subscribePattern": "<Handler>.onUpdate = (payload) => { … }",
    "unsubscribePattern": "<Handler>.onUpdate = () => {}",
    "prerequisite": "socket connected + authenticated",
    "subscribeOrder": "subscribe trước khi gọi GNNetwork.connectSocket() để không bỏ lỡ event ngay sau handshake",
    "list": [
      {
        "name": "OnGroupMessageUpdateEventHandler",
        "payloadClass": "GroupMessageUpdate",
        "anchor": "ongroupmessageupdateeventhandler",
        "scope": "Group",
        "payloadKeys": ["groupMessages", "groupId", "characterId?"]
      },
      {
        "name": "OnGroupMemberUpdateEventHandler",
        "payloadClass": "GroupMemberUpdate",
        "anchor": "ongroupmemberupdateeventhandler",
        "scope": "Group",
        "payloadKeys": ["members", "groupId"]
      },
      {
        "name": "OnGamePlayerFriendUpdateEventHandler",
        "payloadClass": "GamePlayerFriendUpdate",
        "anchor": "ongameplayerfriendupdateeventhandler",
        "scope": "GamePlayer",
        "payloadKeys": ["playerFriends", "characterId?"]
      },
      {
        "name": "OnGamePlayerGroupUpdateEventHandler",
        "payloadClass": "GamePlayerGroupUpdate",
        "anchor": "ongameplayergroupupdateeventhandler",
        "scope": "GamePlayer",
        "payloadKeys": ["playerGroups", "characterId?"]
      },
      {
        "name": "OnCharacterPlayerFriendUpdateEventHandler",
        "payloadClass": "CharacterPlayerFriendUpdate",
        "anchor": "oncharacterplayerfriendupdateeventhandler",
        "scope": "CharacterPlayer",
        "payloadKeys": ["playerFriends", "characterId"]
      },
      {
        "name": "OnCharacterPlayerGroupUpdateEventHandler",
        "payloadClass": "CharacterPlayerGroupUpdate",
        "anchor": "oncharacterplayergroupupdateeventhandler",
        "scope": "CharacterPlayer",
        "payloadKeys": ["playerGroups", "characterId"]
      }
    ]
  },
  "configSchema": {
    "docPath": "docs/reference/CONFIG.md",
    "class": "GNServerSettingsOptions",
    "ctorUsage": "const settings = new GNServerSettings(); settings.config({ serverAddress, serverPort, gameId, secretKey, ... }); GNNetwork.init(settings)",
    "fields": [
      { "name": "serverAddress", "type": "string", "default": "127.0.0.1" },
      { "name": "serverPort", "type": "number", "default": 2202, "unit": "port" },
      { "name": "serverSocketPort", "type": "number", "default": 2901, "unit": "port" },
      { "name": "useSsl", "type": "boolean", "default": false },
      { "name": "useSocket", "type": "boolean", "default": true },
      { "name": "useHttp", "type": "boolean", "default": true },
      { "name": "defaultTimeoutInSeconds", "type": "number", "default": 20, "unit": "seconds" },
      { "name": "messageType", "type": "MessageType", "default": "MsgPack" },
      { "name": "sendRate", "type": "number", "default": 20, "unit": "messages_per_second" },
      { "name": "reconnectDelay", "type": "number", "default": 5000, "unit": "milliseconds" },
      { "name": "pingInterval", "type": "number", "default": 20000, "unit": "milliseconds" },
      { "name": "pingTimeout", "type": "number", "default": 20000, "unit": "milliseconds" },
      { "name": "secretKey", "type": "string" },
      { "name": "gameId", "type": "string" },
      { "name": "logType", "type": "LogType", "default": "All" }
    ],
    "runtimeOnlySetters": [
      { "name": "useReverseProxy", "setter": "settings.setUseReverseProxy(true)", "default": false }
    ]
  },
  "errorHandling": {
    "docPath": "docs/reference/ERROR_HANDLING.md",
    "responseFieldAccess": "public_fields",
    "responseFields": ["returnCode", "errorCode", "invalidMembers", "debugMessage", "responseData"],
    "checkOrder": [
      "if (res.returnCode !== ReturnCode.Ok) return;",
      "if (res.errorCode !== ErrorCode.Ok) return;",
      "useResult(res.responseData);"
    ],
    "okValue": 1,
    "warning": "Typed response (mọi *Async() và callback form) dùng PUBLIC FIELDS, KHÔNG phải getter. Low-level OperationResponse (raw transport) mới dùng getReturnCode() etc."
  },
  "scenarios": {
    "docPath": "docs/COOKBOOK.md",
    "list": [
      { "id": 1, "title": "Init SDK + bootstrap tối thiểu", "anchor": "scenario-1-init-sdk--bootstrap-tối-thiểu", "apis": ["GNNetwork.init"] },
      { "id": 2, "title": "Login by account + retrieve profile", "anchor": "scenario-2-login-by-account--retrieve-profile", "apis": ["GNNetwork.authenticate.loginByAccountAsync"] },
      { "id": 3, "title": "Refresh token và persist session", "anchor": "scenario-3-refresh-token-và-persist-session", "apis": ["GNNetwork.authenticate.refreshAuthTokenAsync"] },
      { "id": 4, "title": "Login by social (Google/Apple/Facebook)", "anchor": "scenario-4-login-by-social-googleapplefacebook", "apis": ["GNNetwork.authenticate.loginByGoogleAsync", "GNNetwork.authenticate.loginByAppleAsync", "GNNetwork.authenticate.loginByFacebookAsync"] },
      { "id": 5, "title": "Connect socket + handle reconnect", "anchor": "scenario-5-connect-socket--handle-reconnect", "apis": ["GNNetwork.connectSocket", "GNNetwork.subscriberOnConnectHandler"] },
      { "id": 6, "title": "Subscribe friend updates", "anchor": "scenario-6-subscribe-friend-updates", "events": ["OnGamePlayerFriendUpdateEventHandler"] },
      { "id": 7, "title": "Subscribe + send group message", "anchor": "scenario-7-subscribe--send-group-message", "events": ["OnGroupMessageUpdateEventHandler"], "apis": ["GNNetwork.group.sendGroupMessageAsync"] },
      { "id": 8, "title": "Group member lifecycle + realtime update", "anchor": "scenario-8-group-member-lifecycle-join--leave--kick--realtime-update", "events": ["OnGroupMemberUpdateEventHandler"], "apis": ["GNNetwork.gamePlayer.joinGroupAsync", "GNNetwork.gamePlayer.leaveGroupAsync", "GNNetwork.group.server.removeMemberAsync"] },
      { "id": 9, "title": "Matchmaking ticket flow", "anchor": "scenario-9-matchmaking-ticket-flow", "apis": ["GNNetwork.multiplayer.createMatchmakingTicketAsync", "GNNetwork.multiplayer.getMatchmakingTicketAsync", "GNNetwork.multiplayer.cancelMatchmakingTicketAsync"] },
      { "id": 10, "title": "Inventory query + grant item (server role)", "anchor": "scenario-10-inventory-query--grant-item-server-role", "apis": ["GNNetwork.gamePlayer.getPlayerInventoryAsync", "GNNetwork.gamePlayer.server.createPlayerItemAsync"] },
      { "id": 11, "title": "Store list → purchase → validate receipt", "anchor": "scenario-11-store-list-catalog--purchase--validate-receipt", "apis": ["GNNetwork.storeInventory.getStoreItemsWithTagAsync", "GNNetwork.storeInventory.buyStoreItemAsync", "GNNetwork.storeInventory.server.validateGooglePlayStoreReceiptAsync"] },
      { "id": 12, "title": "CloudScript execute + customTags", "anchor": "scenario-12-cloudscript-execute-function--customtags", "apis": ["GNNetwork.cloudScript.executeFunctionAsync"] },
      { "id": 13, "title": "Override authToken / secret", "anchor": "scenario-13-override-authtoken--secret-impersonate-cross-role" },
      { "id": 14, "title": "Admin login qua DashboardApi", "anchor": "scenario-14-admin-login-qua-dashboardapi", "apis": ["GNNetwork.dashboard.loginByAdminAccountAsync"] },
      { "id": 15, "title": "Cleanup & shutdown flow", "anchor": "scenario-15-cleanup--shutdown-flow", "apis": ["GNNetwork.disconnectSocket"] },
      { "id": 16, "title": "Diagnose OperationNotAllow", "anchor": "scenario-16-diagnose-operationnotallow", "apis": ["GNNetwork.inventory.admin.setAmountAsync"] }
    ]
  },
  "apiGroups": [
    {
      "name": "AuthenticateApi",
      "guideDoc": "docs/guides/AUTHENTICATE.md",
      "referenceDoc": "docs/reference/API_AUTHENTICATE.md",
      "dtoDoc": "docs/reference/dto/AUTHENTICATE.md",
      "apiDts": "dist/runtime/GNNetworkAuthenticateApi.d.ts",
      "modelDts": [
        "dist/runtime/entity/models/AuthenticateModels.d.ts",
        "dist/runtime/entity/models/AuthenticateRequestModels.d.ts",
        "dist/runtime/entity/models/AuthenticateResponseModels.d.ts"
      ],
      "transport": "http",
      "methodCount": 18,
      "routes": [
        {
          "namespace": "GNNetwork.authenticate",
          "requestRole": "Client",
          "useWhen": "login player, register account, refresh auth token"
        }
      ],
      "emptyNamespaces": [
        "GNNetwork.authenticate.server",
        "GNNetwork.authenticate.admin"
      ],
      "permissionRuleDoc": "docs/reference/API_AUTHENTICATE.md",
      "recommendedSecretPermissions": {
        "client": "otherSelfEnable cho các method login/register (login luôn là acting-on-unauth-user)",
        "server": "serverSelfEnable nếu backend cần issue token cho user cụ thể",
        "admin": "adminSelfEnable nếu dashboard cần impersonate/provision tài khoản"
      }
    },
    {
      "name": "DashboardApi",
      "guideDoc": "docs/guides/DASHBOARD.md",
      "referenceDoc": "docs/reference/API_DASHBOARD.md",
      "dtoDoc": "docs/reference/dto/DASHBOARD.md",
      "apiDts": "dist/runtime/GNNetworkDashboardApi.d.ts",
      "modelDts": [
        "dist/runtime/entity/models/DashboardModels.d.ts",
        "dist/runtime/entity/models/DashboardRequestModels.d.ts",
        "dist/runtime/entity/models/DashboardResponseModels.d.ts"
      ],
      "transport": "http",
      "methodCount": 26,
      "routes": [
        {
          "namespace": "GNNetwork.dashboard",
          "requestRole": "Client",
          "useWhen": "dashboard, analytics, secret, maintenance, admin login",
          "specialCase": "backend resolve admin context từ authToken sau login admin"
        }
      ],
      "emptyNamespaces": [
        "GNNetwork.dashboard.server",
        "GNNetwork.dashboard.admin"
      ],
      "permissionRuleDoc": "docs/reference/API_DASHBOARD.md",
      "recommendedSecretPermissions": {
        "client": "secretKey bootstrap chỉ cần cho phép loginByAdminAccount; sau login backend tự resolve quyền admin từ authToken"
      }
    },
    {
      "name": "ContentApi",
      "guideDoc": "docs/guides/CONTENT.md",
      "referenceDoc": "docs/reference/API_CONTENT.md",
      "dtoDoc": "docs/reference/dto/CONTENT.md",
      "apiDts": "dist/runtime/GNNetworkContentApi.d.ts",
      "modelDts": [
        "dist/runtime/entity/models/ContentModels.d.ts",
        "dist/runtime/entity/models/ContentRequestModels.d.ts",
        "dist/runtime/entity/models/ContentResponseModels.d.ts"
      ],
      "transport": "http",
      "methodCount": 21,
      "routes": [
        {
          "namespace": "GNNetwork.content",
          "requestRole": "Client",
          "useWhen": "content config hoặc file metadata từ app hoặc player side"
        },
        {
          "namespace": "GNNetwork.content.server",
          "requestRole": "Server",
          "useWhen": "trusted backend hoặc worker xử lý content hoặc file metadata"
        },
        {
          "namespace": "GNNetwork.content.admin",
          "requestRole": "Admin",
          "useWhen": "dashboard hoặc backoffice quản trị content hoặc file metadata"
        }
      ],
      "permissionRuleDoc": "docs/reference/API_CONTENT.md",
      "recommendedSecretPermissions": {
        "client": "selfEnable cho các method app-level query; otherSelfEnable nếu cần đọc content của user khác",
        "server": "serverSelfEnable cho trusted backend upload/download metadata",
        "admin": "adminSelfEnable cho dashboard quản trị content"
      }
    },
    {
      "name": "MultiplayerApi",
      "guideDoc": "docs/guides/MULTIPLAYER.md",
      "referenceDoc": "docs/reference/API_MULTIPLAYER.md",
      "dtoDoc": "docs/reference/dto/MULTIPLAYER.md",
      "apiDts": "dist/runtime/GNNetworkMultiplayerApi.d.ts",
      "modelDts": [
        "dist/runtime/entity/models/MultiplayerModels.d.ts",
        "dist/runtime/entity/models/MultiplayerRequestModels.d.ts",
        "dist/runtime/entity/models/MultiplayerResponseModels.d.ts"
      ],
      "transport": "http",
      "methodCount": 30,
      "routes": [
        {
          "namespace": "GNNetwork.multiplayer",
          "requestRole": "Client",
          "useWhen": "matchmaking ticket hoặc match query gắn với auth token hiện tại"
        },
        {
          "namespace": "GNNetwork.multiplayer.server",
          "requestRole": "Server",
          "useWhen": "trusted backend thao tác ticket hoặc match của user cụ thể"
        },
        {
          "namespace": "GNNetwork.multiplayer.admin",
          "requestRole": "Admin",
          "useWhen": "ops hoặc dashboard liệt kê và quản lý ticket hoặc match"
        }
      ],
      "hardRules": [
        "không dùng socket để tạo hoặc join hoặc cancel hoặc query matchmaking ticket",
        "flow chuẩn là create hoặc join ticket rồi poll getMatchmakingTicket rồi mới getMatch"
      ],
      "permissionRuleDoc": "docs/reference/API_MULTIPLAYER.md",
      "recommendedSecretPermissions": {
        "client": "selfEnable cho create/cancel ticket của chính user; otherSelfEnable nếu cần query ticket user khác",
        "server": "serverSelfEnable cho trusted backend điều phối match",
        "admin": "adminSelfEnable cho dashboard liệt kê/quản lý ticket"
      }
    },
    {
      "name": "StoreInventoryApi",
      "guideDoc": "docs/guides/STORE_INVENTORY.md",
      "referenceDoc": "docs/reference/API_STORE_INVENTORY.md",
      "dtoDoc": "docs/reference/dto/STORE_INVENTORY.md",
      "apiDts": "dist/runtime/GNNetworkStoreInventoryApi.d.ts",
      "modelDts": [
        "dist/runtime/entity/models/StoreInventoryModels.d.ts",
        "dist/runtime/entity/models/StoreInventoryRequestModels.d.ts",
        "dist/runtime/entity/models/StoreInventoryResponseModels.d.ts"
      ],
      "transport": "http",
      "methodCount": 42,
      "routes": [
        {
          "namespace": "GNNetwork.storeInventory",
          "requestRole": "Client",
          "useWhen": "store catalog, buy, present, receipt validation cho flow app hoặc player"
        },
        {
          "namespace": "GNNetwork.storeInventory.server",
          "requestRole": "Server",
          "useWhen": "trusted backend purchase fulfillment hoặc store workflow"
        },
        {
          "namespace": "GNNetwork.storeInventory.admin",
          "requestRole": "Admin",
          "useWhen": "dashboard hoặc ops quản trị catalog hoặc log"
        }
      ],
      "permissionRuleDoc": "docs/reference/API_STORE_INVENTORY.md",
      "recommendedSecretPermissions": {
        "client": "selfEnable cho buy/present/validate receipt của chính user",
        "server": "serverSelfEnable cho backend fulfillment, webhook validate receipt",
        "admin": "adminSelfEnable cho dashboard CRUD catalog, log, remove status"
      }
    },
    {
      "name": "InventoryApi",
      "guideDoc": "docs/guides/INVENTORY.md",
      "referenceDoc": "docs/reference/API_INVENTORY.md",
      "dtoDoc": "docs/reference/dto/INVENTORY.md",
      "apiDts": "dist/runtime/GNNetworkInventoryApi.d.ts",
      "modelDts": [
        "dist/runtime/entity/models/InventoryModels.d.ts",
        "dist/runtime/entity/models/InventoryRequestModels.d.ts",
        "dist/runtime/entity/models/InventoryResponseModels.d.ts"
      ],
      "transport": "http",
      "methodCount": 102,
      "routes": [
        {
          "namespace": "GNNetwork.inventory",
          "requestRole": "Client",
          "useWhen": "player app thao tác trên item thuộc session hoặc ownership hiện tại"
        },
        {
          "namespace": "GNNetwork.inventory.server",
          "requestRole": "Server",
          "useWhen": "trusted backend xử lý item hoặc ownership hoặc statistics"
        },
        {
          "namespace": "GNNetwork.inventory.admin",
          "requestRole": "Admin",
          "useWhen": "GM tool hoặc dashboard vận hành dữ liệu inventory"
        }
      ],
      "permissionRuleDoc": "docs/reference/API_INVENTORY.md",
      "recommendedSecretPermissions": {
        "client": "selfEnable cho query/statistics item của chính user; otherSelfEnable nếu xem item user khác",
        "server": "serverSelfEnable cho grant/transfer/remove item từ trusted backend",
        "admin": "adminSelfEnable cho GM tool setAmount, setOwner, setRemoveStatus"
      }
    },
    {
      "name": "GroupApi",
      "guideDoc": "docs/guides/GROUP.md",
      "referenceDoc": "docs/reference/API_GROUP.md",
      "dtoDoc": "docs/reference/dto/GROUP.md",
      "apiDts": "dist/runtime/GNNetworkGroupApi.d.ts",
      "modelDts": [
        "dist/runtime/entity/models/GroupModels.d.ts",
        "dist/runtime/entity/models/GroupRequestModels.d.ts",
        "dist/runtime/entity/models/GroupResponseModels.d.ts"
      ],
      "transport": "http",
      "methodCount": 120,
      "routes": [
        {
          "namespace": "GNNetwork.group",
          "requestRole": "Client",
          "useWhen": "player app thao tác trên group đã tồn tại"
        },
        {
          "namespace": "GNNetwork.group.server",
          "requestRole": "Server",
          "useWhen": "trusted backend xử lý group lifecycle hoặc member hoặc message"
        },
        {
          "namespace": "GNNetwork.group.admin",
          "requestRole": "Admin",
          "useWhen": "dashboard hoặc GM tool vận hành dữ liệu group"
        }
      ],
      "realtimeHandlers": [
        "dist/runtime/networking/handler/OnGroupMessageUpdateEventHandler.d.ts",
        "dist/runtime/networking/handler/OnGroupMemberUpdateEventHandler.d.ts"
      ],
      "permissionRuleDoc": "docs/reference/API_GROUP.md",
      "recommendedSecretPermissions": {
        "client": "selfEnable cho member của group đã join; otherSelfEnable cho query group khác",
        "server": "serverSelfEnable cho backend manage lifecycle, currency, message",
        "admin": "adminSelfEnable cho GM tool kick member, reset statistics, setRemoveStatus"
      }
    },
    {
      "name": "MasterPlayerApi",
      "guideDoc": "docs/guides/MASTER_PLAYER.md",
      "referenceDoc": "docs/reference/API_MASTER_PLAYER.md",
      "dtoDoc": "docs/reference/dto/MASTER_PLAYER.md",
      "apiDts": "dist/runtime/GNNetworkMasterPlayerApi.d.ts",
      "modelDts": [
        "dist/runtime/entity/models/MasterPlayerModels.d.ts",
        "dist/runtime/entity/models/MasterPlayerRequestModels.d.ts",
        "dist/runtime/entity/models/MasterPlayerResponseModels.d.ts"
      ],
      "transport": "http",
      "methodCount": 256,
      "routes": [
        {
          "namespace": "GNNetwork.masterPlayer",
          "requestRole": "Client",
          "useWhen": "player app thao tác trên account hoặc profile của chính user hiện tại",
          "userIdBehavior": "có thể bỏ userId để target user hiện tại"
        },
        {
          "namespace": "GNNetwork.masterPlayer.server",
          "requestRole": "Server",
          "useWhen": "trusted backend xử lý account hoặc profile của player cụ thể",
          "userIdBehavior": "các flow self-target phải truyền userId rõ ràng"
        },
        {
          "namespace": "GNNetwork.masterPlayer.admin",
          "requestRole": "Admin",
          "useWhen": "dashboard hoặc GM tool vận hành dữ liệu master player",
          "userIdBehavior": "các flow self-target phải truyền userId rõ ràng"
        }
      ],
      "permissionRuleDoc": "docs/reference/API_MASTER_PLAYER.md",
      "recommendedSecretPermissions": {
        "client": "selfEnable cho profile/identity/currency của chính user; otherSelfEnable cho search/leaderboard/xem user khác",
        "server": "serverSelfEnable cho backend provisioning, link/unlink identity, change currency",
        "admin": "adminSelfEnable cho GM tool ban, reset password, send push notification"
      }
    },
    {
      "name": "GamePlayerApi",
      "guideDoc": "docs/guides/GAME_PLAYER.md",
      "referenceDoc": "docs/reference/API_GAME_PLAYER.md",
      "dtoDoc": "docs/reference/dto/GAME_PLAYER.md",
      "apiDts": "dist/runtime/GNNetworkGamePlayerApi.d.ts",
      "modelDts": [
        "dist/runtime/entity/models/GamePlayerModels.d.ts",
        "dist/runtime/entity/models/GamePlayerRequestModels.d.ts",
        "dist/runtime/entity/models/GamePlayerResponseModels.d.ts"
      ],
      "transport": "http",
      "methodCount": 156,
      "routes": [
        {
          "namespace": "GNNetwork.gamePlayer",
          "requestRole": "Client",
          "useWhen": "player app thao tác trên gameplay profile của chính user hiện tại",
          "userIdBehavior": "có thể bỏ userId để target user hiện tại"
        },
        {
          "namespace": "GNNetwork.gamePlayer.server",
          "requestRole": "Server",
          "useWhen": "trusted backend xử lý lifecycle game player của user cụ thể",
          "userIdBehavior": "các flow self-target phải truyền userId rõ ràng"
        },
        {
          "namespace": "GNNetwork.gamePlayer.admin",
          "requestRole": "Admin",
          "useWhen": "dashboard hoặc GM tool vận hành dữ liệu game player",
          "userIdBehavior": "các flow self-target phải truyền userId rõ ràng"
        }
      ],
      "realtimeHandlers": [
        "dist/runtime/networking/handler/OnGamePlayerFriendUpdateEventHandler.d.ts",
        "dist/runtime/networking/handler/OnGamePlayerGroupUpdateEventHandler.d.ts"
      ],
      "permissionRuleDoc": "docs/reference/API_GAME_PLAYER.md",
      "recommendedSecretPermissions": {
        "client": "selfEnable cho gameplay profile/relation của chính user; otherSelfEnable cho friend/group query sang user khác",
        "server": "serverSelfEnable cho backend create character, change currency, manage friend/group",
        "admin": "adminSelfEnable cho GM tool"
      }
    },
    {
      "name": "CharacterPlayerApi",
      "guideDoc": "docs/guides/CHARACTER_PLAYER.md",
      "referenceDoc": "docs/reference/API_CHARACTER_PLAYER.md",
      "dtoDoc": "docs/reference/dto/CHARACTER_PLAYER.md",
      "apiDts": "dist/runtime/GNNetworkCharacterPlayerApi.d.ts",
      "modelDts": [
        "dist/runtime/entity/models/CharacterPlayerModels.d.ts",
        "dist/runtime/entity/models/CharacterPlayerRequestModels.d.ts",
        "dist/runtime/entity/models/CharacterPlayerResponseModels.d.ts"
      ],
      "transport": "http",
      "methodCount": 159,
      "routes": [
        {
          "namespace": "GNNetwork.characterPlayer",
          "requestRole": "Client",
          "useWhen": "player app thao tác trên character cụ thể đang thuộc ownership hợp lệ",
          "targetBehavior": "gần như luôn phải truyền characterId rõ ràng"
        },
        {
          "namespace": "GNNetwork.characterPlayer.server",
          "requestRole": "Server",
          "useWhen": "trusted backend xử lý lifecycle hoặc relation của character cụ thể",
          "targetBehavior": "gần như luôn phải truyền characterId rõ ràng"
        },
        {
          "namespace": "GNNetwork.characterPlayer.admin",
          "requestRole": "Admin",
          "useWhen": "dashboard hoặc GM tool vận hành dữ liệu character",
          "targetBehavior": "gần như luôn phải truyền characterId rõ ràng"
        }
      ],
      "realtimeHandlers": [
        "dist/runtime/networking/handler/OnCharacterPlayerFriendUpdateEventHandler.d.ts",
        "dist/runtime/networking/handler/OnCharacterPlayerGroupUpdateEventHandler.d.ts"
      ],
      "permissionRuleDoc": "docs/reference/API_CHARACTER_PLAYER.md",
      "recommendedSecretPermissions": {
        "client": "selfEnable cho character thuộc ownership user; otherSelfEnable cho view character khác",
        "server": "serverSelfEnable cho backend create/remove character, manage friend/group ở cấp character",
        "admin": "adminSelfEnable cho GM tool"
      }
    },
    {
      "name": "CloudScriptApi",
      "guideDoc": "docs/guides/CLOUDSCRIPT.md",
      "referenceDoc": "docs/reference/API_CLOUDSCRIPT.md",
      "dtoDoc": "docs/reference/dto/CLOUDSCRIPT.md",
      "apiDts": "dist/runtime/GNNetworkCloudScriptApi.d.ts",
      "modelDts": [
        "dist/runtime/entity/models/CloudScriptModels.d.ts",
        "dist/runtime/entity/models/CloudScriptRequestModels.d.ts",
        "dist/runtime/entity/models/CloudScriptResponseModels.d.ts"
      ],
      "transport": "http",
      "methodCount": 15,
      "routes": [
        {
          "namespace": "GNNetwork.cloudScript",
          "requestRole": "Client",
          "useWhen": "app public chỉ execute function nếu backend cho phép"
        },
        {
          "namespace": "GNNetwork.cloudScript.server",
          "requestRole": "Server",
          "useWhen": "trusted backend execute hoặc publish theo workflow backend"
        },
        {
          "namespace": "GNNetwork.cloudScript.admin",
          "requestRole": "Admin",
          "useWhen": "dashboard hoặc backoffice quản trị version và live status"
        }
      ],
      "hardRules": [
        "editFunctionAsync không sửa source code, chỉ flag enabled hoặc live của version",
        "muốn đổi source code phải addFunctionAsync để tạo version mới",
        "không có public delete function hoặc hard delete version"
      ],
      "permissionRuleDoc": "docs/reference/API_CLOUDSCRIPT.md",
      "recommendedSecretPermissions": {
        "client": "selfEnable cho executeFunction nếu backend cho phép app public execute",
        "server": "serverSelfEnable cho backend execute/publish theo workflow trusted",
        "admin": "adminSelfEnable cho dashboard addFunction/editFunction/publish version"
      }
    }
  ]
}
