CodeGym /Các khóa học /ChatGPT Apps /Yêu cầu của Store và các quyền tối thiểu

Yêu cầu của Store và các quyền tối thiểu

ChatGPT Apps
Mức độ , Bài học
Có sẵn

1. ChatGPT Store là gì trong ngữ cảnh của khóa học

Bắt đầu từ bức tranh tổng thể. ChatGPT Store là một danh mục ứng dụng bên trong ChatGPT, nơi người dùng có thể truy cập, tìm App của bạn, bật nó và sử dụng trong các cuộc hội thoại bình thường. Với bạn, đây không chỉ là một “mặt tiền” mà là kênh phân phối có quy tắc, tương tự “App Store” cho thế giới LLM.

Trong khóa này, chúng ta phân biệt ba chế độ hoạt động của App:

  • Chế độ thứ nhất — Dev Mode. App gắn với tài khoản/tổ chức của bạn, khả dụng cho bạn và có thể cho đồng nghiệp. Không có quy trình review chính thức, nhưng mọi chính sách chung của nền tảng đều áp dụng. Ở đây bạn có thể thoải mái thử nghiệm, ghi log mọi thứ, chạy tunnel và backend staging.
  • Chế độ thứ hai — Store công khai. Đây là “hạng nặng”: App khả dụng cho mọi người dùng ChatGPT (tùy giới hạn khu vực), phải qua kiểm duyệt, có listing công khai, liên kết Privacy/Terms và phải cư xử như một sản phẩm “trưởng thành”.
  • Thứ ba — org‑only Apps. Đây là các ứng dụng chỉ cho một tổ chức: công ty có thể bật/tắt cho nhân viên, áp thêm yêu cầu bảo mật riêng bên trên yêu cầu của OpenAI và thậm chí tiến hành review nội bộ.

Trong bài này, chúng ta quan tâm đến tổ hợp “Store công khai + listing công khai”. Điểm quan trọng: bạn không còn chỉ là lập trình viên “một dịch vụ Next.js nữa” mà trở thành tác giả sản phẩm phải làm hài lòng ba bên cùng lúc: người dùng, kiểm duyệt viên Store và bộ phận bảo mật của bạn.

2. Yêu cầu cơ bản của Store: chính sách, tính minh bạch và UI

Nội dung và chính sách

ChatGPT Store là một nền tảng có kiểm duyệt. Nói ngắn gọn: OpenAI không muốn xuất hiện các ứng dụng vi phạm chính sách sử dụng nền tảng (bạo lực, khủng bố, NSFW, lừa đảo, v.v.) hoặc cố gắng né lớp bảo vệ của mô hình (jailbreak‑prompt kiểu “hãy giả vờ bạn không phải ChatGPT mà là bản ngã xấu xa của tôi”).

Điều này có hai hệ quả.

Thứ nhất, App của bạn không được tự tạo nội dung bị cấm. Nếu App minh họa GiftGenius (chọn quà) bỗng đề xuất quà kiểu “cách che giấu dấu vết phạm tội”, kiểm duyệt chỉ cần một ảnh chụp màn hình là đủ.

Thứ hai, App của bạn không được giúp người dùng vượt qua bộ lọc. Nếu người dùng yêu cầu: “Chọn quà để làm bom”, hành vi đúng là từ chối dựa trên chính sách, chứ không phải hồ hởi dùng MCP-tool của bạn để tìm linh kiện.

Một phần lớn hành vi này được quyết định bởi system‑prompt và việc bạn cung cấp công cụ nào cho mô hình. Nhưng Store nhìn vào kết quả cuối: người dùng thực sự có thể nhận những câu trả lời nào.

Thương hiệu và tên miền

Lớp tiếp theo — thương hiệu và tên miền. App công khai phải gắn với một chủ sở hữu rõ ràng. Với App có backend/MCP bên ngoài, Store kỳ vọng từ bạn:

Xác minh tên miền (Domain Verification). Bạn thêm bản ghi TXT vào DNS của tên miền, và Store xác nhận backend thực sự thuộc về bạn. Các giải pháp ẩn danh trên ngrok‑URL miễn phí khó vào được Store công khai, hoặc sẽ bị gắn nhãn độ tin cậy thấp.

