Skip to content

Release as one signed bundle; the customer guide; the EULA - #4

Merged
brianmacy merged 3 commits into
mainfrom
brian/public-bundle-release
Oct 30, 2026
Merged

brianmacy merged 3 commits into
mainfrom
brian/public-bundle-release

Conversation

@brianmacy

@brianmacy brianmacy commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Release as one signed bundle; the customer guide; the EULA

What this does

Turns this repository into exactly what customers need and nothing else: the guide, the
EULA pointer, and one workflow that signs a release's files. It is the output of a full-tree
replace (scripts/sync_public.sh in the private source repository, which authors
everything here; nothing in this repository is edited by hand).

A release is now one download: sz-snowflake-<release>.tar.gz holds the Snowflake Native
App files, the three role images (sz-snowflake-setup, -resolver, -replicator; distroless,
uid 65532) for linux/amd64 and linux/arm64 as docker archives, and the infrastructure and
install scripts. The infrastructure SQL and the install script are also attached on their own so
they can be read before the large download, with SHA256SUMS and a cosign signature per file.
There is no image build here and no public image registry: Snowflake users cannot reach one, and
the install script pushes the images to the customer's own Snowflake image repository.

Changes

Added README.md rewritten as the customer guide; docs/install.md, docs/use.md, docs/troubleshooting.md; .github/workflows/sign-release.yaml; assets/senzing-logo.jpg (the guide's header); scripts/check_release_assets.sh (the exact file set a release must hold; also run by the signing workflow)
Replaced LICENSE: was the Apache-2.0 text; now a short file saying the software is licensed under the Senzing End User License Agreement, with the URL (https://senzing.com/end-user-license-agreement/). The EULA text is not copied. CHANGELOG.md rewritten for the above
Removed (Sam's PR #2) Dockerfile, .dockerignore: the images are built in the private repository
Removed (Sam's PR #2) .github/workflows/docker-build-and-publish.yaml: replaced by sign-release.yaml.
Removed (Sam's PR #2) .github/workflows/README.md (describes internal process), .claude/settings.json (not needed in a customer repository), .github/CODEOWNERS (no reviewer automation)
Changed .github/dependabot.yml: the docker ecosystem entry goes (no Dockerfile); .gitignore: the payload lines go
Kept as they were .github/linters/*, the fleet-standard workflows (labels, project board, Claude attribution check, Claude PR review, dependabot approve and merge, link issues, lint workflows, move to done, spellcheck), .vscode/cspell.json

The EULA

Installing is not accepting. After the app exists, an administrator accepts the Senzing EULA in
the app: CALL SZ_SNOWFLAKE.API.SZ_ACCEPT_EULA('I_ACCEPT_THE_SENZING_EULA') (or
sz-snowflake-install.sh --accept-eula). Until then setup refuses with -20109 and SZ_HEALTH
reports EULA_NOT_ACCEPTED. The acceptance is recorded with the time, user and release. The guide
(README.md, docs/install.md step 3, docs/troubleshooting.md) covers it. Releases start at
Senzing 4.4.3 (4.4.3-1).

The signing workflow

sign-release.yaml runs when a release is published. It authenticates to nothing outside this
repository and builds nothing. It requires: a tag <senzing_version>-<build> (e.g. 4.4.3-7: no
v, an integer build); not a pre-release; a release authored by the publishing account
(repository variable PAYLOAD_PUBLISHER_LOGIN, fails closed when unset); a release not
already signed; exactly the contracted file set matching SHA256SUMS. It then signs every file
and SHA256SUMS keyless (cosign sign-blob), verifies each signature against the identity below
and attaches <file>.sigstore.json.

Customers verify one identity, which names only this repository:

https://github.com/Senzing/sz-snowflake/.github/workflows/sign-release.yaml@refs/tags/<release>

The release itself is created by the private build with a fine-grained token (this repository
only, Contents read/write; it never pushes to a branch), so the ruleset that restricts tag creation
needs to allow that token's account.

Settings needed in this repository

Variable PAYLOAD_PUBLISHER_LOGIN the login of the account that owns the publishing token
Ruleset: tag creation allow that account
Org secrets SLACK_BOT_TOKEN, SLACK_CHANNEL optional, as before (the failure notification is a no-op without them)

Checks done on this tree

The source repository runs, on every change, scripts/check_public_refs.sh (no internal
references: the private organization, spec or milestone names, lab identifiers, Apache or
contribution text) and, before a tag, requires this repository's main to equal public/.
The leak scan used on the build output was also run over this tree.

Also in this pull request (synced 2026-10-30)

  • Public Preview, provided as-is: a notice at the top of the README and in its License
    section; during the preview any release can make breaking changes (Versions section).
  • docs/ai-assisted.md: install, resolve and report with an AI assistant (Snowflake Cortex Code,
    Claude Code), with the Senzing MCP server and a local Streamlit report on the results.
  • Install and use docs for the newer app calls: register sources by name, one-call
    SZ_CONFIGURE, SZ_HEALTH.RESOLVE_STATE as the done signal, setup progress.
  • Senzing brand lockup and section labels on every page.
  • CONTRIBUTING.md: issues are welcome; contributions and pull requests are not (overrides the
    organization default).

Resolves #2

Replace the placeholder image build with the customer guide and one signing
workflow. A release is one download (the Native App files, the three role
images for amd64 and arm64, the infrastructure and install scripts), signed
keyless as sign-release.yaml at the release tag. LICENSE now points at the
Senzing End User License Agreement instead of carrying the Apache-2.0 text.

Removed: Dockerfile, .dockerignore, docker-build-and-publish.yaml (its required
check "docker build (pull request)" goes with it), CODEOWNERS,
.github/workflows/README.md, .claude/settings.json.
@brianmacy
brianmacy requested a review from a team as a code owner October 30, 2026 11:47
@github-actions

Copy link
Copy Markdown

🤖 Claude Code Review

Code review

Code quality

Item Status Notes
Style conventions ✅ The workflow and shell are consistent, with set -euo pipefail and pinned third-party actions.
No commented-out code ✅ The long comments in sign-release.yaml are explanatory prose.
Meaningful names ✅
DRY ❌ The tag and release regex appears in both sign-release.yaml:~72 and scripts/check_release_assets.sh:~30. The "exactly one of each asset" logic is also duplicated. These are minor.
Defects ❌ See below.
.claude/CLAUDE.md ✅ There isn't one. .claude/settings.json was deleted, so the repo no longer suppresses Claude attribution on commits and PRs. Confirm that is intended.

Defects

  1. The "re-run after a partial failure" path doesn't work (sign-release.yaml, "Download the release files" and "contracted set" steps).

    • Signing uploads <file>.sigstore.json files one at a time, with SHA256SUMS.sigstore.json last. The comment says a run that failed before that file "can be re-run".
    • A re-run downloads the whole release into assets/ with no pattern, so the leftover *.sigstore.json files are included.
    • check_release_assets.sh requires an exact file set and fails on any extra file.
    • Fix: download with --pattern '!*.sigstore.json', or exclude those files from the exact-set check.
  2. Deleting .github/CODEOWNERS may leave branch protection inert or blocking.

    • The deleted file's own comment says the code-owner review requirement does nothing without it.
    • The required status check docker build (pull request) also no longer exists, because docker-build-and-publish.yaml was removed.
    • If either rule is still configured on main, PRs will be unprotected or unmergeable. Update the rulesets and check that CODEOWNERS isn't needed elsewhere.
  3. Checksum parsing assumes text-mode SHA256SUMS (sign-release.yaml, wait loop and signing loop).

    • read -r _ listed and awk '{print $2}' return *name for binary-mode lines (hash *name). The check and the signing loop would then fail on every file.
    • The while read loop also drops a final line that has no trailing newline.
  4. Replacing LICENSE is a significant legal change.

    • The Apache-2.0 text is replaced by a link to the EULA, so GitHub no longer detects a license.
    • Please confirm Legal approved this. The README and CHANGELOG should say that the license changed.
  5. Smaller issues

    • gh release edit --notes-file rewrites the release body. A CRLF body or one with trailing newlines is altered, and the "Verify" notes are appended again on each re-run.
    • The sign-release.yaml header and comments narrate the previous design ("the previous design handed a GitHub App private key…"). That history belongs in the commit message or PR description.
    • Releases signed in a per-arch layout are not covered by the README's verify loop, which lists only the combined bundle.

Testing

Item Status Notes
Unit tests for new functions ❌ scripts/check_release_assets.sh has no tests.
Integration tests ❌ None for the workflow.
Edge cases ❌ Binary-mode checksums, partial re-runs, extra assets and a missing build.yaml are untested.
Coverage above 80% ❌ No coverage.

Add a small bats or shell test with fixture directories for the good case, an extra file, a bad checksum, a missing role image and a stray .sigstore.json.

Documentation

Item Status Notes
README updated ✅ It is rewritten as the customer guide.
API docs ✅ docs/install.md, docs/use.md and docs/troubleshooting.md are added.
Inline comments ✅
CHANGELOG updated ✅ It now says the Apache-2.0 license was replaced by the EULA only implicitly. Say so explicitly.
CommonMark and prettier ❌ The tables use compact `
.github/workflows/README.md deleted ❌ The standard-set workflows it described still exist and are now undocumented.

Security

Item Status Notes
No hardcoded credentials ✅ Slack secrets come from org secrets.
Input validation ✅ The tag regex, pre-release check, author check (fail-closed) and exact asset set are all enforced. $(awk …) word-splitting is safe because the names are validated.
Error handling ⚠️ Good overall, but see defect 1.
No sensitive data in logs ✅
License files (.lic, AQAAAD) ✅ None found in the diff. I couldn't inspect the binary assets/senzing-logo.jpg.

Security notes on the workflow:

  • The workflow runs scripts/ from the tag checkout while holding contents: write and id-token: write. Anyone who can create the tag controls what runs, so the tag ruleset is the real control. Keep it enforced and document that dependency.
  • Using ${{ vars.PAYLOAD_PUBLISHER_LOGIN }} and github.event.release.author.login via env: rather than inline in run: is the correct approach.

Summary

The signing design is sound. Fix the re-run defect (1) and the checksum parsing (3) before merge, confirm the ruleset and CODEOWNERS fallout (2) and the license change (4), add tests for the script, and run prettier on the new markdown.

Automated code review analyzing defects and coding standards

@github-actions

Copy link
Copy Markdown

🤖 Claude Code Review

PR Code Review

This PR replaces the container build-and-publish pipeline with a release-signing workflow, a verification script and a customer guide. Several things need attention. The first two are the most important.

Code Quality

  • ❌ Defects and risks
    • Deleted .github/CODEOWNERS. The deleted file's own comment says branch protection on main requires code-owner review, and that this requirement is inert without the file. Removing it silently disables the review gate. Nothing in the PR says this is intended. Restore it unless the ruleset was changed too.
    • LICENSE swapped from Apache-2.0 to a pointer to the EULA (LICENSE:1-5). This is a significant legal change. Confirm legal sign-off. The new text is not a license file, only a URL. A repo-wide LICENSE change should also be in the CHANGELOG, and it isn't.
    • Stale references to the removed Dockerfile and payload build.
      • .vscode/cspell.json still lists payload/** and payload-download/** in ignorePaths and keeps words like dockerignore, dpkg and buildkit.
      • .gitignore dropped /payload/ while .vscode/cspell.json still treats it as a build directory.
    • .claude/settings.json deleted. This removed the attribution opt-out. Confirm that is intended.
    • Checksum parsing is fragile.
      • sign-release.yaml (download step) reads SHA256SUMS with read -r _ listed. It also uses awk '{print $2}' in the sign loop and in scripts/check_release_assets.sh. A binary-mode line (<hash> *name) leaves a leading * in the name, so the checks would reject it.
      • The for asset in $(awk …) loop in the sign step is unquoted and subject to word splitting. This is safe only because the check script has already vetted the names. Prefer while read.
    • scripts/check_release_assets.sh final line. ${archs[*]/#/linux/} only prefixes the first element. With two archs it prints linux/amd64 arm64. This is cosmetic.
    • Missing helper files. The check script calls scripts/build_yaml.sh when build.yaml exists. The workflow comments mention scripts/release_assets.sh and scripts/version_order.sh. None of these is in the diff. Confirm they exist, or the script fails once build.yaml appears.
    • Inconsistent token use. sign-release.yaml uses secrets.GITHUB_TOKEN in one step and github.token in another. Use one.
  • ❌ DRY. The semver-style tag regex is duplicated across the workflow, the script and the docs.
  • ✅ Naming. Variable names are clear.
  • ✅ Commented-out code. None found.
  • ✅ .claude/CLAUDE.md. The PR neither adds nor changes one.

Testing

  • ❌ No tests. scripts/check_release_assets.sh has non-trivial logic: exact-set checks, per-arch vs combined modes, and tar layout validation. It has no automated tests, such as a bats or shell fixture covering the following:
    • a missing file
    • an extra file
    • a checksum mismatch
    • a bad bundle layout
    • a bad tag
  • ❌ Edge cases and coverage. Not covered, and coverage is below 80%.
  • ❌ Workflow validation. No test exercises the sign-release workflow, for example a dry run or an act run.

Documentation

  • ✅ README, install, use and troubleshooting docs are added and thorough.
  • ✅ CHANGELOG is updated.
  • ✅ Inline comments explain the complex logic.
  • ❌ CHANGELOG. It does not record the license change, the removal of the publish workflow and Dockerfile, or the removal of the Dependabot docker ecosystem. These should appear under Removed or Changed. The Semantic Versioning line and link were dropped without comment.
  • ❌ Markdown formatting (CommonMark and prettier).
    • README tables use compact |---|---| separators and unaligned cells. Prettier would reformat them.
    • README uses raw HTML (<p>, <br clear>, <sub>). This is valid but likely trips markdownlint MD033 unless that rule is disabled.
    • docs/troubleshooting.md has a bare URL (https://senzing.com/end-user-license-agreement/), which is MD034. Wrap it in <...> or use a link.
    • .vscode/cspell.json: ignorePaths was expanded to multiple lines, but the original single-line array fit within 80 columns. Prettier would collapse it again.
    • Several CHANGELOG lines run past 80 columns, though prose wrap may be set to preserve.
  • ❌ Doc inconsistency. .github/workflows/README.md was deleted. The workflow list it documented, including the new sign-release.yaml, is no longer described anywhere. Keep or update it.

Security

  • ✅ License files. No .lic files or AQAAAD strings are in the diff.
  • ✅ No hardcoded credentials. Secrets come from the secrets context and are passed through env: rather than interpolated into scripts.
  • ✅ Workflow hardening.
    • Actions are pinned by SHA.
    • Default permissions are {}, with narrow job-level grants.
    • The tag, pre-release flag and author are validated.
    • Signing runs only on release: published, with no workflow_dispatch.
    • Re-signing is refused.
  • ❌ Minor concerns.
    • docs/install.md tells users to run ALTER SECRET SZ_LICENSE SET SECRET_STRING = '<base64>'. The license lands in shell or SQL history. Mention using a prompt or a file-based approach.
    • The release-publisher check trusts the repository variable PAYLOAD_PUBLISHER_LOGIN, which is fail-closed. Anyone with write access can edit it, so document that it is a trust anchor.
    • The README cosign verify snippet shows <release> in the identity. Warn users against loosening it to a regexp.
  • ✅ Error handling. Fail-closed validation, set -euo pipefail, and clear ::error:: messages throughout.
  • ✅ Logging. Nothing sensitive is logged. The notify step passes only the repository name.

Summary

The signing design is sound. Before merging, fix the CODEOWNERS removal, get explicit sign-off on the LICENSE change, add tests for the asset-check script, clean up the stale cspell and gitignore entries, and format the Markdown and JSON with prettier.

Automated code review analyzing defects and coding standards

@github-actions

github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Super-linter summary

Language Validation result
CHECKOV Pass ✅
GITHUB_ACTIONS Pass ✅
GITHUB_ACTIONS_ZIZMOR Pass ✅
GITLEAKS Pass ✅
GIT_MERGE_CONFLICT_MARKERS Pass ✅
JSCPD Pass ✅
PRE_COMMIT Pass ✅
SPELL_CODESPELL Pass ✅
TRIVY Pass ✅
YAML Pass ✅
YAML_PRETTIER Pass ✅

All files and directories linted successfully

For more information, see the GitHub Actions workflow run

Powered by Super-linter

…ew versioning policy; install and report with an AI assistant (docs/ai-assisted.md); register sources by name, SZ_CONFIGURE, RESOLVE_STATE and setup progress in the install/use/troubleshooting docs; Senzing brand lockup and section labels on every page; CONTRIBUTING.md (issues welcome; no contributions or pull requests)
@github-actions

Copy link
Copy Markdown

🤖 Claude Code Review

PR Code Review

This PR retires the container build and publish pipeline (Dockerfile, docker-build-and-publish.yaml) and replaces it with a signed-release model: sign-release.yaml, scripts/check_release_assets.sh, the customer docs, the EULA licence and CONTRIBUTING.md. I reviewed the diff only and ran nothing. Line numbers for new files are approximate.

Code Quality

  • ✅ Style and idioms. The shell is set -euo pipefail throughout, quoted, and consistent with the surrounding workflows. The workflow keeps SHA-pinned third-party actions and the zizmor-style comments.
  • ✅ No commented-out code, meaningful names, DRY. No issues.
  • ❌ Defects
    1. .github/workflows/sign-release.yaml, download step (~L108-L135) and attach step (~L180-L195): a partial signing run cannot be re-run.
      • The comment says "A run that failed before that file can be re-run".
      • Attach uploads every *.sigstore.json except SHA256SUMS.sigstore.json first.
      • If a later upload fails, the release holds some *.sigstore.json files but not the SHA256SUMS one, so the "already signed" guard passes.
      • The step then runs gh release download "$TAG" --dir assets with no pattern and pulls those bundles in.
      • check_release_assets.sh requires an exact file set and rejects them with "$dir holds … but must hold exactly …".
      • Fix: download with --pattern for only the contracted files, or delete or skip *.sigstore.json before the check.
    2. Same file, attach step: the notes edit comes after the "finished" marker. gh release edit --notes-file runs after SHA256SUMS.sigstore.json is uploaded. If the edit fails, the version is permanently "signed" and cannot be re-run. Edit the notes before uploading the marker.
    3. .github/CODEOWNERS deleted.
      • The deleted file's own comment says that branch protection requiring code-owner review is "inert without this file".
      • Branch protection on main may therefore stop enforcing review.
      • CHANGELOG.md still lists "CODEOWNERS" under scaffolding, which now contradicts the diff.
      • Confirm this is intentional, or restore it.
    4. Required status check docker build (pull request). The removed workflow was documented as the required check on main. If branch protection still requires it, every PR will block forever. Update the ruleset in the same change.
    5. scripts/check_release_assets.sh L12. It calls scripts/build_yaml.sh whenever build.yaml exists, but that script is not in this diff. This is harmless in the public repo while build.yaml is absent, and a hard failure if the file ever appears without the script.
    6. sign-release.yaml download loop. while read -r _ listed drops a final SHA256SUMS line that has no trailing newline. The final exact-set check catches this later, so it only causes a confusing wait.
    7. --clobber on signature upload. It contradicts "a signed version is never re-signed". It is harmless given the guard, but it is not needed.
  • ✅ .claude/CLAUDE.md. None exists. Deleting .claude/settings.json (attribution overrides) is fine.

Testing

  • ❌ Unit and integration tests. check_release_assets.sh has non-trivial logic: exact-set match, checksum list, tar layout, per-arch versus combined mode. It ships without any test, such as a fixture directory with passing and failing cases. The workflow's validation regexes are also untested.
  • ❌ Edge cases. These are untested: partial re-run (defect 1), a missing trailing newline in SHA256SUMS, symlink or traversal members in the tarball, and the pre-release flag. Listing the tar is safe because nothing is extracted, but member types are not checked.
  • ❌ Coverage > 80%. No coverage is measurable.

Documentation

  • ✅ README updated. The README, CHANGELOG.md, docs/install.md, docs/use.md, docs/troubleshooting.md, docs/ai-assisted.md and CONTRIBUTING.md are all new or rewritten, and the changelog is updated.
  • ❌ .github/workflows/README.md deleted. sign-release.yaml is therefore undocumented, though the other thin-caller workflows still exist. Restore the file with an updated section.
  • ❌ Markdown and prettier.
    • docs/ai-assisted.md Prompt 1, step 6: the continuation lines of the SQL (SZ_SNOWFLAKE.SZ.ENTITY_RECORD) AS RECORDS, …) lack the > prefix. They render only through lazy continuation, and prettier would rewrite them.
    • Tables in README.md, docs/install.md, docs/use.md and docs/troubleshooting.md are not column-aligned. Only docs/ai-assisted.md is aligned, so the files are inconsistent. Run prettier on all of them.
    • The header uses inline HTML (<p>, <img align>, <samp>, <sub>). Confirm it passes the repo's markdownlint.json (MD033, MD041).
  • ❌ docs/install.md. The SZ_CONFIGURE example uses GEN_ARM_G1_4, while the default pool family is x64 (docs/use.md). The example may mislead amd64 users. The GRANT … TO ROLE <reader_role> line has no matching install-script option.
  • ⚠️ LICENSE. Replacing Apache-2.0 with a pointer to the Senzing EULA is a significant legal change. Confirm legal sign-off, and that the Dockerfile's org.opencontainers.image.licenses removal covers all remaining references.
  • ⚠️ .vscode/cspell.json. Words for deleted content remain (buildkit, dockerignore, useradd, kernelsam).
  • ⚠️ .github/dependabot.yml. The docker ecosystem entry was removed correctly. brianmacy is still assigned elsewhere.

Security

  • ✅ No hardcoded credentials. None found.
  • ✅ No .lic files or AQAAAD strings. None found.
  • ✅ Sign-release hardening.
    • Permissions default to {} with job-scoped contents: write and id-token: write.
    • release.tag_name, prerelease, the author login and workflow_ref all go through env:, never inline in run:.
    • Third-party actions are SHA-pinned.
    • There is no workflow_dispatch.
    • The tag, pre-release flag and publisher checks fail closed, and the exact-set check is enforced.
    • Each signature is verified immediately against the exact identity.
    • The Slack token reaches only the notify step.
  • ✅ Input validation and logging. Validation is present, and the failure messages do not leak sensitive data.
  • ⚠️ Integrity only. As the workflow itself notes, SHA256SUMS provides integrity, not authenticity. Security rests on the author check, the tag ruleset and the no-re-sign guard. PAYLOAD_PUBLISHER_LOGIN must be set as a repository variable before the first release.
  • ⚠️ Floating tag. senzing-factory/build-resources/slack-failure-notification@v4 is a floating tag (first-party, consistent with the rest of the repo).

Summary

The signing design is sound. Fix defects 1 and 2 (re-run and ordering), confirm the CODEOWNERS and required-check removals against the branch rules, add tests for check_release_assets.sh, and run prettier over the docs.

Automated code review analyzing defects and coding standards

@brianmacy
brianmacy merged commit a43810c into main Oct 30, 2026
22 checks passed
@brianmacy
brianmacy deleted the brian/public-bundle-release branch October 30, 2026 21:26
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