Commit Graph

143 Commits

Author SHA1 Message Date
1967fe8695 feat: add CLI script for company enrichment (arm_company.py)
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Allows running the same enrichment workflow as the "Uzbrój firmę" button
directly from the command line, without needing browser/admin login.

Usage: python3 scripts/arm_company.py <company_id> [--force]

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 16:34:35 +01:00
a77db328f0 fix: use upload date (not meeting date) for board document storage path
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
DocumentUploadService.get_file_path() resolves paths using uploaded_at,
so import scripts must store files in directories matching that date.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 12:29:57 +01:00
a8f2178b7e feat: activate board document upload/download with meeting 2/2026 import
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Add document management routes (upload, download, soft-delete) to board blueprint,
link BoardDocument to BoardMeeting via meeting_id FK, add documents section to
meeting view template, and include import scripts for meeting 2/2026 data and PDFs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 12:04:44 +01:00
ce9513b4bb fix: Remove Brave Search from social media audit — too many false positives
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Brave Search matched unrelated companies by name token (e.g. VINDOR matched
vindorclothing, vindormusic, beautybyneyador). Social media profiles are now
sourced only from website scraping and manual admin entry.

- Disabled BraveSearcher initialization and call in audit_company()
- Removed Brave Search step from audit progress animation
- Updated missing profile message with explanation and link to profile editor
- Added migration 071 to clean up existing brave_search entries

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 18:20:52 +01:00
f2f65abca2 revert: Remove city-aware token matching, keep handle-based exclude fix
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
City tokens caused too many false positives (matching any business from
the same city). Reverted to name-only matching. The exclude fix
(checking handle instead of full URL substring) is preserved as it
fixes a genuine bug where 'p' in exclude list matched any URL.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 18:05:40 +01:00
9892e07b26 fix: Check excludes against extracted handle, not full URL
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
The 'p' exclude in SOCIAL_MEDIA_EXCLUDE matched any URL containing
the letter 'p' (e.g. ?locale=pl_PL). Now extracts handle first
and checks exclusion with exact match on first path segment.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 17:52:16 +01:00
304f0a5002 fix: Add city-aware token matching to social media Brave Search validator
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Company name tokens have weight 2, city tokens weight 1. City-only
matches accepted only for top-3 Brave results to prevent false positives.
Fixes detection of facebook.com/itwejherowo for Informatyk1 (Wejherowo).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 17:43:00 +01:00
a0c85b6182 fix: Remove direct LinkedIn URL check - risk of false positives
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Direct slug check (e.g. linkedin.com/company/waterm) can match
a different company with the same name. LinkedIn public metadata
is too minimal to verify location/industry without API access.
Rely on Brave Search with title/description validation instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 12:16:19 +01:00
990c6537cb fix: Prioritize LinkedIn company pages over personal profiles
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
- Add direct URL check for linkedin.com/company/{slug} before Brave Search
- Prioritize /company/ over /in/ in search result ranking
- Use targeted query "company_name linkedin.com/company" first
- Fall back to personal profile search only if company page not found
- Verify page title matches company name to avoid false positives

Fixes: WATERM showed employee's personal profile instead of existing
company page at linkedin.com/company/waterm

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 11:08:13 +01:00
6633b94644 fix: Implement Brave Search for LinkedIn detection and fix URL construction
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
- Replace placeholder _search_brave() with real Brave API integration
- Fix LinkedIn URL construction: /in/ profiles were incorrectly built as /company/
- Add word-boundary matching to validate search results against company name
- Track source (website_scrape vs brave_search) per platform in audit results
- Increase search results from 5 to 10 for better coverage

Fixes: WATERM LinkedIn profile not detected (website has no LinkedIn link,
but Brave Search finds the personal /in/ profile)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 10:52:09 +01:00
05a09812a5 fix(seo-audit): Move load_dotenv before module-level env reads
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
DATABASE_URL and PAGESPEED_API_KEY are read at module level (import
time), so load_dotenv must run before third-party imports that
reference these variables.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 15:27:43 +01:00
824b482357 fix(seo-audit): Load .env automatically for API keys
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Add load_dotenv() to seo_audit.py so it reads GOOGLE_PAGESPEED_API_KEY
and DATABASE_URL from .env without requiring manual env var passing.
Fixes PageSpeed 429 errors when running audit via SSH.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 15:26:47 +01:00
7b2c4ce739 fix(seo-audit): Add SSL certificate check to SEO audit script
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
seo_audit.py was missing SSL columns (has_ssl, ssl_expires_at,
ssl_issuer) in its INSERT/UPDATE query, causing all SEO-audited
companies to show has_ssl=false regardless of actual certificate status.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 10:58:00 +01:00
fae99a3137 fix(social-audit): Add 'tr' (Meta Pixel) and other FB endpoints to exclude list
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
The scraper was matching facebook.com/tr (Meta Pixel tracking endpoint)
as a valid Facebook profile handle. Added 'tr', 'privacy', 'policies',
'ads', 'business', 'legal', 'flx' to the Facebook exclusion list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 16:44:53 +01:00
72ba8e05f1 feat(calendar): Show 3 upcoming events on homepage + WhatsApp data import
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
- Display up to 3 next events with RSVP status instead of just one
- Add import script for WhatsApp Norda group data (Feb 2026):
  events, company updates, Alter Energy, Croatia announcement

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 16:29:07 +01:00
7802dcd5e1 fix(i18n): Fix Polish diacritics in audit templates and scraper encoding
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
- Fix ~190 hardcoded Polish strings missing diacritical characters
  across seo_audit.html, gbp_audit.html, social_audit.html
