◀ Playbook index
NO.30.8

⚖️ Governance

Updated: 2026-10-27

In one line

Governance is deciding who can do what.

Start with your orgs. Then shape them with teams, policies and rulesets.

Rules flow downward, to repos and to Copilot.

Three org models 📖 Docs 🏢 Ricoh case

DEMOBase permissionFOR PRESENTER ONLY
  1. ORG BASE PERMISSION

    theomonfort-org → Member privileges ↗

    Organization settings → Access → Member privileges → Base permissions

    Open the dropdown: No permission, Read, Write, Admin.

    No permission = Single org / 🔴 Red. Write = 🟢 Green / 🟡 Sandbox. Changes apply to every member at once, so show it without saving.

First decision: how many orgs? Each model changes what everyone can see by default.

▸ Click a model

1 · Single org

Single organization

Everything in one org; teams and repo permissions do the rest. By default you only see the repos you're added to (Org base permission = None). Left there it silos people, so add an all-members team to shared repos by default.

2 · Red / Green / SB

Red-green-sandbox

You run three orgs. 🟢 Green is the default home, ~90% of repos: everyone reads and pushes from day one, so InnerSource happens (base permission = Write). 🔴 Red is confidential, invite-only (base permission = None). 🟡 Sandbox is for experiments, and takes personal repos if you block them (base permission = Write).

3 · Portfolio

Portfolio company

One org per top-level division (one below the CEO). Reorgs happen inside a division, so those survive. Orgs move between enterprises, which helps with M&A.

🏢 FIELD CASE — RICOH

One org per department meant 100+ orgs and no way to find code. Now one shared org everyone can join hosts InnerSource and publishes the enterprise settings as Markdown.

Granting access 📖 Docs

Now let people in: IdP → teams → repos. Never individuals.

flowchart LR
  IDP["🪪 IdP (Okta)<br/>single source"]
  ENT["🏛️ Enterprise Team 📖<br/>Admin · all orgs"]
  ORG["🏢 Org Team 📖<br/>this org · from org chart"]
  REPO["📦 Repository"]
  IDP -->|"SCIM (EMU only)"| ENT
  IDP -->|"SCIM / team sync"| ORG
  ORG -->|Write etc.| REPO
  ENT -->|Admin| REPO

  classDef idp fill:#1a0a2e,stroke:#ffb000,color:#ffb000,stroke-width:2px
  classDef ent fill:#2a0a0a,stroke:#ff5555,color:#ff5555,stroke-width:2px
  classDef org fill:#0a0e27,stroke:#00f0ff,color:#00f0ff,stroke-width:2px
  classDef repo fill:#0a1a14,stroke:#9bbc0f,color:#9bbc0f,stroke-width:2px
  class IDP idp
  class ENT ent
  class ORG org
  class REPO repo

  click ENT href "https://docs.github.com/en/enterprise-cloud@latest/admin/managing-accounts-and-repositories/managing-users-in-your-enterprise/create-enterprise-teams" "Enterprise teams docs" _blank
  click ORG href "https://docs.github.com/en/organizations/organizing-members-into-teams/about-teams" "Organization teams docs" _blank

Org vs enterprise teams 📖 Docs

Many orgs → enterprise team. One org → org team.

🏢 Org team🏛️ Enterprise team
🎯 ScopeOne orgMany orgs
🎫 GrantsRepo roles, org roles, CopilotAll of the left + enterprise roles
🪪 IdP sync✅ EMU, ✅ personal accounts✅ EMU, ❌ personal accounts
💰 Cost center❌✅ members follow the team
💬 @mention@org/team@/ent:team
📂 CODEOWNERS✅❌ (as of 2026-10-14)

⚠️ Assigning an enterprise team to an org adds its members with no invite. Outside collaborators become enterprise members and use a license.

Policies

DEMOEnterprise-assigned usersFOR PRESENTER ONLY
  1. POLICIES FOR ENTERPRISE-ASSIGNED USERS

    octodemo → AI controls → Copilot ↗

    Enterprise → AI controls → Copilot → Policies for enterprise-assigned users

    Open the dropdown: Enabled, Disabled.

    Disabled = every policy left on "Let organizations decide" is off for users licensed directly by the enterprise. Show it without saving.

People are in. Policies decide what they may do — set at org and enterprise, never at the repo.

  • 🏛️ Enterprise — SSO / SCIM, allowed features, base policy for every org
  • 🤖 Copilot models — the global model policy sets the default for new models. Enterprise teams can get extras (preview ↗).
  • 🏢 Org — member privileges, repo creation, 2FA, Copilot and Actions access
  • 📦 Repo — holds no policy, only inherits. The one thing a repo adds is a ruleset.
  • 🔁 Rules flow down. An org can tighten enterprise rules, never loosen them.
  • 👤 Copilot license, no org: “Let organizations decide” doesn’t apply. The enterprise’s Policies for enterprise-assigned users setting decides instead; if it is disabled, those features are off. Copilot policies ↗

🎯 Set guardrails top-down. Never repo by repo. Org policies ↗ · Enterprise policies ↗

Admin roles 📖 Docs

Policies are set. Now, who may change them? That is not a repo role.

  • 🏛️ Enterprise owner — every setting and policy, yet no org settings or content by default
  • 🏢 Org owner — full control of one org. Keep it small, never below two.
  • 🛡️ Security manager — read on every repo plus alert management. Security teams need no Owner
  • 🧩 Custom org roles — bundle only what is needed, e.g. “view the audit log” (GHEC)

🎯 Owner is a key, not a job title. Look for a smaller role first. Org roles ↗ · Custom org roles ↗

Repository roles

Now inside the repo: who does what. Roles are cumulative.

RoleAdds to the role below
👀 ReadView, clone, open issues
🔺 TriageManage issues and PRs — label, assign, close
✍️ WritePush and merge
🛠️ MaintainNon-destructive repo settings
👑 AdminFull control — access, visibility, deletion

🧩 If none fit, build a custom repository role at org level from any base role. Custom roles ↗

Rulesets 📖 Docs

DEMOCritical servicesFOR PRESENTER ONLY
  1. CREATE CUSTOM PROPERTY

    Prerequisites: dedicated demo repos, org owner, GitHub Team / Enterprise, one colleague with Write access for approval.

    theomonfort-org → Custom properties ↗

    Organization settings → Repository → Custom properties → New property

    Name: business_criticality
    Description: Business impact of service disruption

    Type: Single select
    Values: critical, standard, experimental

    Allow repository actors to set this property: OFF (central control prevents repo-level opt-out)
    Require this property for all repositories: OFF
    Default: none → Save property

  2. ASSIGN REPO VALUES

    Same Custom properties page → Set values → select existing demo repos → Edit properties

    business_criticality = critical → Save changes

    Repeat for another demo repo, setting it to experimental.

    Example names only: payments-api / order-service = critical; recommendations-lab = experimental. Substitute your actual demo repos.

  3. CREATE ONE ORG RULESET

    theomonfort-org → Rulesets ↗

    Organization settings → Repository → Rulesets → New ruleset → New branch ruleset

    Ruleset name: Critical services: reviewed changes
    Enforcement status: Active
    Bypass list: leave empty

    Target repositories: Repositories matching a filter
    Filter: props.business_criticality:critical

    Target branches: Add a target → Default branch

    Require a pull request before merging: ON
    Required approvals: 1
    Dismiss stale pull request approvals when new commits are pushed: ON
    Require conversation resolution before merging: ON

    Block force pushes: ON
    Restrict deletions: ON

    Restrict updates: OFF
    Require status checks to pass before merging: OFF
    Require signed commits: OFF → Create

  4. VERIFY THE PAYOFF

    Push a new change directly to a critical repo's default branch → rejected. Open a PR from a working branch → one other person's approval required.

    Custom properties → Set values → select the experimental demo repo → Edit properties → business_criticality = critical → Save changes

    In that repo's Settings → Rules → Rulesets, show the same org ruleset applies. Change the classification, not the ruleset.

Policies say what is allowed, roles say who acts. Rulesets say what the code must pass.

  • 🛡️ Branch protection’s successor — reviews, checks, signing, force-push bans, in one object
  • 🏛️ Defined at ENT / ORG / REPO — set it high and every repo below inherits it
  • 🔁 They stack — when several apply, the strictest wins. No loosening below
  • 🧪 Evaluate mode — measure impact without enforcing. Start here on existing repos

🎯 Don’t grant bypass. A ruleset with bypass is a request, not a rule. Org rulesets ↗

12 anti-patterns

That is the structure. Here is what breaks it. 01, 02 and 11 are the hard ones to undo.

▸ Click a number — the damage, then the fix

01Org per team

01One org per team or project

❌ ResultCollaboration fragments, admin work multiplies, innersource stops working.

✅ InsteadDraw the boundary with teams and repo permissions inside one org.

02Orgs = org chart

02Orgs mapped to the management hierarchy

❌ ResultEvery reorg forces a matching GitHub restructure.

✅ InsteadMap only to the highest, static divisions — or not at all.

03Admin as base

03Admin granted as the base permission

❌ ResultEvery member gets destructive rights on every repo.

✅ InsteadBase Read or Write, then elevate through teams.

04Allow all Actions

04"Allow all actions" with no review

❌ ResultUnvetted third-party actions become a supply-chain path into your builds.

✅ InsteadKeep an allow list and pin actions by commit SHA.

05Unlimited spending

05Spending limits left unlimited

❌ ResultInvoiced accounts default to unlimited, so overspend is silent.

✅ InsteadSet explicit limits and track them with cost centers.

06Manual provisioning

06Manual user provisioning only

❌ ResultLeavers keep their access, because nothing revokes it.

✅ InsteadSCIM provisioning and deprovisioning from the IdP.

07API polling

07Polling the API instead of using webhooks

❌ ResultBurns the rate limit and adds load for no new information.

✅ InsteadEvent-driven webhooks.

08Log retention

08Ignoring audit log retention

❌ ResultDefault retention is short, so evidence is gone when you need it.

✅ InsteadConfigure audit log streaming or export.

09App per org

09Enterprise-wide apps installed org by org

❌ ResultAdmin work multiplies, approvals scatter, configuration drifts.

✅ InsteadEnterprise-level GitHub App installation.

10Owner for everything

10Owner where a custom role would do

❌ ResultEnterprise and Org Owner are far broader than the actual need.

✅ InsteadCustom roles scoped to one capability.

11Late model switch

11Changing the user access model after rollout

❌ ResultStandard ↔ EMU is a migration, not a setting you flip.

✅ InsteadChoose it when the enterprise is created.

12No offboarding

12No offboarding path

❌ ResultDormant accounts keep access and keep consuming licences.

✅ InsteadUnaffiliated users policy plus SCIM deprovisioning.

SELECT A NUMBER ▸

The 21 guardrails 📖 Well-Architected

Values to set, and where. 19 to 21 are Copilot. Short on time? 03, 15, 18.

▸ Click a number · ENT / ORG / REPO = where you set it

01Actions scope

01Actions execution scopeORG

⚙️ Set toRestrict Actions to specific repositories, not all of them.

02Allowed actions

02Which actions may runENT

⚙️ Set toGitHub-created and Verified Creator only.

03Workflow token

03Default workflow token permissionENT / ORG

⚙️ Set toread-only. It ships as read/write.

💡 WhyA stolen token can otherwise write through Actions.

04PR auto-approval

