Skip to main content

Broadcast

2 min read

GitHub Action — Tier 1 release broadcasting

The Action source lives in the private monorepo at packages/broadcast-action. The bundled artifact is mirrored to the public sizls/broadcast-action repository on every release, signed via Sigstore keyless OIDC tied to the release workflow identity. Consumers reference the public repo by SHA.


Quickstart

# .github/workflows/release-broadcast.yml
on:
  release:
    types: [published]

jobs:
  broadcast:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: sizls/broadcast-action@<sha>
        with:
          platforms: bluesky,mastodon
          config-path: .sizl/broadcast.config.ts
        env:
          BLUESKY_APP_PASSWORD: ${{ secrets.BLUESKY_APP_PASSWORD }}
          MASTODON_TOKEN: ${{ secrets.MASTODON_TOKEN }}

Pin the action by SHA (not tag) so the published binary you verified yesterday is the binary that runs tomorrow.

Tier policy

The Action is Tier 1 only. A GitHub Actions runner is ephemeral — it can dispatch a one-shot post and exit, but it cannot host the 15-minute Tier 2 approval window. If your config declares a Tier 2/3 event, the Action refuses with a structured error and a doc link to the Worker template.

::error::Event "release/feature-flag-rollout" is configured for Tier 2 approval,
but the Action runs ephemeral runners that cannot host a 15-minute approval
window. Use the Cloudflare Worker template instead:
https://directive.run/docs/broadcast/worker

The refusal is enforced at the contract layer, not via runtime check. The Action's tier resolver inspects the resolved tier before any platform call.

Sigstore verification

Every release of sizls/broadcast-action is signed with Sigstore keyless OIDC. Verify before pinning:

cosign verify-blob \
  --certificate-identity-regexp '^https://github.com/sizls/broadcast/\.github/workflows/release-action\.yml@refs/tags/' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --bundle dist/bundle.sigstore.json \
  dist/index.js

The signing identity is the release workflow, not a long-lived key — there is no key to lose. If an attacker pushed an unsigned binary to the public mirror, cosign verify-blob would fail against the workflow-ref identity regex.

Inputs

InputRequiredDescription
platformsyesComma-separated allowlist for this run. The Action rejects events whose config emits adapters outside this list.
config-pathyesPath to your broadcast.config.ts in the repo.
dry-runnoWhen true, the Action skips the platform call and prints what would have posted. Receipt still signed and emitted.

Outputs

OutputDescription
cassette-hashesJSON array of cassette hashes for each dispatched post. Use it as the input to a downstream verify step.

What stays private

The Action source — and the @sizl/broadcast runtime it depends on — live in the private monorepo. The bundled JavaScript binary is what consumers run. This is the deliberate posture: the moat is the brand + Pluck Bureau key issuance + the posts-index hosting, not the binary's opacity.

Previous
Overview
Next
CLI

Stay in the loop. Sign up for our newsletter.

We care about your data. We'll never share your email.

Powered by Directive. This signup uses a Directive module with facts, derivations, constraints, and resolvers – zero useState, zero useEffect. Read how it works

Directive - Constraint-Driven Runtime for TypeScript | AI Guardrails & State Management