fix(#251): enforce strict website_scan v2 contract - #265
Conversation
Add backward-compatible mapping for legacy and alias website-scan fields so business name, description, address, industry, and founded year consistently populate the canonical business_profile payload while preserving existing canonical properties. Made-with: Cursor
Clarify the canonical business_profile response contract and the new server-side alias normalization/description isolation behavior so frontend validation can target stable fields. Made-with: Cursor
Align website scan outputs with the permanent v2 schema by using business_address, rejecting legacy shapes, and constraining industry to Business Foundation options so preprod/frontend consume a deterministic contract. Made-with: Cursor
Prevent preprod/prod pulumi deploys from failing when the shared purposepath-coaching ECR repository is absent by creating it as a fallback and reusing the shared name. Made-with: Cursor
|
🍹 The Update for mottych/purposepath-coaching-api/preprod (at 96d1e98) was successful. ✨ Neo ExplanationA new coaching API Docker image has been built and is being deployed to the preprod Lambda function, updating the container from the previous image version to the newly built one. This is a routine code deployment with no risk of downtime or data loss.Root Cause AnalysisA new version of the coaching API application has been built and is being deployed to the preprod environment. The Docker image was rebuilt with a new Dependency ChainA new Docker image ( Risk analysisNo stateful resources are being replaced or deleted. This is a standard Lambda container image swap — the function will serve the new image on its next invocation with no infrastructure recreation required. Resource Changes Name Type Operation
~ coaching-image docker:index/image:Image update
~ coaching-api aws:lambda/function:Function update
|
Stamp scan_id and captured_at server-side on every website_scan response so stale model-provided values cannot leak to clients, and document the behavior in prompt/spec contracts. Made-with: Cursor
Bind purposepath-coaching to a stable Pulumi resource using Repository.get when it already exists so subsequent updates do not attempt to delete a non-empty repository. Made-with: Cursor
Summary
website_scanv2 response contract with canonical fields only (no legacy alias handling).business_description,industry,year_founded,business_address) and reject legacy flat payload shapes.scan_idandcaptured_atserver-owned metadata that are always generated at validation time.Incident Context
Issue #251 reported missing or noisy business profile data from website scans. Root cause was permissive/variable payload handling and unconstrained metadata values.
Validation Evidence
business_profile.business_addressis present (andheadquarters_locationis absent)industryis constrained/normalized to allowed enum valuesscan_idandcaptured_atare server-generated per responseTest Plan
uv run ruff check coaching/src/api/models/onboarding.py coaching/tests/unit/test_onboarding_models.py coaching/src/core/topic_seed_data.py coaching/src/core/retrieval_method_registry.pyuv run mypy coaching/src/api/models/onboarding.py --explicit-package-basesuv run pytest coaching/tests/unit/test_onboarding_models.py -k WebsiteScanResponse