Releases: easybytehub/hullwork
Release list
v0.1.0a9
0.1.0a9 — an instance an operator can run from the page (#25)
Everything an operator needed a shell for in the first hour is on the page now, and the page itself
was rebuilt around what a person comes to look at.
Administration without a shell (DR-0022). Connect a project, re-read its manifest, disable it,
rotate its webhook secret, name it in the tracker — all from the browser, behind the operator's
password, through the same functions the terminal calls rather than a second implementation. doctor
and config became views: why an instance that is running will not work, and what this process
actually received. The receiver still holds no credential that can push, and no route here can attempt
a fix; that split is the product and none of this touches it.
Reading your own instance without a credential you can lose (DR-0021). The page URL reads. The
password acts. A read link handed to a colleague opens the instance and reaches nothing that
administers it.
The page is furniture, not a document (DR-0023). The landing view was 357 words and 11 numbers of
arithmetic before you could do anything; it is the work now — what arrived, what happened to it, and
one sentence saying whether any of it needs you. Navigation is a persistent sidebar of the nouns this
product has. The instance report keeps every number it had and lives behind its own noun.
Then measured rather than argued: the work went from 43% of a 1680px window to 79%, twenty ad-hoc
type sizes became a nine-step scale no rule may leave, and the two colours failing WCAG AA — one of
them carrying the sentence that explains what the URL is — now clear 4.5:1 in both themes.
Twenty-six checks before you build anything (hullwork preflight). They used to run after two
containers were up. They run against the environment file you just wrote, and say which of three
answers each one is — including could not check this from here, which is a first-class answer.
And the default is now to pull. A real deployment scaffolded by hullwork init runs the published
image; building is still there, explicit, for people changing the code.
Signed-off-by: Javier Miralles Rancaño 68760931+FlagshipDev@users.noreply.github.com
v0.1.0a8
0.1.0a8 — the dependency signal, and what it refuses to claim (#20)
What this release makes reachable that was not before.
A second signal
Hullwork verifies which of the things your tools claim are actually true. Until now it did that for
one signal: a production error becomes a failing test, then a fix, then a draft pull request. This
release adds the second.
hullwork deps --checkout . reads the versions your lock files pin, asks OSV what is published
against those exact versions, and prints what came back. No credential of any kind — no forge, no
model, no database. The one host it contacts takes no key and no account.
--verify then answers the question nobody else does: it applies each published fix in a sandbox
and runs your own test suite against it. The verdict is ranked by what it asks of a person —
fix your suite first, needs work, blocked, ready to take — worst first.
--open opens a draft pull request for the ones that passed, one per package, never a batch, and
never anything else. --fix asks an agent to change your code so an upgrade that breaks your suite
fits, without being allowed to touch your dependency files.
What it refuses to claim, which is most of the point
The claim on a verified upgrade is exact: your suite passed before this change and passes after
it. Never "safe", never "this fixes the vulnerability". A suite that does not exercise the
dependency stays green without ever loading the new version, and the pull request says so.
And it says no more often than yes. Measured on four real third-party repositories before this
release: one clean verdict. The rest could not be measured at all — a suite that reaches the network
a sandbox denies by design, a pin in a file the image does not install from, an image the project
brings ready-made. Each is reported as what it is, with the reason and what to change, rather than
verified wrongly.
hullwork features
New, and it answers before you have decided anything: feature by feature, whether this can serve
your project, which requirement is missing when it cannot, and what it will not do even when it
can. No credential, no container, no socket, nothing written.
The Sentry webhook route
Enabled. Authenticated by the token in its URL — the same credential a GlitchTip route has, checked
the same way, because GlitchTip cannot sign its webhooks at all. Sentry's signature is not
verified, and SECURITY.md says once, for both providers, what that does not cover: anyone who
obtains the URL can post to it. Treat it as a secret; hullwork projects rotate-secret replaces it.
A number about itself
hullwork status and the page now report what arrived and how much of it left a person's desk with
evidence attached — including a row for what Hullwork put on that desk rather than took off it.
That row is the one this product can be embarrassed by, and it is printed above the others.
One new manifest field
autofix.open_upgrades, false by default. Opening a verified upgrade as a pull request is the first
thing a project can refuse while Hullwork is able to do it: having a capability is not the same as
having agreed to it. Every other default in that block already refuses.
Note that a manifest carrying this field is rejected by earlier releases, which forbid unknown
fields by design. A project that does not set it is unaffected.
Fixed
- A verified-green verdict could be produced for a version that was never installed — twice, by two
different routes: a pin in a file outsideruntime.dependencies, andinstall: none, which is
the default. Both are now refused before a container is built, with the reason and the remedy. - A fix phase that created test configuration where a project had none could switch the suite
off and publish with the mechanism inside its own diff. The guard against editing that
configuration had never covered inventing it. deps --verifydid not hand the source to the image build, so any project whose installer reads
its own files could not be verified at all.- Requirements files outside a root
requirements.txtwere not read:requirements/prod.txt,
requirements-dev.txtand their shape were invisible, and the report said nothing about the gap. - Agent runs discovered a missing model credential, and a missing gateway image, at the most
expensive possible moment. Both are answered in under a second now.
Still true, and worth reading before relying on any of it
Nobody outside this project has installed Hullwork. Every measurement in this release was taken by
the people who wrote it. docs/status.md is the honest scope and it changes weekly.
Signed-off-by: Javier Miralles Rancaño 68760931+FlagshipDev@users.noreply.github.com
v0.1.0a7
0.1.0a7: the page stopped being a report and became where you decide (#17)
Five items since 0.1.0a6, and they are one thing seen from four angles. The read-only page told an
operator that two items had been waiting twenty-one hours and gave them no way to do anything about it
— on an instance whose own operator was looking at it.
What changed
Two buttons on an item waiting for a decision — let the agent try it and I will take this one —
and the state machine chose which two: LEGAL[WAITING_APPROVAL] does not contain REJECTED, because
that state means a reviewer closed a pull request and it feeds a tally keyed by the label they used.
Calling this "reject" would have filed a decision about whether to attempt into the count of review
decisions, and the number would have drifted with nobody able to see why.
The read URL gains no authority. It is a bearer credential in a path — a saved page, a screenshot,
a forwarded link — so it keeps reading everything and can spend nothing. Acting needs a second
credential that never appears in a URL: hullwork password, once, and then a login a browser's password
manager fills in. Sessions are rows, so ending them all is a DELETE rather than a key rotation that
happens to log everybody out.
This reverses a decision approve argued for in writing — "an approval endpoint would be a
permanent attack surface for something done by one person a handful of times" — and the ground it
stood on had moved. "The operator already has the host" now means ssh, docker compose exec and a CLI,
from a page read on a laptop.
The page answers before it reports. One sentence in the largest type, then the items by name
rather than a count, then the machine's figures as a subordinate row, then everything an evaluator wants
behind native <details>. The old board put the operator's own queue in the second of six identical
cards, so finding it meant reading six labels.
And it now shows what this instance has proved — found, tried, merged, held, came back — in figures,
because a page for a self-hosted product is also the only shop window it has. The motif is the product's
own mechanism: a red-to-green rule under the header, once, and nowhere else.
Two secure designs that were not usable
The credential behind those buttons changed twice before this release, and both earlier attempts were
sound and unusable. A stored key had to be pasted into a form. A one-time link had to be fetched from
the host every twelve hours — open the page, ssh, run a command, copy a link, open it, come back,
reload: eight steps, against the single command the whole exercise set out to improve on.
The reason given for skipping the obvious answer was wrong, and it cost a milestone: a chosen password
was said to need scrypt or argon2 and therefore a new dependency in the half of Hullwork that listens on
a network. hashlib.scrypt is in the standard library — 37 ms per attempt at n=2**14, which is the
work factor and most of the answer to online guessing, with a ten-try lockout for the rest.
What is not shown
Nobody has pressed either button. The instance logs decided from the page when it happens and has
zero of them. Everything here is verified against the code — the read token cannot decide, a wrong CSRF
token cannot, the lockout closes and reopens on its own, both themes render — and none of that is the
claim. The claim is that an operator can decide from a browser in two steps, and the only instrument
that can measure it is an operator. Each of the five items now carries that as its gate.
docs/status.md is unchanged in its list of what nobody has shown, and it is still
the section that matters.
Signed-off-by: Javier Miralles Rancaño 68760931+FlagshipDev@users.noreply.github.com
v0.1.0a6
0.1.0a6: the documented --credential-file becomes a thing you can run (#14)
docs/connecting-a-project.md shows hullwork projects add --credential-file, and the image those
documents pin — 0.1.0a5 — answers unrecognized arguments. Item 163's fix landed after that
release, so the sentence was true of main and false of the artefact anybody actually pulls.
This bumps the five places that name a version. What it releases: --credential-file for
projects add and rotate-secret, which takes the only high code-scanning alert — a credential
with nowhere to go but standard output — and gives it a mode-600 file instead; plus items 162 and
164, which closed the rest of the alerts.
Signed-off-by: Javier Miralles Rancaño 68760931+FlagshipDev@users.noreply.github.com
v0.1.0a5
0.1.0a5: the first release whose artefacts carry provenance anybody can verify (#8)
Scorecard's Signed-Releases has been sitting at 0/10 with the mechanism already in place, because the
check reads the assets of releases that exist — and 0.1.0a1 through a4 all predate it. A fix
that cannot be verified is a claim, which is the one thing this repository is not allowed to publish.
So: a version, and it earns one under the policy written a few commits ago — "a capability that is
now reachable in the artefact, where it was not before". What a consumer can do with this release and
could not with the previous four:
gh attestation verify oci://ghcr.io/easybytehub/hullwork:0.1.0a5 -R easybytehub/hullwork
gh attestation verify hullwork-0.1.0a5-py3-none-any.whl -R easybytehub/hullwork
Which answers which commit, which workflow and which runner produced this, signed by GitHub through
OIDC — no key of ours to store, rotate or leak. The bundle is attached to the release as
v0.1.0a5.intoto.jsonl as well, so a tool that reads a release's assets can find it without going
through this repository's API. That second copy is the entire reason the check was scoring zero.
Nothing else changed. This is a release cut to prove a mechanism, which the policy allows exactly once
per mechanism and never for a measurement — that is what edge is for now.
Signed-off-by: Javier Miralles Rancaño 68760931+FlagshipDev@users.noreply.github.com
v0.1.0a4
Version 0.1.0a4
The first published image that carries its reporting destination from the build rather than from an
environment variable somebody set. PRIVACY.md names the host: errors.easybyte.es, a small relay that
re-checks every payload's shape on arrival and is the only thing exposed to the internet — the
tracker behind it has no public address.
v0.1.0a3
Version 0.1.0a3
v0.1.0a2
The published image was missing both optional extras, and the docs promised both
Found by running the artefact rather than reading the source. The Dockerfile's ARG EXTRAS=
is empty and the release workflow passed no --build-arg, so 0.1.0a1 shipped without
sentry-sdk and without psycopg:
- with
HULLWORK_ERROR_DSNset the container exits 3, telling you to run apip install
nobody can run against an image they pulled — a capability the FAQ,docs/status.mdand the
deployment notes all describe; - a
postgresql+psycopg://URL died asModuleNotFoundError: No module named 'psycopg'in a
raw SQLAlchemy traceback, while the support matrix says Postgres works.
Nobody noticed because a development checkout installs [dev], which carries both. The defect
was only reachable through the artefact.
The release now builds with [postgres,telemetry], and a test asserts both by name so a later
edit cannot drop one silently the way their absence was never noticed.
And the case that survives the fix — building your own image without the extra — gets a
sentence instead of the traceback: which extra carries the driver, and that SQLite needs
nothing. By asking the dialect rather than matching the URL against drivers we recognise, so a
driver nobody here thought of is refused the same way.
Version 0.1.0a2, because the fix lives in the build and only a release can carry it.
v0.1.0a1
Hullwork: from production errors to reviewable draft pull requests
Self-hosted. Your forge, your error tracker, your model endpoint, and a human gate on every
merge. One declarative file per repository; no per-project glue code.
Pre-alpha: both halves run end to end, five attempts have reached a draft pull request, and
nobody outside this project has installed it. docs/status.md says what works, what does not,
and what nobody has demonstrated, with dates. docs/an-attempt-end-to-end.md walks through one
real attempt from the instance's own database — the error at 11:35, the merged fix at 12:27,
the four gates with their exit codes and the provenance seal as stored.
Two properties everything else rests on. The half that answers webhooks cannot push and refuses
to start if it finds a credential that can; the half that can push listens on nothing. And which
model answered is read off the wire by Hullwork's own recording gateway rather than taken from
configuration, so a different model answering is a recorded violation instead of a shrug.
This repository is the software and how to run it. The reasoning behind it — decision records,
the constitution, the specifications, the plan — is kept in the project's own repository and
cited by name throughout the source; ask and any of it will be published.