- Fix encoding issue in SEO scraper: requests defaults to ISO-8859-1
  when server omits charset, causing mojibake for UTF-8 pages.
  Now uses apparent_encoding detection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 09:44:59 +01:00
70e40d133b feat(oauth): Add OAuth integration UI, API clients, and audit enrichment (Phase 3)
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
- Company settings page with 4 OAuth cards (GBP, Search Console, Facebook, Instagram)
- 3 API service clients: GBP Management, Search Console, Facebook Graph
- OAuth enrichment in GBP audit (owner responses, posts), social media (FB/IG Graph API),
  and SEO prompt (Search Console data)
- Fix OAuth callback redirects to point to company settings page
- All integrations have graceful fallback when no OAuth credentials configured

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 15:55:02 +01:00
ef39ebf8a3 refactor(seo): Rename FID to INP across entire codebase
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Google replaced First Input Delay (FID) with Interaction to Next Paint
(INP) as a Core Web Vital in March 2024. This renames the DB column
from first_input_delay_ms to interaction_to_next_paint_ms, updates the
PageSpeed client to prefer the INP audit key, and fixes all references
across routes, services, scripts, and report generators. Updated INP
thresholds: good ≤200ms, needs improvement ≤500ms.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 12:58:41 +01:00
b1438dd514 feat(audit): Phase 0 quick wins - fix bugs, enrich AI prompts, add metrics
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
GBP audit:
- Fix review_response_rate bug: check ownerResponse instead of authorAttribution.displayName
- Mark has_posts/has_products/has_qa as OAuth-dependent in AI prompt
- Add review_keywords and description_keywords to AI prompt

SEO audit:
- Replace deprecated FID with INP (Core Web Vital since March 2024)
- Pass 10 additional metrics to AI prompt: FCP, TTFB, TBT, Speed Index,
  meta title/desc length, html lang, Schema.org field details
- Update templates with INP thresholds (200ms/500ms)

Social media audit:
- Calculate engagement_rate from industry base rates × activity multiplier
- Calculate posting_frequency_score (0-10 based on posts_count_30d)
- Enrich AI prompt with page_name, freq_score, engagement, last_post_date
- Add avg engagement rate and brand name consistency check to prompt

Completeness: 52% → ~68% (estimated)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 11:24:03 +01:00
02696c59a4 feat: Add new services, scripts, and competitor dashboard
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
- google_places_service.py: Google Places API integration
- competitor_monitoring_service.py: Competitor tracking service
- scripts/competitor_monitor_cron.py, scripts/generate_audit_report.py
- blueprints/admin/routes_competitors.py, templates/admin/competitor_dashboard.html

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 12:00:54 +01:00
42ddeabf2a feat(backend): Add enhanced audit models and scraper improvements
- database.py: GBPReview, CompanyCitation, CompanyCompetitor, CompetitorSnapshot, AuditReport models
- gbp_audit_service.py: Enhanced review analysis, NAP consistency, keyword analysis
- scripts/seo_audit.py: Core Web Vitals, heading/image/link analysis, SSL, analytics detection
- scripts/social_media_audit.py: Profile enrichment, content types, posting frequency

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 12:00:42 +01:00
60d28a5c24 fix(social-audit): Fix Facebook URL truncation and improve scraping patterns
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
- Add regex pattern for Facebook /p/PageName-ID/ multi-segment URLs
- Add 'p' to Facebook exclusion list (bare /p is always truncated)
- Add minimum length validation for extracted social handles
- Strip Instagram tracking params (?igsh=, &utm_source=) from handles

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 19:29:06 +01:00
14ce54d8b5 fix(social-audit): Fix Facebook profile.php URLs being saved without ID
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
The regex was capturing 'profile.php' as a username instead of extracting
the numeric ID from profile.php?id=XXX links. Added dedicated pattern for
profile.php URLs and added profile.php to exclusion list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 18:03:01 +01:00
c0d60481f0 refactor(rbac): Migrate legacy is_admin checks to role-based has_role()/set_role()
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Replace ~20 remaining is_admin references across backend, templates and scripts
with proper SystemRole checks. Column is_admin stays as deprecated (synced by
set_role()) until DB migration removes it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 21:06:22 +01:00
554adc2aa0 fix(migration): Fix email_verified in secretary creation
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 15:28:22 +01:00
d7f08c8d3a fix(migration): Use is_verified instead of email_verified
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 15:26:55 +01:00
84a8e46186 fix(migration): Correct email addresses for production rada members
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Fixes email mismatches that would have created duplicate accounts:
- Artur Wiertel: norda-biznes.info → waterm.pl (existing prod ID=3)
- Andrzej Gorczycki: zukwejherowo.pl → ekofabrykawejherowo.pl (prod ID=41)
Adds secretary (Magdalena Klóska) and deactivates corrupted duplicate (ID=40).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 15:26:04 +01:00
a57187e05f test: Add comprehensive testing infrastructure
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
- pytest framework with fixtures for auth (auth_client, admin_client)
- Unit tests for SearchService
- Integration tests for auth flow
- Security tests (OWASP Top 10: SQL injection, XSS, CSRF)
- Smoke tests for production health and backup monitoring
- E2E tests with Playwright (basic structure)
- DR tests for backup/restore procedures
- GitHub Actions CI/CD workflow (.github/workflows/test.yml)
- Coverage configuration (.coveragerc) with 80% minimum
- DR documentation and restore script

