smoke-compose (gated on image-build):
* Rebuilds rutster-edge/engine/brain:smoke from warm GHA cache.
* Runs deploy/smoke/compose_smoke.sh — `docker compose up -d --wait`,
asserts all four services State=running, curls /healthz + /readyz
through Caddy TLS (internal CA). Lighter than the all-in-one smoke
(which already proved the WS path) — its job is the orchestrator
shape + the network_mode: "service:engine" brain->engine tap posture.
smoke-reload (gated on smoke):
* Reuses rutster-allinone:smoke + the allinone_smoke.py WS helpers.
* Runs deploy/smoke/reload_during_call.py — holds a live WS streaming
frames at 20ms while a concurrent `caddy reload` fires mid-call;
asserts zero frames dropped + WS survives across the reload.
Regresses the stream_close_delay 24h mitigation against caddy #6420/
#7222 (TLS brief §5 risk 1; spec §9 reload-during-call smoke).
Both jobs run on ubuntu-latest — separate runners for clearer failure
attribution + parallelism (the smoke gate is the failing CI signal,
not a single serial run).
Signed-off-by: Aaron D. Lee <himself@adlee.work>
Adds the smoke job to .github/workflows/ci.yml, gated on image-build.
Runs deploy/smoke/allinone_smoke.py against the freshly-built
rutster-allinone:smoke image:
* Boots the all-in-one container with RUTSTER_LOCAL_CERTS=true (Caddy
internal CA, no ACME in CI per spec §9).
* Extracts Caddy's internal-CA root cert from /data/caddy/pki/
authorities/local/root.crt via docker cp.
* Opens wss:// WS to /twilio/media-stream using the extracted root
(Python stdlib ssl + socket — no pip install required, CI runner-
image ships Python 3 + ssl).
* Sends Twilio's connected+start handshake frames (the same JSON
sequence crates/rutster-trunk/tests/ws_ping.rs uses).
* Streams 200 PCM-zeroed frames at 20ms cadence as Twilio Media events.
* Asserts the engine replies with at least one text frame — proving
the real edge->FOB WS path works end-to-end through TLS.
The compose smoke + reload-during-call smoke (Task 9) gate on this job.
Signed-off-by: Aaron D. Lee <himself@adlee.work>
Extends .github/workflows/ci.yml with an image-build job, gated on the
existing fmt/clippy/test/deny/sim-bench matrix
(needs: [fmt, clippy, test, deny, sim-bench]). Builds all four images via
docker buildx against deploy/Dockerfile's named --targets, with type=gha
caching scoped per image so warm caches take image-build from ~6min to
~90s.
Tags the freshly-built :ci-<sha> images as :smoke too, for the
downstream smoke job to consume. Runs `caddy validate` inside the
freshly-built rutster-edge as a cheap Caddyfile-syntax regression.
No changes to the existing fmt/clippy/test/deny/sim-bench/twilio-live
jobs — those stay the cargo-side source of truth.
Signed-off-by: Aaron D. Lee <himself@adlee.work>
The routine CI gate stays feature-default-off: MockCallControlClient is the
per-PR test surface. A new twilio-live job runs ONLY on manual
workflow_dispatch (maintainer triggers pre-release) -- it exercises clippy
--features=twilio-live + the live TwilioCallControlClient tests against real
Twilio credentials (TWILIO_* secrets). Never runs per-PR.
Seam gate verified UNCHANGED: loop_driver.rs (744bf314...) + rtc_session.rs
(f47d63b9...) blob hashes match the slice-4 Task 10 pins exactly -- the trunk
leg's tick lives entirely in rutster-trunk/src/loop_driver.rs (a separate file
in a separate crate), so the media-crate seam files stay byte-identical.
cargo deny: reqwest (rustls-tls) + base64 + async-trait introduce ZERO new
duplicate dep versions (verified via `cargo tree -d` with vs without
--features=twilio-live: identical duplicate sets -- the existing skip list in
deny.toml remains sufficient). Local cargo-deny 0.18.3 cannot parse the
`-or-later` SPDX form + CVSS 4.0 advisory entries (pre-existing limitation
documented in deny.toml; CI's cargo-deny-action@v2 bundles 0.19.x which handles
both) -- CI is the authoritative deny gate.
Two rustdoc intra-doc-link warnings in my code fixed (mock.rs private-item
link -> plain inline code; lib.rs redundant explicit link target simplified).
Two pre-existing rustdoc warnings remain in rutster-tap/protocol.rs +
rutster/tap_engine.rs (out of scope -- pre-existing from slices 2-3, not
introduced by slice-5).
T10 of slice-5. This is the final task on the dev-b chain (T2 + T6 + T9 + T10
all landed).
Signed-off-by: Aaron D. Lee <himself@adlee.work>
deny.toml allows the permissive Rust-ecosystem licenses + our own
GPL-3.0-or-later; bans duplicate versions of tokio/serde/bytes/tracing
to catch dep-tree divergence early; restricts sources to crates.io. CI
runs fmt --check, clippy -D warnings, test --all (matrix: stable +
MSRV 1.85), and cargo deny check on push + PR to main. The CI job
installs libopus-dev — the opus crate's FFI dependency (PORT_PLAN §7
'Core (FFI)' disposition).