Skip to content

build(notify): publish helper 2.0.0 immutably#116

Merged
psimaker merged 4 commits into
mainfrom
agent/helper-publication-rollout
Jul 14, 2026
Merged

build(notify): publish helper 2.0.0 immutably#116
psimaker merged 4 commits into
mainfrom
agent/helper-publication-rollout

Conversation

@psimaker

@psimaker psimaker commented Jul 14, 2026

Copy link
Copy Markdown
Owner

Summary

  • define the exact notify-v2.0.0 source, image, binary, checksum, SBOM, manifest, and rollout-evidence contract
  • add an owner-only, existing-tag, verified-commit publication workflow with no latest mutation and no asset replacement
  • publish a non-root scratch image and five reproducible platform binaries with exact digests and repository-bound attestations
  • make Docker and binary installation fail closed on stale pulls, missing checksums, duplicate entries, malformed digests, or verification failure
  • prove the supported helper-first sequence 1.8.0 → 2.0.0 → 1.8.0 → the same 2.0.0 identity
  • document compatibility, monitoring, abort, recovery, retention, and honest evidence boundaries

Why

Helper runtime and packaging readiness are merged, but no Helper 2.0 artifact or helper-first rollout exists yet. This PR adds the reviewable publication and rollout gate. It does not create a tag, image, binary, release, deployment, pairing, namespace, or app transfer during PR review or merge.

Security and privacy

  • bind dispatch to the repository owner, exact existing tag, exact manifest, GitHub-verified source commit, tag ref, and fresh origin/main ancestry
  • scan the exact helper source before any registry mutation, then scan the published image and all five compiled binaries
  • generate rootfs-based SPDX inventory for the actual Go binaries and require provenance plus SPDX attestations
  • distinguish a real GHCR 404 from registry failures; never treat an unreadable tag as absent
  • allow draft resume only for byte-identical assets; public retries are read-only and abort on missing or different content
  • never move latest, use --clobber, delete a release, rewrite a tag, or change repository security settings
  • require 2.0.0 candidate logs to omit configured test credentials, identifiers, paths, and URLs
  • record truthfully that immutable 1.8.0 restores its legacy configured-endpoint startup fields during rollback

Compatibility and existing users

Trigger v1 and Relay v1 remain wire-compatible. Existing installations are not pulled, restarted, paired, trusted, or reconfigured. Diagnostics remains dormant unless an operator explicitly supplies the supported host-bind configuration; no namespace is created automatically. Docker Host-Bind on standard Linux with rootful Docker remains the only supported diagnostics packaging row.

Local evidence

  • go test ./... -count=1, go test -race ./... -count=1, go vet ./..., and govulncheck ./...: pass
  • notify/tests/runtime-packaging/run.sh: old → new → old → new pass on clean head; credential bytes and TLS pin preserved; candidate sensitive-log assertion pass
  • notify/tests/m4-docker/run.sh: pass
  • two-instance Syncthing upload E2E with the pinned Linux test binary: pass
  • ShellCheck 0.10.0, actionlint 1.7.12, publish-safety policy, installer dry-run, design-token lint, and 759-key localization parity: pass
  • five binaries built twice byte-identically; rootfs Trivy result 0 HIGH/CRITICAL findings; normalized 21-component SPDX output byte-identical
  • scratch image built and verified non-root, read-only capable, network-independent for --version, and without /bin/sh

The required rootful-Linux installer proof and all PR security/review checks remain CI gates. Exact public-image rollout evidence is intentionally unavailable until the merged commit is tagged and the owner-gated workflow succeeds.

Rollback and retention

Rollback is fixed to notify-v1.8.0, commit e4f9e3088d7b7bc47943ff59db73de369c16c543, image index sha256:6e2b333dd16633d93c5104a72a2b133f4e0d95166757ee081930626e08858154. Credentials and synchronized content are preserved across rollback and must be revalidated on forward recovery. Backups, versions, conflicts, remote history, and tombstones may retain opaque artifacts; cleanup remains digest-directed and evidence-orthogonal.

