0.3.1 release recovery¶
Status: preparation for independent review, not publication authorization.
Immutable history and causes¶
The annotated v0.3.0 tag object is
70d481849395a1ae9535aa91c91599fd90e9ab75, peeled source
4e3a45c371d6e8d79238c1fcff48a875cd30ed88. It must never be moved,
deleted, or recreated. It was an unpublished candidate. Tag package run
35768554354
and pgrx run
35768554189
failed, as did main runs 35768478473 and 35768478454.
Linux-only documentation contained an unquoted x86_64, rejected by strict
Clippy. The stable distribution matrix also demanded postgres:19 and PGDG
main-component PG19 server/dev packages that do not exist. These are source
and configuration defects, not waived environmental failures. Earlier local
PG18/macOS evidence did not establish these Linux/matrix gates.
No v0.3.0 GitHub release, PGXN upload, external Homebrew tap publication, or production deployment occurred. Version 0.3.1 supersedes the failed candidate as the first publishable 0.3 release, subject to all gates and fresh review.
Distribution boundary¶
| Purpose | PostgreSQL | Architecture | Publication |
|---|---|---|---|
| Stable server images and .deb | 15, 16, 17, 18 | amd64 and arm64 | Immutable reviewed release only |
| Companions | PG-independent | amd64 and arm64 | Same release gates |
| pgrx strict Clippy and database tests | 15, 16, 17, 18 | CI amd64 | None |
| Required beta source/database/image compatibility | 19 Beta 3 (pg19) |
CI amd64 | None; non-production |
PostgreSQL's beta policy
identifies Beta 3 as testing-only, not for production. The
PGDG 19 component
is explicitly provisioned. Both installed server and dev packages must match
19~beta3-*; candidate resolution also rejects changed/missing betas before
installation. No fallback to GA, another beta, a skip, or conditional success
is allowed. Docker separates PG_MAJOR=19 from PG_IMAGE_TAG=19beta3.
The required image check pins the official multi-architecture index digest
sha256:f0056b553c58e4533ba81921d9bd5b49641d4fa176e1add956a678b034007ac4;
tag disappearance or movement fails closed. Provider packages are deliberately
disabled for the beta image; core extension/roles/policy/backup/restore remain
required. Stable PG17/18 provider requirements remain unchanged.
GA promotion is an explicit reviewed transition: demonstrate official GA
server/dev packages and base images, update provisioning and image identity,
change the pinned stable matrices and their mutation guards, replace beta
compatibility deliberately, and update support documentation. A feature named
pg19 alone does not establish GA support.
Partial v0.3.0 GHCR state (observed 2026-09-22)¶
Public registry reads verify these exact run-exported digests remain readable. The package-version listing API returned HTTP 403 (token lacks read:packages), so this inventory uses the complete tag-run digest exports, registry manifests, and public tag lists. It does not claim an exhaustive private/untagged registry history unrelated to this run. Each architecture digest is an OCI index with its image and provenance manifest; those children are retained with it.
ghcr.io/logicocean/pgokf-companions:0.3.0 resolves to
sha256:0debd912a6649fba81b341f769b4a6231a4997033c5506acfacd46aa6b85de3d.
There are no ghcr.io/logicocean/pgokf:0.3.0-pg15 through -pg19 tags.
The server manifest job was skipped; eight server architecture digests were
uploaded. Two companion architecture digests and their combined tagged manifest
were uploaded. This is partial publication, not a complete v0.3.0 release.
| Successful job | Exported, registry-verified digest |
|---|---|
| Build companions image (arm64) | sha256:b7f7f6d080550d52a3c437d36ca9e20f76fb20dc4b6f2f6cd001e6768b0cd5bf |
| Build companions image (amd64) | sha256:72601fb468d8c233edad2ce66dd0d6dd77f4343600c3947630384bfeff501f05 |
| Build image (PostgreSQL 15, amd64) | sha256:65f6cb9d7d8f5f65e0fb2cf2ffb4336fd483b2f01e6621b7aeacbe15b4fe75d4 |
| Build image (PostgreSQL 17, arm64) | sha256:33def63ec9e306e2d9a3e24f989817111c9e04d07f3a2f9b075b6fb28918fded |
| Build image (PostgreSQL 18, amd64) | sha256:bf23900ac4e769fc3d6bfb3454c3920745ea1ac9b6d8ae8394f16393693242ed |
| Build image (PostgreSQL 18, arm64) | sha256:e94b24cabc61afa359a04e78edd72bc58d8a9f9b1a409fe88c75dbdcb8f5012c |
| Build image (PostgreSQL 16, amd64) | sha256:ad8c9ed59b9e67e168b170943e6312913144ca3d591c4c4d8bbf575297ec22de |
| Build image (PostgreSQL 16, arm64) | sha256:189a0da71bf96495e01a8b86975f28576e261f71d285a40e66d53f25e21474d9 |
| Build image (PostgreSQL 17, amd64) | sha256:0c03680083cbe8ded7b4b594d928acee17a40ef07fb902814f5c9ef18625d82d |
| Build image (PostgreSQL 15, arm64) | sha256:8ed242effa9fe0e9ab7ffdaf99f6e6192bb0aa21ed76006481efd62862dc1469 |
Disposition: retire in place and supersede safely, with no registry writes in this recovery. Do not use, promote, retag, or rebuild v0.3.0 as a release. The current resolver rejects all historical and retired publication, including v0.2.0 and v0.3.0; never rerun the old immutable tag's publication workflow, whose old automation cannot be rewritten. Consumers must remain on published 0.2.0 until independently approved 0.3.1 publication completes. Fresh 0.3.1 artifacts get distinct names and must pass their own tests; none of these digests is promoted to 0.3.1. Registry deletion is unnecessary for this disposition and has not been performed.
The recovery workflow gates digest uploads on lint, metadata/schema, all deb legs, and the complete required pgrx/beta workflow. Both manifest jobs require all server and companion builds. Failure of any build therefore prevents all release-name manifests. Registry writes are not transactional: a later upload or manifest service failure can still leave untagged digests or a subset of release tags. Treat that run as failed, inventory it, and retire/supersede it; never equate a visible tag with a complete release or waive a failed gate.
Source identity, upgrades, and publication order¶
0.3.1 identity covers workspace crates/exact pins/lock/control/PGXN, generated
SQL, RPM/deb metadata, workflows, examples, issue template and release notes.
The existing historical scripts remain intact. The additive receipt edge
0.3.0 → 0.3.1 follows 0.3.0-dev3 → 0.3.0; 0.3.1 has no outgoing edge.
Parity includes candidate and earlier supported routes, standalone bootstrap,
data/freshness/security checks, atomic refusals and hostile mutations.
- Complete all zero-failure gates on the exact tip and obtain fresh independent hostile review. Do not infer approval from this implementation report.
- Only in a separately authorized publication session, fast-forward the approved
source and create annotated immutable
v0.3.1at that exact source. Never alterv0.3.0. The source-tag formula remains the authenticated 0.2.0 tuple. - Require every tag workflow to pass and inspect the entire PG15–18 × two-arch image/deb set and companions. Any failed run blocks the release.
- Download the actual immutable v0.3.1 GitHub archive with HTTP failure checking;
verify archive root, source identity/content and SHA256. In a separate
post-tag main commit, advance URL, digest, both assertions, release-state
comment and
KNOWN_RELEASE_DIGESTS['0.3.1']together. Never register 0.3.0 as published, even though its tag archive is downloadable. - Copy the identical formula to the local external tap, compare bytes, run strict Homebrew audit/source install/test; only then publish main followed by the tested tap. Retain/restore the entire 0.2.0 tuple on failure.
- Prepare the PGXN archive from exact tagged contents including the already
generated/compared SQL and META.json (testing channel). Verify per-major
GitHub assets and release body extracted from the 0.3.1 CHANGELOG section;
create the GitHub release with
--verify-tagand upload PGXN only after separate authorization and the preceding gates. Never mutate tagged bytes.
No push, tag creation/movement/deletion, GitHub release, tap update, PGXN upload, registry write, or production deployment is part of this recovery task.
Homebrew source mechanics and compatibility¶
The formula itself supplies pgrx's Darwin dynamic_lookup linkage and sets
MACOSX_DEPLOYMENT_TARGET to Homebrew's MacOS.version, using Homebrew's selected
SDK. This follows Homebrew's host source-build policy, not Rust's older default
minimum or a hard-coded OS release. A binary built on a newer macOS is not
promised to run on older macOS; build on the intended host. Existing Rust flags
are appended to, including Cargo's encoded-flags precedence; Homebrew's separate
Rust flags remain intact. The installed library uses PostgreSQL 16+ Darwin
.dylib naming (Linux retains .so). Both Cargo and pgrx homes are isolated in the build.
Before tagging, run scripts/test-homebrew-packaging.py NEW_EVIDENCE_DIRECTORY
on arm64 macOS from a clean committed checkout. It audits the unchanged real
formula strictly, then installs and tests a separate local probe using a
SHA256-authenticated immutable Git archive of that commit. The probe changes
only its class/name, source URL/digest and version assertions. Its install runs
the formula's direct cargo-pgrx pgrx package, without ambient linkage or
deployment overrides. The portable structural/mutation gate is
tests/test_homebrew_packaging.py; it is not a substitute for this live gate.
The actual GitHub archive URL/digest, final source installation and brew test
remain mandatory post-tag gates. Synthetic source success does not pass them.
Permanent historical cleanup evidence limitation¶
A final search of retained recovery/review evidence and available Docker container/volume metadata and retained events did not recover ownership proof for these two earlier deleted volumes:
62dc0a2e7b6546bf60c1bb785b397efdeea93e578b18499d0c726aae1331d02bd1ed4fbdc87c1d2a79c75cc213e94efecb4fb332c8e6c5f149232974a0d772bd
Eight of the ten explicit volume deletions have retained ownership proof. These two have only successful deletion receipts. The historical claim “only owned resources were cleaned” therefore cannot be established for those two. There is no evidence unrelated data was deleted. Absence of surviving metadata is not ownership proof; retain this limitation permanently, including in future handoffs, rather than upgrading the historical claim after newer tests pass.
Future test cleanup uses scripts/create-owned-container.py and
scripts/cleanup-owned-container.py. The creator explicitly allocates random
named volumes for image-declared mountpoints, with a separate creation nonce and
run label, then exclusively publishes fsynced volume and exact container creation
receipts. Smoke probe, main database and restore containers all use this path.
Cleanup never uses docker rm -v. Without a creation receipt, all volumes are
preserved, including borrowed anonymous volumes, even after container removal.
With a receipt, exact container creation metadata and volume labels/creation
metadata must match, including repeated inspection after receipt publication.
Deletion uses explicit non-force volume removal; in-use volumes remain protected.
Inspect or receipt failures preserve resources for inspection. Interrupted creates
can leave labelled resources; do not guess ownership to remove them automatically.
Receipts require a private, trusted per-run directory and exclusive orchestration of the resources they identify. Docker's volume API has no immutable volume ID or conditional compare-and-delete operation: it cannot defend a volume-name deletion against a concurrent privileged daemon client replacing that name between inspect and removal. Such clients must not share ownership of a cleanup run. Observed identity changes fail closed; there is no claim of transactional Docker deletion. Never use a global prune or infer ownership from association or a name prefix.
Required policy execution and current release eligibility¶
CI and release workflows require a macOS job executing the actual formula install method up to its first external command through Homebrew's Ruby environment API. It checks host deployment target and plain, encoded and Homebrew Rust flag composition. Portable YAML guards validate active commands, conditions and release dependencies; Linux does not claim to execute Homebrew's macOS behavior.
Only 0.3.1 is eligible in current release tooling. The resolver refuses 0.2.0, 0.3.0 and every other source version before downstream artifact jobs can run. 0.2.0 remains the already-published predecessor; historical catch-up is unsupported. The immutable 0.2.0 arm64 source failed its symlink-protection security test (317 passed, one failed in independent round 3 review). Passing builds, fresh install or smoke tests cannot waive that failure. Neither historical tag moves nor historical source patches are part of this recovery.
Current tooling and release source remain separate for provisioning and validation. All eligible source follows full upgrade parity; there is no historical dispatcher, fresh-install exception, missing-snapshot fallback, or skipped policy gate. The compatibility guard expands matrix exclusions and includes and requires PG15–18 plus the explicit PG19 Beta 3 leg. Workflow shells remove BASH_ENV and ENV before starting no-profile/no-rc Bash with errexit and pipefail. Guards reject startup-hook environment injection, environment-file writes and shell overrides. This is a reviewed workflow policy, not a sandbox for arbitrary malicious actions or a compromised runner.