Staging environment: VM 248, staging.nordabiznes.pl

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 07:52:34 +01:00
ebc3dd63d3 fix: Redirect loop in membership apply + add registry lookup for admin + action legends 2026-02-01 14:05:41 +01:00
9b8d68348e feat: Enhanced website extraction - no limits, more categories
- Removed limits on services (was 10) and keywords (was 8)
- Added new extraction categories:
  - products: physical/digital products
  - brands: partners, certifications (VMware, Veeam, etc.)
  - specializations: specific competencies
  - target_customers: customer types (SMB, enterprise, etc.)
  - regions: geographic coverage
- Merged all data into services_extracted and main_keywords
- Increased content limit to 20000 chars for AI

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 08:50:15 +01:00
83a33f49ff fix: Load .env file in website content updater
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 08:43:06 +01:00
d96cd78c47 feat: Add automatic website content updater with Gemini 3 Flash
- New script: scripts/website_content_updater.py
- Uses Gemini 3 Flash (free tier) for AI extraction
- Extracts: services_extracted, main_keywords, content_summary
- Supports: single company, batch, stale-days filtering, dry-run
- Rate limiting: 2s between API calls
- Documented cron setup in CLAUDE.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 08:42:04 +01:00
52061fa949 feat: Display ALL KRS data in company profile
- Add krs_raw_data, krs_fetched_at, krs_registration_date,
  krs_representation, krs_activities columns to Company model
- Save complete KRS API response for full data access
- Display in company profile:
  - Board members (zarząd) with functions and avatars
  - Shareholders (wspólnicy) with share amounts
  - Representation method (sposób reprezentacji)
  - Business activities (PKD codes)
  - Registration date with years active
  - KRS address with region info
  - OPP (public benefit) status
  - Metadata (stan_z_dnia, data_odpisu)
- Add migration 037_krs_extended_data.sql

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 07:44:33 +01:00
7bfbfa6279 feat: Auto-switch between CEIDG and KRS APIs for company enrichment
- Add enrich_companies_from_registries() that tries KRS first for companies
  with KRS number, then falls back to CEIDG
- Add update_company_from_krs() to save KRS data to Company model
- Fix CEIDG search to use 'nip' parameter directly
- Keep enrich_companies_from_ceidg() as alias for compatibility

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 07:27:50 +01:00
448937dabd fix: Rename pkd_codes column to ceidg_pkd_list to avoid backref conflict
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 07:22:32 +01:00
9f2b261df2 feat: Extend CEIDG data storage and enrichment
- Add new Company fields: ceidg_id, ceidg_status, pkd_codes (JSONB),
  correspondence address, owner_citizenships, ceidg_raw_data
