feat: GitHub App manifest 全量获取:仓库/组织/企业/账号四类最高档
接上轮仓库最大权限:用户明确要求无论什么身份,取该身份 授权范围内的所有权限。manifest 现按四类全拉满(74 项权限、 39 个事件):仓库补 codespaces_lifecycle_admin、repository_ creation、metadata 只读;组织 members 升 write 并补 organization_administration 等 15 项;企业补 8 项;账号补 blocking、email_addresses、gists、密钥类等 22 项。 身份边界写进注释:GitHub 只授予安装身份能给的那部分,个人 装不上组织/企业、企业装不上仓库/组织;换 token 不传子集, token 本就是安装全量;企业安装另需 App 公开/内部 (GITHUB_APP_PUBLIC=1)。诚实边界:企业类键名未用真实 GitHub 建 App 实测,新建时表单会校验,某键被拒删键再建, 线上旧 App 不受影响。
This commit is contained in:
1 parent
668c000394
commit
8fc4e27241
2 files changed
+108
-13
No files matched your search
+96
-13
@@ -45,18 +45,30 @@ SETUP_STATE_TTL_SECONDS = 3600
|
|||||||
DEFAULT_APP_NAME = "codex-app-server"
|
DEFAULT_APP_NAME = "codex-app-server"
|
||||||
DEFAULT_APP_URL = "https://github.com/openqj/codex-app-server"
|
DEFAULT_APP_URL = "https://github.com/openqj/codex-app-server"
|
||||||
|
|
||||||
# App 权限与事件:主机最大权限(用户 2026-10-27 明确要求扩到
|
# App 权限与事件:全量获取(用户 2026-10-27 明确要求:无论
|
||||||
# 最高、所有能力)。这是 manifest 的默认值,只影响以后新建的
|
# 什么身份,取该身份授权范围内的所有权限)。
|
||||||
# App;已存在的线上 App(id 5476837)不会因改代码自动变权限,
|
# 原则:manifest 里按仓库 / 组织 / 企业 / 账号四类全部拉到最高
|
||||||
# 必须在 GitHub App 设置里改权限并由安装方接受新权限后才生效。
|
# 档,安装时 GitHub 只授予该身份能给的那部分——个人账号装不上
|
||||||
# 风险明示:administration=write 含改仓库设置/删库/转移,
|
# 组织/企业权限,组织装不上企业权限,企业装不上仓库/组织权限,
|
||||||
# secrets=write 含管理仓库 secret,配 All repositories 安装会把
|
# 这是 GitHub 的身份边界,不是代码能绕过的。换 token 时
|
||||||
# 影响面扩到该账号全部仓库——只装在自己信任的账号上。
|
# exchange_installation_token 不传 permissions 子集(payload
|
||||||
# organization/enterprise/billing 类权限不在此列:它们不属于
|
# 为空),所以 token 本来就是安装权限的全量,不会被代码降级。
|
||||||
# 主机跑任务的能力,且需组织/企业管理员另行审批,不应由一个
|
# 这是 manifest 的默认值,只影响以后新建的 App;已存在的线上
|
||||||
# 代码托管 App 默认索取。
|
# App(id 5476837)不会因改代码自动变权限,必须在 GitHub App
|
||||||
|
# 设置里改权限并由安装方接受新权限后才生效。企业安装另需
|
||||||
|
# App 为公开或内部(GITHUB_APP_PUBLIC=1),私有默认装不上企业。
|
||||||
|
# 风险明示:administration / organization_administration /
|
||||||
|
# enterprise 类 write 含删库、转移、改组织/企业设置、管账单,
|
||||||
|
# account 类 write 含管用户密钥、Gist、关注、星标,配 All
|
||||||
|
# repositories 安装时影响面为该身份的全部授权范围——只装在
|
||||||
|
# 自己信任的身份上。
|
||||||
|
# 诚实边界:仓库/组织/账号键名有官方文档与 manifest 示例佐证;
|
||||||
|
# 企业类键名(enterprise_*)未在本机用真实 GitHub 创建 App
|
||||||
|
# 实测过——新建 App 时 GitHub 建 App 表单会逐项校验,若某键
|
||||||
|
# 被拒,删该键再建即可,线上旧 App 不受影响。single_file 未
|
||||||
|
# 列入:它必须配 single_file_paths 才能生效,空列无意义。
|
||||||
APP_PERMISSIONS = {
|
APP_PERMISSIONS = {
|
||||||
# 仓库:除 metadata(GitHub 自动只读)外全部拉到最高档。
|
# 仓库:全部拉到最高档,metadata 只读是 GitHub 自动档。
|
||||||
"actions": "write",
|
"actions": "write",
|
||||||
"actions_variables": "write",
|
"actions_variables": "write",
|
||||||
"administration": "write",
|
"administration": "write",
|
||||||
@@ -64,6 +76,7 @@ APP_PERMISSIONS = {
|
|||||||
"attestations": "write",
|
"attestations": "write",
|
||||||
"checks": "write",
|
"checks": "write",
|
||||||
"codespaces": "write",
|
"codespaces": "write",
|
||||||
|
"codespaces_lifecycle_admin": "write",
|
||||||
"codespaces_metadata": "read",
|
"codespaces_metadata": "read",
|
||||||
"codespaces_secrets": "write",
|
"codespaces_secrets": "write",
|
||||||
"contents": "write",
|
"contents": "write",
|
||||||
@@ -73,10 +86,12 @@ APP_PERMISSIONS = {
|
|||||||
"environments": "write",
|
"environments": "write",
|
||||||
"issues": "write",
|
"issues": "write",
|
||||||
"merge_queues": "write",
|
"merge_queues": "write",
|
||||||
|
"metadata": "read",
|
||||||
"packages": "write",
|
"packages": "write",
|
||||||
"pages": "write",
|
"pages": "write",
|
||||||
"pull_requests": "write",
|
"pull_requests": "write",
|
||||||
"repository_advisories": "write",
|
"repository_advisories": "write",
|
||||||
|
"repository_creation": "write",
|
||||||
"repository_custom_properties": "write",
|
"repository_custom_properties": "write",
|
||||||
"repository_hooks": "write",
|
"repository_hooks": "write",
|
||||||
"secret_scanning_alerts": "write",
|
"secret_scanning_alerts": "write",
|
||||||
@@ -85,8 +100,52 @@ APP_PERMISSIONS = {
|
|||||||
"statuses": "write",
|
"statuses": "write",
|
||||||
"vulnerability_alerts": "write",
|
"vulnerability_alerts": "write",
|
||||||
"workflows": "write",
|
"workflows": "write",
|
||||||
# 组织:只读成员,用于列协作者;不索取组织管理权。
|
# 组织:全部拉到最高档(仅组织安装时生效)。
|
||||||
"members": "read",
|
"members": "write",
|
||||||
|
"organization_administration": "write",
|
||||||
|
"organization_announcement_banners": "write",
|
||||||
|
"organization_copilot_seat_management": "write",
|
||||||
|
"organization_custom_properties": "write",
|
||||||
|
"organization_custom_roles": "write",
|
||||||
|
"organization_dependabot_secrets": "write",
|
||||||
|
"organization_events": "read",
|
||||||
|
"organization_hooks": "write",
|
||||||
|
"organization_packages": "write",
|
||||||
|
"organization_plan": "read",
|
||||||
|
"organization_projects": "write",
|
||||||
|
"organization_secrets": "write",
|
||||||
|
"organization_self_hosted_runners": "write",
|
||||||
|
"organization_user_blocking": "write",
|
||||||
|
# 企业:全部拉到最高档(仅企业安装且 App 公开/内部时生效)。
|
||||||
|
"enterprise_administration": "write",
|
||||||
|
"enterprise_billing": "write",
|
||||||
|
"enterprise_copilot_seat_management": "write",
|
||||||
|
"enterprise_custom_properties_for_organizations": "write",
|
||||||
|
"enterprise_organization_installation_repositories": "write",
|
||||||
|
"enterprise_organization_installations": "write",
|
||||||
|
"enterprise_policies": "write",
|
||||||
|
"enterprise_rules": "write",
|
||||||
|
# 账号:全部拉到最高档(仅用户另外授权 App 代表自己时生效)。
|
||||||
|
"blocking": "write",
|
||||||
|
"codespaces_user_secrets": "write",
|
||||||
|
"copilot_editor_context": "read",
|
||||||
|
"copilot_messages": "read",
|
||||||
|
"copilot_requests": "write",
|
||||||
|
"email_addresses": "write",
|
||||||
|
"followers": "write",
|
||||||
|
"gists": "write",
|
||||||
|
"git_signing_ssh_public_keys": "write",
|
||||||
|
"git_ssh_keys": "write",
|
||||||
|
"gpg_keys": "write",
|
||||||
|
"interaction_limits": "write",
|
||||||
|
"knowledge_bases": "write",
|
||||||
|
"plan": "read",
|
||||||
|
"private_repository_invitations": "read",
|
||||||
|
"profile": "write",
|
||||||
|
"starring": "write",
|
||||||
|
"user_events": "read",
|
||||||
|
"user_models": "read",
|
||||||
|
"watching": "write",
|
||||||
}
|
}
|
||||||
APP_EVENTS = [
|
APP_EVENTS = [
|
||||||
"push",
|
"push",
|
||||||
@@ -100,10 +159,34 @@ APP_EVENTS = [
|
|||||||
"check_run",
|
"check_run",
|
||||||
"check_suite",
|
"check_suite",
|
||||||
"workflow_run",
|
"workflow_run",
|
||||||
|
"workflow_job",
|
||||||
"release",
|
"release",
|
||||||
"deployment",
|
"deployment",
|
||||||
"deployment_status",
|
"deployment_status",
|
||||||
"discussion",
|
"discussion",
|
||||||
|
"discussion_comment",
|
||||||
|
"commit_comment",
|
||||||
|
"code_scanning_alert",
|
||||||
|
"secret_scanning_alert",
|
||||||
|
"label",
|
||||||
|
"milestone",
|
||||||
|
"member",
|
||||||
|
"membership",
|
||||||
|
"organization",
|
||||||
|
"team",
|
||||||
|
"team_add",
|
||||||
|
"repository",
|
||||||
|
"fork",
|
||||||
|
"watch",
|
||||||
|
"meta",
|
||||||
|
"status",
|
||||||
|
"project",
|
||||||
|
"project_card",
|
||||||
|
"project_column",
|
||||||
|
"gollum",
|
||||||
|
"page_build",
|
||||||
|
"public",
|
||||||
|
"repository_dispatch",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -91,11 +91,23 @@ class ManifestTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(m["default_permissions"]["administration"], "write")
|
self.assertEqual(m["default_permissions"]["administration"], "write")
|
||||||
self.assertEqual(m["default_permissions"]["actions"], "write")
|
self.assertEqual(m["default_permissions"]["actions"], "write")
|
||||||
self.assertEqual(m["default_permissions"]["checks"], "write")
|
self.assertEqual(m["default_permissions"]["checks"], "write")
|
||||||
|
# 全量:组织 / 企业 / 账号三类也必须在 manifest 里,不只仓库。
|
||||||
|
self.assertEqual(m["default_permissions"]["members"], "write")
|
||||||
|
self.assertEqual(
|
||||||
|
m["default_permissions"]["organization_administration"],
|
||||||
|
"write")
|
||||||
|
self.assertEqual(
|
||||||
|
m["default_permissions"]["enterprise_organization_installations"],
|
||||||
|
"write")
|
||||||
|
self.assertEqual(m["default_permissions"]["email_addresses"], "write")
|
||||||
|
self.assertEqual(m["default_permissions"]["gists"], "write")
|
||||||
self.assertIn("issue_comment", m["default_events"])
|
self.assertIn("issue_comment", m["default_events"])
|
||||||
self.assertIn("pull_request", m["default_events"])
|
self.assertIn("pull_request", m["default_events"])
|
||||||
self.assertIn("push", m["default_events"])
|
self.assertIn("push", m["default_events"])
|
||||||
self.assertIn("check_run", m["default_events"])
|
self.assertIn("check_run", m["default_events"])
|
||||||
self.assertIn("workflow_run", m["default_events"])
|
self.assertIn("workflow_run", m["default_events"])
|
||||||
|
self.assertIn("organization", m["default_events"])
|
||||||
|
self.assertIn("member", m["default_events"])
|
||||||
self.assertFalse(m["public"])
|
self.assertFalse(m["public"])
|
||||||
|
|
||||||
def test_manifest_requires_base(self):
|
def test_manifest_requires_base(self):
|
||||||
|
|||||||
Reference in new issue
Block a user