In-core ~30-line table-driven codec (no dep). The ITU-T G.711 µ-law
companding formula is a piece of telephony history worth teaching (AGENTS.md
learner-facing comment mandate). 3× linear upsample on decode; 3× decimation
downsample on encode. The resampler artifacts are below the barge-in trigger
threshold (LocalVadReflex only needs RMS energy); rubato lands in a post-
spearhead refinement if a downstream consumer needs better (spec §6.6).
Task T1 of slice-5 — T3 (TwilioMediaStreamsServer) consumes this codec.
Signed-off-by: Aaron D. Lee <himself@adlee.work>
The live Twilio call-control client. Originates outbound calls via Twilio's
Calls.json API (TwiML <Connect><Stream> instructs Twilio to fork audio back
to our /twilio/media-stream WSS endpoint); hangs up via Status=completed.
HTTP basic auth over HTTPS; auth_token is NEVER logged (ADR-0009 -- provider
credentials never reach the brain) -- tracing fields expose only caller-
controlled values (to, from) + the CallSid's last 4 chars.
Feature-gated behind `twilio-live` so the routine CI gate stays feature-
default-off: MockCallControlClient is the per-PR test surface; the maintainer
runs cargo test --features=twilio-live when validating a release. reqwest +
tracing + serde_json are optional deps (dep:foo syntax) -- pulled in only
when the feature is on, keeping the default resolve lean.
The env parser (config::twilio_credentials) follows slice-5/seams' pure-
function pattern: takes Option<String> inputs (testable without env mutation),
returns Ok(None) when all four RUTSTER_TWILIO_* vars are unset (WebRTC-only
mode), Ok(Some) when all four present + parse, Err on partial config (fail-
fast at startup) or malformed values. TwilioCredentials is imported by the
binary but never re-exported through the workspace (ADR-0009).
T6 of slice-5. Depends on T2 (TwilioCredentials + CallControlClient trait).
Signed-off-by: Aaron D. Lee <himself@adlee.work>
The provider call-control seam (green zone, ADR-0008). The trait locks the
boundary so the next provider (Telnyx, etc.) is an implementation, not a
refactor. MockCallControlClient is the CI test double; the live
TwilioCallControlClient (T6) lives behind the twilio-live feature flag.
TwilioCredentials lives ONLY in crates/rutster-trunk/ -- never re-exported
through the workspace (ADR-0009 -- provider credentials never reach the
brain). Its Debug impl is hand-written (NOT derived) so the auth_token
renders as <redacted>, never leaking into tracing/panic output.
Option<SpendToken> on originate is the pre-paved seam for spearhead step-6
(spend cap); this slice passes None everywhere. The signature is locked so
step 6 is additive, not a refactor.
T2 of slice-5. lib.rs gains `pub mod provider;` -- stacked-branches carve-out
(rebase-merge, not squash) per AGENTS.md Git workflow; dev-c rebases forward
for the FOB-side pub mod declarations (g711/twilio_media_streams/session/
loop_driver).
Signed-off-by: Aaron D. Lee <himself@adlee.work>
ADR-0007 lands in code:
- Rename crates/rutster-signaling-sip → crates/rutster-trunk. The crate was
a stub anyway (lib.rs with a doc-comment + crate_compiles() test); the
rename locks the new boundary shape — the future rented-transport
ingress (CPaaS media-leg fork / out-of-tree SBC glue, **no SIP stack**)
lands here at spearhead step 5.
- rutster-trunk/src/lib.rs doc-comment now describes the ADR-0007 split:
CPaaS media-leg adapter as primary, out-of-tree SBC for on-prem
graduation. Cross-refs ADR-0007 + ADR-0008 (FOB vs. green zone: trunk
is green zone; SIP lives outside the trust boundary).
- rutster-spend/src/lib.rs doc-comment updated to quote ADR-0007's
'rutster mediates both the provider call-control API and the brain tap'
framing — the spend gate sits in that boundary, structurally preventing
a runaway brain from exceeding spend/pacing. Pulling spend out into a
service re-introduces the 3-vendor structural hole.
Cargo bumps:
- edition = '2024' (slice-1's pinned Rust 1.85 + edition-2024 floor
already requires this; rutster-media's let-else pattern in
OpusDecoder::decode · Slice-2's let-else in AcceptOffer's Uuid
parse_str · all rely on edition 2024's stabilized let-chains / let-else).
- repository = 'https://git.adlee.work/alee/rutster' (the self-hosted
Gitea remote — matches 'git remote -v' origin). The github.com/anomalyco
URL was stale from the pre-pivot copy.
- Cargo.lock regenerated by cargo for the rename.
No behavioral code changes — the trunk crate's body is still the stub
crate_compiles() test. FOB membership (per ADR-0008) is unchanged:
rutster-trunk will be FOB-internal at step 5 because it's the media-leg
ingress (hot path); spend-spend stays FOB because spend is
security-constitutive.