- Add enrich_companies_from_ceidg() to fetch full CEIDG details
- Add fetch_full_ceidg_details() for detailed API calls
- Add update_company_from_ceidg() to save all CEIDG fields
- Add --enrich and --apply flags for batch enrichment
- Add migration 036_ceidg_extended_data.sql

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 07:21:21 +01:00
79a1a60621 feat: Add CEIDG API name search and --missing-nip option
- Add search_ceidg_by_name() for API v3 name-based queries
- Add search_missing_nip_companies() to find NIP for companies without NIP
- Add --missing-nip flag to search for all companies missing NIP
- Add --apply-nip flag to save found NIPs to database
- Fix API endpoint: /api/ceidg/v3/firmy (not /firma)
- Correctly extract NIP from wlasciciel object in response

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 07:16:22 +01:00
99f7a5a88a fix: Remove sticky sidebar on account pages + add Companies to admin menu
Changes:
- Remove position: sticky from konto sidebar (dane, prywatnosc, bezpieczenstwo, blokady)
- Add "Firmy" link to admin dropdown menu (before "Użytkownicy")
- Add scan_websites_for_nip.py script for data quality

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 07:03:55 +01:00
cebe52f303 refactor: Rebranding i aktualizacja modelu AI
- Zmiana nazwy: "Norda Biznes Hub" → "Norda Biznes Partner"
- Aktualizacja modelu AI: Gemini 2.0 Flash → Gemini 3 Flash
- Zachowano historyczne odniesienia w timeline i dokumentacji

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 14:08:39 +01:00
652a441a30 feat(admin): Add AI model comparison page
- New admin page /admin/model-comparison for comparing AI responses
- Side-by-side comparison: old model (2.5 Flash-Lite) vs new (3 Flash)
- Questions from real conversations (Artur Wiertel, Maciej Pienczyn)
- Run simulation button to generate new responses
- Added link in admin menu under "Porównanie modeli"

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 08:45:33 +01:00
4b38f8953c feat(categories): Hierarchiczna struktura kategorii
- Dodanie parent_id do tabeli categories
- Model Category z relacją parent/subcategories
- 4 główne grupy: Usługi, Budownictwo, Handel, Produkcja
- Skrypt assign_category_parents.py do przypisania podkategorii
- Migracja 030_add_category_hierarchy.sql

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 20:51:15 +01:00
b6bbb32483 feat(ui): Norda Partner, Strefa Gościa, uproszczenie forum
- Landing page: przycisk "Norda Partner" + kontakt Izby (email, WhatsApp)
- Landing page: link "Strefa Gościa" → norda-biznes.info
- Menu "Więcej": dodano "Strefa Gościa (Izba)" dla zalogowanych
- Forum: ukryto filtry kategorii/statusów (uproszczenie UX)
- README: zmiana "AI Assistant" → "NordaGPT"
- Skrypt import firmy testowej "Kaszubia 2030"
- .gitignore: wykluczenie notatek ze spotkań (MEETING_*.md)

Zmiany na podstawie spotkania 2026-01-28 i uwag Artura Wiertla.
Wzór nawigacji: Vaillant.pl (Klienci indywidualni / Profesjonaliści)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 20:11:35 +01:00
ebbf75e7a0 fix(calendar): Poprawiono godzinę "Chwila dla Biznesu" z 18:00 na 19:00
Skrypt importu miał błędną godzinę 18:00. Faktyczne spotkania
"Chwila dla Biznesu" odbywają się o 19:00.

Zaktualizowano:
- Komentarz w linii 50
- Opis wydarzenia (description)
- time_start: time(19, 0)

Istniejące wydarzenia w bazie zostały zaktualizowane ręcznie (UPDATE SQL).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 21:56:55 +01:00
96fa0058c2 feat(zopk): Rozbudowa bazy wiedzy ZOPK
- Dodano skrypt cron do automatycznej ekstrakcji wiedzy (scripts/cron_extract_knowledge.py)
- Dodano panel deduplikacji faktów (/admin/zopk/knowledge/fact-duplicates)
- Dodano API i funkcje auto-weryfikacji encji i faktów
- Dodano panel Timeline ZOPK (/admin/zopk/timeline) z CRUD
- Rozszerzono dashboard bazy wiedzy o statystyki weryfikacji i przyciski auto-weryfikacji
- Dodano migrację 016_zopk_milestones.sql dla tabeli kamieni milowych
- Naprawiono duplikat modelu ZOPKMilestone w database.py

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 10:57:11 +01:00
6d1f75bce5 fix(admin): Naprawiono błędne nazwy endpointów w breadcrumbs
Zmieniono admin_dashboard i admin_zopk_dashboard na admin_zopk

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 09:03:01 +01:00
7cc5f033fe fix: Poprawiono nazwy kluczy w pipeline skrypcie
Zmieniono 'processed' -> 'success' i 'generated' -> 'success' aby
pasowały do wartości zwracanych przez batch_extract() i
generate_chunk_embeddings().

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 00:27:08 +01:00
cbd9c5cc4d feat(zopk): Skrypt pipeline do automatycznej ekstrakcji wiedzy
Uruchamia po kolei: scraping treści, ekstrakcję AI, generowanie embeddingów.
Do użycia w cron job co godzinę.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 23:39:49 +01:00
c13ad09e3a feat(zopk): Skrypt do naprawy źródeł newsów z Google News
Problem: Newsy z Google News RSS miały source_domain='news.google.com'
i favicon Google zamiast prawdziwego źródła.