04Automatic approval of pull requestsENT / ORG

⚙️ Set toDisabled. It is on by default.

💡 WhyOtherwise a PR can be merged around code review.

05Forking

05Repository forkingENT / ORG

⚙️ Set toOff unless a repo clearly needs it.

06Visibility change

06Changing repository visibilityENT / ORG

⚙️ Set toRestrict who can flip a repo's visibility.

07Fine-grained PATs

07Fine-grained personal access tokensENT / ORG

⚙️ Set toRequire an approval flow.

💡 WhyYou get a review of who reaches what, with which permission.

08Outside collabs

08Inviting outside collaboratorsENT

⚙️ Set toOwners only. It ships as "No policy", so any member can invite.

09Public repos

09Creating public repositoriesENT

⚙️ Set toBlocked, unless open source is governed separately.

10Webhook secret

10Webhook secretORG / REPO

⚙️ Set toAlways set, so the receiver can verify the signature.

11Webhook SSL

11Webhook transportORG / REPO

⚙️ Set toSSL on every endpoint.

12Rulesets

12Repository rulesetsENT / ORG / REPO

⚙️ Set toUse rulesets for reviews, checks and protected branches.

13CODEOWNERS

13CODEOWNERSREPO

⚙️ Set toDefine it under .github/, with an explicit owner per path.

14Commit signing

14Commit signingREPO

⚙️ Set toRequired wherever possible.

💡 WhyBlocks commit injection. Copilot cloud agent commits are already signed.

15Ruleset bypass

15Bypassing rulesetsREPO

⚙️ Set toNot allowed. A ruleset with a bypass list is a suggestion.

16Runner groups

16Runner groupsENT / ORG

⚙️ Set toAssign each group to a limited set of repos.

💡 WhyA group open to every repo exposes self-hosted runners.

17Push protection

17Bypassing push protectionORG

⚙️ Set toLimit to named roles and teams. By default anyone with write can bypass.

18Audit log stream

18Audit log streamingENT

⚙️ Set toConfigured, to your SIEM or object store.

💡 WhyThe most forgotten item, and the best source for spotting abuse.

19Agent permissions

19Copilot permissionsENT

⚙️ Set toNo YOLO mode, via disableBypassPermissionsMode.

💡 WhyIn allow-all mode the agent runs anything without asking.

20Agent sandbox

20Copilot local sandboxENT

⚙️ Set toEnforced, with enabled: true and allowBypass: false.

💡 WhyThe agent stays in the workspace, away from ~/.ssh and Keychain.

21MCP allowlist

21MCP server allowlistENT

⚙️ Set toallowedMcpServers lists only vetted servers.

💡 WhyAn unvetted MCP server can receive your code and tokens.

SELECT A NUMBER ▸

Copilot managed settings (NEW)

DEMO3 deployment methodsFOR PRESENTER ONLY
  1. SERVER-MANAGED (.github-private)

    theomonfort-org/.github-private → copilot/managed-settings.json ↗

    The baseline for everyone in the enterprise. Show permissions, enabledPlugins and allowedMcpServers. teams/ and team-mappings.json in the same folder override it per team.

    Push to the default branch: applied within about an hour. Restart the client or sign in again to apply it now.

  2. FILE-BASED (file on the device)

    In Finder, press ⌘⇧G and paste the path:

    /Library/Application Support/GitHubCopilot/

    A managed-settings.json sits there (on this Mac: telemetry settings).

    Same JSON as server-managed. The CLI only reads it if it's owned by root and not group- or world-writable. Restart the client after a change.

  3. MDM (managed preferences)

    In Terminal, run:

    plutil -p "/Library/Managed Preferences/com.github.copilot.plist"

    On this Mac it shows "remoteControl.mode" => "disabled".

    MDM doesn't deploy a JSON file: it pushes dot-separated keys with string values (Intune and similar tools). When settings overlap, MDM → server-managed → file win in that order.

Same idea for Copilot clients: copilot/managed-settings.json overrides local settings. Order: MDM → server-managed → file → user. Get started ↗ · All keys ↗

▸ + reveals what the key controls · the date opens its changelog

modelOVERRIDABLE2026-09-02

Set the default model for new conversations (auto or any other). Users can still switch.

permissions.*OVERRIDABLE2026-09-09

Admins control what Copilot can do. Priority: deny > ask > allow.
🚫 disableBypassPermissionsMode: no YOLO / allow-all
❌ deny: never runs, even if the user says yes (e.g. Shell(rm -rf *))
⚠️ ask: user approval every time, even in YOLO (e.g. Shell(git push *))
✅ allow: runs without a prompt (e.g. Shell(npm test *))
Rules use Shell() / Read() / Edit() / Domain(). Unlisted ones ask first

sandboxOVERRIDABLE2026-07-29

Enforce the local sandbox (CLI and Copilot app only). By default:
✅ Read/write the working folder, run tools, git / gh, internet
❌ Any other file (e.g. ~/.ssh), macOS Keychain
⚠️ Users can approve a command to run outside it (block with allowBypass: false)
Default permissions ↗

features.computerUseLOCKED2026-10-01

Turn off computer use (Copilot clicking and typing in desktop apps, CLI and Copilot app only).
❌ false: blocked, a local setting can't turn it back on
✅ true or unset: each user decides

enabledPluginsADDITIVE · marketplacesOVERRIDABLE2026-08-26

🏪 extraKnownMarketplaces: add your plugin repo, with autoUpdate
🧩 enabledPlugins: force on (true, auto-install) or off (false)
🔒 strictKnownMarketplaces: only listed repos ([] blocks all)

allowedMcpServers · deniedMcpServersOVERRIDABLE2026-08-06

Allowlist allowedMcpServers: only these run (strict). [] = built-ins only.
Denylist deniedMcpServers: only these are blocked (loose), even if allowed.
Match by URL (* ok) or command. Built-ins like GitHub MCP can't be blocked.

remoteControlLOCKED2026-07-30

Remote control of sessions on this device: require SSO, or turn it off.

telemetryLOCKED2026-07-08

OpenTelemetry export to your own collector.

teams/ + team-mappings.json2026-08-03

One baseline, plus a per-team value on OVERRIDABLE keys. Wrap the default in { "overridable": … }, then set a plain value in teams/*.json. Left out, the baseline applies. sandbox and marketplace lists are replaced whole.
Not on this slide (as of 2026-10-14): autoTier is overridable, forceRemoteSettingsRefresh is locked.
User in several teams: the least restrictive value wins.

.github-private & source org

They live in one repo you own, set in Enterprise → AI controls → Agents.

.github-private/
├── agents/                    # published enterprise-wide
├── .github/agents/            # staging, test before publishing
└── copilot/
    ├── managed-settings.json  # the baseline
    ├── team-mappings.json     # file → enterprise team
    └── teams/*.json           # per-team override
  • 🏢 You pick the org. The repo name and copilot/ paths are fixed.
  • 🔒 Applies to everyone on the plan, repo access or not. Keep it internal and guard copilot/** with CODEOWNERS.
  • ✅ Config errors show up under Copilot settings validation. 2026-09-25 ↗

★ Where it fits

Five layers, one rule: set them from the top.

LayerScopeExamples
🏢 Policiesorg → enterprise2FA, visibility, feature access
🔑 Admin rolesorg → enterpriseOwner, Security manager, custom
👤 Permission rolesRepositoryRead / Write / Admin
🛡️ RulesetsBranches and tagsRequired reviews, required checks, signing
🤖 Managed settingsCopilot clientsDefault model, bypass lock, plugins

🎯 Top-down wins. Per-repo does not scale.

For cost allocation and spending controls, see Cost centers & budgets ↗.

Slides 日本語