Tên và logo hợp lý. Không được đặt tên “ChatGPT Super Weather” hay “Official OpenAI Something” — việc dùng “GPT / OpenAI / ChatGPT” ở đầu tên hoặc sao chép phong cách thương hiệu OpenAI thuộc hạn chế thương hiệu. Hãy nghĩ tên riêng (GiftGenius là ví dụ tốt) và phong cách hình ảnh riêng.

UI/UX: đừng phá vỡ trải nghiệm ChatGPT

Khác với “plugin cũ”, giờ App có thể render widget UI của mình ngay trong chat. Điều này mở ra rất nhiều cơ hội… và cũng vô số cách để làm hỏng trải nghiệm.

Store có một nguyên tắc đơn giản: widget phải mang lại cảm giác “bản địa” so với ChatGPT. Phông chữ, khoảng cách, màu sắc, hành vi ở chế độ tối/sáng và trên di động — tất cả cần gọn gàng, không gây cảm giác bạn nhét vào chat một banner quảng cáo hay cả một SPA riêng.

Store cũng không thích UI chiếm dụng chat: các “miếng dính” toàn màn hình khổng lồ, modal “hãy đăng ký ngay”, autoscroll và các pattern hung hãn khác. Widget của bạn là thẻ/wizard/công cụ bên trong hội thoại, chứ không phải một vũ trụ riêng.

Về bản chất, kiểm duyệt nhìn vào ba thứ: bạn có vi phạm chính sách nội dung không, có gây hiểu nhầm không (về phần này sẽ có khối riêng ở cuối bài khi nói về listing và sự khớp với manifest) và có biến ChatGPT thành bãi rác quảng cáo với UX tệ không. “Tính minh bạch” ở đây nghĩa là sự phù hợp giữa những gì App thực sự làm được và những gì bạn tuyên bố trong mô tả và UI.

3. Store nhìn các quyền của App như thế nào

Một trục yêu cầu lớn khác là các quyền bạn yêu cầu từ người dùng và hệ thống bên ngoài. Ở đây Store không chỉ nhìn vào bảo mật, mà còn xem các quyền đó có tương xứng với giá trị ứng dụng tuyên bố hay không.

Giờ đến phần “ngon” với kỹ sư: mô hình quyền. Trong bối cảnh Apps SDK và MCP, bạn có ba mức truy cập chính.

Để trực quan, có thể vẽ như sau:

graph TD
    A[Manifest/cấu hình App] --> B[Model capabilities]
    A --> C[OAuth scopes]
    A --> D[MCP tools & ACP]
    D --> E[Mức độ xác nhận của người dùng]

Model capabilities — nghiêm ngặt mà nói không phải “quyền” theo nghĩa giống OAuth-scopes hay write-tools, mà là tập khả năng tích hợp của mô hình. Nhưng khi thiết kế bảo mật, ta thuận tiện coi đây là lớp truy cập đầu tiên cũng cần tối thiểu hóa.

Mức 1: model capabilities

Đây là những gì mô hình có thể làm “tự thân”, không cần gọi backend của bạn: duyệt web, tạo ảnh DALL‑E, v.v.

Nếu bật cả duyệt web và MCP-tools, đôi khi mô hình sẽ quyết định nhiệm vụ dễ hơn nếu giải bằng tìm kiếm web, thay vì dùng công cụ chuyên biệt của bạn — đặc biệt khi mô tả tools mơ hồ hoặc ưu tiên không được cố định trong prompt. Vì vậy, nếu App vốn đã gọi API của bạn qua MCP, hãy cân nhắc tắt browsing hoặc cố định ưu tiên MCP-tools rõ ràng trong prompt.

Tức là ở lớp này bạn đã áp dụng nguyên tắc quyền tối thiểu: tắt mọi thứ không cần cho giá trị thực của App.

Mức 2: OAuth scopes

Nếu App dùng xác thực (Mô‑đun 10), bạn sẽ yêu cầu các scope từ nhà cung cấp bên ngoài: openid, email, profile, orders.read, orders.write, v.v.