Rozwiązanie: Nowy skrypt fix_google_news_sources.py który:
- Wyciąga nazwę źródła z tytułu (po " - ")
- Mapuje 59 źródeł na ich prawdziwe domeny
- Aktualizuje source_domain i image_url (favicon)

Wynik: 143/143 newsów zaktualizowanych z poprawnymi źródłami.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 08:06:40 +01:00
8055589a08 fix: Usunięto Session z decode_google_news_url, dodano max_depth
- Zamieniono requests.Session() na bezpośredni requests.get()
- Dodano max_depth=3 jako zabezpieczenie przed nieskończoną rekurencją
- Jawne zamykanie response.close() po każdym request

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 07:45:02 +01:00
af4c0d157a fix: Naprawiono wyciek połączeń HTTP w fix_google_news_images.py
- Dodano context manager (with) dla sesji requests
- Jawne zamykanie odpowiedzi HTTP (response.close())
- Dodano flush=True do print dla natychmiastowego outputu
- Rozwiązuje problem 725+ otwartych połączeń

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 07:40:00 +01:00
637ec2fc75 feat: Skrypt do naprawy obrazków newsów z Google News 2026-01-15 06:19:53 +01:00
c2205b0815 fix: Poprawione dekodowanie URL Google News + użycie source_domain 2026-01-15 06:10:59 +01:00
8ead7798df fix: Ładowanie DATABASE_URL z .env w skrypcie obrazków 2026-01-15 06:08:59 +01:00
cf56fe7d8a feat(zopk): Skrypt do pobierania obrazków dla newsów
Strategia pobierania obrazków:
1. Rozwiń URL Google News do oryginalnego źródła
2. Pobierz og:image z meta tagów strony
3. Fallback: logo domeny (Clearbit API)
4. Fallback: favicon (Google Favicon API)

