Skip to content

Octoform 0.3.1 behavior baseline

This document records the behavior shipped in @hector21/octoform@0.3.1. It is an audit baseline for documentation and compatibility work, not a roadmap. Future multi-owner and organization governance work is intentionally absent.

The evidence was collected from the published npm artifact, its generated type declarations, the source commit tagged v0.3.1, the test suite, and the GitHub API descriptions identified below. When prose and executable behavior differ, this baseline reports the executable behavior.

Published artifact

Property Observed value
Package @hector21/octoform@0.3.1
npm integrity sha512-jP3YhMyq9+DF+Jw9JRSTG/66pZg+0J2nsAnorJd0ktMZyJwsAfj8kXCvjFlIVrUtsm/q+WiaDQ94ubZjqi9K9w==
npm shasum 93d42cb44696ff1d9d1d692a5655b434a3a849f5
Packed size 71,428 bytes
Unpacked size 257,062 bytes
Entries 62
Runtime ESM, Node.js 20 or newer
Executable octoformbin/octoform.js

The artifact contains bin/, compiled dist/ JavaScript and declarations, source maps, documentation, examples, README, changelog, license, and package metadata. It does not contain src/ or test/. A clean installation imports the package and executes octoform --help successfully.

CLI surface

Command Options Read/write contract Observed successful exit
audit --config Read-only inventory and findings 0, including findings
plan --config, --repo, --type Read-only desired/current diff 0
apply --config, --repo, --type, --yes Shows a plan, confirms, then mutates 0 when all changes apply
classify --config, --apply Proposes types; writes property values only with --apply 0
properties sync --config Creates/updates the organization custom-property schema and values 0

Global aliases are -h for --help and -y for --yes. The default configuration path is octoform.yml. Tokens are read from GITHUB_TOKEN, then GH_TOKEN. There is no JSON output mode in v0.3.1.

Observed argument and exit behavior

Invocation Exit Output behavior
octoform 2 Usage on standard output
octoform --help 0 Usage on standard output
octoform plan --help 0 Global usage on standard output
octoform --nonsense 2 Error on standard error, usage on standard output
option without its value 2 Error on standard error, usage on standard output
invalid configuration or authentication 1 Diagnostic on standard error
declined apply 1 No mutation
partially or fully failed apply 1 Per-change results are reported

Command and subcommand names are checked only after configuration loading and client creation. Consequently, an unknown command or invalid properties subcommand can return configuration/authentication exit 1 before it reaches the intended usage exit 2. This contradicts the unconditional wording in the current exit-code reference and is a confirmed v0.3.1 limitation.

Configuration surface

Every scalar policy is unmanaged when omitted. Managed values layer in this order: defaults, the repository's resolved types.<type>, then repos.<name>. null cancels an inherited scalar and resolves to unmanaged. An empty configuration fragment does not change a repository.

Block Fields and behavior
root owner, imports, defaults, types, repos, exclude, classify, audit
exclude Repository names removed from inventory and all later processing
classify Custom-property name and first-match rules by file, shallow JSON, and visibility
audit Description, topics, maximum topics, and type expectations; never mutates
manage false keeps a repository visible to audit but suppresses policy planning
features issues, wiki, projects, discussions
merge squash, merge commit, rebase, auto-merge, update branch, delete branch after merge
security vulnerability alerts, automated fixes, private reporting, secret scanning, push protection, code-scanning default setup
repo description, homepage, topics, forking, web commit sign-off
default_branch desired name and guarded rename_from allowlist
ensure_branches Creates missing branches from the current default branch
rulesets Named active branch rulesets with target branches, approvals, checks, force-push block, deletion block
environments Named environments and required user reviewers
files create-if-missing only, with local source resolved relative to its declaring file

Imports resolve relative to the declaring YAML file, can import other files, and reject cycles. Imported fragments may omit owner; the final resolved configuration must contain one owner. Object fields merge recursively, while declared arrays replace the inherited array at their policy level.

Desired-state coverage

Resource Read Plan Apply Important boundary
Repository features Yes Yes Yes Discussions are read but not written by REST in this version
Merge settings Yes Yes Yes Applied in one repository settings patch
Repository metadata/topics Yes Yes Yes Topics use their dedicated endpoint
Security toggles Yes Yes Yes Unreadable state blocks rather than assumes disabled
Default branch Yes Yes Yes Rename requires rename_from; affected workflow files are named
Ensured branches On demand Yes Yes Created from the current default branch SHA
Rulesets On demand Yes Yes Only modeled rules are compared; unknown remote rules are preserved conceptually
Environments On demand Yes Yes Team reviewers are unreadable and block replacement
Files On demand Yes Yes Missing-only; no overwrite or deletion
Repository type property Yes Yes classify --apply / properties sync Organization custom property; personal fallback is local config
Audit expectations Yes Findings Never Findings still exit 0

Archived repositories are inventoried but policy planning skips them. A policy with manage: false is also skipped. --repo and --type narrow plan/apply; they do not change desired values.

GitHub API usage

