Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 169 additions & 0 deletions docs/KEP-0002-hosted-candidate-correction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
# KEP-0002: Hosted candidate correction receipt

Status: Proposed

Decision owner: Repository owner

Last updated: 2026-08-17

Target release: Before `v0.1.0-beta.1`

## Summary

Add a fail-closed receipt for a candidate that changes after the first public
push. Keep the pre-first-push receipt immutable.

The correction receipt must bind the old candidate, new candidate, local
checks, remote refs, pull request, and hosted runs. It must bind the final tree.

This KEP does not authorize a tag or a pull-request merge.

## Context

The first publication used an absent repository as a privacy and identity
gate. That fact cannot stay true after repository creation.

Hosted Windows checks then found three host assumptions. The corrected
candidate passed every required hosted check before `main` moved.

The original receipt still proves the pre-first-push boundary. It does not bind
the corrected final commit.

## Decision request

Approve a second receipt type for post-first-push corrections. Require that
receipt before a corrected candidate moves to `main`.

## Required sequence

If the first hosted candidate fails, use this sequence:

1. Keep `main` at the reviewed bootstrap.
2. Keep the verification pull request open.
3. Fix the finding on the candidate branch.
4. Run every local release gate on the corrected commit.
5. Scan the complete history and worktree for secrets.
6. Check the complete author and committer identity set.
7. Fast-forward only the candidate branch.
8. Run every required hosted check on the corrected commit.
9. Create the private correction receipt.
10. Close the verification pull request without merging it.
11. Fast-forward `main` only to the receipt's candidate commit.
12. Check the remote commit and tree.

Do not force-push a candidate branch. If a fast-forward is not possible, create
a new branch.

## Receipt contract

The command must write one new private JSON file. It must not overwrite a
file or write inside the source checkout.

The receipt must bind:

- the schema version and generation time.
- the target repository and visibility.
- the reviewed bootstrap commit and tree.
- the first receipt digest.
- the old candidate commit and tree.
- the new candidate commit and tree.
- the complete merge-free correction range.
- the complete reviewed delta path list.
- the local object and secret-scan results.
- the public author and committer identity result.
- the remote candidate and `main` refs.
- the pull-request number, state, head, base, and merge result.
- each required run ID, event, head commit, status, and conclusion.
- each required check context and GitHub App integration ID.

The receipt must exclude tokens, email addresses, local paths, private reports,
and raw security logs.

## Command behavior

Add a Go command under `scripts/`. The command must accept explicit repository,
bootstrap, old candidate, candidate ref, and pull request values. It must also
accept explicit run, path manifest, and output values.

The command must use bounded timeouts for GitHub, Git, and secret-scan
commands. It must reject incomplete dependency injection in tests.

The command must stop unless:

- the checkout is clean.
- the new candidate is the checked-out commit.
- the old candidate is an ancestor of the new candidate.
- the correction range is merge-free.
- the complete bootstrap delta matches the path manifest.
- object checks and secret scans pass.
- all history identities match the public owner identity.
- the target repository exists and is public.
- the remote candidate ref equals the new candidate.
- the pull request is open, unmerged, and points to the new candidate.
- every required hosted run succeeded on the new candidate.

The first version must create the receipt before `main` moves. A separate mode
can check `main` after the fast-forward.

## Failure behavior

If a check fails, return a typed error and write no receipt. Do not weaken the
check after repository creation.

Preserve the old receipt, candidate refs, pull request, and hosted runs after a
failure.

## Test plan

Test these cases:

- exact one-commit correction success.
- multiple linear correction commits.
- moved candidate ref.
- changed path manifest.
- merge commit in the correction range.
- failed or pending hosted run.
- run for a different head commit.
- pull request with a different head.
- merged pull request.
- private or different target repository.
- changed public identity.
- secret-scan or object-check failure.
- existing output file.
- output path inside the checkout.
- open receipt directory on Unix.
- external-command timeout.
- deterministic redaction and schema validation.

