Notifier Bootstrap Pack Guide

The Bootstrap Pack gives operators a deterministic set of configuration files to stage the Notifier service in sealed or fully air-gapped environments. The assets ship alongside the Offline Kit under bootstrap/notify/ and can be copied directly onto the hosts that run StellaOps.Notifier.WebService.

Contents

FilePurpose
notify.yamlSealed-mode configuration derived from etc/notify.airgap.yaml. It disables external resolution by pointing to in-cluster services and honours the shared EgressPolicy.
plugins/notify/base/Required Notify base connector bundle. It is generated by devops/build/package-runtime-plugins.ps1 -Module notify -Profile base and contains only the StellaOps.Notify.Connectors.InApp and StellaOps.Notify.Connectors.InAppInbox entry assemblies, their dependency DLLs such as StellaOps.Notify.Connectors.Shared.dll, notify-plugin.json, checksums, and detached assembly signatures such as <assembly>.dll.sig. Missing either base connector keeps /readyz unready.
plugins/notify/recommended/Optional recommended delivery overlay generated by devops/build/package-runtime-plugins.ps1 -Module notify -Profile recommended. The current admissible bundle set contains the real Email and Webhook connector entry assemblies, dependency DLLs, manifests, checksums, and detached signatures.
plugins/notify/harness/Deterministic harness overlay generated by devops/build/package-runtime-plugins.ps1 -Module notify -Profile harness. It includes the required InApp/InAppInbox base connectors plus StellaOps.Notify.Plugin.Dummy, a dry-run INotifyChannelConnector that responds without external delivery.
plugins/notify/{email,chat,paging,regulatory}/Optional connector overlays generated by devops/build/package-runtime-plugins.ps1 -Module notify -Profile <profile>. External delivery overlays contain Email, Slack, Teams, Webhook, PagerDuty, OpsGenie, Discord, and Telegram; the regulatory overlay contains CSAF, DORA, DoraInfoSharing, ENISA, and NCS. DORA runtime adapters ship generated manifest.json metadata because their source projects intentionally do not carry notify-plugin.json.
notify-web.secret.exampleDeterministic template for the Authority client secret. Replace the value before running the service.
rules/airgap-ops.rule.jsonBootstrap rule subscribing to air-gap drift, bundle import, and portable export completion events. Update channel identifiers before import.
templates/airgap-ops-email.template.jsonEmail template used by the bootstrap rule with remediation guidance, checksum context, and download locations.
README.mdThis guide, also embedded in the pack for quick operator reference.

Usage

  1. Populate secrets – copy notify-web.secret.example to notify-web.secret, change NOTIFY_WEB_CLIENT_SECRET to the value issued by Authority, and store it with restrictive permissions (for example chmod 600).

  2. Drop configuration – place notify.yaml in the location expected by the runtime (/app/etc/notify/notify.yaml for the containers we ship). The file assumes PostgreSQL is reachable at Host=postgres;Database=stellaops;Username=stellaops;Password=airgap-password and Authority at https://authority.airgap.local – adjust if your deployment uses different hostnames.

  3. Build and sign base plug-ins - run devops/build/package-runtime-plugins.ps1 -Module notify -Profile base -SignNotifyBundles -NotifyCosignKeyPath <offline-cosign-key> -NotifyCosignPublicKeyPath <offline-cosign-pub> before creating the bootstrap pack. Without the detached Cosign signatures, production compose rejects the mounted bundle during readiness. The private key is an operator-supplied input; only the public key is copied into the mounted trust-root directory as cosign.pub. For local compose acceptance and air-gapped bootstrap proof, the same producer can generate the recommended, harness, email, chat, paging, and regulatory profiles with -UseOfflineDevSigner; never commit or distribute the generated private key.

  4. Import rule/template – with the Notify CLI or REST API, import templates/airgap-ops-email.template.json first, then rules/airgap-ops.rule.json. Update the channel identifiers inside the rule so they match your sealed SMTP relay (for example email:airgap-ops).
    The rule now also delivers portable export completion notices; ensure your downstream process watches for checksum and location details in the payload.

  5. Mount secrets/config – for Docker Compose use:

    volumes:
      - ./bootstrap/notify/notify.yaml:/app/etc/notify/notify.yaml:ro
    env_file:
      - ./bootstrap/notify/notify-web.secret
    

    Kubernetes Secret and pod mounting instructions are unsupported for Stella Ops deployments.

  6. Verify plug-in readiness - set notify:plugins:directory to the mounted profile root such as /app/plugins/notify/base, keep notify:plugins:ensureDirectoryExists=false, and call GET /readyz after mounting the base bundle and trust root. GET /healthz only proves the process is alive; /readyz fails with the missing base connector assembly names when the base plug-ins are absent or mounted at a path that does not match notify:plugins:directory. If a mounted connector is unsigned or the Cosign verifier cannot verify it against /app/trust-roots/plugins/notify, /readyz remains unready and GET /internal/plugins/status reports the plugin as rejected with the admission reason.

  7. Verify sealed mode – with the configuration in place the Notifier resolves channels that point to local relays (SMTP, syslog, file sink). Any attempt to contact an external webhook is denied by StellaOps.AirGap.Policy with remediation guidance.

How it is packaged

ops/offline-kit/build_offline_kit.py automatically copies the configuration and secret template into bootstrap/notify/ during Offline Kit creation. The same staging directory is what we sign and publish as the Bootstrap Pack, so the artefacts stay deterministic across releases.

Refer to etc/notify.airgap.yaml if you need to regenerate the pack or build a site-specific overlay from source control.