Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: connector-ci

on:
pull_request:
push:
branches: [main]

permissions:
contents: read

jobs:
relay:
name: Relay connector
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09

- name: Install Rust 1.95
uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772
with:
toolchain: 1.95.0
components: clippy, rustfmt

- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6

- name: Verify the packaged conformance vector
run: |
actual="$(
openssl dgst -sha256 relay/tests/fixtures/connector-v1-vectors.json |
awk '{print $NF}'
)"
test "${actual}" = "18d7218047bd77b599c0639b69c4fead31149beccbc13156fd387512bc818b91"

- name: Format
run: cargo fmt --all -- --check

- name: Test
run: cargo test --workspace --all-features --locked

- name: Lint
run: cargo clippy --workspace --all-targets --all-features --locked -- -D warnings

- name: Build documentation
env:
RUSTDOCFLAGS: -D warnings
run: cargo doc --workspace --no-deps --all-features --locked

- name: Verify the crates.io package
run: cargo publish --manifest-path relay/Cargo.toml --dry-run --locked
110 changes: 110 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
name: publish-relay-connector

on:
release:
types: [published]
workflow_dispatch:
inputs:
release_tag:
description: Existing version-matched release tag to resume
required: true
type: string

permissions:
contents: read

concurrency:
group: crates-io-publish
cancel-in-progress: false

jobs:
validate:
if: >-
github.event_name == 'workflow_dispatch' ||
(
github.event_name == 'release' &&
github.event.release.prerelease == false &&
startsWith(github.event.release.tag_name, 'pocketstation-relay-v')
)
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09
with:
fetch-depth: 0

- name: Install Rust 1.95
uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772
with:
toolchain: 1.95.0
components: clippy, rustfmt

- name: Validate the release tag
env:
EVENT_NAME: ${{ github.event_name }}
RELEASE_TAG: ${{ github.event.release.tag_name || inputs.release_tag }}
run: |
set -euo pipefail
version="$(
cargo metadata --format-version 1 --no-deps |
jq -r '.packages[] | select(.name == "pocketstation-relay") | .version'
)"
expected_tag="pocketstation-relay-v${version}"
if [[ "${RELEASE_TAG}" != "${expected_tag}" ]]; then
echo "release tag ${RELEASE_TAG} must equal ${expected_tag}" >&2
exit 1
fi
tag_commit="$(git rev-list -n 1 "${RELEASE_TAG}")"
git fetch origin main
if ! git merge-base --is-ancestor "${tag_commit}" origin/main; then
echo "release commit is not contained in origin/main" >&2
exit 1
fi
if [[ "${EVENT_NAME}" == "release" && "${tag_commit}" != "${GITHUB_SHA}" ]]; then
echo "release tag does not resolve to the checked-out commit" >&2
exit 1
fi

- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6

- name: Verify the package
run: |
actual="$(
openssl dgst -sha256 relay/tests/fixtures/connector-v1-vectors.json |
awk '{print $NF}'
)"
test "${actual}" = "18d7218047bd77b599c0639b69c4fead31149beccbc13156fd387512bc818b91"
cargo fmt --all -- --check
cargo test --workspace --all-features --locked
cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
RUSTDOCFLAGS='-D warnings' cargo doc --workspace --no-deps --all-features --locked
cargo publish --manifest-path relay/Cargo.toml --dry-run --locked

publish:
needs: validate
runs-on: ubuntu-latest
timeout-minutes: 15
environment: crates-io
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09

- uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772
with:
toolchain: 1.95.0

- name: Publish pocketstation-relay
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: |
set -euo pipefail
version="$(
cargo metadata --format-version 1 --no-deps |
jq -r '.packages[] | select(.name == "pocketstation-relay") | .version'
)"
if curl --fail --silent --show-error \
"https://crates.io/api/v1/crates/pocketstation-relay/${version}" \
>/dev/null; then
echo "pocketstation-relay ${version} is already published"
exit 0
fi
cargo publish --manifest-path relay/Cargo.toml --locked
6 changes: 4 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

186 changes: 38 additions & 148 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,166 +1,56 @@
# PocketStation Connector Registry
# PocketStation connectors

Find the first-party packages that connect a PocketStation Session to an
external service.
Use a Connector to send audio from a PocketStation `Session` to an external
service. Connectors are separate packages, so their network and provider
dependencies do not become Core dependencies.

This repository is the source registry and shared verification workspace for
connectors maintained by the PocketStation project. Each connector is an
independent package with its own protocol scope, compatibility contract,
documentation, tests, and release lifecycle.
## Available connector

The repository root is a catalog. Package-specific setup and implementation
guidance belongs inside each connector directory.
PocketStation Relay is the only first-party connector currently available.

## Available connectors
| Package | Sends | Destination |
|---|---|---|
| [`pocketstation-relay`](https://crates.io/crates/pocketstation-relay) | independent named audio buses | [PocketStation Relay](https://github.com/pocketstation-io/relay) over WebRTC |

| Connector | Package | Direction | Connects to | Release | Documentation |
|---|---|---|---|---|---|
| PocketStation Relay | [`pocketstation-relay`](https://crates.io/crates/pocketstation-relay) | outbound audio | [PocketStation Relay](https://github.com/pocketstation-io/relay) over WebRTC | `0.1.1` | [Guide](relay/README.md) · [Rust API](https://docs.rs/pocketstation-relay) |
Install the Rust packages:

That is the complete first-party registry today. A connector not listed here
does not inherit PocketStation maintenance, compatibility, or evidence claims.

## Choose a connector

Use `pocketstation-relay` when you need to publish independent, named audio
buses from a Rust PocketStation Session to PocketStation Relay.

There is not currently a first-party LiveKit, generic WHIP, OpenAI, Deepgram,
or arbitrary WebRTC connector in this registry. Those services have different
authentication, negotiation, lifecycle, and outcome contracts. Support requires
a dedicated adapter; changing a URL is not sufficient.

For installation and a complete application-plus-microphone example, go
directly to the [PocketStation Relay connector guide](relay/README.md).

## What “first-party” means

A connector in this registry must have all of the following:

- a named maintainer and an active product or ecosystem requirement;
- a finite, typed configuration contract with secret redaction;
- an explicit provider/protocol compatibility boundary;
- canonical PocketStation Connector and Endpoint lifecycle integration;
- bounded preparation, delivery, cancellation, drain/abort, and shutdown;
- stable provider error classification and observable terminal outcomes;
- executable conformance, saturation, rollback, and failure tests;
- real protocol integration evidence;
- an independently installable package and isolated consumer proof;
- an intentional versioning and compatibility policy.

Passing component tests does not automatically establish remote production
readiness, every network topology, every platform, or competitive superiority.
Those claims require separately identified evidence.

## Architecture boundary

```text
PocketStation Core
Session + Graph + Endpoint lifecycle
Connector contract
independently packaged provider adapter
external service or protocol
```

Responsibilities stay deliberately separated:

| Owner | Responsibility |
|---|---|
| [`pocketstation`](https://github.com/pocketstation-io/pocketstation) | provider-neutral graph, bounded routing, lineage, lifecycle, recording, observations, Connector contract |
| This registry | first-party connector packages, compatibility, conformance, packaging, release ownership |
| Provider/service repository | wire protocol, server behavior, authentication authority, remote delivery |

Connectors are outbound Endpoint specializations. Inbound media remains a
PocketStation `Source`; transformations remain `Operator`s. A larger
bidirectional integration may compose all three without introducing another
Session or runtime.

Core never gains a closed provider enum. Adding a connector must not add its
WebRTC, SDK, authentication, or protocol dependencies to Core.

## Registry policy

This is a curated first-party registry, not a collection of every possible
integration.

A proposed connector moves through these stages:

1. **Scope** — identify a real user workflow and the exact protocol boundary.
2. **Ownership** — assign maintainers, security ownership, and compatibility
responsibilities.
3. **Contract** — declare inputs, capabilities, configuration, credentials,
limits, readiness, errors, and outcomes.
4. **Implementation** — use the canonical Core lifecycle without duplicating
graph, queue, or Session authority.
5. **Conformance** — prove rollback, saturation, discontinuity, cancellation,
drain/abort, failure containment, and exact destruction.
6. **Integration** — exercise the real external service and record the evidence
boundary honestly.
7. **Distribution** — package, inspect, install, and run from an isolated
consumer before release.

An example or experimental adapter is not promoted into this registry merely
because it compiles.

## Repository layout

```text
connectors/
├── README.md this registry and its policies
├── Cargo.toml shared verification workspace only
└── relay/
├── README.md package setup, behavior, and operational limits
├── Cargo.toml independently released crate
├── src/ Relay-specific implementation
└── tests/ package and portable-semantics conformance
```bash
cargo add pocketstation pocketstation-relay
```

Package directories own their user documentation. The repository README owns
only discovery, support status, shared boundaries, and registry policy.
Then follow the [Relay connector guide](relay/README.md) to publish application
and microphone audio as separate buses.

## Versioning and compatibility
See the [release notes](relay/RELEASE_NOTES.md) before upgrading.

Connector packages version independently from this repository and from
PocketStation Core.
## What the Relay connector handles

- Published crate versions and Git tags are immutable.
- Each package declares the Core versions it supports.
- Provider protocol compatibility is proved by that package, not inferred from
Core's trait definitions.
- A breaking provider or public Rust API change requires the package's normal
semantic-versioning process.
- A repository commit is not a release until its package artifact, tag, and
isolated consumer agree on the same source.
The package owns the Relay-specific work:

Current compatibility:
- source capability authentication;
- WebRTC signaling, ICE, DTLS, Opus, and RTP;
- named AudioBus publication;
- finite startup and shutdown deadlines;
- redacted credentials and structured failures.

| Package | Connector version | PocketStation Core | Evidence boundary |
|---|---:|---:|---|
| `pocketstation-relay` | `0.1.1` | `1.1.1` | component and same-host integration; remote production breadth not implied |
PocketStation Core continues to own capture, graph compilation, bounded
routing, recording, and Session lifecycle.

## Develop and verify the registry

Run the complete workspace gate from the repository root:

```bash
cargo fmt --all -- --check
cargo test --workspace --all-targets --all-features --locked
cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps
```
## Current limits

Package and real-service verification requirements remain in each connector's
own guide and release process.
There are no first-party LiveKit, OpenAI, Deepgram, Twilio, generic WHIP, or
generic WebRTC connectors in this repository. Each service requires its own
authentication, media negotiation, lifecycle, and error handling; changing a
URL is not enough.

## Community connectors
The Relay connector's published evidence covers component and same-host
integration tests. It does not claim every NAT topology, platform, or production
load.

Third-party connectors can implement the same open Core contract without
living in this repository. Their maintainers own distribution, provider
compatibility, security response, and support claims.
## Build another connector

If a community connector is later considered for first-party support, it must
pass the registry policy above. Adoption is an ownership commitment—not only a
directory move.
Third-party packages can implement PocketStation's open Connector API without
living in this repository. Start with the
[Core Connector guide](https://github.com/pocketstation-io/pocketstation/blob/main/docs/guides/connectors.md).
The package author owns provider compatibility, security updates, distribution,
and support.
Loading