- Rename "Score Breakdown" → "Opportunity Score" with subtitle
"Higher = more issues = better sales opportunity"
- "No issues detected" at 0 points shows green "✓ No issues found —
low opportunity" instead of ambiguous gray text
- Explains why Technical Health 0/40 is actually good (no problems)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Trash icon button in Actions column with confirmation dialog
- Calls DELETE /admin/prospecting/prospects/{id} (existing endpoint)
- Reloads list after successful deletion
- Toast notification on success/failure
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Register hosting public page router in main.py (POC preview at
/hosting/sites/{id}/preview was returning 404 because the
public_page_router was set on module definition but never mounted)
- Suppress urllib3 InsecureRequestWarning in enrichment service
(intentional verify=False for prospect site scanning)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New scrape_content() method in enrichment_service: extracts meta
description, H1/H2 headings, paragraphs, images (filtered for size),
social links, service items, and detected languages using BeautifulSoup
- Scans 6 pages per prospect: /, /about, /a-propos, /services,
/nos-services, /contact
- Results stored as JSON in prospect.scraped_content_json
- New endpoints: POST /content-scrape/{id} and /content-scrape/batch
- Added to full_enrichment pipeline (Step 5, before security audit)
- CONTENT_SCRAPE job type for scan-jobs tracking
- "Content Scrape" batch button on scan-jobs page
- Add beautifulsoup4 to requirements.txt
Tested on batirenovation-strasbourg.fr: extracted 30 headings,
21 paragraphs, 13 images.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add PROSPECTING_BATCH_DELAY_SECONDS config (default 1.0s) — polite
delay between prospects in batch scans to avoid rate limiting
- Apply delay to all 5 batch API endpoints and all Celery tasks
- Fix Celery tasks: error_message → error_log (matches model field)
- Add batch-scanning.md docs with rate limiting guide, scaling estimates
for 70k+ URL imports, and pipeline order recommendations
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- SecurityReportService generates standalone branded HTML reports from
stored audit data (grade badge, simulated hacked site, detailed
findings, business impact, call-to-action with contact info)
- GET /security-audit/report/{prospect_id} returns HTMLResponse
- "Generate Report" button on prospect detail security tab opens
report in new browser tab (printable to PDF)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Complete security audit integration into the enrichment pipeline:
Backend:
- SecurityAuditService with 7 passive checks: HTTPS, SSL cert, security
headers, exposed files, cookies, server info, technology detection
- Constants file with SECURITY_HEADERS, EXPOSED_PATHS, SEVERITY_SCORES
- SecurityAuditResponse schema with JSON field validators + aliases
- Endpoints: POST /security-audit/{id}, POST /security-audit/batch
- Added to full_enrichment pipeline (Step 5, before scoring)
- get_pending_security_audit() query in prospect_service
Frontend:
- Security tab on prospect detail page with grade badge (A+ to F),
score/100, severity counts, HTTPS/SSL status, missing headers,
exposed files, technologies, and full findings list
- "Run Security Audit" button with loading state
- "Security Audit" batch button on scan-jobs page
Tested on batirenovation-strasbourg.fr: Grade D (50/100), 11 issues
found (missing headers, exposed wp-login, server version disclosure).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New model: ProspectSecurityAudit with score, grade, findings_json,
severity counts, has_https, has_valid_ssl, missing_headers, exposed
files, technologies, scan_error
- Add last_security_audit_at timestamp to Prospect model
- Add security_audit 1:1 relationship on Prospect
Part of Phase 1: Security Audit in Enrichment Pipeline. Service,
constants, migration, endpoints, and frontend to follow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Detect API-level errors (quota exceeded, invalid URL) in response JSON
and store in scan_error instead of silently writing zeros
- Show scan error message on the performance card when present
- Show "No performance data — configure PAGESPEED_API_KEY" when all
scores are 0 and no error was recorded
- Add accessibility and best practices scores to performance card
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Restructure score_breakdown from flat dict to grouped by category:
{technical_health: {flag: pts}, modernity: {...}, ...}
- Each category row shows score/max with progress bar + per-flag detail
(e.g. Technical Health 15/40 → "very slow: 15 pts")
- Color-coded: green for positive flags, orange for issues
- "No issues detected" shown for clean categories
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Score Breakdown: show point-by-point contributions from score_breakdown
dict, sorted by value, color-coded green (positive) vs red (negative)
- Tech Profile: prominent CMS badge (WordPress, Shopify, etc.) with
e-commerce platform tag, "Custom / Unknown CMS" fallback
- Add SSL issuer and expiry date to tech profile card
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix contact_type column: Enum(ContactType) → String(20) to match the
migration (fixes "type contacttype does not exist" on insert)
- Rewrite scrape_contacts with structured-first approach:
Phase 1: tel:/mailto: href extraction (high confidence)
Phase 2: regex fallback with SVG/script stripping, international phone
pattern (requires + prefix, min 10 digits)
Phase 3: address extraction from Schema.org JSON-LD, <address> tags,
and European street address regex (FR/DE/EN street keywords)
- URL-decode email values, strip tags to plain text for cross-element
address matching
- Add /mentions-legales to scanned paths
Tested on batirenovation-strasbourg.fr: finds 3 contacts (email, phone,
address) vs 120+ false positives and a crash before.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reverts the expandable sub-row design back to a clean one-row-per-member
table. All per-store management now happens inside the edit modal.
Table: simple 4-column layout (Member | Stores & Roles | Status | Actions)
with view + edit buttons. Store badges show orange for pending stores.
Edit modal enhanced with per-store cards showing:
- Store name, code, and status badge (Active/Pending)
- Role dropdown + Update button (for active stores)
- Resend invitation button (for pending stores)
- Remove from store button
- "Remove from all stores" link at bottom
Removed: expandedMembers, flattenedRows, toggleMemberExpand,
resendStoreInvitation, resendInvitation (member-level).
Added: resendForStore, removeFromStore (work inside edit modal).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Using debug flag for environment detection is unreliable — if left
True in prod, links would point to localhost. Now uses the proper
is_production() from environment module.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Email clients need absolute URLs to make links clickable. The
acceptance_link was a relative path (/store/invitation/accept?token=...)
which rendered as plain text. Now prepends the platform domain with
the correct protocol.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add wallet diagnostics page at /admin/loyalty/wallet-debug (super admin only)
with explorer-sidebar pattern: config validation, class status, card inspector,
save URL tester, recent enrollments, and Apple Wallet status panels
- Fix Google Wallet fat JWT: include both loyaltyClasses and loyaltyObjects in
payload, use UNDER_REVIEW instead of DRAFT for class reviewStatus
- Fix StorefrontProgramResponse schema: accept google_class_id values while
keeping exclude=True (was rejecting non-None values)
- Standardize all module configs to read from .env file directly
(env_file=".env", extra="ignore") matching core Settings pattern
- Add MOD-026 architecture rule enforcing env_file in module configs
- Add SVC-005 noqa support in architecture validator
- Add test files for dev_tools domain_health and isolation_audit services
- Add google_wallet_status.py script for querying Google Wallet API
- Use table_wrapper macro in wallet-debug.html (FE-005 compliance)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix IPv6 host parsing with _strip_port() utility
- Remove dangerous StorePlatform→Store.subdomain silent fallback
- Close storefront gate bypass when frontend_type is None
- Add custom subdomain management UI and API for stores
- Add domain health diagnostic tool
- Convert db.add() in loops to db.add_all() (24 PERF-006 fixes)
- Add tests for all new functionality (18 subdomain service tests)
- Add .github templates for validator compliance
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move 39 documentation files from top-level docs/ into each module's
docs/ folder, accessible via symlinks from docs/modules/. Create
data-model.md files for 10 modules with full schema documentation.
Replace originals with redirect stubs. Remove empty guide stubs.
Modules migrated: tenancy, billing, loyalty, marketplace, orders,
messaging, cms, catalog, inventory, hosting, prospecting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add 55 unit tests for hosting module (hosted site service, client
service service, stats service) with full fixture setup
- Fix table_empty_state macro: add x_message param for dynamic Alpine.js
expressions rendered via x-text instead of server-side Jinja
- Fix hosting templates (sites, clients) using message= with Alpine
expressions that rendered as literal text
- Fix prospecting templates (leads, scan-jobs, prospects) using
nonexistent subtitle= param, migrated to x_message=
- Align hosting and prospecting admin templates with shared design system
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The pagination() macro expects startIndex, endIndex, pageNumbers, totalPages,
nextPage(), and previousPage() to be defined in the Alpine.js component.
Added these to scan-jobs.js, prospects.js, and leads.js.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The API router was missing prefix="/prospecting", causing all endpoints to
register at /api/v1/admin/stats instead of /api/v1/admin/prospecting/stats.
Also fix 500 errors on prospects, leads, and scan-jobs pages caused by
importing non-existent macro names (table_empty → table_empty_state,
pagination_controls → pagination).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move db.commit() from services to API endpoints and Celery tasks.
Services now use db.flush() only; endpoints own the transaction.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Migrates scanning pipeline from marketing-.lu-domains app into Orion module.
Supports digital (domain scan) and offline (manual capture) lead channels
with enrichment, scoring, campaign management, and interaction tracking.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>