Ở đây, nguyên tắc tối giản đặc biệt quan trọng:

  • Nếu bạn chỉ cần phân biệt người dùng, thường openid (định danh ẩn danh) là đủ, và không cần email.
  • Nếu quả thật cần email, điều đó phải minh bạch trong UX và mô tả quyền: “cần để gửi hóa đơn và nhắc nhở đơn hàng cho bạn”, chứ không phải “để phòng sau này”.

Ngoài ra, hãy cố làm ủy quyền “khi cần”: trước tiên cho người dùng thử các chức năng cơ bản không cần đăng nhập, và chỉ xin quyền khi họ thực sự muốn, ví dụ “lưu danh sách quà yêu thích” hoặc “xem lịch sử đơn hàng”. Điều này giảm ma sát và tăng chuyển đổi.

Ví dụ cấu hình scope cho MCP‑tools (rút gọn):

// server/mcp/config/auth.ts
export const OAUTH_SCOPES = {
  basic: ["openid"],
  orders: ["openid", "orders.read"],
  checkout: ["openid", "orders.read", "orders.write"]
};

Mức 3: MCP‑tools và hành động “consequential”

Mức thứ ba là các MCP-tool của bạn và ACP/Instant Checkout. Mỗi tool trong MCP-server có thể là:

  • chỉ đọc (read‑only): lấy tỷ giá, gợi ý quà tặng, xem danh mục;
  • thay đổi trạng thái (consequential): tạo đơn hàng, gửi email, trừ tiền.

Với các công cụ loại thứ hai, Store kỳ vọng mô hình xác nhận nghiêm ngặt hơn. Ý tưởng: không phải mọi thứ đều được gọi “một cách tự động”. Trên nền tảng, điều này thường thể hiện qua cờ consequential: true và chính sách xác nhận (always_allow so với ask_user).

Ví dụ đăng ký MCP‑tool với security‑schemes và đánh dấu đây là hành động thay đổi trạng thái:

// server/mcp/tools/createOrder.ts
server.registerTool(
  "create_order",
  {
    title: "Create order",
    description: "Tạo đơn hàng mới trong GiftGenius.",
    inputSchema: {
      type: "object",
      properties: {
        productId: { type: "string" },
        quantity: { type: "integer", minimum: 1 }
      },
      required: ["productId", "quantity"]
    },
    _meta: {
      securitySchemes: [{ type: "oauth2", scopes: ["orders.write"] }]
    },
    // trường giả, ý tưởng: hành động này thay đổi trạng thái
    consequential: true
  },
  async ({ input, security }) => {
    // ... logic tạo đơn hàng
  }
);

Ví dụ về scope và security‑schemes lấy từ tài liệu chính thức về MCP-tools, nơi công cụ có thể không cần xác thực hoặc được bảo vệ bằng OAuth2.

Từ góc nhìn Store, điều này chuyển thành câu chữ dễ hiểu “Ứng dụng này có thể tạo và quản lý đơn hàng trong cửa hàng GiftGenius” và có thể kèm một bước xác nhận riêng.

4. Quyền dưới góc nhìn người dùng và người kiểm duyệt

Với chúng ta, kỹ sư, App là manifest, MCP-server và rất nhiều TypeScript. Với Store, đó là tập sự kiện: App có thể làm gì với dữ liệu người dùng và với thế giới bên ngoài.

Có thể hình dung bảng sau:

Mức truy cập Ví dụ cho GiftGenius Store/người dùng sẽ thấy
Model capabilities Browsing: off, DALL‑E: off “App không tự vào internet, không tạo media”
OAuth scopes openid, orders.read “Đọc các đơn hàng trong tài khoản GiftGenius của bạn”
Read‑only MCP tools search_products, get_price_history “Xem danh mục và giá”
Consequential MCP tools create_order, cancel_order “Tạo và hủy đơn hàng”

Ý chính: mỗi yếu tố kỹ thuật phải map sang một hành động dễ hiểu với con người. Trong kế hoạch của mô‑đun, điều này được nêu rõ: MCP-tool kỹ thuật get_user_orders chuyển thành câu trong listing “Xem danh sách đơn hàng của bạn trong cửa hàng của chúng tôi”.

Nếu bạn không thể giải thích một quyền trong một đến hai câu — đó là tín hiệu nguy hiểm. Có thể bạn đang yêu cầu quá mức, hoặc trộn nhiều tác vụ vào cùng một App.

5. Nguyên tắc quyền tối thiểu cần thiết

Trong thế giới backend thông thường, nguyên tắc PoLP (Principle of Least Privilege) thường bị xem như “ừ thì, cần giới hạn role trong DB, để sau làm”. Với ChatGPT Apps, đây không phải “để sau”, mà là tiêu chí vào Store và là yếu tố chuyển đổi người dùng.

Điểm quan trọng:

  • App càng xin ít quyền, mức tin cậy cơ bản của người dùng càng cao. Hội thoại trong ChatGPT là không gian nơi người dùng kỳ vọng mức riêng tư nhất định. App đột ngột xin quyền vào cả tài khoản, thanh toán và danh bạ trông rất đáng ngờ.
  • Quyền càng rõ ràng và hẹp, reviewer càng dễ xét duyệt. Người kiểm duyệt cần nhanh chóng hiểu App làm gì và mức độ phù hợp với chính sách cùng thực hành bảo mật tốt. App over‑permissioned thường bị “để lại và yêu cầu làm rõ”, đôi khi bị từ chối.
  • Truy cập càng tối thiểu và “just‑in‑time”, UX càng mượt. Màn hình xác thực là điểm ma sát mạnh. Nếu App mang lại giá trị trước cả khi xác thực (ví dụ, hiển thị top quà tặng không gắn với người dùng), người dùng sẽ sẵn lòng cấp quyền mở rộng sau đó hơn.

Vì vậy, “quyền tối thiểu” trong Store không chỉ là bảo mật, mà còn là marketing và tăng trưởng. Trong mô‑đun 18 nhấn mạnh rằng quyền tối thiểu là lợi thế cạnh tranh, không phải thủ tục hành chính.

6. Ví dụ: quyền của GiftGenius trước và sau “giảm quyền”

Để không chỉ lý thuyết, hãy lấy nhân vật giả định — GiftGenius. Giả sử bạn thiết kế “hết cỡ” và có danh sách khả năng cần như sau:

  1. Đọc danh mục sản phẩm và lọc quà tặng.
  2. Xem lịch sử đơn hàng của người dùng.
  3. Tạo đơn hàng mới và hủy đơn hiện có.
  4. Lưu “danh sách yêu thích” trong tài khoản người dùng.
  5. Gửi email thông báo về giảm giá.

Ở mức cấu hình có thể thể hiện như sau:

// server/mcp/config/permissions-naive.ts
export const PERMISSIONS_NAIVE = {
  capabilities: { webBrowsing: true, dalle: false },
  oauthScopes: ["openid", "email", "orders.read", "orders.write"],
  tools: {
    searchProducts: { consequential: false },
    getUserOrders: { consequential: false },
    createOrder: { consequential: true },
    cancelOrder: { consequential: true },
    saveFavoriteList: { consequential: true },
    sendDiscountEmail: { consequential: true }
  }
};

Trên giấy tờ, tập này có vẻ hợp lý (“sớm muộn gì cũng cần”), nhưng cho bản phát hành đầu tiên lên Store thì quá tay:

  • Bạn không nhất thiết phải đọc lịch sử đơn hàng ngay. Có thể giới hạn ở đề xuất một lần và checkout an toàn qua ACP/Instant Checkout, nơi luồng thanh toán vốn đã do nền tảng kiểm soát.
  • Thông báo email — là câu chuyện riêng: cần lưu email, giải thích trong Privacy Policy và xử lý hủy đăng ký. Với MVP GiftGenius, điều này hầu như luôn dư thừa.

Theo nguyên tắc tối giản, bạn có thể gom bộ quyền khởi động tối thiểu:

// server/mcp/config/permissions-v1.ts
export const PERMISSIONS_V1 = {
  capabilities: { webBrowsing: false, dalle: false },
  oauthScopes: [], // không đăng nhập, hoạt động ẩn danh
  tools: {
    searchProducts: { consequential: false },
    createOrder: { consequential: true }
  }
};

Trong phiên bản này:

  • App không truy cập tài khoản người dùng, không đọc lịch sử, không gửi email.
  • Tất cả thao tác nhạy cảm (tạo đơn hàng) đi qua ACP/Instant Checkout, nơi người dùng thấy luồng thanh toán tiêu chuẩn.

Trong listing có thể viết minh bạch: “Gợi ý quà tặng và tạo đơn hàng trong cửa hàng GiftGenius. Ứng dụng không lưu lịch sử chat của bạn và không gửi thông báo email.” Điều này vừa làm người dùng vừa làm người review thấy dễ chịu.

Sau này, khi có lưu lượng ổn định và niềm tin, bạn có thể phát hành cập nhật với quyền bổ sung (lịch sử đơn, yêu thích) và cập nhật tương ứng trong listing và Privacy Policy.

7. Cách mô tả quyền trong listing

Manifest và cấu hình là ngôn ngữ dành cho máy. Người kiểm duyệt và người dùng đọc một văn bản khác hẳn: tiêu đề, mô tả, khối “Ứng dụng này có thể làm gì” và liên kết đến Privacy/Terms.

Trong mô‑đun 17 nhấn mạnh việc mapping: scopes và công cụ kỹ thuật → hành động dễ hiểu với con người.

Với GiftGenius v1, ta có thể trình bày như sau.

Về mặt kỹ thuật:

  • Browsing: off
  • DALL‑E: off
  • MCP tools: search_products (read‑only), create_order (consequential)

Trong listing:

  • “Gợi ý quà tặng dựa trên mô tả hoặc tham số của bạn (giới tính, độ tuổi, ngân sách, sở thích).”
  • “Có thể tạo đơn hàng trong cửa hàng GiftGenius thông qua checkout bảo mật ngay trong ChatGPT.”
  • “Không yêu cầu quyền truy cập email hay lịch sử đơn hàng của bạn, không gửi thông báo.”

Nếu sau đó thêm OAuth‑login và orders.read, mô tả sẽ được cập nhật trung thực:

  • “Khi kết nối tài khoản GiftGenius, ứng dụng có thể xem các đơn hàng trước đây của bạn để đưa ra gợi ý cá nhân hóa hơn.”

Rất quan trọng là không hứa điều App không làm, và không bỏ qua các hành động nhạy cảm. Tài liệu tập hợp cho mô‑đun 18 nhấn mạnh: thông tin trong listing phải khớp chính xác với hành vi thực, đặc biệt với các nội dung nhạy cảm như thanh toán và PII.

8. Liên hệ giữa yêu cầu của Store và kiến trúc của bạn

Cần thấy rằng yêu cầu của Store không tồn tại trong chân không. Tất cả những yêu cầu này không phải “thêm một biểu mẫu từ marketing”. Về bản chất, Store kiểm tra những gì bạn đã làm trong các mô‑đun về bảo mật và production:

  • Nếu bạn cấu hình OAuth, làm cẩn thận các endpoint .well-known và kiểm tra token, sẽ thật kỳ lạ nếu App bỗng xin người dùng nửa internet qua các scope rộng. App như vậy dễ rớt review vì over‑permissioned.
  • Nếu bạn thực hiện nghiêm túc chính sách retention và PII‑scrub, bạn sẽ dễ viết Privacy Policy trung thực và vượt qua kiểm tra. Store và người dùng có thể mở liên kết để so sánh cam kết với quy trình thực tế.
  • Nếu bạn tối ưu ổn định cho MCP-server, log và metrics (các mô‑đun về observability và SLO), người review sẽ ít đặt câu hỏi về hiệu năng và lỗi công cụ.

Quyền tối thiểu làm hoàn chỉnh bức tranh: bạn không chỉ an toàn và ổn định, mà còn “khiêm tốn” trong yêu cầu dữ liệu người dùng.

9. Bài tập nhỏ trong quá trình học

Để không chỉ lý thuyết, hãy phân tích ngay App hiện tại của bạn (hoặc GiftGenius) theo từng bước.

Đầu tiên, hãy liệt kê tất cả hành động thực sự mà App làm được. Ví dụ: “gợi ý quà tặng”, “tạo đơn hàng”, “hiển thị lịch sử”, “lưu vào yêu thích”, “gửi email cho đồng nghiệp”. Tốt nhất viết bằng văn bản thường, chưa nghĩ đến chi tiết kỹ thuật.

