Skip to content

Release 0.4.0 - #140

Merged
Gorka Gonzalo (d0ubl3g) merged 92 commits into
mainfrom
dev
Oct 12, 2026
Merged

Gorka Gonzalo (d0ubl3g) merged 92 commits into
mainfrom
dev

Conversation

@d0ubl3g

Copy link
Copy Markdown
Contributor

Release 0.4.0: merges dev into main. The full notes are the ## [0.4.0] section of CHANGELOG.md, which also becomes the release notes.

For users and scripts

Changed (scripting surface)

Two existing failure cases now exit with a different code; scripts that depend on them should check:

Fixes

Release and infrastructure

macOS binaries remain unsigned in this release, as in 0.3.x.

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Describe the module design principles in CONTRIBUTING

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
The weekly check still compares the published /v1 document with
openapi/v1.json and classifies breaking changes with the pinned
oasdiff, but it no longer pushes a branch, regenerates the client or
opens a pull request. It opens or updates one issue labelled
openapi-drift, closes it when the documents match again, and fails the
run on drift. A failed fetch, parse or oasdiff run is reported in an
issue labelled openapi-check-failed. Permissions are reduced to
contents: read and issues: write.

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Report OpenAPI drift in an issue instead of a pull request

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
…msiexec

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Document defining a profile before signing in to it, and waiting for msiexec

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
A workflow builds synthetic packages and a throwaway MinIO with throwaway keys, publishes releases with build.sh and publish.sh, installs and upgrades with apt and dnf, and checks that the builder and the clients refuse forged packages and indexes.

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
…an image

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Run the repository builder's security tests in CI

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Closes #52

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Document proxies and TLS inspection

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Read the X-HS-Tenant header of 2xx answers into ResponseMeta::tenant_id when it is present
exactly once and holds a UUID. It is informational only and not a tenant-isolation check.

Refs #48

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Link the beta programme and its terms from the README

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Expose the tenant the API answered for in the response metadata

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
State the interface stability policy

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
The document can publish the vocabulary of a query parameter as
x-hs-known-values. The generator reads it (an array of strings, anything
else is an error) and emits it on the operation as known_values, which
Operation::known_values(param) looks up. The vocabularies are open, so the
values are for help and warnings, not for refusing input.

The vendored document does not carry the extension yet: the only change to
the generated file is the empty known_values field on each operation.

Refs #53

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Read known filter values from the OpenAPI document

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Add output contract tests that run the binary against a mock API and
pin exit codes 0 to 8, the --json shape (including fields the CLI does
not know), the --csv header, quoting and formula guard, and the split
between standard output and standard error. Document in CONTRIBUTING
that changing them is a change to the scripting surface.

Refs #58

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Refs #53

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Test the scripting surface: exit codes, JSON, CSV and output streams

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Warn when a filter value is not one the API lists

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Refs #25

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
When the API document lists the English alert severities and the user types one of the legacy values, say which name to use and until when the legacy one is accepted. The value is still sent as typed. Refs #53

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Refs #25

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Once standard output has seen a broken pipe, the exit code mapping turned any failure into exit 0. A later, unrelated failure (an API error after the reader went away) must still fail, so the closed reader now applies only to a failure converted from a broken-pipe I/O error, and only when standard output saw one too.

Refs #105.

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Treat only a closed standard output as a closed pipe

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Windows on Arm devices could only run the x64 build under emulation.
Each release now also ships hodeishield-<version>-aarch64-pc-windows-msvc.zip.

The arm64 build runs natively on the windows-11-arm runner, so the C code
of aws-lc-sys is compiled by the toolchain of the target and the CI tests
run where the binary runs. Signing stays on the x64 runner, through the
same release-signing environment and Azure profile as the x64 exe; the
import check now also verifies the PE machine type matches the archive
name. The archive joins SHA256SUMS, the cosign signatures, the provenance
subjects and the SBOM set. The MSI and winget stay x64 only. Scoop lists
the arm64 zip when a release has it.

CI runs the test suite, clippy and the import check on windows-11-arm.

Refs #37

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Build, sign and test Windows on Arm

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
The README Stability section says that giving an existing case a different
exit code is a breaking change and that the changelog lists it under
"Changed (scripting surface)", with what to do about it. Two unreleased
entries did exactly that but sat under Fixed:

