Repository navigation
fix(vcon): keep draft-04 JSON bodies as values on write - #209
Merged
Merged
Conversation
draft-ietf-vcon-vcon-core-04 §2.3.2: with encoding "json" the body is the JSON value itself (object/array), not a stringified copy. Adapters now emit raw values, so the conserver must stop converting them back into strings on write. - common/vcon.py: add_attachment/add_analysis keep dict/list bodies as values with encoding forced to "json"; JSON validation only applies to str bodies claiming encoding "json" (the legacy -02 stringified shape). - common/lib/vcon_redis.py: VconRedis._enforce_spec_on_write no longer stringifies dict/list bodies. It still fixes a real mismatch (dict/list body with encoding "none"/absent) by stamping encoding to "json" without touching the value. - common/lib/vcon_egress_compat.py: the inverse (_body_to_legacy) now handles both shapes — a native dict/list body under encoding "json" is flipped straight to legacy encoding "none"; a str body is parsed first as before. - common/lib/links/filters.py: is_included's includes substring match now also matches a dict/list body via its JSON-serialized form, since it can no longer assume body is always a string. - conserver/links/post_analysis_to_slack: the customer_frustration includes check and the summary-body-as-Slack-text path now tolerate a raw dict/list body the same way. Every other storage backend (postgres, mongo, s3, elasticsearch, utopia, redis_storage, vcon_mcp, file) persists the whole vCon dict as JSON/BSON/ JSONB rather than treating body specially, so raw bodies already round-trip unchanged; elasticsearch already had an isinstance(body, str) guard before parsing. No migration: existing stored vCons keep string bodies, and every reader (Vcon.decoded_body, egress_compat, filters, storage get()) still accepts both shapes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…N-1111)
Updates existing tests that asserted the old stringify-on-write behavior,
and adds coverage for the new draft-ietf-vcon-vcon-core-04 §2.3.2 shape:
- common/tests/test_vcon_redis_spec_enforce.py,
common/tests/test_vcon_egress_compat.py, common/tests/test_encoding.py,
common/tests/lib/filters/test_is_included.py, tests/core/test_vcon.py,
common/tests/test_api_branches.py: updated to expect dict/list bodies to
stay native (not JSON-stringified), plus new cases for the
encoding-mismatch fix, the legacy stringified shape staying untouched,
and filters/is_included matching a raw dict/list body.
- common/tests/test_api.py: new end-to-end test posting a dict lawful_basis
body and a list tags body through POST /vcon and reading them back via
GET /vcon/{uuid} as a dict and a list.
- tests/storage/test_s3.py, tests/storage/test_postgres_body_roundtrip.py
(new), tests/storage/test_mongo_body_roundtrip.py (new),
tests/storage/test_elasticsearch_body_roundtrip.py (new),
tests/storage/test_vcon_mcp_body_roundtrip.py (new),
common/storage/file/test_file_storage.py,
common/storage/redis_storage/test_redis_storage.py (new): each storage
backend round-trips a raw dict/list body unchanged, with external
services mocked.
Full suite: 750 passed, 17 skipped (was 731 passed, 17 skipped on
origin/main baseline; +19 net from new/updated tests).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Under vCon core draft-04 §2.3.2, when
encodingis"json"thebodyis the JSON value itself, not a stringified copy. Adapters now emit raw values, but the conserver converted them back to strings on ingest and in theVconhelpers, so every stored vCon and every link saw the -02 shape. This keeps raw values raw. Readers already accepted both forms and still do.Changes
common/vcon.py:add_attachment/add_analysiskeep a dict or listbodyas a value withencoding: "json". JSON validation runs only for a string body labelledjson(the legacy form).common/lib/vcon_redis.py:_stringify_json_bodybecomes_normalize_json_body_encoding. It no longer stringifies; it only setsencoding: "json"on a dict or list body that arrived withnoneor no encoding. Runs on ingest, on everyVconRedisstore, and insync_vcon_from_storage.common/lib/vcon_egress_compat.py: the legacy 0.0.1 egress shape handles both a raw and a stringified body.common/lib/links/filters.py:includesmatching serialises a dict or list body before the substring check.post_analysis_to_slack: the frustration check and summary text tolerate raw bodies.Behaviour change for consumers
vCons leaving the conserver (storage, webhooks, vcon-mcp) now carry raw JSON bodies where they used to carry strings. A downstream reader that assumes a string body needs to accept both forms. The legacy egress layer still produces the 0.0.1 shape for consumers that request it. Existing stored vCons keep their string bodies; no migration.
Tests
Refs CON-1111
🤖 Generated with Claude Code