Repository navigation
fix: retain partial visual regions #320
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
34a0c98
799671a
41d164c
0f8bc28
8bcc6d6
ba93fd7
91a95a9
acc5976
cf7331a
0161c45
67fca36
c132b8c
260e919
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # 2.13.1 Buyer-safe image evidence | ||
|
|
||
| Buyer views and search keep legitimate captions while suppressing internal | ||
| VISION instructions. Region responses with invalid JSON value types now fail | ||
| closed with an explicit type error instead of being treated as valid evidence. |
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -185,6 +185,7 @@ | |||||||||||
| has_real_source_context, | ||||||||||||
| ) | ||||||||||||
| from lineageweave.http_client import HttpClientError | ||||||||||||
| from lineageweave.observability import configure_telemetry | ||||||||||||
|
|
||||||||||||
| _POST_READ = "post_read" | ||||||||||||
| _POST_ADMIN = "post_admin" | ||||||||||||
|
|
@@ -194,6 +195,7 @@ | |||||||||||
| async def lifespan(app: FastAPI): | ||||||||||||
| """Open one asyncpg pool and one Valkey client for the process, and | ||||||||||||
| close both on shutdown.""" | ||||||||||||
| configure_telemetry("lineageweave") | ||||||||||||
| settings = load_settings() | ||||||||||||
| app.state.pool = await create_pool(settings.database_url) | ||||||||||||
| app.state.valkey = create_valkey_client(settings.valkey_url) | ||||||||||||
|
|
@@ -2655,6 +2657,11 @@ async def chat_about_post( | |||||||||||
| status.HTTP_503_SERVICE_UNAVAILABLE, | ||||||||||||
| "Post chat is unavailable: contextual-orchestrator returned no complete evidence object", | ||||||||||||
| ) from exc | ||||||||||||
| except Exception as exc: # noqa: BLE001 - provider boundary is fail-closed. | ||||||||||||
| raise HTTPException( | ||||||||||||
| status.HTTP_503_SERVICE_UNAVAILABLE, | ||||||||||||
| "Post chat is unavailable: contextual-orchestrator returned no complete evidence object", | ||||||||||||
| ) from exc | ||||||||||||
|
Comment on lines
+2660
to
+2664
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Duplicate unreachable exception handler A second
Suggested change
Was this helpful? React with 👍 or 👎 to provide feedback. |
||||||||||||
| cited_ids = list(answer.cited_post_ids) | ||||||||||||
| async with pool.acquire() as conn: | ||||||||||||
| await persist_post_chat(conn, post_id, question, answer.answer_text, cited_ids) | ||||||||||||
|
|
||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| # ADR 0121: Keep Internal Image Instructions Out of Buyer Evidence | ||
|
|
||
| ## Status | ||
|
|
||
| Accepted | ||
|
|
||
| ## Context | ||
|
|
||
| VISION analysis may receive or inherit an internal instruction such as | ||
| `This post is an image. Ask questions to read its text.` or its Korean | ||
| equivalent. That text is an agent instruction, not a caption describing the | ||
| source image. Persisted legacy content can still contain it even after the | ||
| prompt is corrected. | ||
|
|
||
| ## Decision | ||
|
|
||
| At the image and visual-region evidence boundary, normalize captions and suppress captions that | ||
| match the known internal instruction forms. Apply the same rule when creating | ||
| LLM/embedding placeholders and when rendering the buyer-facing post body. | ||
| Retain the original image, OCR text, tags, region coordinates, and provenance; | ||
| only the non-evidence caption is removed. If no useful caption remains, show | ||
| the image and available evidence without inventing a description. | ||
|
|
||
| The instruction matcher uses concrete imperative phrases for Korean text | ||
| extraction guidance rather than ordinary words such as `텍스트` or `질문`, so | ||
| legitimate captions that describe an image containing text remain evidence. | ||
|
|
||
| The configured Vision destination is also a trust boundary. The client rejects | ||
| credential-bearing URLs, invalid ports, loopback/private/link-local/reserved | ||
| IP literals, and known local or cloud-metadata hostnames even when local HTTP | ||
| is explicitly enabled. Compose uses the service name `orchestrator` for its | ||
| local HTTP route; a caller cannot opt into an internal IP destination by | ||
| setting `allow_insecure_http`. | ||
|
|
||
| Vision parse failures and unexpected provider failures are also trust-boundary | ||
| events. Their raw response or exception text is never returned in an API | ||
| payload or persisted as post-content detail; the product exposes a stable | ||
| unavailable message and schedules a retry where applicable. | ||
|
|
||
| ## Consequences | ||
|
|
||
| - Buyer screens cannot expose the analysis agent's instruction as post content. | ||
| - Existing persisted image rows are safe immediately; re-ingestion is not | ||
| required merely to hide the legacy caption. | ||
| - OCR, region evidence, and semantic search remain available. | ||
| - New provider-specific instruction variants require an explicit, reviewed | ||
| pattern and a regression test rather than a broad caption guess. | ||
| - A malformed or attacker-controlled Vision endpoint fails closed at client | ||
| construction, before an API key or image payload is sent. | ||
| - A malformed provider response cannot disclose gateway diagnostics through a | ||
| buyer-facing error or durable ingestion record. | ||
|
|
||
| ## References — APA 7th | ||
|
|
||
| MITRE. (2026). *CWE-209: Generation of error message containing sensitive | ||
| information*. https://cwe.mitre.org/data/definitions/209.html | ||
|
|
||
| National Institute of Standards and Technology. (2020). *Security and privacy | ||
| controls for information systems and organizations* (NIST Special Publication | ||
| 800-53 Rev. 5). https://doi.org/10.6028/NIST.SP.800-53r5 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📝 Info: Synchronous span held across await points
tracedstarts a synchronous current span and wraps awaited Valkey calls (e.g.publish_activity_eventawaitsclient.xaddinside thewith). Holding a current span across an await can attach concurrently scheduled tasks to the wrong parent span. Harmless for the current single-producer/reader paths; trace parenting could mislead if concurrency grows.Was this helpful? React with 👍 or 👎 to provide feedback.