Użycie: python scripts/fetch_news_images.py [--dry-run] [--limit N]

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 06:08:10 +01:00
22e73e4f80 feat: Email DKIM/SPF/DMARC config + year_established data fill
- Added release notes v1.19.0 with today's changes
- Email: DKIM, SPF, DMARC configured for nordabiznes.pl
- Data: year_established filled for 71/111 companies (64%)
- Script: fix_year_established.py for KRS date migration

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 15:01:01 +01:00
c8075e0872 feat: Add email test script for manual testing
Script sends welcome emails to specified addresses for testing
DKIM/SPF/DMARC configuration.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 14:09:17 +01:00
3221740502 feat: Dodanie daty przystąpienia do Izby NORDA na profilu firmy
- Nowa kolumna member_since w tabeli companies
- Karta "Członek Izby NORDA od" na profilu firmy (niebieski kolor #3b82f6)
- Wyświetlanie liczby lat w Izbie
- Import 57 dat przystąpienia z pliku Excel od Artura
- Skrypt import_member_since.py do importu dat

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 06:57:00 +01:00
59c50e0267 fix: Handle None values in SEO audit result extraction
Bug: When page fetch fails (SSL error), result['onpage'] is None.
Using dict.get('key', {}) returns None when key exists with None value.

Fix: Use 'or {}' pattern to handle both missing keys and None values.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 18:20:19 +01:00
abe1cd38a1 feat: Add PKD codes and CEIDG owner data to company profiles
- Add pkd_code, pkd_description columns for business activity classification
- Add business_start_date column from CEIDG
- Add owner_first_name, owner_last_name for JDG companies
- Create import script scripts/import_ceidg_to_db.py
- Add PKD card display in company profile template
- Add owner section for JDG companies without KRS
- Track SQL migrations in git (database/migrations/*.sql)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 16:07:03 +01:00
f174f4d4da feat: Link Users to Persons (KRS data)
- Add person_id column to users table
- Template shows person profile link when person_id exists
- Add script to match and link users to persons by name

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 15:07:02 +01:00
ffc6d8219f feat: Add toggle button to hide/show test items on B2B board
- Add is_test field to Classified model
- Add test-item styling (opacity + gray border + badge)
- Add yellow toggle button with localStorage persistence
- Add script to mark existing classifieds as test
2026-01-13 13:08:11 +01:00
08d6c0b069 feat: Add 'test' category for forum topics to separate test content
- Add 'test' to ForumTopic.CATEGORIES with Polish label 'Testowy'
- Add gray styling for test topics (badge + card opacity)
- Add scripts to list and mark test topics
2026-01-13 11:48:08 +01:00
9eae623d3e feat: Add source tracking to events + import scripts
- Add source and source_note fields to NordaEvent model
- Create import_calendar_2026.py for NORDA calendar events
- Create import_excel_members_2026_01_13.py for new members
- Add .private/ to .gitignore (confidential materials)

Imported 26 events from Kalendarz Izby NORDA 2026 (Artur Wiertel)
Imported 31 new member companies from Excel

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 10:22:24 +01:00
986360f7d5 feat: Add URL normalization and inline audit sections
- Add normalize_social_url() function to database.py to prevent
  www vs non-www duplicates in social media records
- Update update_social_media.py to normalize URLs before insert
- Update social_media_audit.py to normalize URLs before insert
- Add inline GBP Audit section to company profile
- Add inline Social Media Audit section to company profile
- Add inline IT Audit section to company profile

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 23:07:03 +01:00
3f9273cff6 feat: Add company logos to search results, hide events section
- Add company logo display in search results cards
- Make logo clickable (links to company profile)
- Temporarily hide "Aktualności i wydarzenia" section on company profiles
- Add scripts for KRS PDF download/parsing and CEIDG API

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 15:32:53 +01:00
f29987f635 auto-claude: 2.6 - Remove hardcoded password from docstring usage example 2026-01-10 12:55:34 +01:00
c228716c0f auto-claude: 2.6 - Replace hardcoded password in scripts/test_collaboration_matching.py with safe fallback 2026-01-10 12:54:39 +01:00
914dac410e auto-claude: 2.5 - Replace hardcoded password in scripts/seo_audit.py with safe fallback 2026-01-10 12:53:29 +01:00
90f9401530 auto-claude: 2.4 - Replace hardcoded password in scripts/seo_report_generator.py with safe fallback 2026-01-10 12:52:01 +01:00
b4dcca6d55 auto-claude: 2.3 - Replace hardcoded password in scripts/social_media_audit.py with safe fallback 2026-01-10 12:50:39 +01:00
fa45b4b793 auto-claude: subtask-7-2 - Test collaboration matching
Created comprehensive test suite for IT audit collaboration matching:

1. Unit tests (tests/test_it_audit_collaboration.py):
   - 12 tests verifying all 6 match types
   - Backup replication, shared licensing, Teams federation
   - Shared monitoring, collective purchasing, knowledge sharing
   - Edge cases for size parsing and similarity

2. Integration test script (scripts/test_collaboration_matching.py):
   - Creates test audits with matching criteria
   - Runs collaboration matching algorithm
   - Verifies matches saved to database

All unit tests pass (12/12).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 09:24:45 +01:00
39cd257f4e Fix YouTube detection overwriting valid matches
- Add 'channel', 'c', 'user', '@' etc. to YouTube exclusion list
- Add 'bold_themes', 'boldthemes' to Twitter/Facebook exclusions (theme creators)
- Fix pattern matching loop to stop after first valid match per platform
- Prevents fallback pattern from overwriting correct channel ID with 'channel'

Fixes issue where youtube.com/channel/ID was being overwritten with
youtube.com/channel/channel by the second fallback pattern.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 05:36:06 +01:00
c319777d58 Social Media audit: progress bar improvements
- Add detailed logging to SocialMediaAuditor (website scan, Brave search, results)
- Slow down progress bar animation (400ms instead of 200ms) for better readability
- Bold "ZNALEZIONO" text for found platforms
- Display Google rating and review count in progress
- Increase wait time before modal close (4 seconds)
- Add console.log for debugging audit response

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 05:29:17 +01:00
8fed190303 fix(social-audit): Convert opening_hours dict to JSON for JSONB column
Fixes: psycopg2.ProgrammingError: can't adapt type 'dict'

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 05:14:01 +01:00
5ed97ac1dd auto-claude: subtask-5-1 - Fix opening_hours and photos data passing in audit_company
Fixed a bug where google_opening_hours and google_photos_count were being
fetched from the Google Places API but not passed through to the result
dictionary correctly:

- Changed 'opening_hours' key to 'google_opening_hours' to match what
  save_audit_result() expects
- Added 'google_photos_count' to the result dictionary

Verified with dry-run: INPI company now shows opening hours schedule
and 10 photos count from Google Business Profile.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 23:08:19 +01:00
aacf2cf54b auto-claude: subtask-2-3 - Update save_audit_result() to store google_opening_hours and google_photos_count
- Added google_opening_hours and google_photos_count to INSERT column list
- Added corresponding placeholders to VALUES list
- Added to ON CONFLICT UPDATE SET clause
- Added to parameter dictionary reading from google_reviews result

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 23:00:22 +01:00
5f2cfa06fd auto-claude: subtask-2-2 - Update get_place_details() to return photos count
- Add google_photos_count to result dictionary initialization
- Extract photos count from API response using len(place['photos'])
- Update logging to include photos count in output

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 22:59:04 +01:00
5fa80f9efa auto-claude: subtask-2-1 - Add 'photos' to fields list in GooglePlacesSearcher
Added 'photos' field to the fields list in get_place_details() method
to enable fetching business photos from Google Places API.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 22:58:04 +01:00
06c22539d7 auto-claude: subtask-4-2 - Add --company-slug support and dotenv loading
- Add --company-slug argument to social_media_audit.py for easier testing
- Add get_company_id_by_slug() method to SocialMediaAuditor class
- Add python-dotenv support to load .env file from project root
- Create verify_google_places.py script for direct API testing

Note: Full verification blocked - current API key (PageSpeed) doesn't have
Places API enabled. Requires enabling Places API in Google Cloud Console
for project NORDABIZNES (gen-lang-client-0540794446).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 20:49:59 +01:00
3d69d53550 auto-claude: subtask-3-4 - Run all tests and verify they pass
Fixed bug in social media exclusion logic that was too aggressive.
The substring check `any(ex in match.lower() for ex in excludes)`
was incorrectly excluding valid usernames containing exclusion
strings (e.g., 'testcompany' was excluded because it contained 'p').

Changed to exact match only to properly handle Instagram post URLs
(`instagram.com/p/...`) without false positives on valid usernames.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 20:41:54 +01:00
3bdbde1621 auto-claude: subtask-2-3 - Update SocialMediaAuditor to use GooglePlacesSearcher
- Add google_places_searcher attribute to SocialMediaAuditor
- Initialize GooglePlacesSearcher if GOOGLE_PLACES_API_KEY env var is set
- Update audit_company() to use Places API directly when available
- Fallback to Brave Search when API key not configured
- Log which data source is being used for reviews

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 20:31:22 +01:00
b389287697 auto-claude: subtask-2-2 - Replace placeholder search_google_reviews() method
Implemented actual Google reviews data collection in BraveSearcher class:
- Uses GooglePlacesSearcher to find company and get place details
- Returns google_rating, google_reviews_count, opening_hours, business_status
- Falls back to Brave Search API parsing when Google API key not available
- Added _search_brave_for_reviews() helper for fallback implementation
- Proper error handling and logging throughout

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 20:29:50 +01:00
4110ef63b5 auto-claude: subtask-2-1 - Add GooglePlacesSearcher class to social_media_audit.py
Implements GooglePlacesSearcher class with:
- find_place() method: searches for business by name and city
  using Google Places findplacefromtext API
- get_place_details() method: retrieves rating, review count,
  opening hours, business status, phone, and website

Features:
- Uses GOOGLE_PLACES_API_KEY environment variable
- Comprehensive error handling (timeout, request errors)
- Polish language locale support
- Follows existing BraveSearcher class pattern

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 20:27:49 +01:00
af003798a7 Napraw połączenie z bazą danych w skryptach SEO (localhost zamiast zewnętrznego IP) 2026-01-08 15:57:39 +01:00
feaf5d5a49 auto-claude: 8.2 - Fix SQL ANY() to IN() for SQLite compatibility
- Changed PostgreSQL-specific ANY(:ids) to use IN clause with
  dynamic placeholders for SQLite/PostgreSQL compatibility
- Verified SEO audit dry-run extracts all metrics correctly:
  - HTTP status, load time, final URL
  - Meta title, H1 count, image analysis
  - Structured data detection
  - robots.txt, sitemap.xml, indexability
  - Overall SEO score calculation (95 for pixlab.pl)

Note: Company ID 26 has no website configured, tested with ID 1 instead.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 09:21:12 +01:00
15ddbba8b5 auto-claude: 7.1 - Create scripts/seo_report_generator.py that generates HTML reports and JSON exports
Features:
- Single company HTML reports with full SEO audit data
- Batch HTML summary reports for multiple companies
- JSON exports for integration with other tools
- SEO recommendations based on audit findings
- CLI interface with --company-id, --batch, --all selection
- Output format options: --html, --json
- Score visualization with color-coded badges
- Core Web Vitals section with threshold indicators
- Issues and recommendations sections
- Statistics calculation for batch reports
- Polish language support in reports

Usage examples:
- python seo_report_generator.py --company-id 26 --html
- python seo_report_generator.py --all --html --output ./reports
- python seo_report_generator.py --batch 1-10 --json

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 09:13:18 +01:00
c24c545cfe auto-claude: 4.3 - Add save_audit_result method with ON CONFLICT DO UPDATE
- Enhanced save_audit_result method with complete column coverage
- Added missing columns to idempotent upsert query:
  - broken_links_count (for future link checking)
  - viewport_configured (derived from meta viewport tag)
  - is_mobile_friendly (derived from viewport content)
  - has_hreflang (for international SEO detection)
- All 45+ SEO columns now properly mapped for database upserts
- ON CONFLICT (company_id) DO UPDATE ensures idempotent operations

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 08:00:12 +01:00
c8eb0829d9 auto-claude: 4.2 - Add CLI argument parsing, progress logging, and error handling
Enhanced scripts/seo_audit.py with comprehensive CLI improvements:

CLI Arguments:
- --company-id: Audit single company by ID
- --company-ids: Audit multiple companies (comma-separated)
- --batch: Audit range of companies (e.g., 1-10)
- --all: Audit all companies
- --dry-run: Print results without database writes
- --verbose/-v: Debug output
- --quiet/-q: Suppress progress output
- --json: JSON output for scripting
- --database-url: Override DATABASE_URL env var

Progress Logging:
- ETA calculation based on average time per company
- Progress counter [X/Y] for each company
- Status indicators (SUCCESS/SKIPPED/FAILED/TIMEOUT)

Summary Reporting:
- Detailed breakdown by result category
- Edge case counts (no_website, unavailable, timeout, ssl_errors)
- PageSpeed API quota tracking (start/used/remaining)
- Visual score distribution with bar charts
- Failed audits listing with error messages

Error Handling:
- Proper exit codes (0-5) for different scenarios
- Categorization of errors (timeout, connection, SSL, unavailable)
- Database connection error handling
- Quota exceeded handling
- Batch argument validation with helpful error messages

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 03:11:22 +01:00
2bebb46f02 auto-claude: 4.1 - Create scripts/seo_audit.py with SEOAuditor class
Implements SEOAuditor class following social_media_audit.py pattern:
- __init__: Initialize database connection and analysis components
- get_companies: Fetch companies by ID, batch, or all
- audit_company: Full SEO audit (PageSpeed, on-page, technical)
- save_audit_result: Upsert to company_website_analysis table
- run_audit: Orchestration with progress logging and summary

Features:
- Integrates GooglePageSpeedClient for Lighthouse scores
- Uses OnPageSEOAnalyzer for meta tags, headings, images, links
- Uses TechnicalSEOChecker for robots.txt, sitemap, canonical
- Calculates overall SEO score from weighted components
- CLI support: --company-id, --batch, --all, --dry-run, --json

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 02:16:36 +01:00
81fc27dfa9 auto-claude: 3.2 - Add TechnicalSEOChecker class to scripts/seo_analyzer.py
Adds TechnicalSEOChecker class that performs technical SEO audits:
- robots.txt: checks existence, parses directives (Disallow, Allow, Sitemap)
  detects if blocks Googlebot or all bots
- sitemap.xml: checks existence, validates XML, counts URLs, detects sitemap index
- Canonical URLs: detects canonical tag, checks if self-referencing or cross-domain
- Noindex tags: checks meta robots and X-Robots-Tag HTTP header
- Redirect chains: follows up to 10 redirects, detects loops, HTTPS upgrades,
  www redirects, and mixed content issues

Includes:
- 8 dataclasses for structured results (RobotsTxtResult, SitemapResult, etc.)
- TechnicalSEOResult container for complete analysis
- check_technical_seo() convenience function
- CLI support: --technical/-t flag for technical-only analysis
- --all/-a flag for combined on-page and technical analysis
- --json/-j flag for JSON output

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 02:12:47 +01:00
0c257f5e48 auto-claude: 3.1 - Create scripts/seo_analyzer.py with OnPageSEOAnalyzer
Add comprehensive on-page SEO analyzer that extracts:
- Meta tags (title, description, keywords, robots, viewport, canonical)
- Open Graph metadata (og:title, og:description, og:image, etc.)
- Twitter Card metadata (card type, site, creator, etc.)
- Heading structure (h1-h6 counts, hierarchy validation)
- Image alt text analysis (missing, empty, quality issues)
- Link analysis (internal/external/nofollow/broken)
- Structured data detection (JSON-LD, Microdata, RDFa)
- Word count and document attributes (DOCTYPE, lang)

Uses dataclasses for structured results following pagespeed_client.py pattern.
Includes CLI interface for testing individual URLs.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 02:07:10 +01:00
9f58e3f8e1 auto-claude: 2.1 - Create scripts/pagespeed_client.py with GooglePageSpeedClient
Implements Google PageSpeed Insights API client with:
- GooglePageSpeedClient class for making API calls
- Exponential backoff retry logic (3 retries, 1-60s backoff)
- RateLimiter class with daily quota tracking (25k req/day)
- Quota persistence to .pagespeed_quota.json
- Support for mobile/desktop strategies
- Core Web Vitals extraction (LCP, FCP, CLS, TTFB)
- Lighthouse audit scores (performance, accessibility, SEO, best-practices)
- Structured dataclasses for results (PageSpeedResult, PageSpeedScore, CoreWebVitals)
- Custom exceptions (QuotaExceededError, RateLimitError, PageSpeedAPIError)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 02:00:37 +01:00
02fc67bf40 Initial commit 2026-01-01 14:01:49 +01:00