Tiếp theo, với mỗi hành động hãy trả lời: “Điều này đụng đến dữ liệu người dùng nào?” và “Có thay đổi trạng thái ở hệ thống bên ngoài không?”. Nhờ vậy bạn tự động chia hành động thành read‑only và consequential.

Sau đó, map các hành động với các mức quyền: nơi nào chỉ cần model capabilities, nơi nào cần OAuth‑scope, và nơi nào cần MCP-tools với cờ consequential: true và có thể kèm bước xác nhận người dùng.

Và giờ hãy “cắt giảm”: có thể bỏ những gì khỏi bản phát hành đầu tiên mà vẫn giữ được giá trị cốt lõi? Thường thì không có lịch sử, yêu thích và thông báo email, App vẫn làm tốt việc chính. Đồng nghĩa các quyền này có thể để lại cho phiên bản 1.1 hoặc 2.0.

10. Những lỗi thường gặp với yêu cầu Store và quyền

Lỗi số 1: “Làm siêu App làm mọi thứ, để Store tự xử.”
Lập trình viên mô tả App như trợ lý vạn năng (“giúp về tài chính, y tế, pháp lý và mua sắm”), gắn cả chục MCP-tools và xin tối đa quyền. App như vậy vừa đụng miền nhạy cảm (y tế/tài chính/pháp lý), vừa xin nhiều dữ liệu, vừa vi phạm nguyên tắc “một App làm một việc”. Kết quả dễ đoán: kiểm duyệt hỏi rất nhiều hoặc từ chối. Tốt hơn hãy làm vài App hẹp với quyền rõ ràng.

Lỗi số 2: Ủy quyền over‑permissioned “để phòng”.
Kinh điển: App xin email, profile, orders.read, orders.write, billing.read, trong khi thực tế chỉ cần “gợi ý quà theo mô tả”. Với người dùng, điều này trông như thu thập dữ liệu tham lam; với Store — là ứng dụng rủi ro. Trong tài liệu bảo mật cho Apps, đây là ví dụ thực hành tệ.

Lỗi số 3: Không khớp giữa manifest và listing.
Trong manifest bạn có create_order, cancel_order và truy cập thao tác thanh toán, còn mô tả chỉ viết “đề xuất quà tặng”. Sớm muộn người review hoặc người dùng sẽ nhận ra App làm được nhiều hơn lời hứa. Điều này phá vỡ niềm tin và có thể dẫn tới việc gỡ App khỏi Store.

Lỗi số 4: Cố giấu hành động nhạy cảm sau UI “vô hại”.
Ví dụ, bạn vẽ nút “Lưu danh sách” trong widget, nhưng thực tế lại gửi email cho cả phòng hoặc tạo task trong hệ thống khác, mà không giải thích trong mục quyền. Store không thích bất ngờ. Tài liệu cho lập trình viên nói rõ: ứng dụng phải làm đúng những gì đã hứa, không có hành vi ẩn.

Lỗi số 5: Đòi đăng nhập “ngay cửa”, trong khi có thể không cần.
App khởi chạy — và lập tức yêu cầu kết nối tài khoản, cấp mọi quyền, nếu không “không hoạt động”, mặc dù một nửa kịch bản có thể làm ẩn danh. Điều này làm giảm chuyển đổi và tạo ấn tượng bạn vội thu thập dữ liệu hơn là mang lại giá trị. Tốt hơn hãy chứng minh App hữu ích trước, rồi mới giải thích vì sao cần quyền bổ sung.

Lỗi số 6: Bỏ qua bối cảnh tổ chức.
Đôi khi lập trình viên làm App “cho mọi người”, nhưng thực chất là công cụ nội bộ. Kết quả là họ đưa vào Store những quyền rất đặc thù (CRM nội bộ, dữ liệu riêng tư của nhân viên) khó giải thích hợp lý cho người dùng đại chúng. Trong các trường hợp như vậy, nên hướng đến chế độ org‑only và review nội bộ, thay vì Store công khai.

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION