Skip to content

Guard the DCO range against a branch's first push, and add the governance files - #1

Merged
HackTuah merged 5 commits into
mainfrom
slice/001-hardening-and-wire-errors
Sep 6, 2026
Merged

Guard the DCO range against a branch's first push, and add the governance files#1
HackTuah merged 5 commits into
mainfrom
slice/001-hardening-and-wire-errors

Conversation

@HackTuah

@HackTuah HackTuah commented Sep 6, 2026

Copy link
Copy Markdown
Member

Two commits. The first carries a demonstrated red.

61d1b30 — guard the DCO range

The DCO job failed on its own first run, and the commits were fine:

fatal: Invalid revision range 0000000000000000000000000000000000000000..HEAD
cannot resolve 0000000000000000000000000000000000000000..HEAD
Process completed with exit code 1

github.event.before is the all-zeros SHA on a branch's first push, because there is no previous state to name. before..HEAD is then not a range, and the job exited before looking at a single commit.

That failing run is the red, and it is the point of having pushed an unproven workflow: a check that has never run is a claim, and its first run is what turns it into a measurement. This one found a defect in itself.

Guarded as the sibling tree guards the same case, with a stricter fallback — that tree checks one commit (sha~1..sha); on a first push every commit reachable from HEAD is new to the remote, so all of them are in scope here. Simulated on both branches before pushing:

all-zeros (first push)   commits in scope: 8    all signed off: yes
ordinary push            commits in scope: 1    all signed off: yes

The job now also prints how many commits it examined, so a run that checks nothing cannot read as a run that found nothing — which is exactly how the original defect hid.

39834d1 — SECURITY.md, CONTRIBUTING.md, dependabot.yml

SECURITY.md states a response commitment one maintainer can keep: acknowledgement within 7 days, an assessment within 30, credit in the advisory, no bounty and no guaranteed fix deadline. A 24-hour turnaround would read better and would be a promise this project cannot honour. It also tells a reporter what to do if nothing comes back.

Scope is drawn at the package boundary — protocol handling, framing and bounds, schema validation, era confusion, disclosure across the wire. Out of scope is what a host's tools do: this package validates and routes, it does not execute.

CONTRIBUTING.md states four enforced rules — DCO sign-off, no tool-attribution trailers, a green gate with no baseline, rebase-only — and names what enforces each.

dependabot.yml covers mix and github-actions weekly. The workflow pins erlef/setup-beam@v1 and actions/checkout@v4, which drift without something watching them.

Not in this PR

The inspect/1 wire-error fix has moved to its own PR, as it is an unrelated change to server.ex.

Note

This branch exists because a repository ruleset now requires pull requests and two checks. It was applied after the first push, and direct pushes to main are correctly refused.

The DCO job failed on its own first run, at 36136a1, and the commits were fine:

    fatal: Invalid revision range 0000000000000000000000000000000000000000..HEAD
    cannot resolve 0000000000000000000000000000000000000000..HEAD
    Process completed with exit code 1

github.event.before is the all-zeros SHA on a branch's first push, because
there is no previous state to name. before..HEAD is then not a range, and the
job exited before it looked at a single commit. That failing run is this
change's red, and it is the point of pushing an unproven workflow: a check that
has never run is a claim, and its first run is what turns it into a
measurement. This one found a defect in itself.

Guarded the way the sibling tree already guards the same case, with a stricter
fallback. That tree uses github.sha~1..github.sha, which checks one commit; on a
first push every commit reachable from HEAD is new to the remote, so all of them
are in scope here.

Simulated on both branches before pushing, since CI is otherwise the only place
to see it:

    all-zeros (first push)   commits in scope: 8    all signed off: yes
    ordinary push            commits in scope: 1    all signed off: yes

The job also now prints how many commits it examined, so a run that checks
nothing cannot read as a run that found nothing.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
SECURITY.md states a response commitment a single maintainer can actually keep:
acknowledgement within 7 days, an assessment within 30, credit in the advisory,
no bounty and no guaranteed fix deadline. A 24-hour turnaround would read better
and would be a promise this project cannot honour, so it is not made. It also
tells a reporter what to do if nothing comes back, which is the part most
policies leave out.

