Skip to content
This repository was archived by the owner on Mar 15, 2026. It is now read-only.

Add product and format card formats with secure rendering - #30

Merged
bokelley merged 12 commits into
mainfrom
add-product-card-formats
Nov 6, 2025
Merged

Add product and format card formats with secure rendering#30
bokelley merged 12 commits into
mainfrom
add-product-card-formats

Conversation

@bokelley

@bokelley bokelley commented Nov 6, 2025

Copy link
Copy Markdown
Contributor

Summary

Adds four new meta formats for displaying product and format information:

  • product_card_standard (300x400) - Compact media product display
  • product_card_detailed (responsive) - Rich media product showcase
  • format_card_standard (300x400) - Format specification display
  • format_card_detailed (responsive) - Detailed format documentation

Product cards are designed for ADCP media/ad inventory products (e.g., "Homepage Leaderboard", "Video Pre-Roll"), not e-commerce products.

Key Architectural Decisions

Individual Assets Instead of Specialized Types

Product cards use 8 individual assets with existing asset types (image, text) rather than a single promoted_offerings asset. This aligns with ADCP principles:

  • Uses existing AssetType.image and AssetType.text
  • Format definition specifies meaning via asset_id (e.g., product_image, product_name, pricing_model)
  • Renderer extracts individual assets from manifest

Product Card Assets

  • product_image (image) - Primary product/placement preview
  • product_name (text) - Display name
  • product_description (text) - Markdown-formatted description
  • pricing_model (text) - e.g., "CPM", "flat_rate"
  • pricing_amount (text) - e.g., "15.00"
  • pricing_currency (text) - e.g., "USD"
  • delivery_type (text) - "guaranteed" or "bidded"
  • primary_asset_type (text) - "display", "video", "audio", "native"

Security Fixes

Fixed two critical security vulnerabilities identified in code review:

  1. Markdown XSS vulnerability - Added bleach library to sanitize markdown-generated HTML, preventing injection of malicious scripts
  2. Missing URL sanitization - Applied sanitize_url() to all image URLs to block dangerous protocols (javascript:, data:, etc.)

Security measures:

  • Defined allowed HTML tags, attributes, and protocols
  • Sanitize all markdown-rendered content
  • Sanitize all image URLs before rendering

Rendering Features

Product Cards

  • Colored badges for delivery_type (green=guaranteed, orange=bidded)
  • Colored badges for primary_asset_type (blue)
  • Markdown support in descriptions with safe HTML sanitization
  • Pricing display: "{model} ${amount} {currency}"
  • Responsive detailed cards with full markdown documentation

Format Cards

  • Displays format specifications as JSON
  • Asset requirements table with type/required/description
  • Supported macros list
  • Markdown support for format descriptions

Implementation

New Files:

  • src/creative_agent/renderers/base.py - Base renderer with shared utilities
  • src/creative_agent/renderers/product_card_renderer.py - Media product card renderer
  • src/creative_agent/renderers/format_card_renderer.py - Format specification renderer
  • src/creative_agent/utils.py - Shared utilities (sanitize_url)
  • scripts/test_card_rendering.py - Local HTML preview generator

Modified Files:

  • src/creative_agent/data/standard_formats.py - Added 4 meta formats
  • src/creative_agent/storage.py - Routes to specialized renderers
  • pyproject.toml - Added markdown and bleach dependencies

Tests:

  • Added tests/unit/test_meta_formats.py (18 tests)
  • Added tests/unit/test_product_card_renderer.py (9 tests)
  • Added tests/unit/test_format_card_renderer.py (10 tests)
  • All 180 tests passing

Testing

Run test script to generate local HTML previews:

uv run python scripts/test_card_rendering.py

Opens output/ directory with rendered examples:

  • product_card_standard.html - "Homepage Leaderboard" 300x400 card
  • product_card_detailed.html - "Video Pre-Roll Package" responsive card
  • format_card_standard.html - Format specification card
  • format_card_detailed.html - Detailed format documentation

Future Enhancements

When ADCP #180 merges with markdown asset type:

  • Update product_card_detailed and format_card_detailed to use AssetType.markdown for description fields
  • Provides better semantic meaning than AssetType.text with markdown content

Test Coverage

  • All 180 tests passing
  • Code coverage: 68.58%
  • Security vulnerabilities: 0

bokelley and others added 12 commits November 6, 2025 06:05
Introduces four new standard formats for visualizing products and formats
in user interfaces:

- product_card_standard: Fixed 300x400px card for product display
- product_card_detailed: Responsive detailed card with full product specs
- format_card_standard: Fixed 300x400px card for format display
- format_card_detailed: Responsive detailed card with full format specs

These meta formats enable rich UI presentations of products and creative
formats, supporting use cases like format catalogs and product showcases.

The standard cards use fixed dimensions while detailed cards are responsive
for maximum flexibility in different UI contexts.

Testing:
- Added comprehensive test suite in test_meta_formats.py
- Updated format count in test_filter_formats.py
- All 65 unit tests pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Adds a modular renderer architecture for creative previews with
specialized renderers for different format types.

Architecture:
- BaseRenderer: Abstract base with common utilities
- ImageRenderer: Handles image-based display formats (default)
- ProductCardRenderer: Renders product_card_standard and product_card_detailed

Product Card Features:
- Standard card (300x400px fixed): Compact product display with image,
  name, markdown description, price, and brand colors
- Detailed card (responsive): Full-featured card with image carousel,
  categories, formatted markdown content, and CTA button
- Markdown conversion: Descriptions support GitHub-flavored markdown
- Brand styling: Respects brand colors and fonts from promoted_offerings
- Graceful fallbacks: Handles missing data with sensible defaults

Dependencies:
- Added markdown>=3.6 for markdown-to-HTML conversion
- Added types-markdown>=3.6 for type checking

Refactoring:
- Moved sanitize_url to utils.py to avoid circular imports
- Updated generate_preview_html to route to specialized renderers

Testing:
- 10 new tests covering standard/detailed cards, markdown, fallbacks
- All 75 unit tests pass
- Coverage increased to 34.26%

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Adds FormatCardRenderer to display creative format specifications
as visual cards, completing the meta format rendering system.

Format Card Features:
- Standard card (300x400px fixed): Compact format display showing
  format name, type, dimensions, and markdown description
- Detailed card (responsive): Full-featured card with complete
  format specification including assets table and supported macros
- JSON parsing: Handles format data as JSON or plain text
- Markdown support: Format descriptions rendered as rich HTML
- Asset requirements table: Shows required/optional assets with types
- Macro display: Lists supported macros with truncation for long lists

Testing:
- 10 new tests for format cards (standard, detailed, fallbacks)
- Test script (scripts/test_card_rendering.py) to generate HTML previews
- All 85 unit tests pass
- Coverage increased to 38.46%

Testing the Rendering:
Run `uv run python scripts/test_card_rendering.py` to generate HTML
previews in the output/ directory. Open these files in your browser
to visually inspect the card rendering.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…erings

Changed product card formats to use individual text and image assets (product_image, product_name, product_description, pricing_model, pricing_amount, pricing_currency, delivery_type, primary_asset_type) instead of a single promoted_offerings asset.

This aligns with the ADCP principle of using existing asset types with specific asset_ids to define meaning, rather than creating new specialized asset types.

Updated ProductCardRenderer to:
- Extract individual assets from manifest
- Display pricing in format: "{model} ${amount} {currency}"
- Show colored badges for delivery_type (guaranteed/bidded) and primary_asset_type
- Render media product cards for ad inventory (not e-commerce products)

Updated tests to match new asset structure.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Removed output directory and temporary analysis files from version control.
These are generated by test scripts and don't need to be tracked.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Fixed two critical security vulnerabilities identified in code review:

1. Markdown XSS vulnerability - Now using bleach library to sanitize markdown-generated HTML, preventing injection of malicious scripts through description fields

2. Missing URL sanitization for images - Now using sanitize_url() utility for all image URLs to block dangerous protocols (javascript:, data:, etc.)

Security measures added:
- Added bleach dependency for HTML sanitization
- Created _sanitize_markdown() method in both renderers
- Defined allowed HTML tags, attributes, and protocols
- Applied URL sanitization to product_image assets

All 180 tests passing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Created <rendered-creative> web component that provides an elegant solution for embedding creative previews in grids and lists.

Features:
- Shadow DOM for complete CSS isolation (no style conflicts)
- Lazy loading with Intersection Observer (only loads when visible)
- Framework agnostic (React, Vue, Angular, vanilla JS)
- Lightweight alternative to iframes

Usage:
  <rendered-creative src="preview-url.com/..." width="300" height="400"></rendered-creative>

Added:
- src/creative_agent/static/rendered-creative.js - Web component implementation
- examples/web-component-grid.html - Working demo with product/format cards
- examples/README.md - Comprehensive usage documentation

Updated renderers to support fragment parameter (preparation for future enhancement where we can return HTML fragments directly instead of full documents for web component consumption).

All 180 tests passing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Added instructions for testing the web component locally with a web server,
since file:// URLs are blocked by CORS policies.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Wrapped bleach.clean() return value with str() for explicit type safety
to avoid mypy no-any-return errors. Kept type:ignore for imports as
type stubs may not be available in all environments.

Changes:
- Wrapped bleach.clean() with str() cast
- Kept type:ignore[import-untyped] for bleach/markdown imports
- All 180 tests passing
- Mypy clean (0 errors)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Added mypy.ini configuration to disable warn_unused_ignores for the renderer
modules since bleach/markdown type stubs may not be available in all
environments (like pre-commit hooks).

This allows the type:ignore comments to work correctly in environments without
stubs while not causing errors in environments with stubs installed.

Changes:
- Added per-module mypy config for product_card_renderer and format_card_renderer
- Re-added type:ignore[import-untyped] comments for bleach and markdown
- All 180 tests passing
- Mypy clean in all environments

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This is the proper fix for the mypy CI failures. The root cause was that
type stubs (types-bleach, types-markdown) were installed in CI but not
in the pre-commit environment, creating inconsistent behavior.

Changes:
- Added types-markdown and types-bleach to pre-commit mypy dependencies
- Removed module-level warn_unused_ignores overrides from mypy.ini
- Removed now-unnecessary type:ignore comments from imports
- Environments now consistent: both have type stubs

This resolves the technical debt from the previous workaround and ensures
consistent type checking across all environments.

All 180 tests passing, mypy clean.

Thanks to code-reviewer agent for identifying the root cause!

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Changed terminology throughout codebase:
- META_FORMATS → INFO_CARD_FORMATS
- 'meta format' → 'info card format' in comments and docs
- test_meta_formats.py → test_info_card_formats.py
- Updated all test class names and docstrings

The term 'info card formats' better describes their purpose (informational
cards for displaying products and formats) without the Facebook association
that 'meta' carries.

All 180 tests passing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@bokelley
bokelley merged commit e0e4814 into main Nov 6, 2025
4 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant