Skip to content

fix(core): embed dialog audio as base64url, not base64 - #15

Merged
howethomas merged 5 commits into
mainfrom
thomashowe/con-1100-base64url-embed
Sep 26, 2026
Merged

howethomas merged 5 commits into
mainfrom
thomashowe/con-1100-base64url-embed

Conversation

@howethomas

Copy link
Copy Markdown
Contributor

With the default MEDIA_BACKEND=embed, every vCon failed the vCon core draft-04 schema: 'base64' is not one of ['base64url', 'json', 'none'] at dialog[0].encoding. Embedded dialog audio is now base64url.

Changes

  • core/base_builder.py: inline audio is encoded with unpadded base64url and labelled encoding: "base64url" (was base64.b64encode and "base64"). Unpadded follows draft-04's reference to JWS-style base64url (RFC 7515, RFC 4648 §5) and matches what the Vapi, Pipecat and ElevenLabs builders already emitted.
  • core/encoding.py (new): base64url_encode / base64url_decode, the decoder restoring padding. The three identical per-adapter helpers are replaced by it.
  • Docs: the README's "vCon Structure" example is updated to the draft-04 shape ("vcon": "0.4.0", mediatype, encoding: "base64url", a lawful basis attachment); adapters/telnyx/BYOK.md updated.
  • Left alone on purpose: ElevenLabs' own API delivers standard base64 (full_audio), still decoded as such; core/media_publisher.py keeps its own content_hash encoder, already unpadded base64url and deliberately kept in step with the SIPREC adapter.

Consumers

The conserver's transcription links decode by encoding, including unpadded base64url, since vcon-dev/vcon-server#208. Deployments on an older conserver should upgrade it before these adapters.

Tests

  • New tests/test_encoding.py: round trip over all byte values, bytes that produce - and _ (no +, / or = in the output), and padding restoration for every length mod 4.
  • Existing assertions in tests/test_builder.py and tests/adapters/telnyx/test_byok_e2e.py now expect and decode base64url.
  • One sample vCon per platform that embeds audio (Twilio, Bandwidth, FreeSWITCH, Asterisk, Telnyx, Vapi, ElevenLabs, Pipecat) with embedded media and LAWFUL_BASIS=consent validates against the vCon working group schema. SignalWire never embeds audio.
  • Fresh venv, pip install -e ".[dev,s3]": ruff check . and black --check . clean; pytest 625 passed (621 on main).

Refs CON-1100

🤖 Generated with Claude Code

howethomas and others added 5 commits September 26, 2026 12:45
draft-ietf-vcon-vcon-core-04's Attachment/Dialog Object schema restricts
`encoding` to "base64url", "json", or "none" -- plain "base64" fails
schema validation. With the default MEDIA_BACKEND=embed, every vCon
core.base_builder produced failed the schema for exactly this reason.

Add core/encoding.py with base64url_encode/decode (unpadded, URL-safe,
matching the JWS-style base64url the spec points to in Section 2.4 --
RFC 7515 Appendix C / RFC 4648 Section 5) and use it in base_builder's
recording-download path instead of base64.b64encode / encoding="base64".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The vapi, pipecat, and elevenlabs builders each defined their own copy
of the same _base64url() helper (already correct: unpadded, URL-safe).
Import core.encoding.base64url_encode instead of maintaining three
byte-identical copies.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two tests asserted the pre-fix, schema-invalid shape: encoding == "base64"
and base64.b64decode() on the dialog body. Update both to encoding ==
"base64url" and core.encoding.base64url_decode(), matching what
core.base_builder now actually emits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Covers arbitrary bytes, bytes that force "-" and "_" into the encoded
output (the base64url replacements for "+" and "/"), and every input
length mod 4 to exercise base64url_decode's padding restoration.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The "vCon Structure" example in README.md still showed the pre-04
"vcon": "0.0.1" / mimetype / encoding: "base64" shape. Update it to
0.4.0 / mediatype / encoding: "base64url" and add a lawful basis
attachment to the example. Also fix a "base64" mention in
adapters/telnyx/BYOK.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@howethomas
howethomas merged commit 7b990c7 into main Sep 26, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant