Publish push gateway chart 0.4.0 through the repository's protected
release lane. The chart implementation and version already landed in
[#8206](https://github.com/block/buzz/pull/8206); this PR adds release
notes without changing runtime behavior.
Merging `push-chart-release/0.4.0` invokes the release bot to create
`push-chart-v0.4.0` and publish the immutable chart to GHCR. Publication
unblocks [the wrapper
chart](https://github.com/squareup/cash-helm-charts/pull/5740) and
subsequent disabled-production preparation. This does not activate any
gateway.
### Validation
Release notes match the merged single-application configuration and
migration guards. Diff checks pass. The source PR's required checks and
PostgreSQL suite passed; chart validation will run again on this release
PR.
Signed-off-by: Tom Brow <tomb@block.xyz>
Buzz push currently selects an application profile, such as `dogfood`,
during client registration. We want each gateway to serve one Apple app
configured by the operator instead. This removes profile selection from
the client, relay, and gateway, while allowing internal and public
gateways to use their own Apple identities.
This PR implements that model in the Buzz source and upstream deployment
chart. Discovery, enrollment, grants, and leases no longer carry an
application-profile selector. Each gateway has one configured Apple
application and APNs transport.
The protocol changes are incompatible with the old registration format,
so relays advertise `buzz-push-v1` instead of `nip-pl`. Old clients do
not discover the new push capability. Updated clients use separate
Keychain records and register again. The [push
notes](https://github.com/block/buzz/blob/push-capability-v1/docs/buzz-push.md)
describe the experimental contract.
Landing this PR is the first step. Publish the matching gateway image
and upstream chart, then land the [shared chart
update](https://github.com/squareup/cash-helm-charts/pull/5740) and
[gateway deployment
update](https://github.com/squareup/builderbot-platform-core-infrastructure/pull/1085).
Before cutover, stop old gateway instances and check legacy registration
state. Migrations refuse to proceed if old gateway installations or
active relay leases remain; they do not delete that state.
Physical-device verification remains necessary before production
activation.
### Validation
Gateway and focused Flutter push tests pass, as do the Swift package,
simulator build, and native notification/enrichment tests. A local relay
advertises `buzz-push-v1` without `nip-pl` or `app_profiles`. The
PostgreSQL suite passed 868 tests; its two migration-test failures were
corrected and pass a focused rerun together with the gateway cutover
guard. Chart rendering and release-contract checks pass.
Desktop JavaScript tests, desktop and web builds, native desktop
compilation, mobile analysis/tests, and desktop native tests pass. The
full Rust unit lane and prescribed `just test` command pass, including
workspace integration tests against task-isolated local services. The
production overlay now requires an explicitly supplied APNs topic, with
omission and rendered-value regression coverage. The corrected Swift
checksum assertion passes the complete package suite: 78 XCTest tests
and 42 Swift Testing tests. No physical-device enrollment or production
cutover is claimed.
Local merge validation: the embedded migration test and formatting pass
after reserving profile migration 0060 behind rollback migration 0059.
The local pre-push Rust lane failed ACP timing/steering tests
(`idle_resets_on_stdout_activity`,
`keepalive_resets_idle_past_deadline`, and the failed/missing-outcome
steering tests). ACP and its dependency manifests are unchanged by this
branch; all four pass in an isolated single-thread rerun. The documented
local-check exception skips only the Rust pre-push lane for publication;
required CI remains mandatory. Mobile and desktop pre-push lanes passed.
Combined migration validation: after rollback 0059 landed, the main
merge preserves profile migration 0060 and both embedded migration
assertions. The focused migration test and formatting pass. The next
local push again failed only the unchanged ACP idle/keepalive timing
tests (1053 passed, 2 failed, 3 ignored); other lanes passed.
Publication uses the same documented local Rust-lane exception; required
CI remains mandatory.
Follow-up review fix: removed the legacy profile column from the
copied-lease fixture. All four event-follow-up contract tests pass on
isolated PostgreSQL databases, covering desired and migrated schemas in
dual and app-only modes. Formatting passes. Publication retains the
prior passing local-lane evidence and uses the authorized pre-push
exception for the known unrelated ACP timing failures; required CI
remains mandatory.
---------
Signed-off-by: Tom Brow <tomb@block.xyz>
Publish gateway chart 0.3.5 through the normal immutable release
workflow. This release includes Deployment metadata annotations from
[#8136](https://github.com/block/buzz/pull/8136), while preserving
chart-owned policy markers and existing default manifests.
Only the chart version and release notes change. The gateway binary
appVersion remains 0.1.0.
### Validation
Full gateway chart render suite and release-contract validation passed.
The feature's full repository validation and exact-head owner review
passed before merge. Publication will be verified from the OCI registry
before advancing the wrapper dependency.
`buzz-review-completed`: Agent validation passed; automated DCO finding
was reconciled against the signed exact-head commit and green DCO check.
Tom confirmed the human-testing rule is inapplicable to this chart-only
release; personal testing is not claimed.
Signed-off-by: Tom Brow <tomb@block.xyz>
Consumers currently need a Kustomize patch to place secret-reloader
annotations on the gateway Deployment. Add optional
`deploymentAnnotations` so they can express that configuration through
Helm values.
The setting applies only to Deployment metadata. The chart's
release-namespace and external-network-policy annotations remain
reserved and cannot be overridden.
### Validation
Full gateway chart render suite passes, including schema rejection of
reserved keys and non-string values, preservation of external-policy
ownership markers, and unchanged Pod annotations and migration hooks.
Repository-wide `just ci` passed with `RUST_TEST_THREADS=1`. The first
parallel run failed five unrelated timing/transport tests; all five
passed isolated reruns and the full serialized run completed
successfully.
`buzz-review-completed`: Codex review is clean on the current commit and
agent render validation exercises the change. Tom confirmed the
repository human-testing requirement does not apply to this chart-only
change; personal human testing is not claimed.
Signed-off-by: Tom Brow <tomb@block.xyz>
Publish push gateway chart 0.3.4 through the normal chart release
workflow. The chart version and implementation were merged in
[#8113](https://github.com/block/buzz/pull/8113); this release PR
records the release notes and triggers the immutable chart tag and OCI
publisher.
Publication is authorized. The pending security review of #8113 is a
blocker for pinning the chart in the later infrastructure PR, not for
this publication. No gateways or relays are activated.
### Validation
The merged implementation passed the complete chart render suite, chart
CI, and all 14 local wrapper tests. This release changes only the
changelog; chart contents are unchanged from the validated
implementation. Published OCI contents and digest will be verified after
publication.
---------
Signed-off-by: Tom Brow <tomb@block.xyz>
Platform-owned service meshes need runtime pod identity and a
replacement network policy without patching rendered gateway manifests.
Add runtime-only pod labels, service account and shutdown-grace
settings, plus an explicit named replacement-policy mode. Migration
isolation remains independent; the default render is unchanged.
Chart 0.3.4 publication and live deployment verification follow in the
separate release and deployment work.
### Validation
Added tests cover runtime-only settings, reserved selector labels,
minimum shutdown grace, replacement-policy acknowledgement and
conflicting settings. The complete chart render suite and
release-contract tests pass. Default rendering matches the current main
chart byte-for-byte. Repository-wide `just ci` reached unit tests but
failed in existing buzz-acp tests outside this chart change. Live mesh
behavior has not been exercised.
---------
Signed-off-by: Tom Brow <tomb@block.xyz>
Prepares publication of the Buzz push gateway chart 0.3.3, including the
optional migration Pod annotations already merged in #8105. This PR adds
release notes only; chart templates, values, and schema are unchanged
from the reviewed implementation.
Merging the `push-chart-release/0.3.3` branch triggers the normal
release workflow: create `push-chart-v0.3.3`, validate the chart, then
publish `oci://ghcr.io/block/buzz/charts/buzz-push-gateway:0.3.3`. Keep
this PR in draft until publication is explicitly authorized. It does not
deploy a gateway.
### Validation
Focused migration annotation renders, release contract checks, and local
chart packaging pass. The merged implementation passed chart CI and
Jude's automated review in #8105. The earlier repository-wide local
`just ci` run failed in unchanged ACP tests; it was not rerun for
release notes. The registry manifest digest can only be verified after
publication.
---------
Signed-off-by: Tom Brow <tomb@block.xyz>
Allow operators to configure migration Pod annotations independently of
runtime Pod annotations. This lets clusters with automatic sidecar
injection opt the migration Job out without changing the gateway
Deployment or Helm hook metadata.
The new string-map setting defaults to empty. Chart version 0.3.3 is
prepared here; publication requires a separate approved chart release
PR.
### Validation
The full chart render suite and focused migration annotation tests pass.
Tests verify unchanged default resources and hooks, independent runtime
annotations, and rejection of non-string annotation values. Independent
agent review found no blockers. Repository-wide `just ci` exited 1 in
unchanged `buzz-acp` tests: idle/stdout keepalive timing and steering
assertions (one failure in the first group, four in the second).
Subsequent recipes were not reached. No rerun or unrelated code fix was
attempted. Human testing remains pending.
Signed-off-by: Tom Brow <tomb@block.xyz>
The relay can use a configurable HTTP(S) gateway delivery URL and signs
the same URL it sends. The gateway verifies NIP-98 against the received
request URL, including authority, port, path and query. App Attest,
scoped grants, replay checks and delivery quotas are unchanged.
Forwarding proxies must preserve Host and supply the original request
scheme through X-Forwarded-Proto. The NIP relay-delivery wording now
defines the configured HTTP(S) URL as the signed URL and labels the
public URL as an example.
<!-- buzz-review-completed -->
---------
Signed-off-by: Tom Brow <tomb@block.xyz>
A valid 30-day push gateway grant lifetime could render in scientific
notation (e.g. `2.592e+06`) in the chart, which the gateway binary does
not accept.
Always ormat the integer as decimal text, preserving the strict gateway
parser.
### Testing
Added regression coverage that feeds actual Helm-rendered environment
values into the production config parser. Covers defaults, values files,
command-line overrides, exact lifetime boundaries, and invalid input
rejection. The default case failed before the fix and passes afterward.
Signed-off-by: Tom Brow <tomb@block.xyz>
The gateway serves plaintext HTTP on its public container port, but the
chart currently advertises that Service port as `https`. Label it `http`
so protocol-aware proxies discover the application's actual protocol.
Numeric port 8080, target port `public`, and the application version
remain unchanged. Consumers that refer to the old Service port name must
update that reference.
Prepare chart version 0.3.1, which is absent from the current release
tags and OCI registry. This ordinary fix branch does not trigger the
chart release lane. Publishing and downstream dependency updates remain
separate steps.
This corrects protocol metadata; it is not evidence of a TLS-origination
failure. Istio controls upstream TLS through DestinationRules and
auto-mTLS independently of this port label.
Validation: added rendered-Service and container-port assertions across
default, production, and Gateway API fixtures. The assertion fails with
the old label and passes with the fix. The full chart render/lint suite
and release-contract checks pass. Repository-wide `just ci` is still
running locally.
---------
Signed-off-by: Tom Brow <tomb@block.xyz>
Make the push gateway origin configurable across the relay, gateway,
mobile client, and deployment chart.
This is a fresh deployment. The gateway has only run on personal
development infrastructure, and push has no existing enabled users.
Legacy migration, configured-to-unconfigured mobile transitions, and
rolling upgrades from pre-launch gateway binaries are not supported.
Populated pre-launch databases are rejected with an informative error
before migrations run; their data is untouched. Mobile builds may omit
the gateway URL, leaving push unavailable. Once push is enabled,
subsequent builds must retain that configuration.
### Validation
- All applicable CI checks pass at
`5f546cfaf403f0386f146d213adfb4392f4ec29c`, including Rust,
mobile/Swift, desktop/integration, security, image builds, and Helm
checks. An unrelated agent cancellation test passed on retry.
- PostgreSQL CI passed 384 tests, including the production-entry-point
regression for refusing populated pre-launch databases before
migrations, fresh initialization, and subsequent initialized
deployments.
- Focused local validation passed all 10 gateway PostgreSQL tests under
the CI discovery filter and all 3 unconfigured-mobile tests.
Repository-wide PostgreSQL discovery validation and the complete
pre-push hooks passed.
- Physical-device APNs/App Attest behavior and deployment to a live
cluster were not verified in this work.
---------
Signed-off-by: Tom Brow <tomb@block.xyz>
Co-authored-by: Codex <noreply@openai.com>
This PR implements MVP, iOS-only,
[NIP-PL](8d2d0ff5ad/docs/nips/NIP-PL.md)-compliant
push notifications.
A relay with `BUZZ_PUSH_ENABLED` will send a push notification for any
message that appears in the in-app Notifications tab.
## Enrollment flow
The first time the client first connects to a relay with
`BUZZ_PUSH_ENABLED`:
```mermaid
sequenceDiagram
autonumber
participant App as Buzz iOS app
participant iOS
participant Relay as Buzz relay
participant Attest as Apple App Attest
participant Gateway as Push gateway
App->>Relay: Fetch NIP-11 push capability
Relay-->>App: Push profile, current relay public key, and limits
par
App->>iOS: Request notification permission
iOS-->>App: Permission result
and
App->>iOS: Register for remote notifications
iOS-->>App: Device token
end
App->>Gateway: Request installation challenge
Gateway-->>App: Single-use challenge
App->>Attest: Attest installation transcript
Attest-->>App: Attestation proof
App->>Gateway: Enroll device token and proof
Gateway-->>App: Installation handle
App->>Gateway: Request delegation challenge
Gateway-->>App: Single-use challenge
App->>Attest: Assert relay-key delegation
Attest-->>App: Assertion
App->>Gateway: Create delegation
Gateway-->>App: Opaque endpoint grant
App->>Relay: Publish encrypted push lease and filters
Relay-->>App: Lease acknowledged
```
## Push-time flow
When a notification-eligible event is received by the relay:
```mermaid
%%{init: {
"sequence": {
"actorMargin": 20,
"width": 110,
"messageMargin": 18,
"diagramMarginX": 8,
"wrap": true
}
}}%%
sequenceDiagram
autonumber
participant Relay as Buzz relay
participant Gateway as Push gateway
participant APNs as Apple Push<br/>Notification service
participant iOS
participant NSE as Notification service<br/>extension
Relay->>Gateway: POST /v1/deliveries/apns<br/>opaque endpoint grant, request ID, expiry, NIP-98 authorization
Gateway->>APNs: POST /3/device/{device-token}<br/>topic, request ID, expiry, constant mutable-content payload
APNs-->>Gateway: 200 OK: request accepted
Gateway-->>Relay: 200 OK: accepted status
APNs-->>iOS: Notification: constant reconnect alert<br/>mutable-content = 1
iOS->>NSE: Invoke extension<br/>original notification content
NSE->>Relay: POST /query: subscription filters, limit 10<br/>NIP-98 authorization
Relay-->>NSE: 200 OK: signed Nostr events<br/>kinds 9, 40002, 45001, or 45003
NSE->>iOS: Complete notification: title, body, subtitle<br/>thread ID, exact-message target
```
relay → push gateway → APNs -> NSE -> Notification Center
## Known limitations
The APNs wake payload is intentionally constant and opaque: it contains
no originating community or message identifier, in keeping with the
implemented NIP-PL privacy design.
The Notification Service Extension must therefore reconnect to the relay
and resolve eligible messages after each wake. Around overlapping wakes,
timing boundaries, or resolution windows, notification presentation may
occasionally omit an expected message or display a message more than
once.
This best-effort behavior is deliberately accepted for the current
implementation and will be measured during the internal rollout to
determine whether the user experience is acceptable before any broader
deployment; the implementation does not claim exactly-once presentation.
## Validation
Live end-to-end hardware validation used an internal remotely hosted
development relay and push gateway, the APNs sandbox, and a physical
iPhone 12 mini:
- A second real Buzz client published a uniquely marked message through
the hosted relay.
- The relay matched the message and sent the constant opaque wake
through the hosted gateway. The gateway made an actual APNs request; no
`simctl push` or simulated notification was used.
- The iPhone received the notification on its lock screen. The
Notification Service Extension reconnected to the relay, fetched the
event, verified its ID and signature, and replaced the placeholder
content with the real notification title and body.
- After the app populated its shared presentation cache, a final marked
notification visibly showed the sender display name, sender avatar, and
hashtag-prefixed channel name.
- Tapping a lock-screen notification opened Buzz and exercised the
notification-response path and navigated to the corresponding message.
Final validation with a dogfood-signed artifact and production App
Attest/APNs configuration remains a release step.
## Independent pre-reviews
- **First pass:**
[Carl](buzz://message?channel=18882f4c-289f-41db-942f-81f6f8066da1&id=74ab9a93bb227f3e762568f1cf9fee66d7495b0edc3918735ff787238b9cc585)
found missing transient retries, executor-key rotation suppression,
duplicate installation renewal, and an unauthenticated challenge write
amplifier. These were resolved by [retry-safe
bootstrap](https://github.com/block/buzz/pull/6269/changes/12c66ea62)
and [authenticated renewal plus a cross-replica
quota](https://github.com/block/buzz/pull/6269/changes/8e5ece0bd).
[sol-max](buzz://message?channel=ad83385f-8e9e-4461-9a35-c1bf2e208532&id=d26d53daa4684669e2ed354638241f13f36c3a97027fe8b4dd738aff09038962)
found delegation generation burning and an edited applied migration,
resolved by [exact-generation
revocation](https://github.com/block/buzz/pull/6269/changes/c26d2159d)
and a [forward-only
migration](https://github.com/block/buzz/pull/6269/changes/956c1d099).
[k3-max](buzz://message?channel=5e46055d-a766-4065-ae25-05d1e4aaa6b2&id=d43139138a0b15f806cbdbeeedd8f69d992cadf2e805876db6fdde6a34c7eda1)
found no blockers.
- **Exact-head re-review:**
[Carl](buzz://message?channel=18882f4c-289f-41db-942f-81f6f8066da1&id=a897721673459301b0cf26e8b85a1478d7ebbb56a4621f93d774c98d395b8f68),
[sol-max](buzz://message?channel=ad83385f-8e9e-4461-9a35-c1bf2e208532&id=fb2159f709ec68f74f7b21459acd76da0e8a7c5c0f3d469f99826b0cc2380849),
and
[k3-max](buzz://message?channel=5e46055d-a766-4065-ae25-05d1e4aaa6b2&id=2ce2842910435f562e9d9cc718595848f281b122c94605e523a4b964254b8bfb)
independently returned **NO BLOCKERS** at `7eb3a650b`; k3-max also
revalidated every remediation and the endpoint-specific App Attest
enrollment bound.
---------
Signed-off-by: Tom Brow <tomb@squareup.com>
Signed-off-by: Tom Brow <tomb@block.xyz>
Co-authored-by: Tom Brow <tomb@squareup.com>
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Jordan Mecom <jm@squareup.com>