Evidence boundary

VaultSync 2.0 remains NO-GO. Product upload, download, and correlated-roundtrip evidence remain unset. Helper signatures prove authorship and binding, not transport route, byte provenance, future delivery, or global health.

psimaker added 3 commits July 14, 2026 10:55
Bind helper 2.0.0 images and binaries to an owner-dispatched tag and verified source commit.

Publish version-only artifacts with checksums, rootfs SBOMs, attestations, exact-digest resume safety, and supported-host rollback/forward-recovery proof.

Keep public retries read-only, scheduled scans digest-bound, and candidate logs free of configured sensitive values.
Default Docker installs to 2.0.0, resolve successful pulls to immutable local image IDs, and fail instead of reusing stale tags.

Require exactly one canonical release checksum before installing any binary.

Update operator guidance and dry-run guards for every fail-closed path.
Document immutable artifacts, compatibility, helper-first upgrade, rollback, forward recovery, monitoring, and abort criteria.

Keep product upload, download, and roundtrip evidence unset and record the immutable 1.8.0 rollback logging boundary.
@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@psimaker, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 32 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: db9f2c01-fffd-459a-91f6-254333c474c6

📥 Commits

Reviewing files that changed from the base of the PR and between 5209fad and 4cba735.

📒 Files selected for processing (3)
  • .github/scripts/notify-publish-safety.rb
  • .github/workflows/docker.yml
  • .github/workflows/security.yml
📝 Walkthrough

Walkthrough

The PR strengthens notify 2.0.0 publication safety, immutable image and binary release handling, checksum enforcement, runtime packaging verification, security scanning, and documentation of rollout evidence.

Changes

Notify publication and rollout

Layer / File(s) Summary
Publication safety policy
.github/scripts/notify-publish-safety.rb
Adds duplicate-YAML detection, expanded job and permission checks, exact asset validation, stricter release mutation rules, attestation checks, and resume-model assertions.
Immutable image publication
.github/workflows/docker.yml
Validates release metadata and source state, resolves immutable image digests, scans images, and conditionally creates provenance and SBOM attestations.
Deterministic release and rollout
.github/workflows/docker.yml, .github/workflows/security.yml, notify/release.json, docs/helper-publication-rollout.md, docs/helper-runtime-packaging-readiness.md, docs/relay-spec.md
Builds reproducible binaries, stages exact release assets, verifies rollout evidence, pins scheduled scans to release digests, and documents publication constraints and evidence boundaries.
Pinned installation and runtime proofs
notify/Dockerfile, notify/scripts/*, notify/tests/runtime-packaging/*, notify/README.md, notify/docker-compose.yml, docs/troubleshooting.md
Uses a scratch runtime image, pinned helper references, mandatory checksum verification, immutable Docker identities, and phase-aware runtime log and recovery assertions.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Poem

Digests stand where tags once flew,
Checksums guard each artifact through.
Binaries march in twins aligned,
Logs keep secrets safely blind.
Rollouts prove what they can do.

🚥 Pre-merge checks | ✅ 7
✅ Passed checks (7 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
No Private Note Leakage ✅ Passed Added logging tests only assert omission of API keys/paths; changed scripts/workflows fetch release metadata and publish artifacts, but do not emit or transmit note contents or secrets.
Bounded Ios Background Work ✅ Passed No Swift background-execution code changed; this PR only updates docs, so the iOS background-work check is not applicable.
Bridge Contract Compatibility ✅ Passed PR diff only touches notify/docs/workflows; no go/bridge or ios SyncBridgeService changes, so the bridge contract is unaffected.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title uses a conventional-commit style prefix and accurately summarizes the main change: immutable publication of Helper 2.0.0.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/helper-publication-rollout

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@psimaker psimaker marked this pull request as ready for review July 14, 2026 09:08

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/docker.yml:
- Around line 796-801: Update the release verification block after extracting
body in the workflow to validate the complete deterministic release body, rather
than only its title and two substrings. Ensure the expected body preserves
compatibility limits and does not present publication as upload, download, or
roundtrip evidence; fail verification when any required evidence-boundary
statement is missing or altered.
- Around line 190-198: Update .github/workflows/docker.yml lines 190-198 to
export the finalized public-release state from the release validation block, and
make image and attestation jobs fail on missing or mismatched artifacts without
pushing or creating anything. Update .github/scripts/notify-publish-safety.rb
lines 362-371 to assert that every publication write step is unreachable when
the release is public.

In @.github/workflows/security.yml:
- Around line 129-131: Update the digest validation in the security workflow to
require exactly one extracted index_digest record before exporting it. Reject
missing, duplicate, multiline, or non-canonical values, and only append the
validated digest to GITHUB_OUTPUT; preserve the existing dependency-integrity
checks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 33e57a9b-57b7-47fc-a9ae-d1652f80577d

📥 Commits

Reviewing files that changed from the base of the PR and between c985539 and 5209fad.

📒 Files selected for processing (15)
  • .github/scripts/notify-publish-safety.rb
  • .github/workflows/docker.yml
  • .github/workflows/security.yml
  • docs/helper-publication-rollout.md
  • docs/helper-runtime-packaging-readiness.md
  • docs/relay-spec.md
  • docs/troubleshooting.md
  • notify/Dockerfile
  • notify/README.md
  • notify/docker-compose.yml
  • notify/release.json
  • notify/scripts/install.sh
  • notify/scripts/tests/install-dry-run-test.sh
  • notify/tests/runtime-packaging/run-linux-host.sh
  • notify/tests/runtime-packaging/run.sh
📜 Review details
🧰 Additional context used
📓 Path-based instructions (9)
**/*

⚙️ CodeRabbit configuration file

**/*: VaultSync syncs private Obsidian notes through Syncthing. Treat data loss,
privacy leaks, security regressions, and broken sync behavior as high priority.
Do not nitpick formatting unless it affects maintainability, correctness, or public API clarity.
Flag any accidental logging, telemetry, crash reporting, or network transfer of note contents,
vault paths, filenames with private context, API keys, APNs tokens, relay keys, or security-scoped bookmark data.

Files:

  • notify/release.json
  • notify/docker-compose.yml
  • docs/troubleshooting.md
  • notify/Dockerfile
  • docs/relay-spec.md
  • notify/scripts/tests/install-dry-run-test.sh
  • notify/README.md
  • docs/helper-publication-rollout.md
  • docs/helper-runtime-packaging-readiness.md
  • notify/tests/runtime-packaging/run-linux-host.sh
  • notify/tests/runtime-packaging/run.sh
  • notify/scripts/install.sh
notify/docker-compose.yml

⚙️ CodeRabbit configuration file

notify/docker-compose.yml: Check that deployment examples do not hard-code real secrets and that environment variables,
restart policy, health checks, and network exposure are reasonable for self-hosted users.

Files:

  • notify/docker-compose.yml
**/*.{md,sh,go,swift}

📄 CodeRabbit inference engine (README.md)

Keep Relay-side request observation and wake-ups received on the iPhone as separate diagnostics evidence; one must not be treated as proof of the other.

Files:

  • docs/troubleshooting.md
  • docs/relay-spec.md
  • notify/scripts/tests/install-dry-run-test.sh
  • notify/README.md
  • docs/helper-publication-rollout.md
  • docs/helper-runtime-packaging-readiness.md
  • notify/tests/runtime-packaging/run-linux-host.sh
  • notify/tests/runtime-packaging/run.sh
  • notify/scripts/install.sh
**/*.md

⚙️ CodeRabbit configuration file

**/*.md: Review public documentation for technical accuracy, privacy/security claims, App Store-facing wording,
setup correctness, and consistency with the free app plus optional Cloud Relay subscription model.

Files:

  • docs/troubleshooting.md
  • docs/relay-spec.md
  • notify/README.md
  • docs/helper-publication-rollout.md
  • docs/helper-runtime-packaging-readiness.md
notify/Dockerfile

⚙️ CodeRabbit configuration file

notify/Dockerfile: Check container security, minimal runtime surface, non-root execution where practical,
HEALTHCHECK behavior, reproducible builds, and safe handling of runtime secrets.

Files:

  • notify/Dockerfile
notify/**/*.{sh,go}

📄 CodeRabbit inference engine (README.md)

The optional notify sidecar must support server-side wake-up requests and must not receive notes, file or folder names, or vault structure.

Files:

  • notify/scripts/tests/install-dry-run-test.sh
  • notify/tests/runtime-packaging/run-linux-host.sh
  • notify/tests/runtime-packaging/run.sh
  • notify/scripts/install.sh
docs/**/helper-publication-rollout.md

📄 CodeRabbit inference engine (docs/helper-runtime-packaging-readiness.md)

Do not claim public helper publication, registry digests, rollout state, or release evidence from source text; establish them only through the owner-gated workflow and evidence defined in helper-publication-rollout.md.

Files:

  • docs/helper-publication-rollout.md
.github/workflows/**/*.yml

⚙️ CodeRabbit configuration file

.github/workflows/**/*.yml: Review CI for correct Go test tags, Xcode/iOS simulator assumptions, secret scoping,
dependency integrity, permissions, Docker publishing safety, and unnecessary privilege escalation.

Files:

  • .github/workflows/security.yml
  • .github/workflows/docker.yml
notify/scripts/install.sh

📄 CodeRabbit inference engine (README.md)

The notify installer must locate the Syncthing configuration, set required permissions, start the helper, support non-standard configuration paths through SYNCTHING_CONFIG, and provide a --dry-run mode that makes no changes.

Files:

  • notify/scripts/install.sh
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-14T09:08:45.390Z
Learning: Publication alone must not be presented as evidence of app upload, download, roundtrip, Relay delivery, APNs delivery, iOS background execution, customer installation success, or user-vault progress.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-14T09:08:45.390Z
Learning: The next app milestone remains blocked until the public helper release and the complete helper-first rollback/forward-recovery workflow succeed.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-14T09:08:56.072Z
Learning: Publication, registry digests, SBOM/vulnerability results, public artifact availability, and helper-first rollback evidence must be read from the exact release and workflow named by the publication manifest, never inferred from the source-readiness document.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-14T09:09:10.381Z
Learning: The system must not claim upload, download, or correlated roundtrip success without a separately approved correlated helper contract and runtime milestone.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-14T09:09:18.617Z
Learning: After applying a troubleshooting fix, retry from the app to confirm the issue is resolved.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-14T09:09:18.617Z
Learning: Use the installation-specific commands for Docker, systemd, launchd, Docker Compose, or Windows when diagnosing `vaultsync-notify`.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-14T09:09:18.617Z
Learning: Treat HTTP 429 from the relay trigger endpoint as a successful reachability result; an inactive subscription is an app-side provisioning issue, not a server failure.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-14T09:09:18.617Z
Learning: Peer-state warnings from `--doctor` must not fail the doctor or health check; legitimately offline peers are not setup errors, and `--healthcheck` must skip peer-state diagnostics.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-14T09:09:18.617Z
Learning: A green relay health check proves reachability only; updated `Last Trigger Received` is required to confirm wake-up delivery.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-14T09:09:18.617Z
Learning: `vaultsync-notify` should read the Syncthing API key from `config.xml`; manually supplied `SYNCTHING_API_KEY` overrides auto-detection and must match the current key if used.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-14T09:09:18.617Z
Learning: Run the helper as the user owning Syncthing's mode-0600 `config.xml`, or configure the container's appropriate `PUID`/`PGID` or user mapping.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-14T09:09:18.617Z
Learning: When diagnosing relay connectivity, verify internet access, `RELAY_URL`, egress rules, relay health, and a subsequent trigger receipt.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-14T09:09:18.617Z
Learning: For pending shares, verify the iOS Device ID is shared by desktop Syncthing, that Syncthing is online and unpaused, and refresh or re-share if necessary.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-14T09:09:18.617Z
Learning: Silent push wake-ups require a valid APNs token and provisioned device, but do not require notification permission; retry APNs registration and provisioning when needed.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-14T09:09:18.617Z
Learning: Connect VaultSync to the Obsidian folder containing `.obsidian`, then rescan and verify detected vaults or pending shares.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-14T09:09:18.617Z
Learning: VaultSync must not move, recreate, or delete vault folders automatically; recovery from moved, replaced, or deleted folders requires the user's manual decision.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-14T09:09:18.617Z
Learning: Renew security-scoped bookmark access by reconnecting to the Obsidian folder and rescanning when a vault becomes inaccessible.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-14T09:09:18.617Z
Learning: Do not promise reliable iPhone-to-server background synchronization; iOS background execution is system-controlled, so users should open VaultSync for foreground syncing.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-14T09:09:18.617Z
Learning: When a required Syncthing device is disconnected, verify it is online and reachable, confirm its device ID, and re-add it only if the ID changed.
Learnt from: CR
Repo: psimaker/vaultsync

Timestamp: 2026-07-14T09:09:18.617Z
Learning: When filing an issue, capture VaultSync and iOS versions, Sync Issues and relay diagnostics, doctor output, and relevant helper logs.
🪛 zizmor (1.26.1)
.github/workflows/docker.yml

[info] 472-472: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)

🔇 Additional comments (15)
.github/scripts/notify-publish-safety.rb (1)

4-20: LGTM!

Also applies to: 29-42, 53-73, 102-112, 126-132, 145-180, 196-206, 218-236, 249-252, 261-331, 341-342

.github/workflows/docker.yml (1)

10-18: LGTM!

Also applies to: 33-43, 54-54, 102-189, 199-290, 305-342, 394-476, 526-795, 802-951

.github/workflows/security.yml (1)

106-128: LGTM!

Also applies to: 133-146

docs/helper-runtime-packaging-readiness.md (1)

3-9: LGTM!

Also applies to: 244-247

docs/relay-spec.md (1)

3-3: LGTM!

notify/scripts/tests/install-dry-run-test.sh (1)

116-126: LGTM!

Also applies to: 185-200

notify/tests/runtime-packaging/run-linux-host.sh (1)

7-11: LGTM!

Also applies to: 27-27, 44-106, 170-190, 223-223, 243-251, 261-284

notify/tests/runtime-packaging/run.sh (1)

6-6: LGTM!

Also applies to: 49-49, 140-165, 180-180, 195-212, 224-225

docs/helper-publication-rollout.md (1)

1-195: LGTM!

docs/troubleshooting.md (1)

98-98: LGTM!

notify/Dockerfile (1)

11-20: LGTM!

notify/README.md (1)

75-75: LGTM!

Also applies to: 94-94, 227-227

notify/docker-compose.yml (1)

19-19: LGTM!

notify/release.json (1)

1-31: LGTM!

notify/scripts/install.sh (1)

38-38: LGTM!

Also applies to: 221-238, 256-256, 271-271, 333-358

Comment thread .github/workflows/docker.yml Outdated
Comment thread .github/workflows/docker.yml Outdated
Comment thread .github/workflows/security.yml Outdated
Carry finalized release state into image, attestation, and release staging so public retries fail closed without mutation.

Compare complete deterministic release notes, require one canonical scheduled-scan digest, and pin security workflow actions.

Keep validated workflow values out of direct shell expressions and enforce every guard in the publication safety policy.
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