Repository navigation
Security
- Python — PyPI shows a change of provenance on 1.0.0. Its 25 wheels were uploaded by a
one-off workflow,pypi-recovery.yml, not byrelease.ymlas every earlier release was.
release.ymlatv1.0.0callspypa/gh-action-pypi-publishfrom inside the Forge's
publish-pypicomposite action, and nested there the action cannot find its own container
image (the runner leavesgithub.action_repositoryempty, actions/runner#2473), so the
release's PyPI upload failed before sending anything. The recovery workflow uploaded the same
bytes thev1.0.0tag run had packed and attested, after the same checks the release runs:
the inventory, every wheel's build provenance and the release attestation. Only the workflow
named in the wheels' PEP 740 publish attestations differs, and a tag's workflow cannot be
replaced, so PyPI flags 1.0.0 (release.yml→pypi-recovery.yml) and will flag the next
release once more, the other way, whenrelease.ymluploads again (below). Every wheel still
verifies from the tag:
gh attestation verify <wheel> --repo SkunkWerkx/HyperUuid --source-ref refs/tags/v1.0.0 --predicate-type https://github.com/SkunkWerkx/.github/predicates/release/v1. (Python)
Added
- Java runs on JDK 21. The jar is multi-release: its base reaches the core through
JNI, from a library built from the core for every platform, and JDK 25+ keeps FFM. The API
and exceptions are the same on both, with two exceptions: the load failure's message and
cause name the path's own library, and a fill above 64 KiB can throwOutOfMemoryErroron
JNI. Anullargument is aNullPointerExceptionnaming the parameter on both. (Java) - Python: a source distribution.
hyperuuid-<version>.tar.gznow ships with the wheels,
so where no wheel fits, pip falls back to building from source (Rust 1.89 or newer and a
C linker); CI proves that build on x86-64 glibc 2.17 and musl. Attested like the wheels.
(PyPI) - C: one archive per platform on the GitHub Release.
hyperuuid-<version>-<rid>.tar.gz
(.zipon Windows) for the eight desktop RIDs, android-arm64, android-x64, iOS, the iOS
simulator, Mac Catalyst on both architectures, and wasi-wasm32 (the Apple mobile and
WebAssembly ones static only):
the generated header, the shared and static libraries (Windows adds the DLL's import
library),hyperuuidConfig.cmakeforfind_packageandFetchContent, andhyperuuid.pc
for pkg-config, every path relative so an archive works wherever it is unpacked. The static
library needs nothing past the C runtime. Packed and attested at the tag from the CI run's
attested libraries and named in the release attestation; CI builds a consumer against each
desktop archive through CMake and pkg-config, shared and static, and against the Apple
mobile ones on a Mac (an iOS device link, the simulator, Mac Catalyst). (C) - C++:
hyperuuid.hppin every C archive. A header-only C++23 binding over the C header,
linked against the same targets:std::expected<T, hyperuuid::errc>from every generating
call (errcis astd::error_codeenum), auuidvalue type withparse,to_stringand
ordering,std::chronooverloads for v7 and timestamps,std::spanfills, the SQL Server
order and inspection in either layout, and the RFC namespaces. CI builds and runs a C++
consumer beside the C one on every desktop archive and the Apple mobile ones. (C++) - Core on big-endian. CI runs the core's test suite, conformance corpus included, on
s390x under QEMU. (repository only) - A TypeScript binding for Node and Bun, on npm as
@skunkwerkx/hyperuuid. A Node-API addon built
with napi-rs, the core linked into the.nodefile, published as eight platform packages
(@skunkwerkx/hyperuuid-<platform>, one per RID) that the root package picks through
optionalDependencies, so nothing compiles at install. Node 22.13 or newer and Bun, CommonJS
and ESM, ids in and out as strings or 16-byteUint8Arrays, and the doors every binding
has: v4, v5 and v7, v7 batches and buffer fills, the SQL Server order, inspection in either
layout, andisAvailable()/nativeVersion(). Where no platform package fits
(--omit=optional, a platform outside the eight) the root falls back to a tenth package,
@skunkwerkx/hyperuuid-wasm32-wasip1, the core built forwasm32-wasip1and run through
node:wasi, a plain dependency of the root so it is always installed: the whole suite passes
on it on Linux x64 (glibc), macOS arm64 and Windows x64, the consumer smoke on Alpine at the
exact Node floor, 22.13.0, and its browser entry in Chromium. Big-endian hosts (s390x
under QEMU) are a printed loss: the smoke's checks pass and the process then never exits, the
runtime reading its reference counts host-endian over little-endian wasm memory.
Bun 1.4.4 cannot load it and stays on the addon; a panic aborts there rather than being
caught. The Node floor is the runtime's,^22.13.0 || >=23.5.0. (TypeScript) - An R binding, as the source package
hyperuuid. A C shim over the core's C ABI,
reached through.Call, with the core built as a static library from the Rust crates
vendored into the tarball, so an install needs Rust but no network. Every function is
vectorised and propagatesNAelement-wise through character, integer, logical and
POSIXctresults; arguments and the raw doors are strict and error. R 4.2 or newer.
(R) - Release plumbing for npm and CRAN. The tag run packs, attests and preserves ten npm
tarballs (the root package, itsoptionalDependenciesinjected at pack time, the eight
platform packages and the WebAssembly package, whose runtime dependencies are pinned from the
lockfile) and the R source tarball; the publish dispatch uploads the npm packages
through Trusted Publishing, platform packages before the root. No job uploads the R tarball:
it is submitted to CRAN by hand from the preserved bytes. CI builds the addon on every RID
and runs its suite on Node there, and on Bun on every RID but win-arm64 and osx-x64 (the
cross-build leg runs Node alone), runs the suite on the WebAssembly fallback on Linux, macOS
and Windows and the consumer scenarios against the packed tarballs from a local registry
(typescript/consumer-tests/), and runsR CMD check --as-cranon linux-x64,
linux-arm64, osx-arm64 and win-x64. Dependabot covers the TypeScript binding's npm and
cargo manifests (the R wrapper crate's only dependency is the core itself at the release
version, and its lock is derived fromrust/Cargo.lockbyr/tools/vendor.sh, never
committed), and
.gitattributeskeepsr/andtypescript/out of the archive Packagist serves.
(repository only) - Every binding reports an exhausted v7 stream as its own error. The core's new
NewV7Error::CounterExhausted(return code 6 over the C ABI) reaches each binding as a
state error, never as a random source failure, at the single and the batch site alike, with
the core's message: Python raisesRuntimeError, RubyHyperUuid::CounterExhaustedError,
PHPCounterExhaustedException, TypeScript an error with code
ERR_HYPERUUID_COUNTER_EXHAUSTED, R a plain error condition, GoErrCounterExhausted, Java
IllegalStateException, C#InvalidOperationException(theTryforms return false) and
SwiftUuidGenerator.Error.counterExhausted. (C#, Java, Go, Python, Ruby, PHP, Swift,
TypeScript, R) - Rust —
uuid1feature.From<uuid::Uuid> for Uuid,From<Uuid> for uuid::Uuid,
From<&Uuid> for uuid::Uuidand==across the two types, behind an off-by-default feature
that addsuuid1.29 or newer without its default features. The bodies carry#[no_panic]
and are linked into the no-panic proof. (Rust)
Changed
- v7 timestamps stop at 9999-12-31T23:59:59.999Z, in both directions. A version 7 is
minted with a timestamp up to 253,402,300,799,999 ms, the last instant .NET'sDateTimeand
Python'sdatetimecan name, so every binding's time type states the whole accepted range;
one millisecond more is the out-of-range error every binding already had for a negative or
48-bit overflowing value. The version-agnostic timestamp door (GetTimestampand its
spellings) answers for a version 7 dated past that cap as it answers for a version 6: no
timestamp. C# and Python used to throw from that door for such a value, since their time types
stop at 9999; every binding now agrees without an exception. The 48-bit field itself reaches
10889, so the per-version millisecond reader (V7UnixMillisand its spellings) still reads a
UUID another generator dated past 9999 as the field says. Go'sNewV7AtTimealso guards the
time.Timeitself:time.Time.UnixMilliwraps silently past the year 292 million, and a date
in year 584,556,019 used to come back as a valid id stamped 1970-01-01T00:00:00.384Z. Every
out-of-range message now names the cap; for PHP, whose exceptions are otherwise 1.0's, the
new wording and the cap are listed under "Differences from 1.0" inphp/README.md. (all) - Go — one backend: the core translated to Go source, no cgo, no binary in git. The Rust
core built forwasm32-wasip1is translated to one Go file by
wasm2go and committed asgo/internal/core/core.go;
go generateingo/regenerates it with a pinned rustc (1.99.1, a reproducibility
constraint) and a 64 KiB guest stack, CI regenerates and diffs it on every push, and
prepare-release.ymlregenerates it at the version. cgo, the thirteen committed archives
undergo/staticlib/, thehyperuuid_localtag and the core freshness check are gone:
go getis the whole install,CGO_ENABLED=0is fine, and the module builds for every
GOOS and GOARCH Go has (a 23-pair cross-compile sweep in CI; iOS andandroid/amd64need
a C linker because Go's own ports link externally there). The whole suite now runs under
TinyGo on wasip1 and under stock Go onjs/wasmandwasip1/wasmin CI, beside the
TinyGo browser page. The core'srandom_getis served from an AES-256-CTR keystream,
keyed fromcrypto/randand rekeyed after 1 MiB or one second, where
golang.org/x/sys/cpureports the CPU features Go's own AES assembly requires (amd64,
arm64, s390x; never underpurego, TinyGo or FIPS 140 mode), and fromcrypto/randper
call everywhere else; a failed or short read isErrRandomSource, never a UUID.
golang.org/x/sysis the module's second dependency. v7 calls run on one primary instance
behind its mutex; v4, v5 and inspection run on the primary when its lock is free, else on a
pooled instance. A v7 batch lives in the primary's guest memory, which grows to the largest
batch asked for and never shrinks (1 GiB atMaxV7Batch, out of reach on 32-bit
WebAssembly hosts);NewV5takes a name of at mostMaxV5Namebytes (2,147,483,647 on a
64-bit host) and returns the newErrNameTooLongpast it. On the Apple M6 aNewV4is 37.0
ns againstgoogle/uuid's 167 and aNewV7At37.3 against 202; the batch of 1000 is 2.84
µs against the cgo binding's 1.84 on the same machine, the batch loss; the README prints
the others beside it (2x under contention on Linux arm64,V7Timestamp4.8x behind
id.Time()). (Go) - R — the wrapper crate depends on the
hyperuuidcrate by exact version, as any
crates.io consumer does, instead of a copy ofrust/staged into the package.
tools/vendor.shresolves that version from the checkout'srust/(a command-line patch,
never a committed file; it refuses a pin that differs fromrust/Cargo.toml), vendors the
core ascargo packagewrites it beside the other crates (15 insrc/rust/vendor.tar.xz),
and rewrites the lock offline so it names the crates.io source; the pin is a version file
prepare-release.ymlbumps withDESCRIPTION. The Rust build is offline from that tarball
only, and stops without it rather than fetch the published core. The release's R tarball
check reads the pin and the vendored core's version.cran-comments.mdstates the core's
no_std, allocation-free and panic-free guarantees, and what is left to the binding and
to R. (R) - PHP — breaking: the package is a native extension, installed with PIE.
pie install skunkwerkx/hyperuuiddownloads a prebuilt Zend extension,hyperuuid, built
from the core with ext-php-rs, from the GitHub Release: 18 zips, PHP 8.3, 8.4 and 8.5 (NTS
only) on six platforms (Linux x64 and arm64 on glibc and on musl, macOS arm64,
Windows x64), each attested and named in the release attestation.composer requireno
longer installs it, and no FFI package is kept.ext-ffi,ffi.enableand preloading,
HYPERUUID_NATIVE_LIBRARYandHyperUuid::isAvailable()are gone;
extension_loaded('hyperuuid')is the check. The classes, methods, defaults, exceptions and
messages are 1.0's otherwise,==on twoUuids is still PHP's loose property comparison,
and aUuidserialized by 1.0 unserializes unchanged (and the other way). Arguments are
taken as 1.0's userland methods took them: weak-mode callers get PHP's coercion
(newV7("1700000000000")still works), strict callers get the sameTypeErrors, and a
DateTimeInterfacewhosegetTimestamp()returns a non-int goes through 1.0's arithmetic.
What does differ: a call with too many arguments is anArgumentCountError(1.0 ignored the
extras), and one with too few is worded as for a built-in function; the privatebytes
property is untyped and notreadonlyin reflection; and aDateTimeInterfacepast the
64-bit millisecond range is aTimestampOutOfRangeExceptionrather than aTypeError. Errors
name the caller's file and line, andisRfc()never matches a version outside 0–15.
php/README.mdlists them under "Differences from 1.0". Stubs for IDEs
and PHPStan are in the repository, inphp/stubs/. No PHP binary is left in git:php/src/
is gone, and nothing stages one. After every publish,
release.ymlhas PIE install the release on every platform and minor. (PHP) - The v7 counter is re-seeded on every new millisecond. The stream used to be one 26-bit
counter, seeded once per process and never reset, so two ids revealed how many were minted
between them, and it wrapped every 67,108,864 UUIDs, rolling a batch's tail a millisecond
forward and leaving individual calls either side of the wrap in reverse order. Now each
millisecond holds 2^20 steps, the stream is re-seeded at random whenever a timestamp moves it
forward (RFC 9562 §6.2 Method 1), a single call takes one step and a batch of n takes ⌈n/64⌉.
A timestamp up to 11 s behind the stream is clamped onto the stream's millisecond, and a
millisecond that runs out splits into the next, up to 1000 ms ahead of the supplied
timestamp; a split that would go further, or past 2^44 − 2, fails with the new
NewV7Error::CounterExhausted(return code 6 over the C ABI) and reserves nothing. The
layout is untouched and the corpus unchanged. The contract is README "v7 ordering,
precisely". Targets without 64-bit atomics keep the old never-reset counter. Measured on the
Apple M6 on 2026-10-27 (Criterion, the same harness against both cores, one process per
case), the change is level within 1%, and its small losses are these: a single v7 costs
600.3 ns a call against 600.7 ns before, 592.3 against 592.2 ns on the real clock, and 1000
singles 590.0 against 585.7 µs (+0.7%); singles from eight contending threads cost 360.5
against 357.1 ns per call in wall time over the eight (+0.9%); a batch of 1000 costs 18.18
against 18.08 µs alone (+0.6%) and 13.17 against 13.23 µs per batch in wall time over eight
threads. The contended figures include the harness's own shared call counter, which all eight
threads increment, so the cores' own difference under contention is somewhat larger than the
wall time shows. A single id draws 11 random bytes, the seed, its low counter bits and its
tail, where it drew 6; the same build drawing 16 cost 720.5 ns single and 511.3 ns contended,
because on macOS agetentropyof 12 bytes or more is slower. The TypeScript and R tables
were re-measured there; the linux-x64 tables predate the change. (Rust, and through it every
binding) - v7 calls more than 11 s behind the stream are no longer ordered. A timestamp more than
11 s behind the newest one the stream has reserved at, or past 2^44 − 2, is minted at
itself, outside the stream: it succeeds, carries its own timestamp exactly, leaves the
stream alone and is ordered against nothing. Callers who mint for ordering at a fixed
historic millisecond in a process that has also minted at the present used to get strictly
increasing ids and now get unordered ones; a batch is still strictly increasing within
itself. (Rust, and through it every binding) - Python — the
cp314-cp314twheel is gone. Each platform ships two wheels where it
shipped three,cp311-abi3for CPython 3.11 and newer with the GIL andcp315-abi3.abi3t
for 3.15 and newer with or without it: 17 wheels a release where 1.0.0 had 25. The
free-threaded 3.14 wheel proved the GIL-free path, and it was bound to one interpreter
version, too narrow an ABI to carry. Free-threaded 3.14 now gets no wheel, and pip builds
the sdist (see Added), which a report-only CI job builds and tests there; free-threaded 3.13
cannot build it, since PyO3 0.30 refuses free-threaded CPython below 3.14. Free-threading
starts at 3.15. (Python) - The release flow, after its first run.
release.ymluploads the wheels as a step of
its ownpypi-publishjob again, so their PEP 740 publish attestations name it; the Forge
commit's step output isrevision, which clears CodeQL's
actions/cache-poisoning/poisonable-step; andpypi-recovery.ymlis gone. (repository only) - Rust, R — minimum Rust is now 1.89 (was 1.85), the floor of current
uuid1.x. Source
installs of the R package and builds from this repository needrustc1.89. (Rust, R) - C# — .NET 10 is supported, on desktop, server and in the browser. The package builds
net10.0andnet11.0from one source, and package validation holds their public APIs
identical. On .NET 10 it covers Windows, Linux (glibc and musl) and macOS, framework-dependent
and Native AOT, and Blazor WebAssembly; iOS, Mac Catalyst and Android stay .NET 11 and later,
and a .NET 10 project for any of them stops at build with the new errorHYPERUUID003, which
names the platform.
HyperUuid.targetsmoves tobuild/net10.0/(andbuildTransitive/net10.0/), one copy NuGet
selects for both frameworks. CI runs the suite and the Native AOT smoke test on both
frameworks on every desktop and musl leg, and a newtest-nuget-packagejob proves from the
packed package that a .NET 10 Native AOT publish links the core in. (C#) - PHP: the floor is 8.3. 8.2 reaches end of life on 2026-12-31. A project on 8.2 keeps
resolving 1.0.x. (Packagist) - Faster ids on macOS. The core draws its random bytes from
CCRandomGenerateBytes,
Apple's user-space CSPRNG seeded by the kernel, the generator Rust's standard library uses
on Apple platforms. It replaces agetentropysyscall per id: a single v7 on an Apple M6
went from 594 to 60 ns. iOS, tvOS, watchOS, visionOS and Mac Catalyst already used it through
getrandom. The TypeScript and R tables are re-measured with it: on Node,newV7()now beats
theuuidpackage'sv7()(2.3x), and R'suuid_v4()is 12.7x faster thanuuid's
UUIDgenerate(), up from 7.1x. (core, and every binding on macOS) - C# — the iOS and Mac Catalyst smoke test runs on the SDK's defaults. Its Mac Catalyst
build setRegistrartomanaged-static, after a Release app on .NET 11's default,
trimmable-static, aborted beforeMain, a fault then put down to the SDK. It was the
test's own: its code touches no Apple API, so the trimmer dropped the platform assembly the
runtime calls into at startup, and the iOS device build, linked in CI but never run, dropped
it as well. One UIKit symbol used in a module initializer, as every real app uses UIKit,
keeps that assembly and puts UIKit back in the native link, so the hand-added UIKit
framework is gone too. The package is unchanged. (repository only) - C# — the benchmarks float to BenchmarkDotNet's prereleases. 0.15.x, the newest
stable, knows no runtime past .NET 10 and stops in its SDK validation on net11.0; the 0.16
previews know .NET 11, and the harness takes them (*-*) until 0.16.0 ships stable.
The harness had stopped there since the C# floor moved to .NET 11, so the C# tables
predate that move. (repository only) - Swift — the core comes from the GitHub Release, not from git. The root
Package.swift
names two zips by URL and checksum, the static-library artifact bundle and the XCFramework,
and SwiftPM downloads them and refuses one whose SHA-256 differs; the 22 committed files
underswift/are gone. Nothing changes in a consumer's manifest. In a checkout, the bundle
is build output:.github/scripts/local-core.shbuilds the host's into it,swift test
links it, andHYPERUUID_LOCAL_COREand the Swift core freshness check are gone. (Swift) - The C header is generated.
include/hyperuuid.hcomes fromrust/src/ffi.rs's doc
comments through cbindgen, and a test fails when the committed copy differs; the Swift
bundle carries the same file. The hand-written header it replaces never mentioned return
code 6. (repository only) - WebAssembly builds assemble a v7 batch without byte swaps. WebAssembly has no byte-swap
instruction, so each item's big-endian stores were chains of shifts and masks; on it, each
item is now one 8-byte load and two 8-byte stores built in little-endian order. The bytes
are the same, and every other target keeps the walk it had, which measured faster natively.
Through the core translated to Go by wasm2go, a batch of 1000 went from 7.7 to 5.4 µs on
Linux x86-64 and from 7.5 to 5.6 µs on Windows (i9-11900H), and from 2.9 to 2.1 µs on an
Apple M6. The raw module gains less: in V8 (Node 24) its batch went from 2.65 to 2.11 µs,
under wasmtime 50 from 13.7 to 13.0 µs. The one loss is the translated core compiled to
WebAssembly a second time, by Go itself (GOOS=js): there the same batch went from 36.0 to
41.5 µs with the AES stream and from 5.8 to 10.6 µs with no entropy at all. The binding
takes the OS source there, where its batch is 13.0 µs (11.6 in the spike with the old
walk). All on the M6, interleaved A/B (walk-ab.sh). A test holds the two walks to each other, and the no-panic proof links the
WebAssembly one on the host (--cfg hyperuuid_words_walk), sinceno-paniccannot see an
aborting panic. (crate, C# Blazor, Go TinyGo, Swift WebAssembly) - The pull-request board runs only what the pull request could have broken. The one
native matrix that built and tested every binding on every host on every push is now one job
per concern: the Rust core on all seven hosts first, with its export check and the C and C++
consumers, then one job per host and binding, each binding's suite started only when its
tree, the core or the workflows changed, after its lint passed once on a Linux arm64 runner.
A classifier reads the pull request's files and fails closed (an unknown path, an empty list
or an API failure runs everything), and one aggregate job is the status to read, red when a
job failed or was skipped while its gate said run. A pull request touching.github/runs
the whole grid: 104 jobs in 19m52, against 84 jobs and 24 min before. The release-mode
board, on dispatch and on the Monday schedule, is unchanged in coverage, and the Forge's
release workflows are untouched. The runner labels name the toolchain (xcode-27,
windows-2025-vs2026,windows-11-vs2026-arm,ubuntu-26.04and its arm64 twin), and the
Go, Swift, Python, Ruby, Java and .NET toolchains the images carry at the pinned versions are
used as installed. (repository only) - One dispatch prepares and attests, one tag publishes. (repository only)
prepare-release.yml
bumps, dates the CHANGELOG heading, runs the full board, packs every registry input, attests each
package and the inventory, preserves them for 90 days and commits the staging commit; pushing
vX.Y.Zat it verifies the preserved bytes, signs the release attestation from the tag and
publishes to the six registries. A retry is the same workflow dispatched at the tag, so the PyPI
and npm publisher isrelease.ymlfrom 1.1.0 on and never changes again (1.0.0's wheels went up
from a one-off workflow after the tag run's upload failed, which PyPI shows as a change of
provenance).stage-native-binaries.ymlis gone; CodeQL runs on the preparation commit inside
that run and must leave no open alert before the staging commit exists.
Fixed
- The shared library names itself. On macOS its install name is
@rpath/libhyperuuid.dylib, not the build machine's path, and on Linux and Android its
soname islibhyperuuid.so, so a program linked against it finds it through its rpath or
the loader's search path. Bindings open it by path and see no difference. (core) - C# — a Debug Blazor WebAssembly build loads (#50).
Chromium refused an unstripped Debug build'sdotnet.native.wasmwith "module uses a mix
of legacy and new exception handling instructions": the package translated the archive's
legacy exception handling with awasm-optpass that rides the SDK's post-link step, and the
SDK skips that step for an unstripped module. The archive no longer needs translating: it is
built with-Zbuild-std, on stable Rust withRUSTC_BOOTSTRAP=1for that one build, for
plain wasm, so it holds no exception-handling instructions and none of the features .NET
10's toolchain rejects (dotnet/runtime#132858), and the package's--translate-to-exnref
item is gone. The same build is what lets .NET 10 link it, and the archive in the package
shrinks from 3.3 MB to 265 KB. (C#) - A v7 batch past 64 MiB of random bytes no longer traps on WASI.
getrandomhanded
the host the whole request in onerandom_get, and wasmtime refuses one past 64 MiB, so a
batch of more than about 11 million v7 ids (aMAX_BATCHdraws 402 MB) aborted the
process. The draw now goes a 64 KiB chunk at a time on WASI; every other target is
unchanged. (Rust, the Ruby and Swift WebAssembly builds, which link its
wasm32-wasip1archive, and Go, whose core is that build translated)
The full list is in CHANGELOG.md.
Verifying
Every file in this release verifies from the tag alone. One attestation, signed by this
repository's release.yml at v1.1.0, names all 99 of them: every registry
package (NuGet, RubyGems, PyPI, crates.io, Maven Central and npm), a CRAN source tarball the maintainer submits by hand and the Swift core's HyperUuidCore.artifactbundle.zip and HyperUuidCoreApple.xcframework.zip, attached below,
and 15 C archives, one per platform, attached below,
and 18 PHP extension zips for PIE, one per platform and PHP minor, attached below. Its predicate is the release inventory attached below.
gh attestation verify <file> --repo SkunkWerkx/HyperUuid \
--source-ref refs/tags/v1.1.0 --predicate-type https://github.com/SkunkWerkx/.github/predicates/release/v1The Swift zips, the PHP extension zips, the Python wheels and sdist, the Node addons inside the npm platform packages and the archives inside the NuGet package and the
jar also carry build provenance from CI run 41282153468
at commit 7eec343, the parent of the tagged commit, signed by the Forge:
gh attestation verify <file> --repo SkunkWerkx/HyperUuid --signer-repo SkunkWerkx/.github --source-digest 7eec343f59a599b055861e27fe1e088bee38ed34inventory.json lists every file with its size and SHA-256 and, for each file with build
provenance, the commit it was built from and the repository that signed it; it carries
build provenance of its own at the tagged commit. PyPI additionally holds a PEP 740 publish attestation for every wheel and the sdist, and npm a provenance statement for every package, linking it to the
publishing run of this repository's release.yml.