diff --git a/.github/workflows/ios-nightly-distribution.yml b/.github/workflows/ios-nightly-distribution.yml
index bc1ed9a36..894ace422 100644
--- a/.github/workflows/ios-nightly-distribution.yml
+++ b/.github/workflows/ios-nightly-distribution.yml
@@ -44,10 +44,8 @@ jobs:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
- # A nightly run ships the same commit to both apps: the production one (via the Nightly
- # configuration above) and the Safetynet one. Kept as a job here rather than a dispatch of
- # release_distribution.yml so that auto_merge below can wait for both legs — a separate run
- # would race the branch deletion.
+ # The Safetynet leg of a nightly, kept as a job here rather than as a dispatch of another
+ # workflow, which would race the branch deletion.
#
# Safetynet is what Release ships — release feature set — running against the nightly
# environment, under its own bundle id so it installs alongside the real app. See
diff --git a/.github/workflows/ios-safetynet-distribution.yml b/.github/workflows/ios-safetynet-distribution.yml
index e0bc2374d..af79ebf92 100644
--- a/.github/workflows/ios-safetynet-distribution.yml
+++ b/.github/workflows/ios-safetynet-distribution.yml
@@ -6,9 +6,10 @@ name: Safetynet Distribution
# environment, under its own bundle id so it installs alongside the real app. See
# Configs/base.safetynet.xcconfig.
#
-# The nightly pipeline already builds Safetynet as a leg of ios-nightly-distribution.yml;
-# this workflow exists for ad-hoc builds outside that pipeline. It deliberately does not
-# reuse ios-build-distribute.yml: that workflow's security gate fails any workflow_dispatch
+# This is the only workflow here that builds Safetynet: the leg in
+# ios-nightly-distribution.yml is held, because Safetynet ships from the app repository.
+# It deliberately does not reuse ios-build-distribute.yml: that workflow's security gate
+# fails any workflow_dispatch
# not triggered by github-actions[bot], which is exactly the human-triggered case here.
# The scope is correspondingly narrower — one variant, no release PR,
# no release notification.
diff --git a/.github/workflows/notification-smoke-test.yml b/.github/workflows/notification-smoke-test.yml
deleted file mode 100644
index 13b2a7979..000000000
--- a/.github/workflows/notification-smoke-test.yml
+++ /dev/null
@@ -1,48 +0,0 @@
-# Posts one message through the notification relay, on demand.
-#
-# It reads the same three secrets the release announcements read, so it proves
-# the wiring without anyone holding the relay token: that the secrets resolve
-# inside a run, that a runner can reach the relay, and that the bot is in the
-# room it is asked to post to. Nothing else exercises that path until a nightly
-# runs.
-name: Notification smoke test
-
-# On demand only. No schedule, no push, no pull request: every run of this
-# workflow puts a message in a room people read.
-on:
- workflow_dispatch:
-
-# Serialises overlapping runs. It does not cap how many messages this sends:
-# nothing here does. Two dispatches put two messages in the room, and a run
-# cancelled mid-flight may already have delivered. `false` rather than
-# `cancel-in-progress`, so a delivery that happened is not hidden behind a
-# cancelled run.
-concurrency:
- group: notification-smoke-test
- cancel-in-progress: false
-
-# The action talks to the relay and to nothing on GitHub.
-permissions: {}
-
-jobs:
- send:
- name: Send one test message
- runs-on: ubuntu-latest
- timeout-minutes: 5
- steps:
- - name: Send one message
- uses: novasamatech/github-actions/send-notification@8c20aeac07cb19b3c2ce1310d1ef2947a373ca5e # v5
- with:
- # The run is named so that an unexpected or repeated message can be
- # traced back to what sent it.
- message: "Testing the new host-api bot, please ignore. ${{ github.repository }} run ${{ github.run_id }}"
- html_message: "Testing the new host-api bot, please ignore. ${{ github.repository }} run ${{ github.run_id }}"
- bot_url: ${{ secrets.NOTIFICATION_BOT_URL }}
- bot_api_token: ${{ secrets.NOTIFICATION_BOT_TOKEN }}
- # One message per room this names, and the count is not reviewable
- # from here because it is a secret. A second room means a second
- # message, with the run still green.
- matrix_room_ids: ${{ secrets.CI_MATRIX_ROOM_IDS }}
- # No retries. A delivery that succeeds but answers 5xx would otherwise
- # be sent again, and one duplicate is worse here than one failure.
- retry_count: "0"
diff --git a/hosts/ios/docs/PUBLISHING.md b/hosts/ios/docs/PUBLISHING.md
index 253c7ffa9..747a0b296 100644
--- a/hosts/ios/docs/PUBLISHING.md
+++ b/hosts/ios/docs/PUBLISHING.md
@@ -87,7 +87,7 @@ Required for any signed build:
| `KEYCHAIN_PASSWORD` | Password for the temporary CI keychain | every signed build |
| `MATCH_PASSWORD` | Passphrase that decrypts the `match` assets | every signed build |
| `FASTLANE_RO_PAT` | Fine-grained PAT with read access to the `match` repo | every signed build |
-| `FASTLANE_RW_PAT` | The same PAT with write access | `update_signing_data.yml` only |
+| `FASTLANE_RW_PAT` | The same PAT with write access | `ios-update-signing-data.yml` only |
| `GOOGLE_SERVICE_INFO_DEV_BASE64` | Base64 development `GoogleService-Info.plist` | PR builds and tests |
| `GOOGLE_SERVICE_INFO_RELEASE_BASE64` | Base64 production `GoogleService-Info.plist` | release and nightly archives, nightly simulator build |
| `GOOGLE_SERVICE_INFO_SAFETY_BASE64` | Base64 Safetynet `GoogleService-Info.plist` (separate Firebase app for `….safety`) | Safetynet archives |
@@ -96,24 +96,24 @@ Required only by the distribution target you actually use:
| Secret | Used for | Read by |
|--------|----------|---------|
-| `CREDENTIAL_FILE_CONTENT` | Google service-account JSON for App Distribution | `firebase_debug_distribution.yml` |
-| `FIREBASE_APP_ID` | Firebase App Distribution app ID (`1:…:ios:…`) | `firebase_debug_distribution.yml` |
+| `CREDENTIAL_FILE_CONTENT` | Google service-account JSON for App Distribution | `ios-firebase-debug-distribution.yml` |
+| `FIREBASE_APP_ID` | Firebase App Distribution app ID (`1:…:ios:…`) | `ios-firebase-debug-distribution.yml` |
| `SENTRY_AUTH_TOKEN` | Uploading dSYMs to Sentry (the build phase skips when `sentry-cli` is unconfigured — see §9) | signed builds |
Optional — these gate reporting steps only, and a fork can leave them unset:
| Secret | Used for | Read by |
|--------|----------|---------|
-| `NOTIFICATION_BOT_URL`, `NOTIFICATION_BOT_TOKEN` | Build success/failure notifications | `_build_distribute.yml`, `nightly_distribution.yml` |
-| `TESTFLIGHT_DISTRIBUTION_LINK`, `WEB_PAGE_DISTRIBUTION_LINK` | One ready-to-render markdown link entry each, e.g. `[TestFlight](https://testflight.apple.com/join/)`. Kept in secrets so access hints stay out of the repo. | `release_distribution.yml`, `nightly_distribution.yml` |
-| `TESTFLIGHT_SAFETY_DISTRIBUTION_LINK`, `WEB_PAGE_SAFETY_DISTRIBUTION_LINK` | A TestFlight join link is per-group per-app, and Safetynet is its own app | `nightly_distribution.yml` |
+| `NOTIFICATION_BOT_URL`, `NOTIFICATION_BOT_TOKEN` | The relay the announcements post through | `ios-nightly-distribution.yml`, `ios-release-distribution.yml` |
+| `CI_MATRIX_ROOM_IDS` | Comma separated rooms to announce into. One message per room | `ios-nightly-distribution.yml`, `ios-release-distribution.yml` |
+| `TESTFLIGHT_DISTRIBUTION_LINK` | One ready-to-render markdown link entry, e.g. `[TestFlight](https://testflight.apple.com/join/)`. Kept in a secret so the access hint stays out of this public repository | `ios-nightly-distribution.yml`, `ios-release-distribution.yml` |
`SENTRY_DSN` and `MELD_BASIC_AUTH_TOKEN` from the first table are also stored as
GitHub Actions secrets, because CI runs `generate_secrets.sh` from
`.github/actions/configure-secrets` instead of reading `env-vars.sh`.
Tester groups are a workflow variable rather than a secret: `FIREBASE_GROUPS` is
-set in `firebase_debug_distribution.yml` (default `polkadotapp-ios`) and can be
+set in `ios-firebase-debug-distribution.yml` (default `polkadotapp-ios`) and can be
overridden per run.
Backend and on-chain endpoints (identity backend, IPFS gateway, DotNS