---
name: ghtier-assess
description: Assess a GitHub organization's security settings against the ghtier hardening checklist (ghtier.com/checklist) and turn the gaps into a prioritized fix plan. Use when the user asks to audit, assess, benchmark or score their GitHub org's security posture, branch protection, Actions settings, secret scanning or owner count, or asks what they should fix next in GitHub. Runs read-only `gh api` calls with the user's own login.
---

# ghtier-assess

Checks a GitHub organization against the ghtier checklist, writes an assessment file the user can
import on https://ghtier.com/checklist, and gives a fix plan based on what actually failed.

Everything is read-only. The runner only sends GET requests. Never change a GitHub setting as part
of this skill; if the user wants you to apply a fix afterwards, ask first, one change at a time.

## 1. Before you run anything

1. Confirm the organization name with the user. Don't guess it from the git remote.
2. Check the tools: `gh auth status` (must be logged in), `jq --version`, `node --version` (18+).
3. Tell the user what access is needed. Most checks need an **organization owner**. Recommend a
   read-only fine-grained token over the default `gh` login: the default login carries the `repo`
   scope, which is Tier 0 on an owner account, and the runner only ever reads. Have the user
   create one at github.com/settings/personal-access-tokens/new:
   - Resource owner: the organization. Repository access: all repositories. Expiration: a few days.
   - Repository permissions: Administration, Contents and Metadata, all read-only.
   - Organization permissions, all read-only: Administration, Custom organization roles, Custom
     properties, Members, Secrets, Self-hosted runners, Webhooks.
   - The organization may need to approve the token first.

   Then run with it: `GH_TOKEN=<the token> node assess.mjs --org <org>`. Let the user paste it
   into their own shell; never ask for it in the conversation.

   A read-only fine-grained token cannot read three things, which come back as "error" or under
   `inventory.errors`. Organization rulesets need Administration: write. The SSO credential
   authorizations and custom repository roles are not available to fine-grained tokens. If the
   user needs those, a classic token with `admin:org` and `read:org` (plus `repo` for per-repo
   checks) covers everything. Offer `gh auth refresh -s admin:org,read:org,repo` and let the user
   run it.

## 2. Run the checks

`assess.mjs` sits next to this file. Run it with the org name:

```bash
node assess.mjs --org <org>
```

- Checks come from https://ghtier.com/data/checklist.json by default. Inside the ghtier
  repo, use the local copy instead: `--checks public/data/checklist.json`.
- Per-repo checks cover the first 200 non-archived repos. Use `--max-repos N` for bigger orgs,
  and tell the user when the output says not every repo was checked.
- `--only id1,id2` re-runs selected items.
- It also builds an access inventory: who holds Tier 0 and Tier 1 (owners, organization role
  holders, the base permission, installed GitHub Apps, outside collaborators, organization
  self-hosted runners, deploy keys with write access, ruleset bypass actors, organization
  webhooks, organization secrets visible to all repositories, runner groups open to all or public
  repositories, and credentials authorized for SAML SSO with their scopes), tiered with the ghtier
  data. Most of it needs an organization owner; parts the login can't read are listed under
  `inventory.errors`, not guessed, and so is anything left out by the `--max-repos` cap. Skip it
  with `--no-inventory`.
- The checks and tier data are fetched from the ghtier site. Each file's SHA-256 is recorded
  under `sources` in the output. To pin them, download the files listed in
  https://ghtier.com/skills/ghtier-assess/SHA256SUMS. Read them, check them with
  `shasum -a 256 -c SHA256SUMS`, and run with `--checks ./checklist.json --pin SHA256SUMS`. The
  run then stops if any file differs.
- The jq rules run with an empty environment, and check calls outside the organization are
  refused.

It writes two files in the current directory and prints a summary:

- `ghtier-assessment-<org>.json`: the raw results.
- `ghtier-report-<org>.html`: a printable report (posture map, who holds Tier 0 and Tier 1,
  remediation plan, all findings). Open it in a browser; its "Save as PDF" button prints it to A4. It's built from
  `report.html` next to this file, which is never fetched over the network: without it the
  report is skipped. The report loads nothing from the network, and its Content Security Policy
  blocks it from sending anything. Skip it with `--no-report`.

If `assess.mjs` isn't available, you can follow the same rules by hand: they are listed under
"Assessing your own organization" in https://ghtier.com/llms.txt, and each item's `check`
in checklist.json has the exact `gh api` paths and jq rule.

## 3. Fill in the gaps

Read the assessment file and checklist.json together.

- **review**: the check ran but can't decide alone (for example the installed app list). Show
  the user the `detail` and ask.
- **error**: usually missing access. Say which permission is missing (the item's `check.needs`).
- **Items with no `check`**: ask the user about them in one short batch, grouped by category.
  Don't mark them done on your own.

## 4. Report back

Give a short plan, not a dump:

1. One line of overall status: counts of pass / partial / fail / not checked.
2. **Who holds Tier 0 and Tier 1**: from `inventory.holders`, name the Tier 0 holders and the
   count of Tier 1 holders. Ask the user whether each Tier 0 holder still needs it. List the
   rows with `tier: null` as things to review, and anything under `inventory.errors` as not
   checked.
3. **Fix first**: failing or partial items, ordered by effort (`quick-win`, then `quarter`, then
   `initiative`). For each, use the item's `text`, the `detail` evidence, its `prerequisites`, and
   its `steps` with `ORG` / `ENTERPRISE` / `REPO` replaced by the real names. End with its `docs`
   link. For per-repo items, list the failing repos from `detail`.
4. Where an item has `scenarioIds`, mention the real incident it relates to, as a link to
   `https://ghtier.com/scenarios/<id without its user-/org-/ent-/app- prefix>`.
5. Point the user at `ghtier-report-<org>.html` for a shareable version, and tell them they
   can import the JSON file on https://ghtier.com/checklist (the "Import assessment"
   button) to see it on the checklist.

Keep org data in the conversation and the local file. Don't paste it into other services.