v0.3.1 does not send X-GitHub-Api-Version. GitHub therefore applies the documented default 2022-11-28. That API version remains supported until 2028-03-10, but relying on an implicit default is a compatibility risk and must be treated separately from this behavior audit.

The implementation uses REST only. It makes no GraphQL request in v0.3.1.

Inventory and discovery

Purpose REST operation
Scope inspection/authenticated identity GET /user
Owner kind and organization plan GET /orgs/{org}
Organization repositories GET /orgs/{org}/repos
Own personal repositories GET /user/repos
Another user's public repositories GET /users/{username}/repos
Repository details/settings GET /repos/{owner}/{repo}
Organization ruleset capability probe GET /orgs/{org}/rulesets
Private repository ruleset capability probe GET /repos/{owner}/{repo}/branches/{branch}/protection

Repository state reads

Resource REST operation
Vulnerability alerts GET /repos/{owner}/{repo}/vulnerability-alerts
Automated security fixes GET /repos/{owner}/{repo}/automated-security-fixes
Private vulnerability reporting GET /repos/{owner}/{repo}/private-vulnerability-reporting
Code-scanning default setup GET /repos/{owner}/{repo}/code-scanning/default-setup
Branch existence GET /repos/{owner}/{repo}/branches/{branch}
Environments GET /repos/{owner}/{repo}/environments
Ruleset summaries/details GET /repos/{owner}/{repo}/rulesets, GET /repos/{owner}/{repo}/rulesets/{ruleset_id}
Files and workflow contents GET /repos/{owner}/{repo}/contents/{path}
Git reference GET /repos/{owner}/{repo}/git/ref/{ref}
Organization property values GET /orgs/{org}/properties/values
Reviewer identity GET /users/{username}

Mutations

Resource REST operation
Repository settings and selected security analysis fields PATCH /repos/{owner}/{repo}
Topics PUT /repos/{owner}/{repo}/topics
Vulnerability alerts PUT or DELETE /repos/{owner}/{repo}/vulnerability-alerts
Automated security fixes PUT or DELETE /repos/{owner}/{repo}/automated-security-fixes
Private vulnerability reporting PUT or DELETE /repos/{owner}/{repo}/private-vulnerability-reporting
Code-scanning default setup PATCH /repos/{owner}/{repo}/code-scanning/default-setup
Default branch rename POST /repos/{owner}/{repo}/branches/{branch}/rename
Branch creation POST /repos/{owner}/{repo}/git/refs
Environment create/update PUT /repos/{owner}/{repo}/environments/{environment_name}
Ruleset create/update POST /repos/{owner}/{repo}/rulesets, PUT /repos/{owner}/{repo}/rulesets/{ruleset_id}
File creation PUT /repos/{owner}/{repo}/contents/{path} without sha
Custom-property schema PUT /orgs/{org}/properties/schema/{custom_property_name}
Custom-property values PATCH /orgs/{org}/properties/values

Authentication and permissions

The CLI's classic-token preflight requires repo for every command. Mutating organization property commands additionally require admin:org. Fine-grained tokens do not expose x-oauth-scopes; absence of that header bypasses the classic-scope check, and each API endpoint remains the authority.

The documented scopes are a coarse v0.3.1 contract, not a minimum fine-grained permission matrix. Repository settings, administration, contents, environments, rules, security events, organization rules, and custom properties can require different fine-grained permissions and owner roles. The versioned documentation must describe those per capability instead of claiming that one classic scope statement precisely covers every token type.

Confirmed limitations and documentation corrections

  1. Unknown command/subcommand validation occurs too late and can report exit 1 for missing config/token instead of usage exit 2.
  2. REST API version selection is implicit (2022-11-28), not pinned in the client.
  3. Discussions can be observed but not applied because the implementation has no GraphQL transport and the setting is not writable through the used REST repository update contract.
  4. Environment reviewer policies model users only. An existing team reviewer makes the field unreadable and blocks a change.
  5. Rulesets model only branch target/include conditions, approvals, status checks, force-push blocking, and deletion blocking.
  6. Personal accounts do not have organization custom properties; repository types must come from configuration there.
  7. Classic scope documentation is not a fine-grained permission matrix.
  8. audit reports findings but deliberately cannot gate CI through its exit code.
  9. No machine-readable CLI output or stable diagnostic-code contract exists.
  10. No repository, ruleset, environment, file, or access removal is inferred from omission; file management is create-if-missing only.

Upstream API evidence

Evidence Value
Effective unversioned REST default 2022-11-28
Current audited REST description 2026-03-10
OpenAPI repository commit b26c240ded1c8b79cb0fb09dee4a21239061fa23
Bundled OpenAPI SHA-256 6f36bc90e67dedbdb256880d0c5daaaba0afa8ce7bde343db7cc7f608492a997f
REST operations in full description 1,220
Mutating REST operations in full description 584
GraphQL mutations observed during audit 274, including 16 deprecated

Primary sources:

The complete endpoint disposition register is generated from reviewed metadata and the pinned API descriptions. It covers the owner/repository scopes relevant to Octoform and records why every operation is declarative, sensitive declarative, operational, observational, or excluded.