- an unreachable system keychain with no API key now exits 3 instead of 1;
- a failure that used to exit 0 (an API error message containing "Broken
  pipe", or a broken pipe that was not standard output) now exits non-zero.

Move them to a new "Changed (scripting surface)" subsection and add what
script authors should do. Also:

- add one entry for the README changes that are already on dev (stability
  policy, proxies and TLS inspection, beta links, defining a profile before
  signing in, waiting for msiexec);
- say the container image is built for each stable release, as the workflow
  skips pre-releases and tags that are not vX.Y.Z;
- merge the second "Added" heading in Unreleased into the first.

Refs #105, #111, #58, #25, #52, #87, #89, #90, #92, #36

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
List the exit code changes as scripting-surface changes

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
SECURITY.md now covers what happens after a report (acknowledgement,
first assessment, status updates, fix targets by CVSS v3.1 severity and
the coordinated disclosure period), where users are told about an
actively exploited vulnerability or a severe incident (the repository's
security advisory first, then a notice at the top of the README, then
the fixed release's notes), and how an advisory for a fixed
vulnerability is published.

Every advisory is written from docs/security-advisory-template.md so
that it has the same fields. The README links to the policy near the top
and keeps an empty, comment-delimited block for a short notice; while it
is empty the README renders as before.

It also states that there is no bounty and no encrypted email for now,
adds a safe-harbour clause, and says how a CVE identifier is requested
(through the advisory, with GitHub as the CVE Numbering Authority).

Refs #120

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Describe the disclosure process and where security notices appear

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
SECURITY.md "Supported versions" replaces "only the latest release
receives fixes" with the support rule: from 1.0.0, each major version
is supported with security fixes for five years, delivered in the
latest release of that major version; fixes stay available to people
whose HodeiShield subscription has ended, since releases are public
downloads. During 0.x, fixes go into the latest 0.x release, and 0.x
has no end-of-support date until 1.0.0 is released. An end-of-support
notice is published twelve months ahead in SECURITY.md, the README
security notice block and the release notes.

docs/user-information.md gathers the product and version
identification, the manufacturer's address and contact, the two ways
to report a vulnerability, the intended purpose, secure use and known
limitations, how each install channel updates and uninstalls, how to
turn off the new-version notice, how to remove the configuration,
update-check record and keychain entries, and where the SBOM is
published. Each release tag keeps the copy that applies to it.

The README links to both and states the rule in one sentence.

Refs #127
Refs #128

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
State the support period and add a user information document

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
List the client tenants of a portfolio credential and read one of them on
data calls. The selection travels as one request header and the client
refuses any answer that does not confirm the same tenant. The module is
hand-written against a draft contract and isolated in portfolio.rs; the
generated client is untouched.

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Add 'tenants list' and the global --tenant and --all-tenants selection on
read commands. A list across tenants labels every row, in the table and in
--json and --csv, with the tenant whose own request returned it. A client
outside the portfolio is reported as not found before any data is read, and
a credential without portfolio scope behaves as before.

Closes #54

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Add the 'Several tenants (MSSP)' section to the README and stop pointing
MSSPs at one profile per client. The section is a draft until the portfolio
part of /v1 is published.

Closes #45

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Read the client tenants as the API describes them: ask for the listing in
ascending name order, require the organisation, and treat a licence status
the CLI does not know as not readable. Accept a tenant confirmation only as
the single lowercase id that was asked for. An API with no listing route is
reported with exit code 7 instead of a generic failure.

A rate limit or a missing data scope now ends an all-tenants walk instead of
being repeated for every client, and the messages name the limit that was
hit and the tenant refusals the API distinguishes.

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
- Tenants with a licence status this version does not know are not read,
  are named on stderr, and make an --all-tenants walk exit non-zero;
  "inactive" is said of inactive tenants only.
- A UUID-shaped input that matches one tenant's id and another's slug is
  ambiguous.
- Slugs with characters outside [a-z0-9-] are shown with the start of the
  tenant id in the table.
- The tenant listing is de-duplicated by id, and a changing total is
  reported.
- A 404/405 on the listing that carries a portfolio error code is the
  API's own error, not "portfolio not offered".
- The tenant rate-limit hint applies only when a client tenant is selected.
- Tenant scoping is a property of each operation (tenant_scoped), set by
  the code generator.
- Add tests for the echo on every operation, retried answers, redirects,
  204/304, partial walks, CSV formula guarding and tenant resolution.

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Name the role that creates a portfolio key (an organisation administrator of an active MSSP
organisation), use the portfolio key name in the changelog, spell the listing column with the
same British spelling as the rest of the text, and show a client organisation in the example.

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
…sation administrator

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
The portfolio entry did not say what --all-tenants does when a client
fails while it is read. In the code, a client that fails with a licence
not in force (exit 8) or not found (exit 5) is named on standard error
and skipped, the other clients' data is printed, and the command exits
non-zero with the code of the first failure; any other failure stops the
run before anything is printed. Say so, mention that --tenant also works
on get and compliance posture and prints the "Client tenant" line, and
rewrap the long line.

Add the Changed entry for the errors that involve a client tenant: the
hints for an unknown client, a missing scope on a portfolio key, the
portfolio rate limits and a missing or unsupported tenant selection.

Refs #45, #54

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Read several client tenants with one portfolio credential

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
The portfolio key and organisation limits are not the only ones: once a client tenant is selected, that tenant's own limits apply and can be tighter.

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Say that a client tenant's own rate limits can be lower

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Vendor the published /v1 document (2026-10-16) and regenerate the client.

- The generator accepts the X-HS-Tenant header parameter: it is not part
  of the generated function, and it marks the operation as tenant-scoped
  (replacing the path rule). Any other header parameter is still an error.
- x-hs-known-values, x-hs-deprecated-values and
  x-hs-deprecated-values-sunset are read from the parameter's schema,
  where the document puts them, and then from the parameter itself.
  Deprecated values and their sunset are emitted with each operation.
- An object declared open (additionalProperties: true) stays a JSON map,
  so error details keep every key.
- The tenant listing is now a generated operation; the portfolio module
  uses it, and sign-in does not ask for its scope.
- The alert severity filter warns about a deprecated value using the
  document's list and sunset. The four replacements stay in a small table,
  checked against the document's deprecated values by a test, until the
  sunset on 2027-01-14.

Refs #53

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Follow version 2026-10-16 of the API document

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
Prepare 0.4.0

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
@d0ubl3g
Gorka Gonzalo (d0ubl3g) merged commit 3405f04 into main Oct 12, 2026
29 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