AI-50: GitHub auth and fork pull request policy
Status
Accepted for the pilot slice.
This record keeps the original decision. Live operator rules are in How to add Harbourmaster reviews to a repository and the GitHub Action reference.
Implementation after the pilot slice changed these parts:
- The workflow skips fork pull requests before checkout. They do not run a read-only review.
- Dependabot has no extra skip rule. A same-repository Dependabot pull request can start a review.
- The trusted OpenCode
publish_reviewplugin publishes the advisory review. The TypeScript runner verifies the marked review and the private receipt.
Decision
Harbourmaster will run the pilot from GitHub Actions using either the workflow
GITHUB_TOKEN for same-repository pull requests or a GitHub App installation
token for org-wide rollout. All GitHub reads and writes must stay behind the
Octokit provider layer. Reviewer runtime code receives only provider-neutral
pull request context and review results.
The pilot starts in comment-only mode. Harbourmaster publishes one pull request review containing the summary and any mappable inline findings. It must not approve, request changes, merge, label, close, or otherwise mutate repository state during this slice.
Consumer repositories run TilloTech/eos/apps/harbourmaster@main, using the
latest Harbourmaster version merged to EOS. EOS self-reviews are an explicit
exception: same-repository, non-draft EOS pull requests run the local action
from the exact pull request head so Harbourmaster changes can be tested before
merge. This invariant does not apply to consumer repositories.
Fork and Dependabot behavior
Fork pull requests are skipped by the supported workflow before checkout. The runner also skips fork pull requests by policy. They do not run read-only context construction or OpenCode review execution.
Dependabot pull requests from the same repository are not forks. They have no extra skip rule and can start a review unless a separate workflow guard excludes them.
The safe boundary is:
- The supported workflow skips fork and draft pull requests before checkout, dependency installation, OIDC, or action execution.
- Do not run
pull_request_targetagainst untrusted head code. - Do not let OpenCode call GitHub APIs directly.
- Load Harbourmaster agents and plugins only from the trusted bundled runtime
configuration. Repository-owned
.opencodefiles are review context, not executable reviewer configuration. - The trusted
publish_reviewplugin publishes the advisory review after the runner validates it.
Required GitHub permissions
Same-repository pilot workflows should request the minimum permissions needed for the enabled phase:
permissions:
contents: read
pull-requests: write
issues: write
contents: read is required to load repository context. pull-requests: write
lets the review job apply harbourmaster-review and create PR reviews.
issues: write lets the job create the repository label when it is missing and
supports issue comment reads for duplicate suppression. Harbourmaster itself
must not add or remove labels; only the workflow label step does.
GitHub App installations need the same repository permissions:
- Contents: read
- Pull requests: read and write
- Issues: read
The supported workflow still uses GITHUB_TOKEN with issues: write to create
the harbourmaster-review label. That label step does not use the App token.
Future checks or status reporting must add only the specific permission needed by that feature.
OpenCode runtime policy
OpenCode is the reviewer runtime, not the GitHub publisher.
- Credentials are passed through explicitly named environment variables owned by the runtime boundary.
- CI uses Harbourmaster's bundled OpenCode configuration and never executes agents or plugins from the repository being reviewed.
- The reviewed repository is passed as an explicit absolute workspace root.
- The canonical workspace path must remain inside a separately supplied trusted
boundary such as
GITHUB_WORKSPACE; symlink escapes are rejected. - OpenCode starts in an isolated diff directory. Before it starts, the trusted
runner writes
review-index.json,shared-pr-context.txt, andreview-discussion.txt. review-index.jsonrecords the repository root, exact base and head, changed paths, statuses, rename paths, patch paths, and per-hunk base, head, and patch-line ranges. A missing patch path isnull.- The editor keeps the required publication and lifecycle context inline. It
invokes
spawn_reviewersdirectly and cannot write or copy review context. - Specialists and the verifier may use only the read-only tools
read,glob,grep, andlist. A session-boundread_moretool can continue a truncated repository result. - The code-quality reviewer receives the canonical checkout root in its prompt and can inspect that checkout alongside the staged diff material. Other specialists and the verifier can inspect only the staged diff material.
- The pinned OpenCode runtime enforces external-directory permissions. A per-run override grants the code-quality reviewer access to the canonical checkout root. All other external-directory access remains denied.
- A trusted hook canonicalizes paths for
read,glob,grep, andlistand rejects symlink escapes before those tools access files. - Shell, mutation, network, and nested-agent access remain denied.
- Harbourmaster contract tests verify these permissions. OpenCode upgrades must preserve this permission contract before the pin moves.
- Repository files and instructions are untrusted review context and cannot override Harbourmaster safety, tool, scope, validation, or publication rules.
- Findings remain limited to behavior introduced by the pull request and must be anchored to changed lines even when repository context supplies evidence.
- Reviewers must start with the index, inspect every relevant changed patch, search callers, read source ranges, and read tests when the role permits those reads. Missing or truncated results do not prove that no finding exists.
- The SDK server may be
owned-per-runfor CI isolation orshared-externalfor local development. CI should preferowned-per-run. - Sessions are scoped to one PR review run and may be shared only across reviewer agents within that run.
- OpenCode output must be validated into the provider-neutral review result schema before any Octokit publishing step.
pull_request_target policy
Harbourmaster must not use pull_request_target for executing untrusted pull
request code. A future trusted maintainer workflow may use pull_request_target
only to publish previously generated, validated artifacts from a trusted source,
and only if it avoids checking out or executing the untrusted head ref.
Consequences
This keeps the pilot safe and reviewable: GitHub permissions are narrow, publishing remains centralized in Octokit, and OpenCode can be swapped or tested behind the runtime contract without leaking provider-specific fields into reviewer logic.