## Alternatives

### Edit the first receipt

Rejected. Editing an immutable receipt destroys its evidence value.

### Rerun the pre-first-push command

Rejected. The target repository now exists, and the checkout now has a remote.

### Trust only the hosted check page

Rejected. A passing page does not bind the local delta, identities, or final
tree.

### Delete and recreate the repository

Rejected. The public history and hosted evidence already exist.

## Rollout gate

Implement and test the command before the beta tag. Generate a private receipt
for the correction from `ed3f1fadfbc74eb0aa41ef8b90e41f403213d33d` to
`206fa8b6a1dde1d97081133e4d447c0881849922`.

Record only the redacted result in public evidence.

## Decision log

| Date | Decision |
| --- | --- |
| 2026-08-17 | Propose a second immutable receipt for hosted candidate corrections. |
20 changes: 16 additions & 4 deletions docs/OSS-PUBLIC-BETA.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,22 @@ The owner approved a capture-only public beta with these boundaries:
- Keep branch landing, merging, pushing, and remote coordination out of scope.
- Use `v0.1.0-beta.1` only after all public-beta gates pass.

## Hosted state on 2026-08-17

The public source repository now exists at
[`nstranquist/wip-commit`](https://github.com/nstranquist/wip-commit).
Commit `206fa8b6a1dde1d97081133e4d447c0881849922` passed the hosted candidate and
final `main` checks.

The active `main` ruleset and security settings passed the hosted setup audit.
[PUBLICATION-EVIDENCE.md](PUBLICATION-EVIDENCE.md) contains the public record.

No beta tag or GitHub release exists. The independent beta, conduct, correction
receipt, security-notification, tag-approval, and tagged-install gates remain.

This approval fixes the repository name, module path, and capture-only scope.
It does not approve a release tag. The project instructions require a human to
perform the first push. Follow
[PUBLICATION-HANDOFF.md](PUBLICATION-HANDOFF.md) for that exact boundary.
It does not approve a release tag. The first-push handoff ran on 2026-08-17.
Do not run [PUBLICATION-HANDOFF.md](PUBLICATION-HANDOFF.md) again.

## Why this plan exists

Expand All @@ -43,7 +55,7 @@ adding a YAML dependency.

Use these status values:

- `verified`: Local evidence passed on the recorded source.
- `verified`: Recorded local or hosted evidence passed on the exact source.
- `prepared`: The repository artifact exists, but hosted evidence is absent.
- `planned`: Owner-controlled implementation work remains.
- `human-gated`: An owner decision or external mutation is required.
Expand Down
48 changes: 33 additions & 15 deletions docs/OSS-PUBLIC-BETA.requirements.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"schema_version": 1,
"plan_id": "wip-oss-public-beta",
"plan_status": "proposed",
"plan_status": "accepted",
"target_version": "v0.1.0-beta.1",
"last_reviewed": "2026-08-16",
"last_reviewed": "2026-08-17",
"status_definitions": {
"verified": "Local evidence passed on the recorded source.",
"verified": "Recorded local or hosted evidence passed on the exact source.",
"prepared": "The repository artifact exists, but hosted evidence is absent.",
"planned": "Owner-controlled implementation work remains.",
"human-gated": "An owner decision or external mutation is required.",
Expand Down Expand Up @@ -114,25 +114,27 @@
"id": "OSS-008",
"gate": "public-beta",
"title": "Run hosted operating-system tests",
"status": "external-evidence",
"status": "verified",
"owner": "repository-owner",
"human_gate": true,
"human_gate": false,
"acceptance": "The exact candidate passes Linux, macOS, Windows, race, vet, lint, module, and dependency-review jobs.",
"evidence": [
{"kind": "workflow", "value": ".github/workflows/ci.yml", "observed_on": "2026-08-14"}
{"kind": "workflow", "value": ".github/workflows/ci.yml", "observed_on": "2026-08-14"},
{"kind": "hosted-run", "value": "https://github.com/nstranquist/wip-commit/actions/runs/31996057770 passed Linux, macOS, Windows, race, lint, and dependency review on commit 206fa8b6a1dde1d97081133e4d447c0881849922.", "observed_on": "2026-08-17"},
{"kind": "hosted-run", "value": "https://github.com/nstranquist/wip-commit/actions/runs/31996220707 passed every main-push job that applies to commit 206fa8b6a1dde1d97081133e4d447c0881849922.", "observed_on": "2026-08-17"}
]
},
{
"id": "OSS-009",
"gate": "public-beta",
"title": "Configure hosted repository protections",
"status": "human-gated",
"status": "verified",
"owner": "repository-owner",
"human_gate": true,
"human_gate": false,
"acceptance": "main requires pull requests, review, required CI, and blocks force pushes and deletion.",
"evidence": [
{"kind": "prepared-runbook", "value": "docs/HOSTED-SETUP.md defines the authority boundary, ruleset sequence, observed-check-name rule, and evidence receipt.", "observed_on": "2026-08-16"},
{"kind": "gap", "value": "No remote is configured in the local checkout.", "observed_on": "2026-08-14"}
{"kind": "hosted-setting", "value": "https://github.com/nstranquist/wip-commit/rules/20926881 is active on main with no bypass actor, rebase-only pull requests, one approval, last-push approval, six provider-bound checks, linear history, and ref protections.", "observed_on": "2026-08-17"}
]
},
{
Expand All @@ -145,7 +147,9 @@
"acceptance": "Private vulnerability reporting, dependency alerts, secret scanning, and security notifications are enabled.",
"evidence": [
{"kind": "prepared-policy", "value": "SECURITY.md and .github/ISSUE_TEMPLATE/config.yml", "observed_on": "2026-08-14"},
{"kind": "prepared-runbook", "value": "docs/HOSTED-SETUP.md defines the current GitHub security-setting sequence and evidence receipt.", "observed_on": "2026-08-16"}
{"kind": "prepared-runbook", "value": "docs/HOSTED-SETUP.md defines the current GitHub security-setting sequence and evidence receipt.", "observed_on": "2026-08-16"},
{"kind": "hosted-setting", "value": "Dependency graph, Dependabot alerts, Dependabot security updates, secret scanning, push protection, and private vulnerability reporting are enabled. GitHub serves SECURITY.md on the security policy page.", "observed_on": "2026-08-17"},
{"kind": "gap", "value": "The maintainer's personal security-alert notification setting is not verified.", "observed_on": "2026-08-17"}
]
},
{
Expand Down Expand Up @@ -186,7 +190,8 @@
"human_gate": true,
"acceptance": "A clean environment installs the tagged command through the public Go module path and runs wip version.",
"evidence": [
{"kind": "gap", "value": "The module path is not public.", "observed_on": "2026-08-14"}
{"kind": "public-install", "value": "A clean unauthenticated clone resolved commit 206fa8b6a1dde1d97081133e4d447c0881849922 and tree c0dd6638adcdc231840ad06406dc9f0caa38e45d. go install at that commit resolved the public pseudo-version and returned wip 0.1.0-beta.1.", "observed_on": "2026-08-17"},
{"kind": "gap", "value": "No public beta tag exists, so the tagged-install acceptance rule remains open.", "observed_on": "2026-08-17"}
]
},
{
Expand All @@ -198,7 +203,7 @@
"human_gate": true,
"acceptance": "The owner creates a signed v0.1.0-beta.1 tag only after every public-beta gate passes.",
"evidence": [
{"kind": "gap", "value": "No remote or tag exists.", "observed_on": "2026-08-14"}
{"kind": "gap", "value": "The public repository exists, but no tag, GitHub release, or explicit tag approval exists.", "observed_on": "2026-08-17"}
]
},
{
Expand Down Expand Up @@ -345,7 +350,7 @@
"human_gate": true,
"acceptance": "After a beta period, the project reviews issue and pull-request response, maintainer load, unresolved security and safety defects, real concurrent use, and a tested backup-administrator, transfer, or archival path.",
"evidence": [
{"kind": "gap", "value": "A local unpublished project has no honest community-health or succession evidence.", "observed_on": "2026-08-16"}
{"kind": "gap", "value": "A new public source candidate has no beta-period community-health or succession evidence.", "observed_on": "2026-08-17"}
]
},
{
Expand Down Expand Up @@ -415,10 +420,10 @@
"status": "verified",
"owner": "repository-owner",
"human_gate": false,
"acceptance": "A source-current, fail-closed preflight binds a clean final candidate to the reviewed bootstrap, a merge-free linear split-commit range, the complete reviewed path delta, zero remotes and tags, owner approval, public author and committer identities, absent target repository, complete non-replaced history, passing object integrity, and passing history and worktree secret scans. It writes a no-overwrite private receipt outside the checkout. A human-only runbook preserves the exact candidate while obtaining hosted checks without merging a pull request.",
"acceptance": "A source-current, fail-closed preflight binds a clean pre-first-push candidate to the reviewed bootstrap, a merge-free linear split-commit range, the complete reviewed path delta, zero remotes and tags, owner approval, public author and committer identities, absent target repository, complete non-replaced history, passing object integrity, and passing history and worktree secret scans. It writes a no-overwrite private receipt outside the checkout. A human-only runbook preserves the exact candidate while obtaining hosted checks without merging a pull request.",
"evidence": [
{"kind": "artifact", "value": "scripts/publication-handoff, docs/PUBLICATION-HANDOFF.md, docs/PUBLICATION-HANDOFF.paths, and docs/PUBLICATION-HANDOFF.schema.json", "observed_on": "2026-08-16"},
{"kind": "gap", "value": "The project instructions prohibit an agent push. Human execution and hosted evidence remain required.", "observed_on": "2026-08-16"}
{"kind": "receipt", "value": "The validated private pre-first-push receipt bound commit ed3f1fadfbc74eb0aa41ef8b90e41f403213d33d, tree 674a65c74d55a08b3f8d560700de1430ade99942, the reviewed bootstrap, and the then-current 17-path manifest before repository creation.", "observed_on": "2026-08-17"}
]
},
{
Expand All @@ -434,6 +439,19 @@
{"kind": "artifact", "value": "go.mod requires Go 1.25.12; docs/RELEASE.md and docs/OSS-PRACTICE-GUIDE.md require exact-minimum verification.", "observed_on": "2026-08-16"},
{"kind": "command", "value": "GOTOOLCHAIN=go1.25.12 GOWORK=off go run golang.org/x/vuln/cmd/govulncheck@v1.7.0 ./...", "observed_on": "2026-08-16"}
]
},
{
"id": "OSS-034",
"gate": "public-beta",
"title": "Bind hosted candidate corrections",
"status": "planned",
"owner": "maintainer",
"human_gate": false,
"acceptance": "A fail-closed Go command binds each post-first-push correction to the old and new candidates, complete path manifest, local checks, remote candidate ref, unmerged pull request, required hosted runs, and final tree in one immutable private receipt before main moves.",
"evidence": [
{"kind": "kep", "value": "docs/KEP-0002-hosted-candidate-correction.md defines the receipt contract, sequence, failure behavior, and test plan.", "observed_on": "2026-08-17"},
{"kind": "gap", "value": "The first receipt binds ed3f1fadfbc74eb0aa41ef8b90e41f403213d33d, while public main is 206fa8b6a1dde1d97081133e4d447c0881849922 after a hosted correction. No source command validates this correction flow yet.", "observed_on": "2026-08-17"}
]
}
]
}
Loading