Scope is drawn at the package boundary: protocol handling, framing and bounds,
schema validation, era confusion, and disclosure across the wire. Out of scope
is what a host's tools do -- this package validates and routes, it does not
execute -- and anything the host injects. The inspect/1 wire leak is listed as
already known, so it is not reported as a discovery and its status is not
mistaken for ignorance of it.

CONTRIBUTING.md states the four enforced rules: DCO sign-off on every commit, no
tool-attribution trailers, a green gate with no baseline, and rebase-only. Each
is checked by something rather than asked for politely, and the file says which.

dependabot.yml covers mix and github-actions, weekly. The workflow pins
erlef/setup-beam@v1 and actions/checkout@v4, which drift without something
watching them.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
@HackTuah
HackTuah force-pushed the slice/001-hardening-and-wire-errors branch from cb91684 to 39834d1 Compare September 6, 2026 20:37
@HackTuah HackTuah changed the title Guard the DCO range, add governance files, and stop leaking Elixir terms onto the wire Guard the DCO range against a branch's first push, and add the governance files Sep 6, 2026
The previous guard caught a branch's first push and missed a force-push. CI
found it, on this branch, at 39834d1:

    fatal: Invalid revision range cb91684..HEAD
    cannot resolve cb91684..HEAD

That is the red. Dropping a commit from a branch leaves github.event.before
naming a SHA that is no longer reachable -- a real-looking value pointing at
something the fetched history does not contain. The old guard tested the
value's SHAPE, which catches only the all-zeros case. This one asks git whether
it RESOLVES, which catches both.

Simulated across all three inputs:

    before=0000000000   fallback: all reachable   commits in scope: 10
    before=deadbeefde   fallback: all reachable   commits in scope: 10
    before=61d1b30224   range before..HEAD        commits in scope: 1

and the old guard on that middle input fails exactly as CI did.

One honesty note on that simulation. The obvious test SHA, cb91684, RESOLVES in
the local clone -- it is on another branch and in the reflog -- so using it here
would have shown a pass and proved nothing about CI, where the checkout does not
contain it. The middle row uses a SHA that resolves nowhere, which is the
condition CI actually hit.

The message now prints the unusable value rather than assuming which case it
was, so a future failure of a third kind says what it saw.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
The package metadata named the old owner:

    Links:
      GitHub: https://github.com/HackTuah/beam_mcp

The repository transferred to ScriptKittyOS. That URL still resolves, by
redirect, which is the whole problem: it would ship inside the published tarball
and appear on the package page, correct-looking and stale, with nothing to
signal it.

Found by running mix hex.build rather than by reading the file. It survived the
transfer because it lives in a module attribute nobody re-read afterwards -- the
same class of defect as the stale citations the sibling tree swept last week,
and the reason that sweep derived its population by grep instead of working from
a list.

Verified after the change:

    Links:
      GitHub: https://github.com/ScriptKittyOS/beam_mcp

Signed-off-by: Ayla Croft <aylacroft@proton.me>
…ing it

CI asks for otp-version 28 and elixir-version 1.18. What it installs is an
Elixir 1.18.5 build compiled for OTP 27, running on OTP 28.5.0.6. The gate
passes on it.

Recorded rather than pinned, and deliberately so: Elixir 1.18 publishes no
otp-28 build, so pinning 1.18.5-otp-28 would fail to resolve, and moving to an
Elixir line that has one is a toolchain decision rather than a CI tidy-up.
Pinning here is the change that looks more rigorous and breaks the build.

The reason to write it down at all is that the workflow reads as a matched pair
and is not one. Someone will look at otp-version: 28 beside elixir-version: 1.18
and assume. Now they will not have to.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
@HackTuah
HackTuah merged commit 32d4382 into main Sep 6, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant