{"ok":true,"meta":{"generatedAt":"2026-06-30T13:15:57.853Z"},"data":{"status":"blocked","localReady":false,"productionReady":false,"env":[{"name":"NEXT_PUBLIC_SITE_URL","configured":true},{"name":"NEXT_PUBLIC_SCHEDULE_URL","configured":true},{"name":"DATABASE_URL","configured":false},{"name":"ADMIN_API_TOKEN","configured":false},{"name":"ADMIN_SESSION_SECRET","configured":false},{"name":"TELEGRAM_WEBHOOK_SECRET","configured":false},{"name":"VIP_CLUB_WEBHOOK_URL","configured":false},{"name":"VIP_CLUB_WEBHOOK_TOKEN","configured":false},{"name":"LEGAL_CONTACT_EMAIL","configured":false},{"name":"ELASTICSEARCH_URL","configured":false},{"name":"ELASTICSEARCH_API_KEY","configured":false},{"name":"UPSTASH_REDIS_REST_URL","configured":false},{"name":"UPSTASH_REDIS_REST_TOKEN","configured":false},{"name":"NEXT_PUBLIC_MEDIA_CDN_URL","configured":false},{"name":"CLOUDFLARE_R2_BUCKET","configured":false},{"name":"CLOUDFLARE_R2_ACCESS_KEY_ID","configured":false},{"name":"CLOUDFLARE_R2_SECRET_ACCESS_KEY","configured":false},{"name":"WEB_VITALS_ENDPOINT_URL","configured":false}],"optionalEnv":[{"name":"SCHEDULE_API_URL","configured":false},{"name":"SCHEDULE_API_TOKEN","configured":false},{"name":"SCHEDULE_AVAILABILITY_PATH","configured":false},{"name":"SCHEDULE_REQUEST_PATH","configured":false},{"name":"NEXT_PUBLIC_SCHEDULE_PROJECT_URL","configured":false},{"name":"NEXT_PUBLIC_SCHEDULE_EMBED_URL","configured":false},{"name":"NEXT_PUBLIC_SCHEDULE_WIDGET_URL","configured":false},{"name":"NEXT_PUBLIC_SCHEDULE_SITE","configured":true},{"name":"NEXT_PUBLIC_SCHEDULE_LANG","configured":false},{"name":"OPENAI_API_KEY","configured":false},{"name":"OPENAI_MODEL","configured":false},{"name":"GOOGLE_TRANSLATE_API_KEY","configured":false},{"name":"ELASTICSEARCH_INDEX","configured":false},{"name":"ELASTICSEARCH_SEARCH_PATH","configured":false},{"name":"SEARCH_CACHE_TTL_SECONDS","configured":false},{"name":"MEDIA_AI_PROVIDER_URL","configured":false},{"name":"MEDIA_AI_PROVIDER_TOKEN","configured":false},{"name":"WEB_VITALS_ENDPOINT_TOKEN","configured":false},{"name":"NEXT_PUBLIC_VAPID_PUBLIC_KEY","configured":false},{"name":"PWA_PUSH_PROVIDER_URL","configured":false},{"name":"PWA_PUSH_PROVIDER_TOKEN","configured":false},{"name":"PRIMARY_DOMAIN_CHECK_URL","configured":false},{"name":"CLOUDFLARE_ACCOUNT_ID","configured":false},{"name":"CLOUDFLARE_ZONE_ID","configured":false},{"name":"CLOUDFLARE_API_TOKEN","configured":false},{"name":"MIRROR_TELEGRAM_ALERT_URL","configured":false},{"name":"MIRROR_DOMAINS","configured":false}],"gates":{"local":[{"id":"catalog-seed","label":"Static catalog seed","status":"pass","detail":"8 profiles, 3 collections"},{"id":"legal-pages","label":"Legal pages","status":"pass","detail":"5 legal documents"},{"id":"data-retention-policy","label":"Data retention policy","status":"pass","detail":"11 records; /legal/data-retention"},{"id":"legal-contact-policy","label":"Legal contact policy","status":"pass","detail":"tzv3-legal-contact-v1; telegram-fallback"},{"id":"legal-audit-policy","label":"Legal production audit policy","status":"pass","detail":"tzv3-legal-audit-policy-v1; pages=6; audit=npm run legal:audit"},{"id":"database-bootstrap-policy","label":"Database bootstrap contract","status":"pass","detail":"tzv3-database-bootstrap-v1; seed=8/27"},{"id":"database-migration-manifest","label":"Database migration manifest","status":"fail","detail":"0/3 migration files"},{"id":"database-seed-manifest","label":"Database seed manifest","status":"pass","detail":"8/16/32/3/12/27 seed baseline"},{"id":"database-seed-payload","label":"Database seed payload export","status":"pass","detail":"npm run database:seed-payload; profiles=8; hash=004ee561992d"},{"id":"database-audit-policy","label":"Database audit policy","status":"pass","detail":"tzv3-database-audit-policy-v1; 8 SELECT-only queries"},{"id":"programmatic-seo","label":"Programmatic SEO seeds","status":"pass","detail":"27 SEO landing pages"},{"id":"technical-seo-audit-policy","label":"Technical SEO audit policy","status":"pass","detail":"npm run seo:audit; 10 checks"},{"id":"unit-test-contract","label":"Unit test contract","status":"pass","detail":"vitest; 34 areas"},{"id":"load-smoke-contract","label":"Light load smoke contract","status":"pass","detail":"npm run load:smoke; 47 routes"},{"id":"safe-growth-policy","label":"High-risk safe growth policy","status":"pass","detail":"safe-growth-v2; 11 skills"},{"id":"deployment-policy","label":"Vercel/Netlify deployment policy","status":"pass","detail":"vercel=vercel.json; ciAudit=true; vercelLinkAudit=true; sourceAudit=true; env=true; ownerInputs=true; originAudit=true; evidenceAudit=true; cloudflareAudit=true; clubHandoff=true; databaseSeedPayload=true; databaseAudit=true; mediaPublicUrls=true; mediaAudit=true; preflight=true; productionPreflight=true; scheduleProviderHandoff=true; scheduleProviderImportPayload=true; scheduleProviderReconciliation=true; scheduleLinksAudit=true; scheduleAudit=true; searchBulkPayload=true; searchAudit=true; secretsRotation=true; telegramHandoff=true; telegramAudit=true; vitalsAudit=true"},{"id":"ci-policy","label":"GitHub Actions TZV3 CI policy","status":"fail","detail":"npm run ci:audit; workflow=.github/workflows/tzv3-ci.yml; productionReady=false"},{"id":"source-control-policy","label":"Website source-control guard","status":"pass","detail":"npm run source:audit; repo=parkourcafe/artesc; productionReady=false"},{"id":"secret-rotation-policy","label":"Secret rotation handoff","status":"pass","detail":"npm run secrets:rotation; missingRequired=16; audits=15"},{"id":"club-handoff-policy","label":"VIP Club receiver handoff","status":"pass","detail":"npm run club:handoff; missing=2; headers=5"},{"id":"public-origin-policy","label":"Public origin contract","status":"pass","detail":"npm run origin:audit; site=https://www.artescort.vip; productionReady=false"},{"id":"production-evidence-manifest","label":"Production evidence manifest","status":"pass","detail":"npm run evidence:audit; stages=14; commands=111; productionCollectionReady=false"},{"id":"vercel-link-policy","label":"Vercel project link guard","status":"pass","detail":"unlinked; project=unlinked"},{"id":"launch-checklist","label":"Owner launch checklist","status":"pass","detail":"tzv3-launch-checklist-v1; 14 stages"},{"id":"owner-inputs-packet","label":"Owner input packet","status":"pass","detail":"tzv3-owner-inputs-v1; 52 inputs; 16 required env missing"},{"id":"frontend-stack","label":"TZV3 frontend library stack","status":"pass","detail":"TanStack Query, React Hook Form, Zod resolver, Framer Motion, UI primitives"},{"id":"brand-identity","label":"ARTESC.SHOP brand palette","status":"pass","detail":"npm run brand:audit; accent=#db006e; ink=#212331"},{"id":"tzv3-completion-audit","label":"TZV3 completion audit","status":"pass","detail":"80% complete; 22 production blockers"},{"id":"schedule-contract","label":"Schedule API contract","status":"pass","detail":"provider=external-iframe"},{"id":"schedule-link-audit-policy","label":"Profile-aware schedule link audit","status":"pass","detail":"npm run schedule:links:audit; profiles=8/8"},{"id":"schedule-provider-handoff-policy","label":"Schedule provider handoff contract","status":"pass","detail":"npm run schedule:provider-handoff; drafts=8/8"},{"id":"schedule-provider-import-payload","label":"Schedule provider import payload","status":"pass","detail":"npm run schedule:provider-import-payload; providers=8; site=artesc"},{"id":"schedule-provider-reconciliation","label":"Schedule provider reconciliation","status":"pass","detail":"npm run schedule:provider-reconciliation; matched=0/8; missing=8"},{"id":"status-stream","label":"Status stream","status":"pass","detail":"/api/status/stream"},{"id":"telegram-status-contract","label":"Telegram live-status contract","status":"pass","detail":"dry-run-no-store; x-webhook-token; commands=6"},{"id":"telegram-handoff-policy","label":"Telegram setup handoff","status":"pass","detail":"npm run telegram:handoff; native=x-telegram-bot-api-secret-token; missing=2"},{"id":"filter-seo-policy","label":"Interactive filter SEO policy","status":"pass","detail":"noindex, follow; canonical=/"},{"id":"review-schema-policy","label":"Moderated review schema policy","status":"pass","detail":"Review JSON-LD waits for real reviews"},{"id":"review-workflow-policy","label":"Real review intake and moderation workflow","status":"pass","detail":"dry-run-static; admin=/api/admin/reviews"},{"id":"reviews-audit-policy","label":"Real reviews production audit policy","status":"pass","detail":"tzv3-reviews-audit-policy-v1; eligible=0; audit=npm run reviews:audit"},{"id":"seo-copy-policy","label":"AI SEO copy contract","status":"pass","detail":"template-dry-run; POST /api/admin/seo-copy"},{"id":"content-review-policy","label":"Generated content review workflow","status":"pass","detail":"POST /api/admin/content-review; 6 checks"},{"id":"favorites-retention","label":"Legal retention mechanics","status":"pass","detail":"browser-localStorage; page=/favorites"},{"id":"smart-match-contract","label":"Smart Match concierge contract","status":"pass","detail":"heuristic-dry-run; GET /api/match?q="},{"id":"video-visits","label":"Video visit cards","status":"pass","detail":"local-mp4-generated; 8 videos"},{"id":"media-enhancement-contract","label":"AI media enhancement contract","status":"pass","detail":"manual-review-dry-run; local-public-assets"},{"id":"media-asset-manifest","label":"Media CDN/R2 asset manifest","status":"pass","detail":"20 assets; 2197676 bytes"},{"id":"media-public-url-policy","label":"Media public URL handoff","status":"pass","detail":"npm run media:public-urls; assets=20; mode=site-origin"},{"id":"pwa-offline","label":"PWA offline shell","status":"pass","detail":"/manifest.webmanifest; /sw.js; pushOptIn=true"},{"id":"pwa-push-opt-in","label":"PWA push opt-in contract","status":"pass","detail":"/api/pwa/push/policy; provider=false; delete=DELETE /api/pwa/push/subscribe; audit=npm run pwa-push:audit"},{"id":"web-vitals-monitoring","label":"Browser Web Vitals monitoring","status":"pass","detail":"local-validated-no-store; next/web-vitals useReportWebVitals"},{"id":"search-contract","label":"Elastic-ready search contract","status":"pass","detail":"local-keyword-fallback; cache=none-local"},{"id":"search-index-manifest","label":"Elastic index manifest","status":"pass","detail":"profiles; 8 docs"},{"id":"search-bulk-payload","label":"Elastic bulk import payload","status":"pass","detail":"profiles; 8 docs; 16 NDJSON lines"},{"id":"api-security-guard","label":"API anti-scraping and rate-limit guard","status":"pass","detail":"edge-memory; 100/min"},{"id":"cloudflare-policy","label":"Cloudflare WAF/CDN policy","status":"pass","detail":"policy-only; waf=3; rate=3"},{"id":"admin-audit-contract","label":"Admin audit log contract","status":"pass","detail":"postgres-required; 6 actions"},{"id":"admin-session-contract","label":"Admin session auth contract","status":"pass","detail":"httpOnly-signed-cookie; ui=/admin/profiles; fallback=x-admin-token header for scripts and curl"},{"id":"admin-security-audit-policy","label":"Admin security audit policy","status":"pass","detail":"tzv3-admin-security-audit-policy-v1; audit=npm run admin:audit; endpoints=6"},{"id":"vip-club-contract","label":"VIP Club verification contract","status":"pass","detail":"dry-run-static; 4 preview profiles; webhook=hmac-sha256; audit=npm run club:audit"},{"id":"i18n-contract","label":"International translation contract","status":"pass","detail":"deterministic-dry-run; en,ar,zh"},{"id":"mirror-monitor-contract","label":"Mirror monitoring contract","status":"pass","detail":"dry-run-static; mirrors=0"}],"production":[{"id":"site-url","label":"Production site URL","status":"pass","detail":"https://www.artescort.vip"},{"id":"vercel-link","label":"Vercel website project link","status":"fail","detail":"Run vercel link for the confirmed Artesc website project."},{"id":"database","label":"PostgreSQL database","status":"fail","detail":"DATABASE_URL missing"},{"id":"database-seed-import","label":"PostgreSQL seed import","status":"fail","detail":"Run migrations and POST /api/admin/seed before production traffic"},{"id":"admin-token","label":"Admin token","status":"fail","detail":"missing"},{"id":"admin-session-secret","label":"Admin session secret","status":"warn","detail":"Use a dedicated ADMIN_SESSION_SECRET in production"},{"id":"schedule-api","label":"Separate schedule embed","status":"pass","detail":"iframe/widget configured; optional SCHEDULE_API_URL not set"},{"id":"elastic-search","label":"Elastic instant search","status":"fail","detail":"Elastic Cloud must be configured for production instant search"},{"id":"redis-cache","label":"Redis cache","status":"fail","detail":"Upstash Redis must be configured for production search/filter caching"},{"id":"media-storage","label":"Cloudflare R2 media storage","status":"fail","detail":"Cloudflare R2/CDN media storage and NEXT_PUBLIC_MEDIA_CDN_URL must be verified outside the app"},{"id":"media-ai-provider","label":"AI media enhancement provider","status":"warn","detail":"Approved upscaling/color-correction provider must be configured before production"},{"id":"pwa-push-provider","label":"PWA push provider","status":"warn","detail":"NEXT_PUBLIC_VAPID_PUBLIC_KEY, PWA_PUSH_PROVIDER_URL, and PWA_PUSH_PROVIDER_TOKEN are required for production push delivery"},{"id":"web-vitals-sink","label":"Web Vitals metrics sink","status":"fail","detail":"Configure WEB_VITALS_ENDPOINT_URL or approved analytics before production"},{"id":"telegram-secret","label":"Telegram webhook secret","status":"fail","detail":"TELEGRAM_WEBHOOK_SECRET missing"},{"id":"cloudflare","label":"Cloudflare/WAF settings","status":"warn","detail":"External DNS/WAF/rate-limit setup must be verified outside the app"},{"id":"legal-contact","label":"Dedicated legal contact","status":"fail","detail":"LEGAL_CONTACT_EMAIL missing"},{"id":"deployment-env","label":"Production deployment env check","status":"fail","detail":"16 required production variables missing or placeholder"}]},"database":{"status":{"configured":false,"provider":"static-seed","writable":false},"catalogStats":null,"auditPolicy":{"version":"tzv3-database-audit-policy-v1","endpoint":"/api/database/audit-policy","command":"npm run database:audit","script":"scripts/tzv3-database-audit.mjs","requiredEnvironment":["DATABASE_URL"],"configured":false,"provider":"static-seed","timeoutSeconds":5,"manifests":{"migrations":"/api/database/migration-manifest","seed":"/api/database/seed-manifest","bootstrap":"/api/database/bootstrap-policy"},"requiredTables":["profiles","media_assets","services","reviews","bookings","collections","programmatic_seo_pages","collection_profiles","status_events","admin_audit_logs"],"requiredIndexes":["profiles_slug_idx","profiles_status_idx","profiles_city_idx","profiles_published_idx","media_assets_profile_idx","services_profile_idx","reviews_profile_idx","reviews_published_idx","bookings_profile_idx","bookings_status_idx","collections_slug_idx","programmatic_seo_pages_slug_idx","programmatic_seo_pages_path_idx","programmatic_seo_pages_indexable_idx","status_events_profile_idx","status_events_source_idx"],"seedBaseline":{"profiles":8,"media_assets":16,"services":32,"collections":3,"collection_profiles":12,"programmatic_seo_pages":27},"selectOnlyQueries":[{"id":"database-required-tables","purpose":"Read public schema table inventory.","sql":"select tablename from pg_tables where schemaname = 'public'"},{"id":"database-required-indexes","purpose":"Read public schema index inventory.","sql":"select indexname from pg_indexes where schemaname = 'public'"},{"id":"database-count-profiles","purpose":"Read seed baseline count for profiles.","sql":"select count(*)::int as value from profiles"},{"id":"database-count-media_assets","purpose":"Read seed baseline count for media_assets.","sql":"select count(*)::int as value from media_assets"},{"id":"database-count-services","purpose":"Read seed baseline count for services.","sql":"select count(*)::int as value from services"},{"id":"database-count-collections","purpose":"Read seed baseline count for collections.","sql":"select count(*)::int as value from collections"},{"id":"database-count-collection_profiles","purpose":"Read seed baseline count for collection_profiles.","sql":"select count(*)::int as value from collection_profiles"},{"id":"database-count-programmatic_seo_pages","purpose":"Read seed baseline count for programmatic_seo_pages.","sql":"select count(*)::int as value from programmatic_seo_pages"}],"expectedChecks":["database-connection","database-required-tables","database-required-indexes","database-seed-baseline"],"expectedOutput":{"ok":"boolean","generatedAt":"ISO timestamp","safety":"read-only/no-secret boundary","checks":"array of { id, ok, messages, ...meta }"},"productionReady":false,"productionBlockers":["DATABASE_URL is missing"],"safety":{"mode":"read-only","writes":false,"printsSecrets":false,"note":"The database audit uses SELECT-only PostgreSQL queries, never mutates data, and must not print DATABASE_URL or admin tokens."}},"migrationManifest":{"version":"tzv3-database-migration-manifest-v1","endpoint":"/api/database/migration-manifest","generatedAt":"2026-06-30T13:15:57.651Z","productionReady":false,"requiredOrder":["drizzle/0001_initial_tzv3.sql","drizzle/0002_review_author_alias.sql","drizzle/0003_programmatic_seo_pages.sql"],"files":[],"missingFiles":["drizzle/0001_initial_tzv3.sql","drizzle/0002_review_author_alias.sql","drizzle/0003_programmatic_seo_pages.sql"],"auditCommand":"npm run database:audit","applyCommand":"psql \"$DATABASE_URL\" -f drizzle/0001_initial_tzv3.sql && psql \"$DATABASE_URL\" -f drizzle/0002_review_author_alias.sql && psql \"$DATABASE_URL\" -f drizzle/0003_programmatic_seo_pages.sql","safety":{"mode":"read-only","writes":false,"printsSecrets":false,"note":"Reads local SQL migration files and returns hashes only. It never connects to PostgreSQL and never prints DATABASE_URL."}},"seedManifest":{"version":"tzv3-database-seed-manifest-v1","endpoint":"/api/database/seed-manifest","generatedAt":"2026-06-30T13:15:57.654Z","productionReady":true,"counts":{"profiles":8,"mediaAssets":16,"services":32,"collections":3,"links":12,"programmaticSeoPages":27},"hashes":{"profiles":"f42b1d08f3d0c381451c56e2ab41d739c6390abf25329c21f7d2acba69411f8a","mediaAssets":"eb7eebcbed46f7d92f7b28e735109b24f90a3f6099f97508c6a1b3dd5737d486","services":"7b798670e2134526ae16f521d92c87774a21845e6299ec8d99fe6e6581f818ec","collections":"c8412182768895327d5db2aee75813a278b777b86ef5f264ac526292aba017f0","collectionLinks":"1a9f14628c665eaca213d2873f66a2416c85d05a25106f1c85d39feffa51fc6b","programmaticSeoPages":"6c755b8917be504bbe1b3a490593147401e37dabdaa1c552efa8b1d7764cb76b","fullSeed":"004ee561992dab0758492afe0f9be4e6b760b67ea5f1db8268f5031fa541197e"},"slugs":{"profiles":["sofia","mira","vera","lina","ksenia","darina","emma","nikol"],"collections":["premium-evening","new","schedule-linked"],"programmaticSeoPages":["spb-center-premium","spb-new-18-25","spb-vip-available","spb-mayakovskaya","spb-private","spb-english","spb-metro-center","spb-metro-petrogradskaya","spb-metro-admiralteyskaya","spb-metro-nevsky","spb-metro-ploshchad-vosstaniya","spb-metro-chernyshevskaya","spb-metro-gostiny-dvor","spb-style-premium","spb-style-vip","spb-style-elite","spb-style-new","spb-status-available","spb-status-tonight","spb-status-request","spb-age-18-25","spb-age-26-35","spb-premium-18-25","spb-vip-26-35","spb-private-18-25","spb-private-26-35","spb-elite-26-35"]},"adminSeedEndpoint":"POST /api/admin/seed","auditCommand":"npm run database:audit","payloadEndpoint":"/api/database/seed-payload","payloadCommand":"npm run database:seed-payload","safety":{"mode":"read-only","writes":false,"printsSecrets":false,"note":"Hashes the static seed payload used by POST /api/admin/seed. It never connects to PostgreSQL and never prints DATABASE_URL or admin tokens."}},"seedPayloadExport":{"version":"tzv3-database-seed-payload-v1","endpoint":"/api/database/seed-payload","command":"npm run database:seed-payload","script":"scripts/tzv3-database-seed-payload.mjs","configured":true,"manifestEndpoint":"/api/database/seed-manifest","adminSeedEndpoint":"POST /api/admin/seed","manifestHash":"004ee561992dab0758492afe0f9be4e6b760b67ea5f1db8268f5031fa541197e","counts":{"profiles":8,"mediaAssets":16,"services":32,"collections":3,"links":12,"programmaticSeoPages":27},"slugs":{"profiles":["sofia","mira","vera","lina","ksenia","darina","emma","nikol"],"collections":["premium-evening","new","schedule-linked"],"programmaticSeoPages":["spb-center-premium","spb-new-18-25","spb-vip-available","spb-mayakovskaya","spb-private","spb-english","spb-metro-center","spb-metro-petrogradskaya","spb-metro-admiralteyskaya","spb-metro-nevsky","spb-metro-ploshchad-vosstaniya","spb-metro-chernyshevskaya","spb-metro-gostiny-dvor","spb-style-premium","spb-style-vip","spb-style-elite","spb-style-new","spb-status-available","spb-status-tonight","spb-status-request","spb-age-18-25","spb-age-26-35","spb-premium-18-25","spb-vip-26-35","spb-private-18-25","spb-private-26-35","spb-elite-26-35"]},"contractReady":true,"productionImportReady":true,"safety":{"mode":"read-only","writes":false,"printsSecrets":false,"note":"Exports the exact static seed payload used by POST /api/admin/seed. It never connects to PostgreSQL, never imports data, and never prints DATABASE_URL or admin tokens."},"productionBoundary":["Record this payload and /api/database/seed-manifest before POST /api/admin/seed.","Production import still requires DATABASE_URL, ADMIN_API_TOKEN, applied migrations, and npm run database:audit after import.","If this payload changes, the manifest fullSeed hash changes and production import evidence must be refreshed."],"payload":{"profiles":[{"slug":"sofia","name":"София","age":23,"city":"Санкт-Петербург","district":"Центр","status":"tonight","statusLabel":"NEW","rate":"25000 ₽ 1 час","height":170,"weight":52,"bust":"2","style":"Премиум","mood":"спокойная классика","intro":"София выбирает камерные встречи, мягкий тон общения и аккуратный вечерний стиль.","languages":["RU","EN"],"tags":["NEW","Центр","Выезд"],"details":["Анкета проходит ручную проверку перед публикацией в каталоге.","Доступность и время встречи вынесены в отдельный модуль расписания.","Для уточнения деталей используйте Telegram или заявку через расписание."],"consentVerified":false,"manualVerificationStatus":"pending","isVip":false,"isPublished":true},{"slug":"mira","name":"Мира","age":26,"city":"Санкт-Петербург","district":"Петроградская","status":"available","statusLabel":"На месте","rate":"30000 ₽ 1 час","height":168,"weight":50,"bust":"2","style":"VIP","mood":"интеллигентная легкость","intro":"Мира держит баланс между светской подачей и живым разговором, хорошо чувствует темп вечера.","languages":["RU","EN","FR"],"tags":["VIP","EN","На месте"],"details":["Анкета проходит ручную проверку перед публикацией в каталоге.","Доступность и время встречи вынесены в отдельный модуль расписания.","Для уточнения деталей используйте Telegram или заявку через расписание."],"consentVerified":false,"manualVerificationStatus":"pending","isVip":true,"isPublished":true},{"slug":"vera","name":"Вера","age":28,"city":"Санкт-Петербург","district":"Адмиралтейская","status":"private","statusLabel":"NEW","rate":"25000 ₽ 1 час","height":174,"weight":55,"bust":"3","style":"Private","mood":"сдержанная уверенность","intro":"Вера работает с приватными заявками, где важны пунктуальность, конфиденциальность и ясные договоренности.","languages":["RU"],"tags":["NEW","Private","Центр"],"details":["Анкета проходит ручную проверку перед публикацией в каталоге.","Доступность и время встречи вынесены в отдельный модуль расписания.","Для уточнения деталей используйте Telegram или заявку через расписание."],"consentVerified":false,"manualVerificationStatus":"pending","isVip":false,"isPublished":true},{"slug":"lina","name":"Лина","age":28,"city":"Санкт-Петербург","district":"Маяковская","status":"available","statusLabel":"NEW","rate":"20000 ₽ 1 час","height":169,"weight":53,"bust":"2","style":"Элит","mood":"яркая подача","intro":"Лина подходит для тех, кому важны легкость общения и аккуратная подача.","languages":["RU"],"tags":["NEW","Маяковская","Салон"],"details":["Анкета проходит ручную проверку перед публикацией в каталоге.","Доступность и время встречи вынесены в отдельный модуль расписания.","Для уточнения деталей используйте Telegram или заявку через расписание."],"consentVerified":false,"manualVerificationStatus":"pending","isVip":false,"isPublished":true},{"slug":"ksenia","name":"Ксения","age":22,"city":"Санкт-Петербург","district":"Невский","status":"tonight","statusLabel":"NEW","rate":"20000 ₽ 1 час","height":166,"weight":49,"bust":"2","style":"Новые","mood":"мягкая энергия","intro":"Ксения сохраняет спокойный темп и внимательность к деталям встречи.","languages":["RU","EN"],"tags":["NEW","EN","Вечер"],"details":["Анкета проходит ручную проверку перед публикацией в каталоге.","Доступность и время встречи вынесены в отдельный модуль расписания.","Для уточнения деталей используйте Telegram или заявку через расписание."],"consentVerified":false,"manualVerificationStatus":"pending","isVip":false,"isPublished":true},{"slug":"darina","name":"Дарина","age":23,"city":"Санкт-Петербург","district":"Площадь Восстания","status":"available","statusLabel":"NEW","rate":"15000 ₽ 1 час","height":172,"weight":54,"bust":"3","style":"Премиум","mood":"деликатный формат","intro":"Дарина лучше раскрывается в заранее согласованном формате без спешки.","languages":["RU"],"tags":["NEW","Центр","На месте"],"details":["Анкета проходит ручную проверку перед публикацией в каталоге.","Доступность и время встречи вынесены в отдельный модуль расписания.","Для уточнения деталей используйте Telegram или заявку через расписание."],"consentVerified":false,"manualVerificationStatus":"pending","isVip":false,"isPublished":true},{"slug":"emma","name":"Эмма","age":24,"city":"Санкт-Петербург","district":"Чернышевская","status":"private","statusLabel":"По запросу","rate":"25000 ₽ 1 час","height":171,"weight":52,"bust":"2","style":"Private","mood":"камерный вечер","intro":"Эмма принимает только подтвержденные заявки и не публикует открытые слоты.","languages":["RU","EN"],"tags":["Private","EN","Центр"],"details":["Анкета проходит ручную проверку перед публикацией в каталоге.","Доступность и время встречи вынесены в отдельный модуль расписания.","Для уточнения деталей используйте Telegram или заявку через расписание."],"consentVerified":false,"manualVerificationStatus":"pending","isVip":false,"isPublished":true},{"slug":"nikol","name":"Николь","age":26,"city":"Санкт-Петербург","district":"Гостиный двор","status":"available","statusLabel":"На месте","rate":"25000 ₽ 1 час","height":167,"weight":51,"bust":"2","style":"VIP","mood":"уверенная классика","intro":"Николь держит уверенную подачу и аккуратно ведет коммуникацию.","languages":["RU"],"tags":["VIP","На месте","Центр"],"details":["Анкета проходит ручную проверку перед публикацией в каталоге.","Доступность и время встречи вынесены в отдельный модуль расписания.","Для уточнения деталей используйте Telegram или заявку через расписание."],"consentVerified":false,"manualVerificationStatus":"pending","isVip":true,"isPublished":true}],"mediaAssets":[{"profileSlug":"sofia","type":"image","src":"/models/sofia.jpeg","alt":"София, Санкт-Петербург","role":"card","sortOrder":0},{"profileSlug":"sofia","type":"image","src":"/models/profile-sofia.jpeg","alt":"София, подробная анкета","role":"profile","sortOrder":1},{"profileSlug":"mira","type":"image","src":"/models/mira.jpeg","alt":"Мира, Санкт-Петербург","role":"card","sortOrder":0},{"profileSlug":"mira","type":"image","src":"/models/profile-mira.jpeg","alt":"Мира, подробная анкета","role":"profile","sortOrder":1},{"profileSlug":"vera","type":"image","src":"/models/vera.jpeg","alt":"Вера, Санкт-Петербург","role":"card","sortOrder":0},{"profileSlug":"vera","type":"image","src":"/models/profile-vera.jpeg","alt":"Вера, подробная анкета","role":"profile","sortOrder":1},{"profileSlug":"lina","type":"image","src":"/models/sofia.jpeg","alt":"Лина, Санкт-Петербург","role":"card","sortOrder":0},{"profileSlug":"lina","type":"image","src":"/models/profile-lina.jpeg","alt":"Лина, подробная анкета","role":"profile","sortOrder":1},{"profileSlug":"ksenia","type":"image","src":"/models/mira.jpeg","alt":"Ксения, Санкт-Петербург","role":"card","sortOrder":0},{"profileSlug":"ksenia","type":"image","src":"/models/profile-ksenia.jpeg","alt":"Ксения, подробная анкета","role":"profile","sortOrder":1},{"profileSlug":"darina","type":"image","src":"/models/vera.jpeg","alt":"Дарина, Санкт-Петербург","role":"card","sortOrder":0},{"profileSlug":"darina","type":"image","src":"/models/profile-darina.jpeg","alt":"Дарина, подробная анкета","role":"profile","sortOrder":1},{"profileSlug":"emma","type":"image","src":"/models/mira.jpeg","alt":"Эмма, Санкт-Петербург","role":"card","sortOrder":0},{"profileSlug":"emma","type":"image","src":"/models/profile-emma.jpeg","alt":"Эмма, подробная анкета","role":"profile","sortOrder":1},{"profileSlug":"nikol","type":"image","src":"/models/sofia.jpeg","alt":"Николь, Санкт-Петербург","role":"card","sortOrder":0},{"profileSlug":"nikol","type":"image","src":"/models/profile-nikol.jpeg","alt":"Николь, подробная анкета","role":"profile","sortOrder":1}],"services":[{"profileSlug":"sofia","name":"Апартаменты","mode":"in_place","price":"25000 ₽ 1 час","isPublic":true,"sortOrder":0},{"profileSlug":"sofia","name":"Выезд","mode":"outcall","price":"по запросу","isPublic":true,"sortOrder":1},{"profileSlug":"sofia","name":"VIP формат","mode":"vip","price":"по запросу","isPublic":true,"sortOrder":2},{"profileSlug":"sofia","name":"Сопровождение","mode":"event","price":"по запросу","isPublic":true,"sortOrder":3},{"profileSlug":"mira","name":"Апартаменты","mode":"in_place","price":"30000 ₽ 1 час","isPublic":true,"sortOrder":0},{"profileSlug":"mira","name":"Выезд","mode":"outcall","price":"по запросу","isPublic":true,"sortOrder":1},{"profileSlug":"mira","name":"VIP формат","mode":"vip","price":"по запросу","isPublic":true,"sortOrder":2},{"profileSlug":"mira","name":"Сопровождение","mode":"event","price":"по запросу","isPublic":true,"sortOrder":3},{"profileSlug":"vera","name":"Апартаменты","mode":"in_place","price":"25000 ₽ 1 час","isPublic":true,"sortOrder":0},{"profileSlug":"vera","name":"Выезд","mode":"outcall","price":"по запросу","isPublic":true,"sortOrder":1},{"profileSlug":"vera","name":"VIP формат","mode":"vip","price":"по запросу","isPublic":true,"sortOrder":2},{"profileSlug":"vera","name":"Сопровождение","mode":"event","price":"по запросу","isPublic":true,"sortOrder":3},{"profileSlug":"lina","name":"Апартаменты","mode":"in_place","price":"20000 ₽ 1 час","isPublic":true,"sortOrder":0},{"profileSlug":"lina","name":"Выезд","mode":"outcall","price":"по запросу","isPublic":true,"sortOrder":1},{"profileSlug":"lina","name":"VIP формат","mode":"vip","price":"по запросу","isPublic":true,"sortOrder":2},{"profileSlug":"lina","name":"Сопровождение","mode":"event","price":"по запросу","isPublic":true,"sortOrder":3},{"profileSlug":"ksenia","name":"Апартаменты","mode":"in_place","price":"20000 ₽ 1 час","isPublic":true,"sortOrder":0},{"profileSlug":"ksenia","name":"Выезд","mode":"outcall","price":"по запросу","isPublic":true,"sortOrder":1},{"profileSlug":"ksenia","name":"VIP формат","mode":"vip","price":"по запросу","isPublic":true,"sortOrder":2},{"profileSlug":"ksenia","name":"Сопровождение","mode":"event","price":"по запросу","isPublic":true,"sortOrder":3},{"profileSlug":"darina","name":"Апартаменты","mode":"in_place","price":"15000 ₽ 1 час","isPublic":true,"sortOrder":0},{"profileSlug":"darina","name":"Выезд","mode":"outcall","price":"по запросу","isPublic":true,"sortOrder":1},{"profileSlug":"darina","name":"VIP формат","mode":"vip","price":"по запросу","isPublic":true,"sortOrder":2},{"profileSlug":"darina","name":"Сопровождение","mode":"event","price":"по запросу","isPublic":true,"sortOrder":3},{"profileSlug":"emma","name":"Апартаменты","mode":"in_place","price":"25000 ₽ 1 час","isPublic":true,"sortOrder":0},{"profileSlug":"emma","name":"Выезд","mode":"outcall","price":"по запросу","isPublic":true,"sortOrder":1},{"profileSlug":"emma","name":"VIP формат","mode":"vip","price":"по запросу","isPublic":true,"sortOrder":2},{"profileSlug":"emma","name":"Сопровождение","mode":"event","price":"по запросу","isPublic":true,"sortOrder":3},{"profileSlug":"nikol","name":"Апартаменты","mode":"in_place","price":"25000 ₽ 1 час","isPublic":true,"sortOrder":0},{"profileSlug":"nikol","name":"Выезд","mode":"outcall","price":"по запросу","isPublic":true,"sortOrder":1},{"profileSlug":"nikol","name":"VIP формат","mode":"vip","price":"по запросу","isPublic":true,"sortOrder":2},{"profileSlug":"nikol","name":"Сопровождение","mode":"event","price":"по запросу","isPublic":true,"sortOrder":3}],"collections":[{"slug":"premium-evening","title":"Дорогие эскорт услуги","description":"Подборка анкет для премиального вечера, салона и приватного формата.","isProgrammatic":false},{"slug":"new","title":"Новые анкеты","description":"Анкеты, которые недавно появились в каталоге и требуют быстрой проверки расписания.","isProgrammatic":false},{"slug":"schedule-linked","title":"С отдельным расписанием","description":"Профили, где доступность подтверждается только во внешнем модуле расписания.","isProgrammatic":false}],"collectionLinks":[{"collectionSlug":"premium-evening","profileSlug":"sofia","sortOrder":0},{"collectionSlug":"premium-evening","profileSlug":"mira","sortOrder":1},{"collectionSlug":"premium-evening","profileSlug":"vera","sortOrder":2},{"collectionSlug":"premium-evening","profileSlug":"darina","sortOrder":3},{"collectionSlug":"new","profileSlug":"sofia","sortOrder":0},{"collectionSlug":"new","profileSlug":"lina","sortOrder":1},{"collectionSlug":"new","profileSlug":"ksenia","sortOrder":2},{"collectionSlug":"new","profileSlug":"darina","sortOrder":3},{"collectionSlug":"schedule-linked","profileSlug":"vera","sortOrder":0},{"collectionSlug":"schedule-linked","profileSlug":"emma","sortOrder":1},{"collectionSlug":"schedule-linked","profileSlug":"mira","sortOrder":2},{"collectionSlug":"schedule-linked","profileSlug":"nikol","sortOrder":3}],"programmaticSeoPages":[{"slug":"spb-center-premium","path":"/spb/center/premium","segments":["center","premium"],"title":"Премиальные анкеты в центре СПб","h1":"Премиальные анкеты в центре Санкт-Петербурга","description":"Подборка премиальных анкет artescort.vip для центра Санкт-Петербурга с быстрым переходом в отдельное расписание.","intent":"Город + район + премиум формат","source":"manual","filters":{"district":"Центр","style":"Премиум"},"isIndexable":true},{"slug":"spb-new-18-25","path":"/spb/new/18-25","segments":["new","18-25"],"title":"Новые анкеты 18-25 в СПб","h1":"Новые анкеты 18-25 в СПб","description":"SEO-посадочная под новые анкеты молодого возраста: быстрый каталог, карточки и расписание вынесено отдельно.","intent":"Город + новые + возраст","source":"manual","filters":{"ageMin":18,"ageMax":25,"tags":["NEW"]},"isIndexable":true},{"slug":"spb-vip-available","path":"/spb/vip/available","segments":["vip","available"],"title":"VIP анкеты на месте в СПб","h1":"VIP анкеты на месте в Санкт-Петербурге","description":"VIP-подборка с актуальными статусами static seed. Реальные слоты проверяются в отдельном schedule-модуле.","intent":"Город + VIP + статус","source":"manual","filters":{"style":"VIP","status":"available"},"isIndexable":true},{"slug":"spb-mayakovskaya","path":"/spb/metro-mayakovskaya","segments":["metro-mayakovskaya"],"title":"Анкеты у метро Маяковская","h1":"Анкеты у метро Маяковская","description":"Локальная посадочная страница под район Маяковская с быстрым переходом к расписанию выбранной анкеты.","intent":"Город + метро","source":"manual","filters":{"district":"Маяковская"},"isIndexable":true},{"slug":"spb-private","path":"/spb/private","segments":["private"],"title":"Private анкеты в СПб","h1":"Private анкеты в Санкт-Петербурге","description":"Закрытый private-формат с ручной проверкой и подтверждением времени во внешнем schedule-модуле.","intent":"Город + private формат","source":"manual","filters":{"style":"Private"},"isIndexable":true},{"slug":"spb-english","path":"/spb/en","segments":["en"],"title":"Анкеты со знанием английского в СПб","h1":"Анкеты со знанием английского в СПб","description":"Подборка анкет с английским языком для гостей Санкт-Петербурга и деловых встреч.","intent":"Город + язык","source":"manual","filters":{"tags":["EN"]},"isIndexable":true},{"slug":"spb-metro-center","path":"/spb/metro/center","segments":["metro","center"],"title":"Анкеты у метро Центр","h1":"Анкеты у метро Центр","description":"Локальная SEO-страница artescort.vip по району Центр: карточки, параметры и быстрый переход в отдельное расписание.","intent":"Город + метро/район","source":"seed-generated","filters":{"district":"Центр"},"isIndexable":true},{"slug":"spb-metro-petrogradskaya","path":"/spb/metro/petrogradskaya","segments":["metro","petrogradskaya"],"title":"Анкеты у метро Петроградская","h1":"Анкеты у метро Петроградская","description":"Локальная SEO-страница artescort.vip по району Петроградская: карточки, параметры и быстрый переход в отдельное расписание.","intent":"Город + метро/район","source":"seed-generated","filters":{"district":"Петроградская"},"isIndexable":true},{"slug":"spb-metro-admiralteyskaya","path":"/spb/metro/admiralteyskaya","segments":["metro","admiralteyskaya"],"title":"Анкеты у метро Адмиралтейская","h1":"Анкеты у метро Адмиралтейская","description":"Локальная SEO-страница artescort.vip по району Адмиралтейская: карточки, параметры и быстрый переход в отдельное расписание.","intent":"Город + метро/район","source":"seed-generated","filters":{"district":"Адмиралтейская"},"isIndexable":true},{"slug":"spb-metro-nevsky","path":"/spb/metro/nevsky","segments":["metro","nevsky"],"title":"Анкеты у метро Невский","h1":"Анкеты у метро Невский","description":"Локальная SEO-страница artescort.vip по району Невский: карточки, параметры и быстрый переход в отдельное расписание.","intent":"Город + метро/район","source":"seed-generated","filters":{"district":"Невский"},"isIndexable":true},{"slug":"spb-metro-ploshchad-vosstaniya","path":"/spb/metro/ploshchad-vosstaniya","segments":["metro","ploshchad-vosstaniya"],"title":"Анкеты у метро Площадь Восстания","h1":"Анкеты у метро Площадь Восстания","description":"Локальная SEO-страница artescort.vip по району Площадь Восстания: карточки, параметры и быстрый переход в отдельное расписание.","intent":"Город + метро/район","source":"seed-generated","filters":{"district":"Площадь Восстания"},"isIndexable":true},{"slug":"spb-metro-chernyshevskaya","path":"/spb/metro/chernyshevskaya","segments":["metro","chernyshevskaya"],"title":"Анкеты у метро Чернышевская","h1":"Анкеты у метро Чернышевская","description":"Локальная SEO-страница artescort.vip по району Чернышевская: карточки, параметры и быстрый переход в отдельное расписание.","intent":"Город + метро/район","source":"seed-generated","filters":{"district":"Чернышевская"},"isIndexable":true},{"slug":"spb-metro-gostiny-dvor","path":"/spb/metro/gostiny-dvor","segments":["metro","gostiny-dvor"],"title":"Анкеты у метро Гостиный двор","h1":"Анкеты у метро Гостиный двор","description":"Локальная SEO-страница artescort.vip по району Гостиный двор: карточки, параметры и быстрый переход в отдельное расписание.","intent":"Город + метро/район","source":"seed-generated","filters":{"district":"Гостиный двор"},"isIndexable":true},{"slug":"spb-style-premium","path":"/spb/style/premium","segments":["style","premium"],"title":"Премиум анкеты в СПб","h1":"Премиум анкеты в Санкт-Петербурге","description":"Подборка artescort.vip в формате Премиум: профильные карточки, ручная проверка и отдельная проверка свободных слотов.","intent":"Город + тип","source":"seed-generated","filters":{"style":"Премиум"},"isIndexable":true},{"slug":"spb-style-vip","path":"/spb/style/vip","segments":["style","vip"],"title":"VIP анкеты в СПб","h1":"VIP анкеты в Санкт-Петербурге","description":"Подборка artescort.vip в формате VIP: профильные карточки, ручная проверка и отдельная проверка свободных слотов.","intent":"Город + тип","source":"seed-generated","filters":{"style":"VIP"},"isIndexable":true},{"slug":"spb-style-elite","path":"/spb/style/elite","segments":["style","elite"],"title":"Элит анкеты в СПб","h1":"Элит анкеты в Санкт-Петербурге","description":"Подборка artescort.vip в формате Элит: профильные карточки, ручная проверка и отдельная проверка свободных слотов.","intent":"Город + тип","source":"seed-generated","filters":{"style":"Элит"},"isIndexable":true},{"slug":"spb-style-new","path":"/spb/style/new","segments":["style","new"],"title":"Новые анкеты в СПб","h1":"Новые анкеты в Санкт-Петербурге","description":"Подборка artescort.vip в формате Новые: профильные карточки, ручная проверка и отдельная проверка свободных слотов.","intent":"Город + тип","source":"seed-generated","filters":{"style":"Новые"},"isIndexable":true},{"slug":"spb-status-available","path":"/spb/status/available","segments":["status","available"],"title":"анкеты на месте в СПб","h1":"анкеты на месте в Санкт-Петербурге","description":"Страница под статус на месте: каталог artescort.vip показывает seed-статус, а реальные слоты проверяются отдельно.","intent":"Город + статус","source":"seed-generated","filters":{"status":"available"},"isIndexable":true},{"slug":"spb-status-tonight","path":"/spb/status/tonight","segments":["status","tonight"],"title":"анкеты на сегодня в СПб","h1":"анкеты на сегодня в Санкт-Петербурге","description":"Страница под статус сегодня: каталог artescort.vip показывает seed-статус, а реальные слоты проверяются отдельно.","intent":"Город + статус","source":"seed-generated","filters":{"status":"tonight"},"isIndexable":true},{"slug":"spb-status-request","path":"/spb/status/request","segments":["status","request"],"title":"анкеты по запросу в СПб","h1":"анкеты по запросу в Санкт-Петербурге","description":"Страница под статус по запросу: каталог artescort.vip показывает seed-статус, а реальные слоты проверяются отдельно.","intent":"Город + статус","source":"seed-generated","filters":{"status":"private"},"isIndexable":true},{"slug":"spb-age-18-25","path":"/spb/age/18-25","segments":["age","18-25"],"title":"Анкеты 18-25 в СПб","h1":"Анкеты 18-25 в Санкт-Петербурге","description":"Возрастная SEO-подборка artescort.vip 18-25: анкеты из seed-каталога, быстрые CTA и отдельное расписание.","intent":"Город + возраст","source":"seed-generated","filters":{"ageMin":18,"ageMax":25},"isIndexable":true},{"slug":"spb-age-26-35","path":"/spb/age/26-35","segments":["age","26-35"],"title":"Анкеты 26-35 в СПб","h1":"Анкеты 26-35 в Санкт-Петербурге","description":"Возрастная SEO-подборка artescort.vip 26-35: анкеты из seed-каталога, быстрые CTA и отдельное расписание.","intent":"Город + возраст","source":"seed-generated","filters":{"ageMin":26,"ageMax":35},"isIndexable":true},{"slug":"spb-premium-18-25","path":"/spb/premium/18-25","segments":["premium","18-25"],"title":"Премиум анкеты 18-25 в СПб","h1":"Премиум анкеты 18-25 в Санкт-Петербурге","description":"Комбинированная SEO-страница artescort.vip: Премиум, возраст 18-25, проверенные карточки и schedule-модуль отдельно.","intent":"Город + тип + возраст","source":"seed-generated","filters":{"style":"Премиум","ageMin":18,"ageMax":25},"isIndexable":true},{"slug":"spb-vip-26-35","path":"/spb/vip/26-35","segments":["vip","26-35"],"title":"VIP анкеты 26-35 в СПб","h1":"VIP анкеты 26-35 в Санкт-Петербурге","description":"Комбинированная SEO-страница artescort.vip: VIP, возраст 26-35, проверенные карточки и schedule-модуль отдельно.","intent":"Город + тип + возраст","source":"seed-generated","filters":{"style":"VIP","ageMin":26,"ageMax":35},"isIndexable":true},{"slug":"spb-private-18-25","path":"/spb/private/18-25","segments":["private","18-25"],"title":"Private анкеты 18-25 в СПб","h1":"Private анкеты 18-25 в Санкт-Петербурге","description":"Комбинированная SEO-страница artescort.vip: Private, возраст 18-25, проверенные карточки и schedule-модуль отдельно.","intent":"Город + тип + возраст","source":"seed-generated","filters":{"style":"Private","ageMin":18,"ageMax":25},"isIndexable":true},{"slug":"spb-private-26-35","path":"/spb/private/26-35","segments":["private","26-35"],"title":"Private анкеты 26-35 в СПб","h1":"Private анкеты 26-35 в Санкт-Петербурге","description":"Комбинированная SEO-страница artescort.vip: Private, возраст 26-35, проверенные карточки и schedule-модуль отдельно.","intent":"Город + тип + возраст","source":"seed-generated","filters":{"style":"Private","ageMin":26,"ageMax":35},"isIndexable":true},{"slug":"spb-elite-26-35","path":"/spb/elite/26-35","segments":["elite","26-35"],"title":"Элит анкеты 26-35 в СПб","h1":"Элит анкеты 26-35 в Санкт-Петербурге","description":"Комбинированная SEO-страница artescort.vip: Элит, возраст 26-35, проверенные карточки и schedule-модуль отдельно.","intent":"Город + тип + возраст","source":"seed-generated","filters":{"style":"Элит","ageMin":26,"ageMax":35},"isIndexable":true}]},"contractFailures":[]}},"deployment":{"version":"tzv3-deployment-v1","endpoint":"/api/infrastructure/deployment/policy","ciPolicyEndpoint":"/api/infrastructure/ci-policy","launchChecklistEndpoint":"/api/infrastructure/launch-checklist","ownerInputsEndpoint":"/api/infrastructure/owner-inputs","sourceControlEndpoint":"/api/infrastructure/source-control","vercelLinkEndpoint":"/api/infrastructure/vercel-link","platforms":{"vercel":{"config":"vercel.json","framework":"nextjs","buildCommand":"npm run build","node":">=20.9.0","productionChecks":["npm run vercel:env:plan","npm run secrets:rotation","npm run ci:audit","npm run github-ci:audit","npm run source:audit","npm run vercel:link:audit","npm run owner-inputs","curl -s https://your-domain.example/api/infrastructure/ci-policy","curl -s https://your-domain.example/api/infrastructure/source-control","curl -s https://your-domain.example/api/infrastructure/vercel-link","curl -s https://your-domain.example/api/infrastructure/public-origin-policy","curl -s https://your-domain.example/api/infrastructure/production-evidence","npm run vercel:env:apply-known -- --write --scope <scope> after confirming the linked Artesc website project","npm run env:check:production","npm run origin:audit -- --require-production","npm run evidence:audit -- --require-production","npm run vercel:env:audit","npm run typecheck","npm test","npm run lint","npm run build","npm audit --omit=dev","npm run preflight:production","npm run admin:audit","curl -s https://your-domain.example/api/database/audit-policy","npm run database:seed-payload","npm run database:audit","npm run telegram:handoff","curl -s https://your-domain.example/api/webhooks/telegram/setup-policy","npm run telegram:audit","npm run club:handoff","curl -s https://your-domain.example/api/club/handoff-policy","npm run club:audit","npm run legal:audit","npm run reviews:audit","npm run media:public-urls","npm run schedule:provider-handoff","npm run schedule:provider-import-payload","npm run schedule:provider-reconciliation -- --require-production","npm run schedule:links:audit","npm run schedule:audit","npm run media:audit","npm run pwa-push:audit","npm run search:bulk-payload","npm run search:audit","npm run vitals:audit","npm run cloudflare:audit","TZV3_BASE_URL=https://your-domain.example npm run readiness","TZV3_BASE_URL=https://your-domain.example npm run seo:audit","TZV3_BASE_URL=https://your-domain.example npm run load:smoke"]},"netlify":{"config":"netlify.toml","buildCommand":"npm run build","plugin":"@netlify/plugin-nextjs"}},"scripts":{"envCheck":true,"productionEnvCheck":true,"vercelLinkAudit":true,"vercelEnvAudit":true,"vercelEnvPlan":true,"vercelEnvApplyKnown":true,"adminAudit":true,"ciAudit":true,"githubCiAudit":true,"cloudflareAudit":true,"clubAudit":true,"clubHandoff":true,"databaseAudit":true,"databaseSeedPayload":true,"evidenceAudit":true,"mediaAudit":true,"mediaPublicUrls":true,"originAudit":true,"ownerInputs":true,"legalAudit":true,"pwaPushAudit":true,"preflight":true,"productionPreflight":true,"readiness":true,"reviewsAudit":true,"scheduleAudit":true,"scheduleLinksAudit":true,"scheduleProviderHandoff":true,"scheduleProviderImportPayload":true,"scheduleProviderReconciliation":true,"searchBulkPayload":true,"searchAudit":true,"secretsRotation":true,"seoAudit":true,"sourceAudit":true,"telegramAudit":true,"telegramHandoff":true,"vitalsAudit":true,"loadSmoke":true},"environment":{"required":[{"name":"NEXT_PUBLIC_SITE_URL","purpose":"Canonical public domain for metadata, sitemap, structured data, and readiness checks","requiredForProduction":true,"configured":true,"placeholder":false},{"name":"NEXT_PUBLIC_SCHEDULE_URL","purpose":"Public link to the separate scheduling module","requiredForProduction":true,"configured":true,"placeholder":false},{"name":"DATABASE_URL","purpose":"PostgreSQL catalog/admin/status persistence","requiredForProduction":true,"configured":false,"placeholder":false},{"name":"ADMIN_API_TOKEN","purpose":"Protected admin write and seed API access","requiredForProduction":true,"configured":false,"placeholder":false},{"name":"ADMIN_SESSION_SECRET","purpose":"Signed HttpOnly admin UI session cookies","requiredForProduction":true,"configured":false,"placeholder":false},{"name":"TELEGRAM_WEBHOOK_SECRET","purpose":"Telegram live-status webhook authentication","requiredForProduction":true,"configured":false,"placeholder":false},{"name":"VIP_CLUB_WEBHOOK_URL","purpose":"Telegram workflow forwarding for VIP verification","requiredForProduction":true,"configured":false,"placeholder":false},{"name":"VIP_CLUB_WEBHOOK_TOKEN","purpose":"Bearer token and HMAC signing secret for VIP Club workflow forwarding","requiredForProduction":true,"configured":false,"placeholder":false},{"name":"LEGAL_CONTACT_EMAIL","purpose":"Dedicated legal/contact inbox for takedown, deletion, and data-subject requests","requiredForProduction":true,"configured":false,"placeholder":false},{"name":"ELASTICSEARCH_URL","purpose":"Elastic Cloud instant search","requiredForProduction":true,"configured":false,"placeholder":false},{"name":"ELASTICSEARCH_API_KEY","purpose":"Elastic Cloud API key for server-side search","requiredForProduction":true,"configured":false,"placeholder":false},{"name":"UPSTASH_REDIS_REST_URL","purpose":"Upstash Redis REST endpoint for search cache and rate-limit state","requiredForProduction":true,"configured":false,"placeholder":false},{"name":"UPSTASH_REDIS_REST_TOKEN","purpose":"Upstash Redis REST token for search cache and rate-limit state","requiredForProduction":true,"configured":false,"placeholder":false},{"name":"NEXT_PUBLIC_MEDIA_CDN_URL","purpose":"Public CDN base URL for catalog images and video visits","requiredForProduction":true,"configured":false,"placeholder":false},{"name":"CLOUDFLARE_R2_BUCKET","purpose":"Production media storage","requiredForProduction":true,"configured":false,"placeholder":false},{"name":"CLOUDFLARE_R2_ACCESS_KEY_ID","purpose":"Cloudflare R2 media storage access key id","requiredForProduction":true,"configured":false,"placeholder":false},{"name":"CLOUDFLARE_R2_SECRET_ACCESS_KEY","purpose":"Cloudflare R2 media storage secret access key","requiredForProduction":true,"configured":false,"placeholder":false},{"name":"WEB_VITALS_ENDPOINT_URL","purpose":"Production browser Web Vitals sink","requiredForProduction":true,"configured":false,"placeholder":false}],"optional":[{"name":"SCHEDULE_API_URL","purpose":"Optional server-side forwarding to the separate schedule service when it exposes availability/request endpoints","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"SCHEDULE_API_TOKEN","purpose":"Bearer token for server-to-server schedule calls","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"SCHEDULE_AVAILABILITY_PATH","purpose":"Existing schedule API path for availability checks","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"SCHEDULE_REQUEST_PATH","purpose":"Existing schedule API path for request forwarding","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"NEXT_PUBLIC_SCHEDULE_PROJECT_URL","purpose":"Ready-made schedule project origin for iframe and widget integrations","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"NEXT_PUBLIC_SCHEDULE_EMBED_URL","purpose":"Ready-made schedule iframe URL without site/lang query params","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"NEXT_PUBLIC_SCHEDULE_WIDGET_URL","purpose":"Ready-made schedule widget script URL without site/lang query params","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"NEXT_PUBLIC_SCHEDULE_SITE","purpose":"Schedule tenant key, expected to be artesc in production","requiredForProduction":false,"configured":true,"placeholder":false},{"name":"NEXT_PUBLIC_SCHEDULE_LANG","purpose":"Default schedule language for iframe/widget rendering","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"OPENAI_API_KEY","purpose":"Approved SEO copy and Smart Match provider","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"OPENAI_MODEL","purpose":"Pinned OpenAI Responses API model for admin-reviewed SEO copy drafts","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"GOOGLE_TRANSLATE_API_KEY","purpose":"Approved production translation provider","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"ELASTICSEARCH_INDEX","purpose":"Elastic profile index name, defaults to profiles","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"ELASTICSEARCH_SEARCH_PATH","purpose":"Elastic search endpoint path, defaults to /{index}/_search","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"SEARCH_CACHE_TTL_SECONDS","purpose":"Upstash Redis TTL for repeated search results","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"MEDIA_AI_PROVIDER_URL","purpose":"Approved media enhancement provider","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"MEDIA_AI_PROVIDER_TOKEN","purpose":"Bearer token for the approved media enhancement provider","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"WEB_VITALS_ENDPOINT_TOKEN","purpose":"Bearer token for the production Web Vitals sink","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"NEXT_PUBLIC_VAPID_PUBLIC_KEY","purpose":"Browser public key for explicit PWA push subscription opt-in","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"PWA_PUSH_PROVIDER_URL","purpose":"Approved provider endpoint for storing explicit PushSubscription records","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"PWA_PUSH_PROVIDER_TOKEN","purpose":"Bearer token for the approved PWA push subscription provider","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"CLOUDFLARE_ACCOUNT_ID","purpose":"Cloudflare automation and mirror monitoring","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"CLOUDFLARE_ZONE_ID","purpose":"Cloudflare DNS/WAF zone","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"CLOUDFLARE_API_TOKEN","purpose":"Cloudflare API token for WAF, DNS, and mirror automation checks","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"PRIMARY_DOMAIN_CHECK_URL","purpose":"Canonical URL used by mirror and uptime checks","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"MIRROR_DOMAINS","purpose":"Comma-separated mirror domains for uptime checks","requiredForProduction":false,"configured":false,"placeholder":false},{"name":"MIRROR_TELEGRAM_ALERT_URL","purpose":"Telegram alert webhook for mirror and primary-domain monitoring","requiredForProduction":false,"configured":false,"placeholder":false}],"requiredMissing":["DATABASE_URL","ADMIN_API_TOKEN","ADMIN_SESSION_SECRET","TELEGRAM_WEBHOOK_SECRET","VIP_CLUB_WEBHOOK_URL","VIP_CLUB_WEBHOOK_TOKEN","LEGAL_CONTACT_EMAIL","ELASTICSEARCH_URL","ELASTICSEARCH_API_KEY","UPSTASH_REDIS_REST_URL","UPSTASH_REDIS_REST_TOKEN","NEXT_PUBLIC_MEDIA_CDN_URL","CLOUDFLARE_R2_BUCKET","CLOUDFLARE_R2_ACCESS_KEY_ID","CLOUDFLARE_R2_SECRET_ACCESS_KEY","WEB_VITALS_ENDPOINT_URL"],"optionalMissing":["SCHEDULE_API_URL","SCHEDULE_API_TOKEN","SCHEDULE_AVAILABILITY_PATH","SCHEDULE_REQUEST_PATH","NEXT_PUBLIC_SCHEDULE_PROJECT_URL","NEXT_PUBLIC_SCHEDULE_EMBED_URL","NEXT_PUBLIC_SCHEDULE_WIDGET_URL","NEXT_PUBLIC_SCHEDULE_LANG","OPENAI_API_KEY","OPENAI_MODEL","GOOGLE_TRANSLATE_API_KEY","ELASTICSEARCH_INDEX","ELASTICSEARCH_SEARCH_PATH","SEARCH_CACHE_TTL_SECONDS","MEDIA_AI_PROVIDER_URL","MEDIA_AI_PROVIDER_TOKEN","WEB_VITALS_ENDPOINT_TOKEN","NEXT_PUBLIC_VAPID_PUBLIC_KEY","PWA_PUSH_PROVIDER_URL","PWA_PUSH_PROVIDER_TOKEN","CLOUDFLARE_ACCOUNT_ID","CLOUDFLARE_ZONE_ID","CLOUDFLARE_API_TOKEN","PRIMARY_DOMAIN_CHECK_URL","MIRROR_DOMAINS","MIRROR_TELEGRAM_ALERT_URL"],"productionReady":false},"productionBoundary":["A green local readiness result does not imply production readiness.","Production requires real env values, not example placeholders or localhost URLs.","Run secrets:rotation before env writes so generated secrets, owner/provider credentials, public defaults, and post-rotation audits are separated without printing values.","Run ci:audit before env writes so GitHub Actions has a no-write TZV3 quality gate for push and pull_request on main.","Run github-ci:audit before production promotion so the hosted GitHub Actions TZV3 CI run is completed successfully on main.","Run source:audit before env writes so the website source repository is GitHub parkourcafe/artesc, not a schedule-project repository.","Run vercel:link:audit before launch so local .vercel/project.json cannot point to the protected schedule project.","Run env:check:production before setting a deployment live.","Confirm /api/infrastructure/vercel-link is linked to the Artesc website project, not the protected schedule project.","Run origin:audit before launch so canonical domain, schedule link, media CDN, route URL proofs, and Vercel link status are checked together.","Run evidence:audit before launch so the no-write evidence plan covers every blocking launch stage and required deployed-domain command.","Run preflight:production with TZV3_BASE_URL before launch to execute the ordered local and production no-write gates.","Run admin:audit before launch so admin session policy, noindex shell, and anonymous rejection boundaries are verified without creating sessions.","Capture /api/database/audit-policy before running database:audit so the expected SELECT-only audit contract is recorded.","Run database:seed-payload before POST /api/admin/seed so the exact no-write static seed payload and hash are recorded.","Run database:audit before launch so required PostgreSQL tables, indexes, and seed baseline counts are verified with read-only queries.","Run telegram:handoff before telegram:audit so Telegram-native setWebhook secret_token, custom relay headers, and no-secret setup templates are confirmed.","Run telegram:audit before launch so the status webhook rejects bad tokens and invalid payloads without writes.","Run club:handoff before club:audit so the external VIP receiver headers, HMAC contract, idempotency, and human-approval boundary are confirmed without creating tickets.","Run club:audit before launch so VIP Club policy reports signed external-webhook forwarding without creating verification tickets.","Run legal:audit before launch so public legal pages, retention records, and a dedicated legal inbox are verified without submitting requests.","Run reviews:audit before launch so Review/AggregateRating JSON-LD is backed by real moderated PostgreSQL reviews without creating review intake.","Run media:public-urls before launch so media used by the catalog and external schedule provider drafts resolves to production-safe HTTPS URLs.","Run schedule:provider-handoff before launch so the external schedule admin/import has profile-mapped provider drafts for site=artesc.","Run schedule:provider-import-payload before launch so the external schedule admin/import receives a clean provider payload for site=artesc.","Run schedule:provider-reconciliation after import so public site=artesc providers match every Artesc profile slug before schedule:audit.","Run schedule:links:audit before launch so every profile CTA carries profile/site/lang into the ready-made schedule iframe.","Run schedule:audit before launch so the production schedule tenant has real providers, not only an empty iframe shell.","Run media:audit before launch so CDN delivery and Cloudflare R2 environment are verified without media writes.","Run pwa-push:audit before launch so VAPID, provider forwarding, and unsubscribe/delete evidence are verified without creating subscriptions.","Run search:bulk-payload before importing the Elastic profile index so settings, mappings, bulk NDJSON, and hashes are recorded.","Run search:audit before launch so Elastic and Upstash Redis are verified with read-only probes.","Run vitals:audit before launch so the approved Web Vitals sink is reachable without posting metrics.","Run Cloudflare audit, readiness, SEO audit, and load smoke against the deployed domain after DNS, database, schedule, and Telegram are connected.","Use /api/infrastructure/owner-inputs, /api/infrastructure/secret-rotation, and /api/infrastructure/launch-checklist as the owner-input, secret handoff, and evidence sequence before declaring TZV3 production-ready."]},"schedule":{"status":{"provider":"external-iframe","configured":true,"writable":false,"publicScheduleUrl":"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en","embed":{"provider":"external-iframe","projectUrl":"https://australia-wlkk.vercel.app","site":"artesc","lang":"en","embedUrl":"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en","widgetUrl":"https://australia-wlkk.vercel.app/api/scheduling/widget?site=artesc&lang=en","snippets":{"iframe":"<iframe\n  src=\"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en\"\n  style=\"width:100%; min-height:900px; border:0;\"\n  loading=\"lazy\"\n></iframe>","widget":"<div data-strand-scheduling data-site=\"artesc\" data-lang=\"en\"></div>\n<script\n  src=\"https://australia-wlkk.vercel.app/api/scheduling/widget?site=artesc&lang=en\"\n  async\n></script>"},"previewPath":"/schedule-preview","draftTestSite":"site-next","productionNote":"site=artesc is the production target. Use site-next only for temporary visual checks while artesc providers are empty."},"install":{"ownership":"external-ready-made-schedule-project","preferredMode":"iframe","iframeHtml":"<iframe\n  src=\"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en\"\n  style=\"width:100%; min-height:900px; border:0;\"\n  loading=\"lazy\"\n></iframe>","widgetHtml":"<div data-strand-scheduling data-site=\"artesc\" data-lang=\"en\"></div>\n<script\n  src=\"https://australia-wlkk.vercel.app/api/scheduling/widget?site=artesc&lang=en\"\n  async\n></script>","draftQaUrl":"/schedule-preview?site=site-next&lang=en","productionQaUrl":"/schedule-preview?site=artesc&lang=en","productionDataGate":"Before launch, the ready-made schedule tenant site=artesc must return at least one real provider from /api/scheduling/public/providers."},"apiBaseUrl":null,"authConfigured":false,"serverApi":{"configured":false,"requiredForProduction":false,"mode":"optional-dry-run-fallback","note":"The ready-made schedule is connected through iframe/widget. SCHEDULE_API_URL is optional and is used only when the schedule provider exposes server-side availability/request endpoints."},"adapter":{"availabilityPath":"/availability","requestPath":"/requests","purpose":"Connects the already-built schedule service through iframe/widget; optional server API forwarding is available when the provider exposes it."},"endpoints":{"status":"/api/schedule/status","availability":"/api/schedule/availability?profile=sofia","request":"/api/schedule/request"}},"linkAuditPolicy":{"version":"tzv3-schedule-link-audit-v1","endpoint":"/api/schedule/link-audit-policy","command":"npm run schedule:links:audit","script":"scripts/tzv3-schedule-links-audit.mjs","configured":true,"schedule":{"provider":"external-ready-made-schedule-project","site":"artesc","lang":"en","projectUrl":"https://australia-wlkk.vercel.app","publicScheduleUrl":"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en","previewPath":"/schedule-preview","sampleProfilePreviewUrl":"/schedule-preview?site=artesc&lang=en&profile=sofia","serverApiRequiredForProduction":false},"summary":{"profileCount":8,"readyProfileLinks":8,"failedChecks":0},"productionReady":true,"productionBoundary":["This audit proves Artesc profile CTA links carry profile/site/lang into the ready-made schedule.","It does not prove the external schedule tenant has provider data; npm run schedule:audit remains the provider-count gate.","SCHEDULE_API_URL remains optional unless the schedule provider exposes server-side availability/request endpoints."],"safety":{"mode":"read-only","writes":false,"printsSecrets":false,"note":"Reads local schedule-link contracts and public pages only. It does not create schedule requests or modify the schedule project."},"profileLinks":[{"slug":"sofia","name":"София","status":"tonight","publicHref":"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=sofia","previewHref":"/schedule-preview?site=artesc&lang=en&profile=sofia","iframeHref":"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=sofia","availabilityApi":"/api/schedule/availability?profile=sofia","ready":true,"checks":[{"id":"public-href-absolute","ok":true,"detail":"Public CTA opens the external ready-made schedule URL."},{"id":"public-href-profile","ok":true,"detail":"Public CTA preserves the profile slug."},{"id":"public-href-site","ok":true,"detail":"Public CTA targets schedule tenant site=artesc."},{"id":"public-href-lang","ok":true,"detail":"Public CTA targets lang=en."},{"id":"preview-href-profile","ok":true,"detail":"Draft preview URL can render a profile-scoped iframe."},{"id":"iframe-href-profile","ok":true,"detail":"Iframe embed builder forwards profile to the ready-made schedule."},{"id":"availability-api-profile","ok":true,"detail":"Local availability API keeps the same profile slug for optional server-side forwarding."}]},{"slug":"mira","name":"Мира","status":"available","publicHref":"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=mira","previewHref":"/schedule-preview?site=artesc&lang=en&profile=mira","iframeHref":"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=mira","availabilityApi":"/api/schedule/availability?profile=mira","ready":true,"checks":[{"id":"public-href-absolute","ok":true,"detail":"Public CTA opens the external ready-made schedule URL."},{"id":"public-href-profile","ok":true,"detail":"Public CTA preserves the profile slug."},{"id":"public-href-site","ok":true,"detail":"Public CTA targets schedule tenant site=artesc."},{"id":"public-href-lang","ok":true,"detail":"Public CTA targets lang=en."},{"id":"preview-href-profile","ok":true,"detail":"Draft preview URL can render a profile-scoped iframe."},{"id":"iframe-href-profile","ok":true,"detail":"Iframe embed builder forwards profile to the ready-made schedule."},{"id":"availability-api-profile","ok":true,"detail":"Local availability API keeps the same profile slug for optional server-side forwarding."}]},{"slug":"vera","name":"Вера","status":"private","publicHref":"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=vera","previewHref":"/schedule-preview?site=artesc&lang=en&profile=vera","iframeHref":"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=vera","availabilityApi":"/api/schedule/availability?profile=vera","ready":true,"checks":[{"id":"public-href-absolute","ok":true,"detail":"Public CTA opens the external ready-made schedule URL."},{"id":"public-href-profile","ok":true,"detail":"Public CTA preserves the profile slug."},{"id":"public-href-site","ok":true,"detail":"Public CTA targets schedule tenant site=artesc."},{"id":"public-href-lang","ok":true,"detail":"Public CTA targets lang=en."},{"id":"preview-href-profile","ok":true,"detail":"Draft preview URL can render a profile-scoped iframe."},{"id":"iframe-href-profile","ok":true,"detail":"Iframe embed builder forwards profile to the ready-made schedule."},{"id":"availability-api-profile","ok":true,"detail":"Local availability API keeps the same profile slug for optional server-side forwarding."}]},{"slug":"lina","name":"Лина","status":"available","publicHref":"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=lina","previewHref":"/schedule-preview?site=artesc&lang=en&profile=lina","iframeHref":"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=lina","availabilityApi":"/api/schedule/availability?profile=lina","ready":true,"checks":[{"id":"public-href-absolute","ok":true,"detail":"Public CTA opens the external ready-made schedule URL."},{"id":"public-href-profile","ok":true,"detail":"Public CTA preserves the profile slug."},{"id":"public-href-site","ok":true,"detail":"Public CTA targets schedule tenant site=artesc."},{"id":"public-href-lang","ok":true,"detail":"Public CTA targets lang=en."},{"id":"preview-href-profile","ok":true,"detail":"Draft preview URL can render a profile-scoped iframe."},{"id":"iframe-href-profile","ok":true,"detail":"Iframe embed builder forwards profile to the ready-made schedule."},{"id":"availability-api-profile","ok":true,"detail":"Local availability API keeps the same profile slug for optional server-side forwarding."}]},{"slug":"ksenia","name":"Ксения","status":"tonight","publicHref":"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=ksenia","previewHref":"/schedule-preview?site=artesc&lang=en&profile=ksenia","iframeHref":"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=ksenia","availabilityApi":"/api/schedule/availability?profile=ksenia","ready":true,"checks":[{"id":"public-href-absolute","ok":true,"detail":"Public CTA opens the external ready-made schedule URL."},{"id":"public-href-profile","ok":true,"detail":"Public CTA preserves the profile slug."},{"id":"public-href-site","ok":true,"detail":"Public CTA targets schedule tenant site=artesc."},{"id":"public-href-lang","ok":true,"detail":"Public CTA targets lang=en."},{"id":"preview-href-profile","ok":true,"detail":"Draft preview URL can render a profile-scoped iframe."},{"id":"iframe-href-profile","ok":true,"detail":"Iframe embed builder forwards profile to the ready-made schedule."},{"id":"availability-api-profile","ok":true,"detail":"Local availability API keeps the same profile slug for optional server-side forwarding."}]},{"slug":"darina","name":"Дарина","status":"available","publicHref":"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=darina","previewHref":"/schedule-preview?site=artesc&lang=en&profile=darina","iframeHref":"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=darina","availabilityApi":"/api/schedule/availability?profile=darina","ready":true,"checks":[{"id":"public-href-absolute","ok":true,"detail":"Public CTA opens the external ready-made schedule URL."},{"id":"public-href-profile","ok":true,"detail":"Public CTA preserves the profile slug."},{"id":"public-href-site","ok":true,"detail":"Public CTA targets schedule tenant site=artesc."},{"id":"public-href-lang","ok":true,"detail":"Public CTA targets lang=en."},{"id":"preview-href-profile","ok":true,"detail":"Draft preview URL can render a profile-scoped iframe."},{"id":"iframe-href-profile","ok":true,"detail":"Iframe embed builder forwards profile to the ready-made schedule."},{"id":"availability-api-profile","ok":true,"detail":"Local availability API keeps the same profile slug for optional server-side forwarding."}]},{"slug":"emma","name":"Эмма","status":"private","publicHref":"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=emma","previewHref":"/schedule-preview?site=artesc&lang=en&profile=emma","iframeHref":"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=emma","availabilityApi":"/api/schedule/availability?profile=emma","ready":true,"checks":[{"id":"public-href-absolute","ok":true,"detail":"Public CTA opens the external ready-made schedule URL."},{"id":"public-href-profile","ok":true,"detail":"Public CTA preserves the profile slug."},{"id":"public-href-site","ok":true,"detail":"Public CTA targets schedule tenant site=artesc."},{"id":"public-href-lang","ok":true,"detail":"Public CTA targets lang=en."},{"id":"preview-href-profile","ok":true,"detail":"Draft preview URL can render a profile-scoped iframe."},{"id":"iframe-href-profile","ok":true,"detail":"Iframe embed builder forwards profile to the ready-made schedule."},{"id":"availability-api-profile","ok":true,"detail":"Local availability API keeps the same profile slug for optional server-side forwarding."}]},{"slug":"nikol","name":"Николь","status":"available","publicHref":"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=nikol","previewHref":"/schedule-preview?site=artesc&lang=en&profile=nikol","iframeHref":"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=nikol","availabilityApi":"/api/schedule/availability?profile=nikol","ready":true,"checks":[{"id":"public-href-absolute","ok":true,"detail":"Public CTA opens the external ready-made schedule URL."},{"id":"public-href-profile","ok":true,"detail":"Public CTA preserves the profile slug."},{"id":"public-href-site","ok":true,"detail":"Public CTA targets schedule tenant site=artesc."},{"id":"public-href-lang","ok":true,"detail":"Public CTA targets lang=en."},{"id":"preview-href-profile","ok":true,"detail":"Draft preview URL can render a profile-scoped iframe."},{"id":"iframe-href-profile","ok":true,"detail":"Iframe embed builder forwards profile to the ready-made schedule."},{"id":"availability-api-profile","ok":true,"detail":"Local availability API keeps the same profile slug for optional server-side forwarding."}]}],"failures":[]},"providerHandoffPolicy":{"version":"tzv3-schedule-provider-handoff-v1","endpoint":"/api/schedule/provider-handoff-policy","command":"npm run schedule:provider-handoff","script":"scripts/tzv3-schedule-provider-handoff.mjs","configured":true,"schedule":{"provider":"external-ready-made-schedule-project","projectUrl":"https://australia-wlkk.vercel.app","site":"artesc","lang":"en","providersEndpoint":"https://australia-wlkk.vercel.app/api/scheduling/public/providers?site=artesc","publicResponseFieldsObservedFromDemoTenant":["id","name","photoUrl","description","services","availability.providerId","availability.available","availability.state","availability.reason","availability.withinSchedule","availability.online","availability.busy","availability.windowStartMin","availability.windowEndMin"]},"summary":{"profileCount":8,"draftProviderCount":8,"contractReadyProviderCount":8,"productionImportReadyProviderCount":8,"contractFailureCount":0,"productionImportWarningCount":0},"contractReady":true,"productionImportReady":true,"productionBoundary":["This policy is a read-only handoff for creating real providers in the already-built schedule project.","It does not write to australia-wlkk and does not prove provider data exists; npm run schedule:audit remains the external provider-count gate.","Before import, replace placeholder/example media origins with production HTTPS media URLs that the schedule iframe can load."],"safety":{"mode":"read-only","writes":false,"printsSecrets":false,"note":"Builds provider draft records from the local Artesc catalog and prints no secret values. It never calls a schedule write endpoint."},"providerDrafts":[{"profileSlug":"sofia","profileName":"София","sourceProfilePath":"/profiles/sofia","schedulePreviewPath":"/schedule-preview?site=artesc&lang=en&profile=sofia","profileQuery":{"profile":"sofia","site":"artesc","lang":"en"},"provider":{"id":"sofia","name":"София","photoUrl":"https://www.artescort.vip/models/sofia.jpeg","description":"София выбирает камерные встречи, мягкий тон общения и аккуратный вечерний стиль.","services":["Премиум","Центр","NEW","Выезд"],"availability":{"providerId":"sofia","available":false,"state":"off","reason":"Awaiting real schedule slots for site=artesc.","withinSchedule":false,"online":false,"busy":false,"windowStartMin":null,"windowEndMin":null}},"contractReady":true,"productionImportReady":true,"checks":[{"id":"id-matches-profile","ok":true,"detail":"Provider id should match the Artesc profile slug used in profile=<slug> links."},{"id":"availability-provider-id-matches-profile","ok":true,"detail":"Availability providerId should use the same profile slug."},{"id":"name-present","ok":true,"detail":"Provider name is required by the public schedule card."},{"id":"description-present","ok":true,"detail":"Provider description is required for the schedule card."},{"id":"services-present","ok":true,"detail":"Provider services should be visible in the public schedule card."},{"id":"photo-url-production-ready","ok":true,"detail":"Photo URL should be HTTPS and production-hosted before importing into the external schedule."}]},{"profileSlug":"mira","profileName":"Мира","sourceProfilePath":"/profiles/mira","schedulePreviewPath":"/schedule-preview?site=artesc&lang=en&profile=mira","profileQuery":{"profile":"mira","site":"artesc","lang":"en"},"provider":{"id":"mira","name":"Мира","photoUrl":"https://www.artescort.vip/models/mira.jpeg","description":"Мира держит баланс между светской подачей и живым разговором, хорошо чувствует темп вечера.","services":["VIP","Петроградская","EN","На месте"],"availability":{"providerId":"mira","available":false,"state":"off","reason":"Awaiting real schedule slots for site=artesc.","withinSchedule":false,"online":false,"busy":false,"windowStartMin":null,"windowEndMin":null}},"contractReady":true,"productionImportReady":true,"checks":[{"id":"id-matches-profile","ok":true,"detail":"Provider id should match the Artesc profile slug used in profile=<slug> links."},{"id":"availability-provider-id-matches-profile","ok":true,"detail":"Availability providerId should use the same profile slug."},{"id":"name-present","ok":true,"detail":"Provider name is required by the public schedule card."},{"id":"description-present","ok":true,"detail":"Provider description is required for the schedule card."},{"id":"services-present","ok":true,"detail":"Provider services should be visible in the public schedule card."},{"id":"photo-url-production-ready","ok":true,"detail":"Photo URL should be HTTPS and production-hosted before importing into the external schedule."}]},{"profileSlug":"vera","profileName":"Вера","sourceProfilePath":"/profiles/vera","schedulePreviewPath":"/schedule-preview?site=artesc&lang=en&profile=vera","profileQuery":{"profile":"vera","site":"artesc","lang":"en"},"provider":{"id":"vera","name":"Вера","photoUrl":"https://www.artescort.vip/models/vera.jpeg","description":"Вера работает с приватными заявками, где важны пунктуальность, конфиденциальность и ясные договоренности.","services":["Private","Адмиралтейская","NEW","Центр"],"availability":{"providerId":"vera","available":false,"state":"off","reason":"Awaiting real schedule slots for site=artesc.","withinSchedule":false,"online":false,"busy":false,"windowStartMin":null,"windowEndMin":null}},"contractReady":true,"productionImportReady":true,"checks":[{"id":"id-matches-profile","ok":true,"detail":"Provider id should match the Artesc profile slug used in profile=<slug> links."},{"id":"availability-provider-id-matches-profile","ok":true,"detail":"Availability providerId should use the same profile slug."},{"id":"name-present","ok":true,"detail":"Provider name is required by the public schedule card."},{"id":"description-present","ok":true,"detail":"Provider description is required for the schedule card."},{"id":"services-present","ok":true,"detail":"Provider services should be visible in the public schedule card."},{"id":"photo-url-production-ready","ok":true,"detail":"Photo URL should be HTTPS and production-hosted before importing into the external schedule."}]},{"profileSlug":"lina","profileName":"Лина","sourceProfilePath":"/profiles/lina","schedulePreviewPath":"/schedule-preview?site=artesc&lang=en&profile=lina","profileQuery":{"profile":"lina","site":"artesc","lang":"en"},"provider":{"id":"lina","name":"Лина","photoUrl":"https://www.artescort.vip/models/sofia.jpeg","description":"Лина подходит для тех, кому важны легкость общения и аккуратная подача.","services":["Элит","Маяковская","NEW","Салон"],"availability":{"providerId":"lina","available":false,"state":"off","reason":"Awaiting real schedule slots for site=artesc.","withinSchedule":false,"online":false,"busy":false,"windowStartMin":null,"windowEndMin":null}},"contractReady":true,"productionImportReady":true,"checks":[{"id":"id-matches-profile","ok":true,"detail":"Provider id should match the Artesc profile slug used in profile=<slug> links."},{"id":"availability-provider-id-matches-profile","ok":true,"detail":"Availability providerId should use the same profile slug."},{"id":"name-present","ok":true,"detail":"Provider name is required by the public schedule card."},{"id":"description-present","ok":true,"detail":"Provider description is required for the schedule card."},{"id":"services-present","ok":true,"detail":"Provider services should be visible in the public schedule card."},{"id":"photo-url-production-ready","ok":true,"detail":"Photo URL should be HTTPS and production-hosted before importing into the external schedule."}]},{"profileSlug":"ksenia","profileName":"Ксения","sourceProfilePath":"/profiles/ksenia","schedulePreviewPath":"/schedule-preview?site=artesc&lang=en&profile=ksenia","profileQuery":{"profile":"ksenia","site":"artesc","lang":"en"},"provider":{"id":"ksenia","name":"Ксения","photoUrl":"https://www.artescort.vip/models/mira.jpeg","description":"Ксения сохраняет спокойный темп и внимательность к деталям встречи.","services":["Новые","Невский","NEW","EN","Вечер"],"availability":{"providerId":"ksenia","available":false,"state":"off","reason":"Awaiting real schedule slots for site=artesc.","withinSchedule":false,"online":false,"busy":false,"windowStartMin":null,"windowEndMin":null}},"contractReady":true,"productionImportReady":true,"checks":[{"id":"id-matches-profile","ok":true,"detail":"Provider id should match the Artesc profile slug used in profile=<slug> links."},{"id":"availability-provider-id-matches-profile","ok":true,"detail":"Availability providerId should use the same profile slug."},{"id":"name-present","ok":true,"detail":"Provider name is required by the public schedule card."},{"id":"description-present","ok":true,"detail":"Provider description is required for the schedule card."},{"id":"services-present","ok":true,"detail":"Provider services should be visible in the public schedule card."},{"id":"photo-url-production-ready","ok":true,"detail":"Photo URL should be HTTPS and production-hosted before importing into the external schedule."}]},{"profileSlug":"darina","profileName":"Дарина","sourceProfilePath":"/profiles/darina","schedulePreviewPath":"/schedule-preview?site=artesc&lang=en&profile=darina","profileQuery":{"profile":"darina","site":"artesc","lang":"en"},"provider":{"id":"darina","name":"Дарина","photoUrl":"https://www.artescort.vip/models/vera.jpeg","description":"Дарина лучше раскрывается в заранее согласованном формате без спешки.","services":["Премиум","Площадь Восстания","NEW","Центр","На месте"],"availability":{"providerId":"darina","available":false,"state":"off","reason":"Awaiting real schedule slots for site=artesc.","withinSchedule":false,"online":false,"busy":false,"windowStartMin":null,"windowEndMin":null}},"contractReady":true,"productionImportReady":true,"checks":[{"id":"id-matches-profile","ok":true,"detail":"Provider id should match the Artesc profile slug used in profile=<slug> links."},{"id":"availability-provider-id-matches-profile","ok":true,"detail":"Availability providerId should use the same profile slug."},{"id":"name-present","ok":true,"detail":"Provider name is required by the public schedule card."},{"id":"description-present","ok":true,"detail":"Provider description is required for the schedule card."},{"id":"services-present","ok":true,"detail":"Provider services should be visible in the public schedule card."},{"id":"photo-url-production-ready","ok":true,"detail":"Photo URL should be HTTPS and production-hosted before importing into the external schedule."}]},{"profileSlug":"emma","profileName":"Эмма","sourceProfilePath":"/profiles/emma","schedulePreviewPath":"/schedule-preview?site=artesc&lang=en&profile=emma","profileQuery":{"profile":"emma","site":"artesc","lang":"en"},"provider":{"id":"emma","name":"Эмма","photoUrl":"https://www.artescort.vip/models/mira.jpeg","description":"Эмма принимает только подтвержденные заявки и не публикует открытые слоты.","services":["Private","Чернышевская","EN","Центр"],"availability":{"providerId":"emma","available":false,"state":"off","reason":"Awaiting real schedule slots for site=artesc.","withinSchedule":false,"online":false,"busy":false,"windowStartMin":null,"windowEndMin":null}},"contractReady":true,"productionImportReady":true,"checks":[{"id":"id-matches-profile","ok":true,"detail":"Provider id should match the Artesc profile slug used in profile=<slug> links."},{"id":"availability-provider-id-matches-profile","ok":true,"detail":"Availability providerId should use the same profile slug."},{"id":"name-present","ok":true,"detail":"Provider name is required by the public schedule card."},{"id":"description-present","ok":true,"detail":"Provider description is required for the schedule card."},{"id":"services-present","ok":true,"detail":"Provider services should be visible in the public schedule card."},{"id":"photo-url-production-ready","ok":true,"detail":"Photo URL should be HTTPS and production-hosted before importing into the external schedule."}]},{"profileSlug":"nikol","profileName":"Николь","sourceProfilePath":"/profiles/nikol","schedulePreviewPath":"/schedule-preview?site=artesc&lang=en&profile=nikol","profileQuery":{"profile":"nikol","site":"artesc","lang":"en"},"provider":{"id":"nikol","name":"Николь","photoUrl":"https://www.artescort.vip/models/sofia.jpeg","description":"Николь держит уверенную подачу и аккуратно ведет коммуникацию.","services":["VIP","Гостиный двор","На месте","Центр"],"availability":{"providerId":"nikol","available":false,"state":"off","reason":"Awaiting real schedule slots for site=artesc.","withinSchedule":false,"online":false,"busy":false,"windowStartMin":null,"windowEndMin":null}},"contractReady":true,"productionImportReady":true,"checks":[{"id":"id-matches-profile","ok":true,"detail":"Provider id should match the Artesc profile slug used in profile=<slug> links."},{"id":"availability-provider-id-matches-profile","ok":true,"detail":"Availability providerId should use the same profile slug."},{"id":"name-present","ok":true,"detail":"Provider name is required by the public schedule card."},{"id":"description-present","ok":true,"detail":"Provider description is required for the schedule card."},{"id":"services-present","ok":true,"detail":"Provider services should be visible in the public schedule card."},{"id":"photo-url-production-ready","ok":true,"detail":"Photo URL should be HTTPS and production-hosted before importing into the external schedule."}]}],"contractFailures":[],"productionImportWarnings":[]},"providerImportPayload":{"version":"tzv3-schedule-provider-import-payload-v1","endpoint":"/api/schedule/provider-import-payload","command":"npm run schedule:provider-import-payload","script":"scripts/tzv3-schedule-provider-import-payload.mjs","configured":true,"sourcePolicyEndpoint":"/api/schedule/provider-handoff-policy","sourcePolicyCommand":"npm run schedule:provider-handoff","tenant":{"provider":"external-ready-made-schedule-project","projectUrl":"https://australia-wlkk.vercel.app","site":"artesc","lang":"en","providersEndpoint":"https://australia-wlkk.vercel.app/api/scheduling/public/providers?site=artesc","providerCountGate":"npm run schedule:audit"},"counts":{"profiles":8,"providers":8,"contractReadyProviders":8,"productionImportReadyProviders":8,"productionImportWarnings":0},"providerIds":["sofia","mira","vera","lina","ksenia","darina","emma","nikol"],"profileMappings":[{"profileSlug":"sofia","providerId":"sofia","sourceProfilePath":"/profiles/sofia","schedulePreviewPath":"/schedule-preview?site=artesc&lang=en&profile=sofia","profileQuery":{"profile":"sofia","site":"artesc","lang":"en"}},{"profileSlug":"mira","providerId":"mira","sourceProfilePath":"/profiles/mira","schedulePreviewPath":"/schedule-preview?site=artesc&lang=en&profile=mira","profileQuery":{"profile":"mira","site":"artesc","lang":"en"}},{"profileSlug":"vera","providerId":"vera","sourceProfilePath":"/profiles/vera","schedulePreviewPath":"/schedule-preview?site=artesc&lang=en&profile=vera","profileQuery":{"profile":"vera","site":"artesc","lang":"en"}},{"profileSlug":"lina","providerId":"lina","sourceProfilePath":"/profiles/lina","schedulePreviewPath":"/schedule-preview?site=artesc&lang=en&profile=lina","profileQuery":{"profile":"lina","site":"artesc","lang":"en"}},{"profileSlug":"ksenia","providerId":"ksenia","sourceProfilePath":"/profiles/ksenia","schedulePreviewPath":"/schedule-preview?site=artesc&lang=en&profile=ksenia","profileQuery":{"profile":"ksenia","site":"artesc","lang":"en"}},{"profileSlug":"darina","providerId":"darina","sourceProfilePath":"/profiles/darina","schedulePreviewPath":"/schedule-preview?site=artesc&lang=en&profile=darina","profileQuery":{"profile":"darina","site":"artesc","lang":"en"}},{"profileSlug":"emma","providerId":"emma","sourceProfilePath":"/profiles/emma","schedulePreviewPath":"/schedule-preview?site=artesc&lang=en&profile=emma","profileQuery":{"profile":"emma","site":"artesc","lang":"en"}},{"profileSlug":"nikol","providerId":"nikol","sourceProfilePath":"/profiles/nikol","schedulePreviewPath":"/schedule-preview?site=artesc&lang=en&profile=nikol","profileQuery":{"profile":"nikol","site":"artesc","lang":"en"}}],"providerImportPayload":[{"id":"sofia","name":"София","photoUrl":"https://www.artescort.vip/models/sofia.jpeg","description":"София выбирает камерные встречи, мягкий тон общения и аккуратный вечерний стиль.","services":["Премиум","Центр","NEW","Выезд"],"availability":{"providerId":"sofia","available":false,"state":"off","reason":"Awaiting real schedule slots for site=artesc.","withinSchedule":false,"online":false,"busy":false,"windowStartMin":null,"windowEndMin":null}},{"id":"mira","name":"Мира","photoUrl":"https://www.artescort.vip/models/mira.jpeg","description":"Мира держит баланс между светской подачей и живым разговором, хорошо чувствует темп вечера.","services":["VIP","Петроградская","EN","На месте"],"availability":{"providerId":"mira","available":false,"state":"off","reason":"Awaiting real schedule slots for site=artesc.","withinSchedule":false,"online":false,"busy":false,"windowStartMin":null,"windowEndMin":null}},{"id":"vera","name":"Вера","photoUrl":"https://www.artescort.vip/models/vera.jpeg","description":"Вера работает с приватными заявками, где важны пунктуальность, конфиденциальность и ясные договоренности.","services":["Private","Адмиралтейская","NEW","Центр"],"availability":{"providerId":"vera","available":false,"state":"off","reason":"Awaiting real schedule slots for site=artesc.","withinSchedule":false,"online":false,"busy":false,"windowStartMin":null,"windowEndMin":null}},{"id":"lina","name":"Лина","photoUrl":"https://www.artescort.vip/models/sofia.jpeg","description":"Лина подходит для тех, кому важны легкость общения и аккуратная подача.","services":["Элит","Маяковская","NEW","Салон"],"availability":{"providerId":"lina","available":false,"state":"off","reason":"Awaiting real schedule slots for site=artesc.","withinSchedule":false,"online":false,"busy":false,"windowStartMin":null,"windowEndMin":null}},{"id":"ksenia","name":"Ксения","photoUrl":"https://www.artescort.vip/models/mira.jpeg","description":"Ксения сохраняет спокойный темп и внимательность к деталям встречи.","services":["Новые","Невский","NEW","EN","Вечер"],"availability":{"providerId":"ksenia","available":false,"state":"off","reason":"Awaiting real schedule slots for site=artesc.","withinSchedule":false,"online":false,"busy":false,"windowStartMin":null,"windowEndMin":null}},{"id":"darina","name":"Дарина","photoUrl":"https://www.artescort.vip/models/vera.jpeg","description":"Дарина лучше раскрывается в заранее согласованном формате без спешки.","services":["Премиум","Площадь Восстания","NEW","Центр","На месте"],"availability":{"providerId":"darina","available":false,"state":"off","reason":"Awaiting real schedule slots for site=artesc.","withinSchedule":false,"online":false,"busy":false,"windowStartMin":null,"windowEndMin":null}},{"id":"emma","name":"Эмма","photoUrl":"https://www.artescort.vip/models/mira.jpeg","description":"Эмма принимает только подтвержденные заявки и не публикует открытые слоты.","services":["Private","Чернышевская","EN","Центр"],"availability":{"providerId":"emma","available":false,"state":"off","reason":"Awaiting real schedule slots for site=artesc.","withinSchedule":false,"online":false,"busy":false,"windowStartMin":null,"windowEndMin":null}},{"id":"nikol","name":"Николь","photoUrl":"https://www.artescort.vip/models/sofia.jpeg","description":"Николь держит уверенную подачу и аккуратно ведет коммуникацию.","services":["VIP","Гостиный двор","На месте","Центр"],"availability":{"providerId":"nikol","available":false,"state":"off","reason":"Awaiting real schedule slots for site=artesc.","withinSchedule":false,"online":false,"busy":false,"windowStartMin":null,"windowEndMin":null}}],"contractReady":true,"productionImportReady":true,"productionImportWarnings":[],"productionBoundary":["Copy providerImportPayload into the already-built schedule admin/import for site=artesc.","This endpoint does not write to australia-wlkk and does not prove the external tenant has provider data.","After import, run npm run schedule:audit and /api/schedule/tenant-status to prove site=artesc returns real providers.","Photo URLs should use production HTTPS media/CDN origins before importing providers into the external schedule."],"safety":{"mode":"read-only","writes":false,"printsSecrets":false,"note":"Exports only schedule provider records derived from public Artesc profile fields. It never calls a schedule write endpoint and never prints schedule admin credentials."},"contractFailures":[]}},"search":{"policy":{"version":"tzv3-search-v3","endpoint":"/api/search","policyEndpoint":"/api/search/policy","indexManifestEndpoint":"/api/search/index-manifest","auditCommand":"npm run search:audit","provider":"local-keyword-fallback","currentMode":"validated keyword search over active catalog payload","productionTarget":{"engine":"Elastic Cloud","index":"profiles","searchPath":"/{index}/_search","instantSearchTargetMs":150,"requiredEnvironment":["ELASTICSEARCH_URL","ELASTICSEARCH_API_KEY"]},"indexManifest":{"version":"tzv3-search-index-manifest-v1","endpoint":"/api/search/index-manifest","productionReady":true,"index":{"provider":"Elastic Cloud","name":"profiles","searchPath":"/{index}/_search","documentVersion":"tzv3-search-profile-document-v1","documentCount":8,"bulkAction":"index","idField":"slug"},"documentCount":8,"slugs":["sofia","mira","vera","lina","ksenia","darina","emma","nikol"],"hashes":{"settings":"53b7d72463b4b50d5223d5549c7b0dbe1a0eff185d821d02b257b638aad45fee","mappings":"af64be91ab32520c1b39b0b758137bbfbd6214e90d81e28086717ee51ee9f243","documents":"8f360482b07dc95c202fd8016a73393585c34dbcbb9608601b004afce4f2d864","fullIndexInput":"74defefad6ca9dd8a06313e0a4c9b69991ef65152583cbdef0631ca07e949b51"},"importEnvironment":["ELASTICSEARCH_URL","ELASTICSEARCH_API_KEY","ELASTICSEARCH_INDEX","ELASTICSEARCH_SEARCH_PATH","UPSTASH_REDIS_REST_URL","UPSTASH_REDIS_REST_TOKEN","SEARCH_CACHE_TTL_SECONDS"],"auditCommand":"npm run search:audit"},"cache":{"provider":"none-local","target":"Upstash Redis for hot filters and repeated search results","ttlSeconds":60,"requiredEnvironment":["UPSTASH_REDIS_REST_URL","UPSTASH_REDIS_REST_TOKEN"],"keyPrivacy":"cache keys are SHA-256 hashes of normalized query fields, not raw search text"},"adapter":{"configured":false,"routeRuntime":"server","elasticSearchBody":"multi_match over name, slug, city, district, style, mood, tags, languages, intro, details","resultContract":"Elastic hits must expose profile slug through _source.slug or fields.slug; /api/search returns only active catalog payloads","fallback":"If Elastic or Redis fails, /api/search degrades to database/static keyword search without storing the query.","audit":"search:audit performs read-only Elastic _search and Upstash Redis GET probes before production launch."},"semanticSearch":{"provider":"pending-approved-provider","endpoint":"/api/match","purpose":"intent parsing and embeddings ranking after moderation approval","requiredEnvironment":["OPENAI_API_KEY"]},"queryContract":{"fields":["q","city","style","status","limit"],"maxQueryLength":120,"maxLimit":100,"emptyQueryBehavior":"returns filtered catalog"},"privacy":{"storesPersonalQueriesLocally":false,"serverTrackingInLocalMode":false,"requiresAnalyticsApprovalBeforeQueryLogging":true}},"indexManifest":{"version":"tzv3-search-index-manifest-v1","endpoint":"/api/search/index-manifest","productionReady":true,"index":{"provider":"Elastic Cloud","name":"profiles","searchPath":"/{index}/_search","documentVersion":"tzv3-search-profile-document-v1","documentCount":8,"bulkAction":"index","idField":"slug"},"documentCount":8,"slugs":["sofia","mira","vera","lina","ksenia","darina","emma","nikol"],"hashes":{"settings":"53b7d72463b4b50d5223d5549c7b0dbe1a0eff185d821d02b257b638aad45fee","mappings":"af64be91ab32520c1b39b0b758137bbfbd6214e90d81e28086717ee51ee9f243","documents":"8f360482b07dc95c202fd8016a73393585c34dbcbb9608601b004afce4f2d864","fullIndexInput":"74defefad6ca9dd8a06313e0a4c9b69991ef65152583cbdef0631ca07e949b51"},"importEnvironment":["ELASTICSEARCH_URL","ELASTICSEARCH_API_KEY","ELASTICSEARCH_INDEX","ELASTICSEARCH_SEARCH_PATH","UPSTASH_REDIS_REST_URL","UPSTASH_REDIS_REST_TOKEN","SEARCH_CACHE_TTL_SECONDS"],"auditCommand":"npm run search:audit"},"bulkPayload":{"version":"tzv3-search-bulk-payload-v1","endpoint":"/api/search/bulk-payload","command":"npm run search:bulk-payload","script":"scripts/tzv3-search-bulk-payload.mjs","configured":true,"sourceManifestEndpoint":"/api/search/index-manifest","sourceManifestHash":"74defefad6ca9dd8a06313e0a4c9b69991ef65152583cbdef0631ca07e949b51","elastic":{"provider":"Elastic Cloud","index":"profiles","createIndexPath":"/profiles","bulkPath":"/_bulk","bulkAction":"index","idField":"slug","contentType":"application/x-ndjson"},"counts":{"documents":8,"bulkLines":16,"slugs":8},"slugs":["sofia","mira","vera","lina","ksenia","darina","emma","nikol"],"hashes":{"createIndexRequest":"728d067b4f99ba828892d2c8719f20f681a007f642952754c74e043fd472c98d","bulkNdjson":"2ca2d741e8e5724aeff0282d161b2c64fa82b94b21b0a21665b8dcf4510978e0","sourceDocuments":"8f360482b07dc95c202fd8016a73393585c34dbcbb9608601b004afce4f2d864","sourceManifest":"74defefad6ca9dd8a06313e0a4c9b69991ef65152583cbdef0631ca07e949b51"},"createIndexRequest":{"settings":{"number_of_shards":1,"number_of_replicas":1,"analysis":{"analyzer":{"profile_text":{"type":"custom","tokenizer":"standard","filter":["lowercase","asciifolding"]}},"normalizer":{"lowercase_keyword":{"type":"custom","filter":["lowercase","asciifolding"]}}}},"mappings":{"dynamic":"strict","properties":{"version":{"type":"keyword"},"id":{"type":"keyword"},"slug":{"type":"keyword"},"name":{"type":"text","analyzer":"profile_text","fields":{"keyword":{"type":"keyword","normalizer":"lowercase_keyword"}}},"age":{"type":"short"},"city":{"type":"text","analyzer":"profile_text","fields":{"keyword":{"type":"keyword","normalizer":"lowercase_keyword"}}},"district":{"type":"text","analyzer":"profile_text","fields":{"keyword":{"type":"keyword","normalizer":"lowercase_keyword"}}},"status":{"type":"text","analyzer":"profile_text","fields":{"keyword":{"type":"keyword","normalizer":"lowercase_keyword"}}},"statusLabel":{"type":"text","analyzer":"profile_text","fields":{"keyword":{"type":"keyword","normalizer":"lowercase_keyword"}}},"style":{"type":"text","analyzer":"profile_text","fields":{"keyword":{"type":"keyword","normalizer":"lowercase_keyword"}}},"mood":{"type":"text","analyzer":"profile_text","fields":{"keyword":{"type":"keyword","normalizer":"lowercase_keyword"}}},"languages":{"type":"text","analyzer":"profile_text","fields":{"keyword":{"type":"keyword","normalizer":"lowercase_keyword"}}},"tags":{"type":"text","analyzer":"profile_text","fields":{"keyword":{"type":"keyword","normalizer":"lowercase_keyword"}}},"intro":{"type":"text","analyzer":"profile_text"},"details":{"type":"text","analyzer":"profile_text"},"rate":{"type":"keyword"},"profilePath":{"type":"keyword"},"canonicalUrl":{"type":"keyword"},"scheduleHref":{"type":"keyword","index":false},"isPublished":{"type":"boolean"},"isVip":{"type":"boolean"},"updatedAt":{"type":"date"},"facets":{"properties":{"city":{"type":"keyword","normalizer":"lowercase_keyword"},"style":{"type":"keyword","normalizer":"lowercase_keyword"},"status":{"type":"keyword"},"languages":{"type":"keyword","normalizer":"lowercase_keyword"},"tags":{"type":"keyword","normalizer":"lowercase_keyword"}}},"sort":{"properties":{"seedOrder":{"type":"integer"},"vipBoost":{"type":"byte"},"availableBoost":{"type":"byte"}}},"searchText":{"type":"text","analyzer":"profile_text"}}}},"bulkNdjson":"{\"index\":{\"_index\":\"profiles\",\"_id\":\"sofia\"}}\n{\"version\":\"tzv3-search-profile-document-v1\",\"id\":\"sofia\",\"slug\":\"sofia\",\"name\":\"София\",\"age\":23,\"city\":\"Санкт-Петербург\",\"district\":\"Центр\",\"status\":\"tonight\",\"statusLabel\":\"NEW\",\"style\":\"Премиум\",\"mood\":\"спокойная классика\",\"languages\":[\"EN\",\"RU\"],\"tags\":[\"Выезд\",\"Центр\",\"NEW\"],\"intro\":\"София выбирает камерные встречи, мягкий тон общения и аккуратный вечерний стиль.\",\"details\":[\"Анкета проходит ручную проверку перед публикацией в каталоге.\",\"Доступность и время встречи вынесены в отдельный модуль расписания.\",\"Для уточнения деталей используйте Telegram или заявку через расписание.\"],\"rate\":\"25000 ₽ 1 час\",\"profilePath\":\"/profiles/sofia\",\"canonicalUrl\":\"https://www.artescort.vip/profiles/sofia\",\"scheduleHref\":\"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=sofia\",\"isPublished\":true,\"isVip\":false,\"updatedAt\":\"2026-06-02T00:00:00.000Z\",\"facets\":{\"city\":\"Санкт-Петербург\",\"style\":\"Премиум\",\"status\":\"tonight\",\"languages\":[\"EN\",\"RU\"],\"tags\":[\"Выезд\",\"Центр\",\"NEW\"]},\"sort\":{\"seedOrder\":1,\"vipBoost\":0,\"availableBoost\":0},\"searchText\":\"София sofia Санкт-Петербург Центр Премиум спокойная классика NEW София выбирает камерные встречи, мягкий тон общения и аккуратный вечерний стиль. NEW Центр Выезд RU EN Анкета проходит ручную проверку перед публикацией в каталоге. Доступность и время встречи вынесены в отдельный модуль расписания. Для уточнения деталей используйте Telegram или заявку через расписание.\"}\n{\"index\":{\"_index\":\"profiles\",\"_id\":\"mira\"}}\n{\"version\":\"tzv3-search-profile-document-v1\",\"id\":\"mira\",\"slug\":\"mira\",\"name\":\"Мира\",\"age\":26,\"city\":\"Санкт-Петербург\",\"district\":\"Петроградская\",\"status\":\"available\",\"statusLabel\":\"На месте\",\"style\":\"VIP\",\"mood\":\"интеллигентная легкость\",\"languages\":[\"EN\",\"FR\",\"RU\"],\"tags\":[\"На месте\",\"EN\",\"VIP\"],\"intro\":\"Мира держит баланс между светской подачей и живым разговором, хорошо чувствует темп вечера.\",\"details\":[\"Анкета проходит ручную проверку перед публикацией в каталоге.\",\"Доступность и время встречи вынесены в отдельный модуль расписания.\",\"Для уточнения деталей используйте Telegram или заявку через расписание.\"],\"rate\":\"30000 ₽ 1 час\",\"profilePath\":\"/profiles/mira\",\"canonicalUrl\":\"https://www.artescort.vip/profiles/mira\",\"scheduleHref\":\"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=mira\",\"isPublished\":true,\"isVip\":true,\"updatedAt\":\"2026-06-02T00:00:00.000Z\",\"facets\":{\"city\":\"Санкт-Петербург\",\"style\":\"VIP\",\"status\":\"available\",\"languages\":[\"EN\",\"FR\",\"RU\"],\"tags\":[\"На месте\",\"EN\",\"VIP\"]},\"sort\":{\"seedOrder\":2,\"vipBoost\":1,\"availableBoost\":1},\"searchText\":\"Мира mira Санкт-Петербург Петроградская VIP интеллигентная легкость На месте Мира держит баланс между светской подачей и живым разговором, хорошо чувствует темп вечера. VIP EN На месте RU EN FR Анкета проходит ручную проверку перед публикацией в каталоге. Доступность и время встречи вынесены в отдельный модуль расписания. Для уточнения деталей используйте Telegram или заявку через расписание.\"}\n{\"index\":{\"_index\":\"profiles\",\"_id\":\"vera\"}}\n{\"version\":\"tzv3-search-profile-document-v1\",\"id\":\"vera\",\"slug\":\"vera\",\"name\":\"Вера\",\"age\":28,\"city\":\"Санкт-Петербург\",\"district\":\"Адмиралтейская\",\"status\":\"private\",\"statusLabel\":\"NEW\",\"style\":\"Private\",\"mood\":\"сдержанная уверенность\",\"languages\":[\"RU\"],\"tags\":[\"Центр\",\"NEW\",\"Private\"],\"intro\":\"Вера работает с приватными заявками, где важны пунктуальность, конфиденциальность и ясные договоренности.\",\"details\":[\"Анкета проходит ручную проверку перед публикацией в каталоге.\",\"Доступность и время встречи вынесены в отдельный модуль расписания.\",\"Для уточнения деталей используйте Telegram или заявку через расписание.\"],\"rate\":\"25000 ₽ 1 час\",\"profilePath\":\"/profiles/vera\",\"canonicalUrl\":\"https://www.artescort.vip/profiles/vera\",\"scheduleHref\":\"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=vera\",\"isPublished\":true,\"isVip\":false,\"updatedAt\":\"2026-06-02T00:00:00.000Z\",\"facets\":{\"city\":\"Санкт-Петербург\",\"style\":\"Private\",\"status\":\"private\",\"languages\":[\"RU\"],\"tags\":[\"Центр\",\"NEW\",\"Private\"]},\"sort\":{\"seedOrder\":3,\"vipBoost\":0,\"availableBoost\":0},\"searchText\":\"Вера vera Санкт-Петербург Адмиралтейская Private сдержанная уверенность NEW Вера работает с приватными заявками, где важны пунктуальность, конфиденциальность и ясные договоренности. NEW Private Центр RU Анкета проходит ручную проверку перед публикацией в каталоге. Доступность и время встречи вынесены в отдельный модуль расписания. Для уточнения деталей используйте Telegram или заявку через расписание.\"}\n{\"index\":{\"_index\":\"profiles\",\"_id\":\"lina\"}}\n{\"version\":\"tzv3-search-profile-document-v1\",\"id\":\"lina\",\"slug\":\"lina\",\"name\":\"Лина\",\"age\":28,\"city\":\"Санкт-Петербург\",\"district\":\"Маяковская\",\"status\":\"available\",\"statusLabel\":\"NEW\",\"style\":\"Элит\",\"mood\":\"яркая подача\",\"languages\":[\"RU\"],\"tags\":[\"Маяковская\",\"Салон\",\"NEW\"],\"intro\":\"Лина подходит для тех, кому важны легкость общения и аккуратная подача.\",\"details\":[\"Анкета проходит ручную проверку перед публикацией в каталоге.\",\"Доступность и время встречи вынесены в отдельный модуль расписания.\",\"Для уточнения деталей используйте Telegram или заявку через расписание.\"],\"rate\":\"20000 ₽ 1 час\",\"profilePath\":\"/profiles/lina\",\"canonicalUrl\":\"https://www.artescort.vip/profiles/lina\",\"scheduleHref\":\"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=lina\",\"isPublished\":true,\"isVip\":false,\"updatedAt\":\"2026-06-02T00:00:00.000Z\",\"facets\":{\"city\":\"Санкт-Петербург\",\"style\":\"Элит\",\"status\":\"available\",\"languages\":[\"RU\"],\"tags\":[\"Маяковская\",\"Салон\",\"NEW\"]},\"sort\":{\"seedOrder\":4,\"vipBoost\":0,\"availableBoost\":1},\"searchText\":\"Лина lina Санкт-Петербург Маяковская Элит яркая подача NEW Лина подходит для тех, кому важны легкость общения и аккуратная подача. NEW Маяковская Салон RU Анкета проходит ручную проверку перед публикацией в каталоге. Доступность и время встречи вынесены в отдельный модуль расписания. Для уточнения деталей используйте Telegram или заявку через расписание.\"}\n{\"index\":{\"_index\":\"profiles\",\"_id\":\"ksenia\"}}\n{\"version\":\"tzv3-search-profile-document-v1\",\"id\":\"ksenia\",\"slug\":\"ksenia\",\"name\":\"Ксения\",\"age\":22,\"city\":\"Санкт-Петербург\",\"district\":\"Невский\",\"status\":\"tonight\",\"statusLabel\":\"NEW\",\"style\":\"Новые\",\"mood\":\"мягкая энергия\",\"languages\":[\"EN\",\"RU\"],\"tags\":[\"Вечер\",\"EN\",\"NEW\"],\"intro\":\"Ксения сохраняет спокойный темп и внимательность к деталям встречи.\",\"details\":[\"Анкета проходит ручную проверку перед публикацией в каталоге.\",\"Доступность и время встречи вынесены в отдельный модуль расписания.\",\"Для уточнения деталей используйте Telegram или заявку через расписание.\"],\"rate\":\"20000 ₽ 1 час\",\"profilePath\":\"/profiles/ksenia\",\"canonicalUrl\":\"https://www.artescort.vip/profiles/ksenia\",\"scheduleHref\":\"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=ksenia\",\"isPublished\":true,\"isVip\":false,\"updatedAt\":\"2026-06-02T00:00:00.000Z\",\"facets\":{\"city\":\"Санкт-Петербург\",\"style\":\"Новые\",\"status\":\"tonight\",\"languages\":[\"EN\",\"RU\"],\"tags\":[\"Вечер\",\"EN\",\"NEW\"]},\"sort\":{\"seedOrder\":5,\"vipBoost\":0,\"availableBoost\":0},\"searchText\":\"Ксения ksenia Санкт-Петербург Невский Новые мягкая энергия NEW Ксения сохраняет спокойный темп и внимательность к деталям встречи. NEW EN Вечер RU EN Анкета проходит ручную проверку перед публикацией в каталоге. Доступность и время встречи вынесены в отдельный модуль расписания. Для уточнения деталей используйте Telegram или заявку через расписание.\"}\n{\"index\":{\"_index\":\"profiles\",\"_id\":\"darina\"}}\n{\"version\":\"tzv3-search-profile-document-v1\",\"id\":\"darina\",\"slug\":\"darina\",\"name\":\"Дарина\",\"age\":23,\"city\":\"Санкт-Петербург\",\"district\":\"Площадь Восстания\",\"status\":\"available\",\"statusLabel\":\"NEW\",\"style\":\"Премиум\",\"mood\":\"деликатный формат\",\"languages\":[\"RU\"],\"tags\":[\"На месте\",\"Центр\",\"NEW\"],\"intro\":\"Дарина лучше раскрывается в заранее согласованном формате без спешки.\",\"details\":[\"Анкета проходит ручную проверку перед публикацией в каталоге.\",\"Доступность и время встречи вынесены в отдельный модуль расписания.\",\"Для уточнения деталей используйте Telegram или заявку через расписание.\"],\"rate\":\"15000 ₽ 1 час\",\"profilePath\":\"/profiles/darina\",\"canonicalUrl\":\"https://www.artescort.vip/profiles/darina\",\"scheduleHref\":\"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=darina\",\"isPublished\":true,\"isVip\":false,\"updatedAt\":\"2026-06-02T00:00:00.000Z\",\"facets\":{\"city\":\"Санкт-Петербург\",\"style\":\"Премиум\",\"status\":\"available\",\"languages\":[\"RU\"],\"tags\":[\"На месте\",\"Центр\",\"NEW\"]},\"sort\":{\"seedOrder\":6,\"vipBoost\":0,\"availableBoost\":1},\"searchText\":\"Дарина darina Санкт-Петербург Площадь Восстания Премиум деликатный формат NEW Дарина лучше раскрывается в заранее согласованном формате без спешки. NEW Центр На месте RU Анкета проходит ручную проверку перед публикацией в каталоге. Доступность и время встречи вынесены в отдельный модуль расписания. Для уточнения деталей используйте Telegram или заявку через расписание.\"}\n{\"index\":{\"_index\":\"profiles\",\"_id\":\"emma\"}}\n{\"version\":\"tzv3-search-profile-document-v1\",\"id\":\"emma\",\"slug\":\"emma\",\"name\":\"Эмма\",\"age\":24,\"city\":\"Санкт-Петербург\",\"district\":\"Чернышевская\",\"status\":\"private\",\"statusLabel\":\"По запросу\",\"style\":\"Private\",\"mood\":\"камерный вечер\",\"languages\":[\"EN\",\"RU\"],\"tags\":[\"Центр\",\"EN\",\"Private\"],\"intro\":\"Эмма принимает только подтвержденные заявки и не публикует открытые слоты.\",\"details\":[\"Анкета проходит ручную проверку перед публикацией в каталоге.\",\"Доступность и время встречи вынесены в отдельный модуль расписания.\",\"Для уточнения деталей используйте Telegram или заявку через расписание.\"],\"rate\":\"25000 ₽ 1 час\",\"profilePath\":\"/profiles/emma\",\"canonicalUrl\":\"https://www.artescort.vip/profiles/emma\",\"scheduleHref\":\"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=emma\",\"isPublished\":true,\"isVip\":false,\"updatedAt\":\"2026-06-02T00:00:00.000Z\",\"facets\":{\"city\":\"Санкт-Петербург\",\"style\":\"Private\",\"status\":\"private\",\"languages\":[\"EN\",\"RU\"],\"tags\":[\"Центр\",\"EN\",\"Private\"]},\"sort\":{\"seedOrder\":7,\"vipBoost\":0,\"availableBoost\":0},\"searchText\":\"Эмма emma Санкт-Петербург Чернышевская Private камерный вечер По запросу Эмма принимает только подтвержденные заявки и не публикует открытые слоты. Private EN Центр RU EN Анкета проходит ручную проверку перед публикацией в каталоге. Доступность и время встречи вынесены в отдельный модуль расписания. Для уточнения деталей используйте Telegram или заявку через расписание.\"}\n{\"index\":{\"_index\":\"profiles\",\"_id\":\"nikol\"}}\n{\"version\":\"tzv3-search-profile-document-v1\",\"id\":\"nikol\",\"slug\":\"nikol\",\"name\":\"Николь\",\"age\":26,\"city\":\"Санкт-Петербург\",\"district\":\"Гостиный двор\",\"status\":\"available\",\"statusLabel\":\"На месте\",\"style\":\"VIP\",\"mood\":\"уверенная классика\",\"languages\":[\"RU\"],\"tags\":[\"На месте\",\"Центр\",\"VIP\"],\"intro\":\"Николь держит уверенную подачу и аккуратно ведет коммуникацию.\",\"details\":[\"Анкета проходит ручную проверку перед публикацией в каталоге.\",\"Доступность и время встречи вынесены в отдельный модуль расписания.\",\"Для уточнения деталей используйте Telegram или заявку через расписание.\"],\"rate\":\"25000 ₽ 1 час\",\"profilePath\":\"/profiles/nikol\",\"canonicalUrl\":\"https://www.artescort.vip/profiles/nikol\",\"scheduleHref\":\"https://australia-wlkk.vercel.app/scheduling/embed?site=artesc&lang=en&profile=nikol\",\"isPublished\":true,\"isVip\":true,\"updatedAt\":\"2026-06-02T00:00:00.000Z\",\"facets\":{\"city\":\"Санкт-Петербург\",\"style\":\"VIP\",\"status\":\"available\",\"languages\":[\"RU\"],\"tags\":[\"На месте\",\"Центр\",\"VIP\"]},\"sort\":{\"seedOrder\":8,\"vipBoost\":1,\"availableBoost\":1},\"searchText\":\"Николь nikol Санкт-Петербург Гостиный двор VIP уверенная классика На месте Николь держит уверенную подачу и аккуратно ведет коммуникацию. VIP На месте Центр RU Анкета проходит ручную проверку перед публикацией в каталоге. Доступность и время встречи вынесены в отдельный модуль расписания. Для уточнения деталей используйте Telegram или заявку через расписание.\"}\n","contractReady":true,"productionImportReady":true,"productionBoundary":["Create or update the Elastic index with createIndexRequest before sending bulkNdjson.","Send bulkNdjson to the configured Elastic /_bulk endpoint with content-type application/x-ndjson.","This payload does not write to Elastic by itself and does not include ELASTICSEARCH_URL or ELASTICSEARCH_API_KEY.","After import, run npm run search:audit and query /api/search on the deployed domain."],"safety":{"mode":"read-only","writes":false,"printsSecrets":false,"note":"Serializes the Elastic create-index body and bulk NDJSON from public profile seed data. It never connects to Elastic or Redis and never prints credentials."},"contractFailures":[]}},"launchChecklist":{"version":"tzv3-launch-checklist-v1","endpoint":"/api/infrastructure/launch-checklist","summary":{"stages":14,"blockingStages":14,"requiredEnvironment":["NEXT_PUBLIC_SITE_URL","NEXT_PUBLIC_SCHEDULE_URL","DATABASE_URL","ADMIN_API_TOKEN","ADMIN_SESSION_SECRET","TELEGRAM_WEBHOOK_SECRET","VIP_CLUB_WEBHOOK_URL","VIP_CLUB_WEBHOOK_TOKEN","NEXT_PUBLIC_MEDIA_CDN_URL","CLOUDFLARE_R2_BUCKET","CLOUDFLARE_R2_ACCESS_KEY_ID","CLOUDFLARE_R2_SECRET_ACCESS_KEY","ELASTICSEARCH_URL","ELASTICSEARCH_API_KEY","UPSTASH_REDIS_REST_URL","UPSTASH_REDIS_REST_TOKEN","WEB_VITALS_ENDPOINT_URL","LEGAL_CONTACT_EMAIL"],"optionalEnvironment":["NEXT_PUBLIC_SCHEDULE_EMBED_URL","NEXT_PUBLIC_SCHEDULE_WIDGET_URL","NEXT_PUBLIC_SCHEDULE_SITE","NEXT_PUBLIC_SCHEDULE_LANG","SCHEDULE_API_URL","SCHEDULE_API_TOKEN","SCHEDULE_AVAILABILITY_PATH","SCHEDULE_REQUEST_PATH","ELASTICSEARCH_INDEX","NEXT_PUBLIC_VAPID_PUBLIC_KEY","PWA_PUSH_PROVIDER_URL","PWA_PUSH_PROVIDER_TOKEN","WEB_VITALS_ENDPOINT_TOKEN","CLOUDFLARE_ACCOUNT_ID","CLOUDFLARE_ZONE_ID","CLOUDFLARE_API_TOKEN","MIRROR_DOMAINS","MIRROR_TELEGRAM_ALERT_URL"],"ownerInputCount":52},"stages":[{"id":"domain","order":1,"title":"Canonical production domain","ownerInputs":["Final domain name","DNS or Cloudflare access","Final brand spelling"],"implementationSteps":["Set NEXT_PUBLIC_SITE_URL to the real HTTPS domain.","Confirm the website source repository is GitHub parkourcafe/artesc, not the ready-made schedule project repository.","Run npm run source:audit and open /api/infrastructure/source-control before Vercel env writes.","Run npm run ci:audit and open /api/infrastructure/ci-policy so GitHub Actions quality gates are present before launch.","Run npm run github-ci:audit after the latest push to capture hosted GitHub Actions success before production promotion.","Run vercel link against the confirmed Artesc website project, not australia-wlkk.","Run npm run vercel:link:audit and confirm the linked project is the Artesc website project before env writes.","Point DNS to the selected Vercel or Netlify project.","Open /api/infrastructure/public-origin-policy and confirm canonical domain, schedule URL, media CDN URL, route proofs, and Vercel link guard.","Verify canonical URLs, robots.txt, sitemap.xml, OpenGraph, and security headers."],"environment":["NEXT_PUBLIC_SITE_URL"],"verification":["npm run source:audit","npm run ci:audit","npm run github-ci:audit","npm run vercel:link:audit","npm run origin:audit -- --require-production","curl -s https://your-domain.example/api/infrastructure/source-control","curl -s https://your-domain.example/api/infrastructure/ci-policy","curl -s https://your-domain.example/api/infrastructure/public-origin-policy","curl -s https://your-domain.example/api/infrastructure/vercel-link","curl -s https://your-domain.example/robots.txt","curl -s https://your-domain.example/sitemap.xml","TZV3_BASE_URL=https://your-domain.example npm run seo:audit"],"blocksProduction":true},{"id":"schedule","order":2,"title":"Ready-made schedule connector","ownerInputs":["Public schedule URL","Schedule iframe URL","Schedule widget script URL","Schedule admin/import access for provider creation","Real providers attached to schedule tenant site=artesc","Schedule API base URL only if server-side availability/request forwarding is required","Schedule API token only if the optional server API requires auth","Availability and request endpoint paths only if the optional server API differs from defaults","Profile slug mapping used by the schedule service"],"implementationSteps":["Set NEXT_PUBLIC_SCHEDULE_URL for all public CTA links.","Set NEXT_PUBLIC_SCHEDULE_EMBED_URL or use the default australia-wlkk embed URL for /schedule-preview.","Keep NEXT_PUBLIC_SCHEDULE_SITE=artesc in production; use site-next only for temporary visual checks.","Open /api/schedule/provider-handoff-policy and create/update provider records in the ready-made schedule tenant with matching profile slugs.","Open /api/schedule/provider-import-payload and copy providerImportPayload into the ready-made schedule admin/import.","Attach real providers to site=artesc in the ready-made schedule project.","Run /api/schedule/provider-reconciliation to verify every imported provider id is visible in public site=artesc.","Optionally set SCHEDULE_API_URL, SCHEDULE_API_TOKEN, SCHEDULE_AVAILABILITY_PATH, and SCHEDULE_REQUEST_PATH when the schedule provider exposes server-side endpoints.","Verify provider handoff, provider import payload, provider reconciliation, profile-aware CTA links, /schedule-preview, npm run schedule:links:audit, npm run schedule:audit, and /api/schedule/status."],"environment":["NEXT_PUBLIC_SCHEDULE_URL","NEXT_PUBLIC_SCHEDULE_EMBED_URL","NEXT_PUBLIC_SCHEDULE_WIDGET_URL","NEXT_PUBLIC_SCHEDULE_SITE","NEXT_PUBLIC_SCHEDULE_LANG","SCHEDULE_API_URL","SCHEDULE_API_TOKEN","SCHEDULE_AVAILABILITY_PATH","SCHEDULE_REQUEST_PATH"],"verification":["npm run schedule:provider-handoff","npm run schedule:provider-import-payload","npm run schedule:provider-reconciliation -- --require-production","npm run schedule:links:audit","npm run schedule:audit","curl -s https://your-domain.example/api/schedule/provider-handoff-policy","curl -s https://your-domain.example/api/schedule/provider-import-payload","curl -s https://your-domain.example/api/schedule/provider-reconciliation","curl -s https://your-domain.example/api/schedule/link-audit-policy","curl -I https://your-domain.example/schedule-preview?site=artesc&lang=en","curl -s https://your-domain.example/api/schedule/tenant-status","curl -s https://your-domain.example/api/schedule/status","curl -s 'https://your-domain.example/api/schedule/availability?profile=sofia'"],"blocksProduction":true},{"id":"database","order":3,"title":"Production PostgreSQL and seed import","ownerInputs":["Supabase, Neon, or PostgreSQL DATABASE_URL","Decision on production region"],"implementationSteps":["Record /api/database/audit-policy, /api/database/migration-manifest, /api/database/seed-manifest, and /api/database/seed-payload before touching production data.","Run npm run database:seed-payload and confirm the no-write payload counts and fullSeed hash before POST /api/admin/seed.","Apply drizzle/0001_initial_tzv3.sql, drizzle/0002_review_author_alias.sql, and drizzle/0003_programmatic_seo_pages.sql.","Set DATABASE_URL in the hosting provider.","Run POST /api/admin/seed with x-admin-token.","Verify profile, media, services, collections, links, and programmatic SEO counts."],"environment":["DATABASE_URL","ADMIN_API_TOKEN"],"verification":["npm run database:seed-payload","npm run database:audit","curl -s https://your-domain.example/api/database/bootstrap-policy","curl -s https://your-domain.example/api/database/audit-policy","curl -s https://your-domain.example/api/database/seed-payload","curl -s https://your-domain.example/api/health","curl -s https://your-domain.example/api/profiles"],"blocksProduction":true},{"id":"admin-security","order":4,"title":"Admin secrets and audit","ownerInputs":["Permission to generate secrets or supplied ADMIN_API_TOKEN and ADMIN_SESSION_SECRET","Admin actor naming convention"],"implementationSteps":["Run npm run secrets:rotation and confirm generated Artesc secrets, owner/provider credentials, public defaults, and post-rotation audits are separated before env writes.","Set ADMIN_API_TOKEN and ADMIN_SESSION_SECRET.","Verify /admin session cookie behavior and protected admin endpoints.","Verify /admin/profiles keeps the profile editor locked until a signed HttpOnly admin session is active.","Verify admin audit logs are written after profile, seed, and moderation operations."],"environment":["ADMIN_API_TOKEN","ADMIN_SESSION_SECRET"],"verification":["npm run admin:audit","npm run secrets:rotation","curl -s https://your-domain.example/api/infrastructure/secret-rotation","curl -s https://your-domain.example/api/admin/session","curl -s https://your-domain.example/api/admin/security-audit-policy","Open https://your-domain.example/admin/profiles and confirm the editor is locked before login, then unlocked after POST /api/admin/session.","curl -s https://your-domain.example/api/admin/audit/policy"],"blocksProduction":true},{"id":"telegram-status","order":5,"title":"Telegram live-status workflow","ownerInputs":["Telegram bot token","TELEGRAM_WEBHOOK_SECRET","Operator chat or workflow IDs"],"implementationSteps":["Run npm run telegram:handoff and review the no-secret BotFather/setWebhook handoff.","Set TELEGRAM_WEBHOOK_SECRET.","For direct Telegram delivery, run setWebhook with secret_token so Telegram sends x-telegram-bot-api-secret-token.","For a custom relay workflow, forward x-webhook-token to POST /api/webhooks/telegram/status.","Forward either JSON payloads or raw Telegram message updates with /status commands.","Send x-telegram-bot-api-secret-token or x-webhook-token with every webhook request.","Verify DB-first status updates and browser SSE badges."],"environment":["TELEGRAM_WEBHOOK_SECRET","DATABASE_URL"],"verification":["npm run telegram:handoff","npm run telegram:audit","curl -s https://your-domain.example/api/webhooks/telegram/setup-policy","curl -s https://your-domain.example/api/webhooks/telegram/status","curl -s https://your-domain.example/api/status","curl -N --max-time 2 https://your-domain.example/api/status/stream"],"blocksProduction":true},{"id":"vip-club","order":6,"title":"VIP Club verification workflow","ownerInputs":["VIP Club Telegram workflow URL","VIP Club webhook signing token","Operator verification procedure"],"implementationSteps":["Run npm run club:handoff and review the no-secret external receiver contract.","Set VIP_CLUB_WEBHOOK_URL and VIP_CLUB_WEBHOOK_TOKEN.","Connect the receiver used by /api/club/verify.","Verify the receiver checks x-artesc-signature, x-artesc-timestamp, and x-idempotency-key.","Keep subscriptions and payments disabled until legal/payment approval is complete."],"environment":["VIP_CLUB_WEBHOOK_URL","VIP_CLUB_WEBHOOK_TOKEN"],"verification":["npm run club:handoff","npm run club:audit","curl -s https://your-domain.example/api/club/policy","curl -s https://your-domain.example/api/club/handoff-policy","curl -s https://your-domain.example/api/club/audit-policy","curl -I https://your-domain.example/club"],"blocksProduction":true},{"id":"media-cdn","order":7,"title":"Media storage and CDN delivery","ownerInputs":["NEXT_PUBLIC_MEDIA_CDN_URL","Cloudflare R2 bucket","R2 access key","R2 secret","Approved media upload workflow"],"implementationSteps":["Open /api/media/asset-manifest and use its publicPath, r2Key, contentType, bytes, and sha256 values as the upload contract.","Open /api/media/public-url-policy and confirm external consumers will receive production HTTPS media URLs, not example or localhost origins.","Upload public catalog images and videos to the CDN path structure from the manifest.","Set NEXT_PUBLIC_MEDIA_CDN_URL for catalog images and video visits.","Set Cloudflare R2 storage env for production media operations.","Verify Next/Image remote patterns and public profile images."],"environment":["NEXT_PUBLIC_MEDIA_CDN_URL","CLOUDFLARE_R2_BUCKET","CLOUDFLARE_R2_ACCESS_KEY_ID","CLOUDFLARE_R2_SECRET_ACCESS_KEY"],"verification":["npm run media:public-urls","npm run media:audit","curl -s https://your-domain.example/api/media/public-url-policy","curl -s https://your-domain.example/api/media/video-policy","curl -s https://your-domain.example/api/media/enhancement-policy","curl -s https://your-domain.example/api/media/asset-manifest"],"blocksProduction":true},{"id":"search-cache","order":8,"title":"Elastic search and Redis cache","ownerInputs":["Elastic URL","Elastic API key","Elastic profile index name","Upstash Redis REST URL","Upstash Redis REST token"],"implementationSteps":["Open /api/search/index-manifest and use its settings, mappings, document payload, and hashes as the index import contract.","Open /api/search/bulk-payload and use createIndexRequest plus bulkNdjson as the copy-ready Elastic import packet.","Create or sync the profile index in Elastic from the manifest.","Set ELASTICSEARCH_URL, ELASTICSEARCH_API_KEY, and ELASTICSEARCH_INDEX.","Set UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN for repeated-result cache.","Verify /api/search reports source elastic or elastic-cache."],"environment":["ELASTICSEARCH_URL","ELASTICSEARCH_API_KEY","ELASTICSEARCH_INDEX","UPSTASH_REDIS_REST_URL","UPSTASH_REDIS_REST_TOKEN"],"verification":["npm run search:bulk-payload","npm run search:audit","curl -s https://your-domain.example/api/search/policy","curl -s https://your-domain.example/api/search/index-manifest","curl -s https://your-domain.example/api/search/bulk-payload","curl -s 'https://your-domain.example/api/search?q=vip%20english'"],"blocksProduction":true},{"id":"reviews-seo","order":9,"title":"Real reviews and Review JSON-LD","ownerInputs":["At least one real moderated review","Admin moderation procedure","Decision to expose Review/AggregateRating JSON-LD"],"implementationSteps":["Collect real review intake through /api/reviews after PostgreSQL is connected.","Moderate reviews through protected /api/admin/reviews.","Publish only verified reviews with authorAlias, rating, text, source, and isPublished=true.","Keep synthetic, paid, duplicate, or unverifiable reviews unpublished and out of JSON-LD."],"environment":["DATABASE_URL","ADMIN_API_TOKEN"],"verification":["npm run reviews:audit","curl -s https://your-domain.example/api/reviews/policy","curl -s https://your-domain.example/api/reviews/audit-policy","curl -s https://your-domain.example/api/seo/review-schema"],"blocksProduction":true},{"id":"pwa-push","order":10,"title":"PWA push provider and unsubscribe evidence","ownerInputs":["Approved PWA push provider endpoint","VAPID public key","PWA push provider bearer token","Provider-side delete/export evidence before notification sends"],"implementationSteps":["Set NEXT_PUBLIC_VAPID_PUBLIC_KEY, PWA_PUSH_PROVIDER_URL, and PWA_PUSH_PROVIDER_TOKEN.","Keep PWA push limited to explicit /favorites opt-in and favorite-status notifications.","Confirm the provider accepts x-artesc-push-event, x-artesc-signature, and x-idempotency-key.","Run the no-write PWA push audit before enabling notification sends."],"environment":["NEXT_PUBLIC_VAPID_PUBLIC_KEY","PWA_PUSH_PROVIDER_URL","PWA_PUSH_PROVIDER_TOKEN"],"verification":["npm run pwa-push:audit","curl -s https://your-domain.example/api/pwa/push/policy","curl -s https://your-domain.example/api/pwa/push/audit-policy"],"blocksProduction":true},{"id":"analytics","order":11,"title":"Web Vitals and analytics sink","ownerInputs":["Approved analytics provider or endpoint","WEB_VITALS_ENDPOINT_URL","WEB_VITALS_ENDPOINT_TOKEN if required"],"implementationSteps":["Set WEB_VITALS_ENDPOINT_URL and optional WEB_VITALS_ENDPOINT_TOKEN.","Confirm provider privacy review and retention.","Verify that forwarded payloads drop href, userAgent, query, and hash."],"environment":["WEB_VITALS_ENDPOINT_URL","WEB_VITALS_ENDPOINT_TOKEN"],"verification":["npm run vitals:audit","curl -s https://your-domain.example/api/performance/vitals"],"blocksProduction":true},{"id":"legal","order":12,"title":"Legal pages and takedown contact","ownerInputs":["LEGAL_CONTACT_EMAIL","Final legal wording","Counsel approval for retention and takedown flow"],"implementationSteps":["Set LEGAL_CONTACT_EMAIL.","Review /legal, /legal/privacy, /legal/data-retention, and /legal/takedown.","Confirm /api/legal/contact-policy shows the dedicated inbox, local no-storage mode, request fields, and service-level targets.","Confirm retention policy and deletion procedure."],"environment":["LEGAL_CONTACT_EMAIL"],"verification":["npm run legal:audit","curl -s https://your-domain.example/legal","curl -s https://your-domain.example/api/legal/retention-policy","curl -s https://your-domain.example/api/legal/contact-policy","curl -s https://your-domain.example/api/legal/audit-policy"],"blocksProduction":true},{"id":"cloudflare","order":13,"title":"Cloudflare DNS, WAF, and monitoring","ownerInputs":["Cloudflare account ID","Zone ID","API token","Mirror domains if used","Telegram alert webhook if used"],"implementationSteps":["Proxy the production domain through Cloudflare.","Configure WAF, bot/rate-limit rules, cache rules, and TLS.","Set mirror monitoring variables when mirror domains are used."],"environment":["CLOUDFLARE_ACCOUNT_ID","CLOUDFLARE_ZONE_ID","CLOUDFLARE_API_TOKEN","MIRROR_DOMAINS","MIRROR_TELEGRAM_ALERT_URL"],"verification":["npm run cloudflare:audit","curl -s https://your-domain.example/api/infrastructure/cloudflare/policy","curl -s https://your-domain.example/api/security/policy","curl -s https://your-domain.example/api/infrastructure/mirrors/check"],"blocksProduction":true},{"id":"final-qa","order":14,"title":"Final deployed-domain QA","ownerInputs":["Deployed URL","Approval to run read-only checks against production"],"implementationSteps":["Run production env check.","Open /api/infrastructure/production-evidence and confirm every blocking stage has a no-write evidence command.","Run readiness, SEO audit, and load smoke on the deployed domain.","Manually verify homepage, profile page, schedule CTA, admin noindex, legal pages, and status badges.","Do not mark production ready until all required gates pass."],"environment":["NEXT_PUBLIC_SITE_URL","NEXT_PUBLIC_SCHEDULE_URL","DATABASE_URL","ADMIN_API_TOKEN","ADMIN_SESSION_SECRET","TELEGRAM_WEBHOOK_SECRET","VIP_CLUB_WEBHOOK_URL","VIP_CLUB_WEBHOOK_TOKEN","LEGAL_CONTACT_EMAIL","ELASTICSEARCH_URL","ELASTICSEARCH_API_KEY","UPSTASH_REDIS_REST_URL","UPSTASH_REDIS_REST_TOKEN","NEXT_PUBLIC_MEDIA_CDN_URL","CLOUDFLARE_R2_BUCKET","CLOUDFLARE_R2_ACCESS_KEY_ID","CLOUDFLARE_R2_SECRET_ACCESS_KEY","WEB_VITALS_ENDPOINT_URL"],"verification":["TZV3_BASE_URL=https://your-domain.example npm run preflight:production","npm run github-ci:audit","npm run secrets:rotation -- --require-production","npm run env:check:production","npm run origin:audit -- --require-production","npm run evidence:audit -- --require-production","curl -s https://your-domain.example/api/infrastructure/production-evidence","npm run admin:audit","npm run database:seed-payload","npm run database:audit","npm run cloudflare:audit","npm run media:public-urls","npm run media:audit","npm run pwa-push:audit","npm run legal:audit","npm run reviews:audit","npm run schedule:provider-handoff","npm run schedule:provider-import-payload","npm run schedule:provider-reconciliation -- --require-production","npm run schedule:links:audit","npm run schedule:audit","npm run search:bulk-payload","npm run search:audit","npm run telegram:handoff","npm run telegram:audit","npm run club:handoff","npm run vitals:audit","TZV3_BASE_URL=https://your-domain.example npm run readiness","TZV3_BASE_URL=https://your-domain.example npm run seo:audit","TZV3_BASE_URL=https://your-domain.example npm run load:smoke"],"blocksProduction":true}],"ownerInputs":["Final domain name","DNS or Cloudflare access","Final brand spelling","Public schedule URL","Schedule iframe URL","Schedule widget script URL","Schedule admin/import access for provider creation","Real providers attached to schedule tenant site=artesc","Schedule API base URL only if server-side availability/request forwarding is required","Schedule API token only if the optional server API requires auth","Availability and request endpoint paths only if the optional server API differs from defaults","Profile slug mapping used by the schedule service","Supabase, Neon, or PostgreSQL DATABASE_URL","Decision on production region","Permission to generate secrets or supplied ADMIN_API_TOKEN and ADMIN_SESSION_SECRET","Admin actor naming convention","Telegram bot token","TELEGRAM_WEBHOOK_SECRET","Operator chat or workflow IDs","VIP Club Telegram workflow URL","VIP Club webhook signing token","Operator verification procedure","NEXT_PUBLIC_MEDIA_CDN_URL","Cloudflare R2 bucket","R2 access key","R2 secret","Approved media upload workflow","Elastic URL","Elastic API key","Elastic profile index name","Upstash Redis REST URL","Upstash Redis REST token","At least one real moderated review","Admin moderation procedure","Decision to expose Review/AggregateRating JSON-LD","Approved PWA push provider endpoint","VAPID public key","PWA push provider bearer token","Provider-side delete/export evidence before notification sends","Approved analytics provider or endpoint","WEB_VITALS_ENDPOINT_URL","WEB_VITALS_ENDPOINT_TOKEN if required","LEGAL_CONTACT_EMAIL","Final legal wording","Counsel approval for retention and takedown flow","Cloudflare account ID","Zone ID","API token","Mirror domains if used","Telegram alert webhook if used","Deployed URL","Approval to run read-only checks against production"],"completionRule":"Production can be treated as TZV3-ready only after every blocking stage has real env/evidence on the deployed domain."},"productionGaps":{"version":"tzv3-production-gap-matrix-v1","missingRequiredEnvironment":["DATABASE_URL","ADMIN_API_TOKEN","ADMIN_SESSION_SECRET","TELEGRAM_WEBHOOK_SECRET","VIP_CLUB_WEBHOOK_URL","VIP_CLUB_WEBHOOK_TOKEN","LEGAL_CONTACT_EMAIL","ELASTICSEARCH_URL","ELASTICSEARCH_API_KEY","UPSTASH_REDIS_REST_URL","UPSTASH_REDIS_REST_TOKEN","NEXT_PUBLIC_MEDIA_CDN_URL","CLOUDFLARE_R2_BUCKET","CLOUDFLARE_R2_ACCESS_KEY_ID","CLOUDFLARE_R2_SECRET_ACCESS_KEY","WEB_VITALS_ENDPOINT_URL"],"missingOptionalEnvironment":["SCHEDULE_API_URL","SCHEDULE_API_TOKEN","SCHEDULE_AVAILABILITY_PATH","SCHEDULE_REQUEST_PATH","NEXT_PUBLIC_SCHEDULE_PROJECT_URL","NEXT_PUBLIC_SCHEDULE_EMBED_URL","NEXT_PUBLIC_SCHEDULE_WIDGET_URL","NEXT_PUBLIC_SCHEDULE_LANG","OPENAI_API_KEY","OPENAI_MODEL","GOOGLE_TRANSLATE_API_KEY","ELASTICSEARCH_INDEX","ELASTICSEARCH_SEARCH_PATH","SEARCH_CACHE_TTL_SECONDS","MEDIA_AI_PROVIDER_URL","MEDIA_AI_PROVIDER_TOKEN","WEB_VITALS_ENDPOINT_TOKEN","NEXT_PUBLIC_VAPID_PUBLIC_KEY","PWA_PUSH_PROVIDER_URL","PWA_PUSH_PROVIDER_TOKEN","CLOUDFLARE_ACCOUNT_ID","CLOUDFLARE_ZONE_ID","CLOUDFLARE_API_TOKEN","PRIMARY_DOMAIN_CHECK_URL","MIRROR_DOMAINS","MIRROR_TELEGRAM_ALERT_URL"],"summary":{"stages":14,"envBlockedStages":10,"evidenceBlockedStages":4,"missingRequiredEnvironmentCount":16,"missingOptionalEnvironmentCount":26,"nextActions":["npm run source:audit","npm run schedule:provider-handoff","Set DATABASE_URL, ADMIN_API_TOKEN","Set ADMIN_API_TOKEN, ADMIN_SESSION_SECRET","Set TELEGRAM_WEBHOOK_SECRET, DATABASE_URL"]},"stages":[{"id":"domain","order":1,"title":"Canonical production domain","status":"needs-deployed-evidence","missingRequiredEnvironment":[],"missingOptionalEnvironment":[],"ownerInputs":["Final domain name","DNS or Cloudflare access","Final brand spelling"],"verification":["npm run source:audit","npm run ci:audit","npm run github-ci:audit","npm run vercel:link:audit","npm run origin:audit -- --require-production","curl -s https://your-domain.example/api/infrastructure/source-control","curl -s https://your-domain.example/api/infrastructure/ci-policy","curl -s https://your-domain.example/api/infrastructure/public-origin-policy","curl -s https://your-domain.example/api/infrastructure/vercel-link","curl -s https://your-domain.example/robots.txt","curl -s https://your-domain.example/sitemap.xml","TZV3_BASE_URL=https://your-domain.example npm run seo:audit"],"nextAction":"npm run source:audit"},{"id":"schedule","order":2,"title":"Ready-made schedule connector","status":"needs-deployed-evidence","missingRequiredEnvironment":[],"missingOptionalEnvironment":["NEXT_PUBLIC_SCHEDULE_EMBED_URL","NEXT_PUBLIC_SCHEDULE_WIDGET_URL","NEXT_PUBLIC_SCHEDULE_LANG","SCHEDULE_API_URL","SCHEDULE_API_TOKEN","SCHEDULE_AVAILABILITY_PATH","SCHEDULE_REQUEST_PATH"],"ownerInputs":["Public schedule URL","Schedule iframe URL","Schedule widget script URL","Schedule admin/import access for provider creation","Real providers attached to schedule tenant site=artesc","Schedule API base URL only if server-side availability/request forwarding is required","Schedule API token only if the optional server API requires auth","Availability and request endpoint paths only if the optional server API differs from defaults","Profile slug mapping used by the schedule service"],"verification":["npm run schedule:provider-handoff","npm run schedule:provider-import-payload","npm run schedule:provider-reconciliation -- --require-production","npm run schedule:links:audit","npm run schedule:audit","curl -s https://your-domain.example/api/schedule/provider-handoff-policy","curl -s https://your-domain.example/api/schedule/provider-import-payload","curl -s https://your-domain.example/api/schedule/provider-reconciliation","curl -s https://your-domain.example/api/schedule/link-audit-policy","curl -I https://your-domain.example/schedule-preview?site=artesc&lang=en","curl -s https://your-domain.example/api/schedule/tenant-status","curl -s https://your-domain.example/api/schedule/status","curl -s 'https://your-domain.example/api/schedule/availability?profile=sofia'"],"nextAction":"npm run schedule:provider-handoff"},{"id":"database","order":3,"title":"Production PostgreSQL and seed import","status":"missing-required-env","missingRequiredEnvironment":["DATABASE_URL","ADMIN_API_TOKEN"],"missingOptionalEnvironment":[],"ownerInputs":["Supabase, Neon, or PostgreSQL DATABASE_URL","Decision on production region"],"verification":["npm run database:seed-payload","npm run database:audit","curl -s https://your-domain.example/api/database/bootstrap-policy","curl -s https://your-domain.example/api/database/audit-policy","curl -s https://your-domain.example/api/database/seed-payload","curl -s https://your-domain.example/api/health","curl -s https://your-domain.example/api/profiles"],"nextAction":"Set DATABASE_URL, ADMIN_API_TOKEN"},{"id":"admin-security","order":4,"title":"Admin secrets and audit","status":"missing-required-env","missingRequiredEnvironment":["ADMIN_API_TOKEN","ADMIN_SESSION_SECRET"],"missingOptionalEnvironment":[],"ownerInputs":["Permission to generate secrets or supplied ADMIN_API_TOKEN and ADMIN_SESSION_SECRET","Admin actor naming convention"],"verification":["npm run admin:audit","npm run secrets:rotation","curl -s https://your-domain.example/api/infrastructure/secret-rotation","curl -s https://your-domain.example/api/admin/session","curl -s https://your-domain.example/api/admin/security-audit-policy","Open https://your-domain.example/admin/profiles and confirm the editor is locked before login, then unlocked after POST /api/admin/session.","curl -s https://your-domain.example/api/admin/audit/policy"],"nextAction":"Set ADMIN_API_TOKEN, ADMIN_SESSION_SECRET"},{"id":"telegram-status","order":5,"title":"Telegram live-status workflow","status":"missing-required-env","missingRequiredEnvironment":["TELEGRAM_WEBHOOK_SECRET","DATABASE_URL"],"missingOptionalEnvironment":[],"ownerInputs":["Telegram bot token","TELEGRAM_WEBHOOK_SECRET","Operator chat or workflow IDs"],"verification":["npm run telegram:handoff","npm run telegram:audit","curl -s https://your-domain.example/api/webhooks/telegram/setup-policy","curl -s https://your-domain.example/api/webhooks/telegram/status","curl -s https://your-domain.example/api/status","curl -N --max-time 2 https://your-domain.example/api/status/stream"],"nextAction":"Set TELEGRAM_WEBHOOK_SECRET, DATABASE_URL"},{"id":"vip-club","order":6,"title":"VIP Club verification workflow","status":"missing-required-env","missingRequiredEnvironment":["VIP_CLUB_WEBHOOK_URL","VIP_CLUB_WEBHOOK_TOKEN"],"missingOptionalEnvironment":[],"ownerInputs":["VIP Club Telegram workflow URL","VIP Club webhook signing token","Operator verification procedure"],"verification":["npm run club:handoff","npm run club:audit","curl -s https://your-domain.example/api/club/policy","curl -s https://your-domain.example/api/club/handoff-policy","curl -s https://your-domain.example/api/club/audit-policy","curl -I https://your-domain.example/club"],"nextAction":"Set VIP_CLUB_WEBHOOK_URL, VIP_CLUB_WEBHOOK_TOKEN"},{"id":"media-cdn","order":7,"title":"Media storage and CDN delivery","status":"missing-required-env","missingRequiredEnvironment":["NEXT_PUBLIC_MEDIA_CDN_URL","CLOUDFLARE_R2_BUCKET","CLOUDFLARE_R2_ACCESS_KEY_ID","CLOUDFLARE_R2_SECRET_ACCESS_KEY"],"missingOptionalEnvironment":[],"ownerInputs":["NEXT_PUBLIC_MEDIA_CDN_URL","Cloudflare R2 bucket","R2 access key","R2 secret","Approved media upload workflow"],"verification":["npm run media:public-urls","npm run media:audit","curl -s https://your-domain.example/api/media/public-url-policy","curl -s https://your-domain.example/api/media/video-policy","curl -s https://your-domain.example/api/media/enhancement-policy","curl -s https://your-domain.example/api/media/asset-manifest"],"nextAction":"Set NEXT_PUBLIC_MEDIA_CDN_URL, CLOUDFLARE_R2_BUCKET, CLOUDFLARE_R2_ACCESS_KEY_ID..."},{"id":"search-cache","order":8,"title":"Elastic search and Redis cache","status":"missing-required-env","missingRequiredEnvironment":["ELASTICSEARCH_URL","ELASTICSEARCH_API_KEY","UPSTASH_REDIS_REST_URL","UPSTASH_REDIS_REST_TOKEN"],"missingOptionalEnvironment":["ELASTICSEARCH_INDEX"],"ownerInputs":["Elastic URL","Elastic API key","Elastic profile index name","Upstash Redis REST URL","Upstash Redis REST token"],"verification":["npm run search:bulk-payload","npm run search:audit","curl -s https://your-domain.example/api/search/policy","curl -s https://your-domain.example/api/search/index-manifest","curl -s https://your-domain.example/api/search/bulk-payload","curl -s 'https://your-domain.example/api/search?q=vip%20english'"],"nextAction":"Set ELASTICSEARCH_URL, ELASTICSEARCH_API_KEY, UPSTASH_REDIS_REST_URL..."},{"id":"reviews-seo","order":9,"title":"Real reviews and Review JSON-LD","status":"missing-required-env","missingRequiredEnvironment":["DATABASE_URL","ADMIN_API_TOKEN"],"missingOptionalEnvironment":[],"ownerInputs":["At least one real moderated review","Admin moderation procedure","Decision to expose Review/AggregateRating JSON-LD"],"verification":["npm run reviews:audit","curl -s https://your-domain.example/api/reviews/policy","curl -s https://your-domain.example/api/reviews/audit-policy","curl -s https://your-domain.example/api/seo/review-schema"],"nextAction":"Set DATABASE_URL, ADMIN_API_TOKEN"},{"id":"pwa-push","order":10,"title":"PWA push provider and unsubscribe evidence","status":"needs-deployed-evidence","missingRequiredEnvironment":[],"missingOptionalEnvironment":["NEXT_PUBLIC_VAPID_PUBLIC_KEY","PWA_PUSH_PROVIDER_URL","PWA_PUSH_PROVIDER_TOKEN"],"ownerInputs":["Approved PWA push provider endpoint","VAPID public key","PWA push provider bearer token","Provider-side delete/export evidence before notification sends"],"verification":["npm run pwa-push:audit","curl -s https://your-domain.example/api/pwa/push/policy","curl -s https://your-domain.example/api/pwa/push/audit-policy"],"nextAction":"npm run pwa-push:audit"},{"id":"analytics","order":11,"title":"Web Vitals and analytics sink","status":"missing-required-env","missingRequiredEnvironment":["WEB_VITALS_ENDPOINT_URL"],"missingOptionalEnvironment":["WEB_VITALS_ENDPOINT_TOKEN"],"ownerInputs":["Approved analytics provider or endpoint","WEB_VITALS_ENDPOINT_URL","WEB_VITALS_ENDPOINT_TOKEN if required"],"verification":["npm run vitals:audit","curl -s https://your-domain.example/api/performance/vitals"],"nextAction":"Set WEB_VITALS_ENDPOINT_URL"},{"id":"legal","order":12,"title":"Legal pages and takedown contact","status":"missing-required-env","missingRequiredEnvironment":["LEGAL_CONTACT_EMAIL"],"missingOptionalEnvironment":[],"ownerInputs":["LEGAL_CONTACT_EMAIL","Final legal wording","Counsel approval for retention and takedown flow"],"verification":["npm run legal:audit","curl -s https://your-domain.example/legal","curl -s https://your-domain.example/api/legal/retention-policy","curl -s https://your-domain.example/api/legal/contact-policy","curl -s https://your-domain.example/api/legal/audit-policy"],"nextAction":"Set LEGAL_CONTACT_EMAIL"},{"id":"cloudflare","order":13,"title":"Cloudflare DNS, WAF, and monitoring","status":"needs-deployed-evidence","missingRequiredEnvironment":[],"missingOptionalEnvironment":["CLOUDFLARE_ACCOUNT_ID","CLOUDFLARE_ZONE_ID","CLOUDFLARE_API_TOKEN","MIRROR_DOMAINS","MIRROR_TELEGRAM_ALERT_URL"],"ownerInputs":["Cloudflare account ID","Zone ID","API token","Mirror domains if used","Telegram alert webhook if used"],"verification":["npm run cloudflare:audit","curl -s https://your-domain.example/api/infrastructure/cloudflare/policy","curl -s https://your-domain.example/api/security/policy","curl -s https://your-domain.example/api/infrastructure/mirrors/check"],"nextAction":"npm run cloudflare:audit"},{"id":"final-qa","order":14,"title":"Final deployed-domain QA","status":"missing-required-env","missingRequiredEnvironment":["DATABASE_URL","ADMIN_API_TOKEN","ADMIN_SESSION_SECRET","TELEGRAM_WEBHOOK_SECRET","VIP_CLUB_WEBHOOK_URL","VIP_CLUB_WEBHOOK_TOKEN","LEGAL_CONTACT_EMAIL","ELASTICSEARCH_URL","ELASTICSEARCH_API_KEY","UPSTASH_REDIS_REST_URL","UPSTASH_REDIS_REST_TOKEN","NEXT_PUBLIC_MEDIA_CDN_URL","CLOUDFLARE_R2_BUCKET","CLOUDFLARE_R2_ACCESS_KEY_ID","CLOUDFLARE_R2_SECRET_ACCESS_KEY","WEB_VITALS_ENDPOINT_URL"],"missingOptionalEnvironment":[],"ownerInputs":["Deployed URL","Approval to run read-only checks against production"],"verification":["TZV3_BASE_URL=https://your-domain.example npm run preflight:production","npm run github-ci:audit","npm run secrets:rotation -- --require-production","npm run env:check:production","npm run origin:audit -- --require-production","npm run evidence:audit -- --require-production","curl -s https://your-domain.example/api/infrastructure/production-evidence","npm run admin:audit","npm run database:seed-payload","npm run database:audit","npm run cloudflare:audit","npm run media:public-urls","npm run media:audit","npm run pwa-push:audit","npm run legal:audit","npm run reviews:audit","npm run schedule:provider-handoff","npm run schedule:provider-import-payload","npm run schedule:provider-reconciliation -- --require-production","npm run schedule:links:audit","npm run schedule:audit","npm run search:bulk-payload","npm run search:audit","npm run telegram:handoff","npm run telegram:audit","npm run club:handoff","npm run vitals:audit","TZV3_BASE_URL=https://your-domain.example npm run readiness","TZV3_BASE_URL=https://your-domain.example npm run seo:audit","TZV3_BASE_URL=https://your-domain.example npm run load:smoke"],"nextAction":"Set DATABASE_URL, ADMIN_API_TOKEN, ADMIN_SESSION_SECRET..."}]},"cloudflare":{"version":"tzv3-cloudflare-policy-v1","endpoint":"/api/infrastructure/cloudflare/policy","provider":"policy-only","configured":false,"requiredEnvironment":["CLOUDFLARE_ACCOUNT_ID","CLOUDFLARE_ZONE_ID","CLOUDFLARE_API_TOKEN"],"optionalEnvironment":["MIRROR_DOMAINS","PRIMARY_DOMAIN_CHECK_URL","MIRROR_TELEGRAM_ALERT_URL"],"dns":{"required":true,"proxyMode":"orange-cloud","tlsMode":"Full (strict)","redirects":["http-to-https","apex-to-canonical-if-needed"]},"waf":{"mode":"managed-rules-plus-custom-rules","requiredRules":[{"id":"block-known-scrapers","action":"block","expression":"(http.user_agent contains \"scrapy\") or (http.user_agent contains \"python-requests\")"},{"id":"challenge-api-bursts","action":"managed_challenge","expression":"(http.request.uri.path contains \"/api/\") and cf.threat_score gt 20"},{"id":"protect-admin","action":"managed_challenge","expression":"http.request.uri.path contains \"/admin\""}]},"rateLimits":[{"id":"public-api","scope":"/api/*","limit":"120 requests per minute per IP","action":"managed_challenge"},{"id":"webhook","scope":"/api/webhooks/*","limit":"30 requests per minute per IP","action":"block-after-threshold"},{"id":"admin","scope":"/api/admin/*","limit":"60 requests per minute per IP","action":"managed_challenge"}],"cacheRules":[{"id":"static-assets","expression":"http.request.uri.path contains \"/_next/static/\" or http.request.uri.path contains \"/models/\" or http.request.uri.path contains \"/videos/\"","ttl":"30 days","cacheStatus":"eligible"},{"id":"api-no-store","expression":"http.request.uri.path contains \"/api/\"","ttl":"respect-origin-no-store","cacheStatus":"bypass"}],"headers":{"originHeaders":["X-Content-Type-Options","X-Frame-Options","Referrer-Policy","Permissions-Policy"],"cloudflareManaged":["Strict-Transport-Security after TLS verification","Bot Fight Mode or WAF managed rules"]},"monitoring":{"mirrorAlertsConfigured":false,"mirrorPolicyEndpoint":"/api/infrastructure/mirrors/policy","mirrorCheckEndpoint":"/api/infrastructure/mirrors/check","requiredBeforeLaunch":["canonical domain reachable","HTTPS certificate valid","WAF rules active","rate limits active"]},"verification":["npm run cloudflare:audit","curl -I https://your-domain.example","curl -s -A Scrapy/2.11 https://your-domain.example/api/profiles","curl -s https://your-domain.example/api/security/policy","curl -s https://your-domain.example/api/infrastructure/cloudflare/policy","curl -s https://your-domain.example/api/infrastructure/mirrors/check"],"productionBoundary":"This policy is a machine-readable setup contract. Actual DNS, WAF, cache, and rate-limit changes must be applied and verified inside Cloudflare."},"legalContact":{"version":"tzv3-legal-contact-v1","endpoint":"/api/legal/contact-policy","pages":{"legalCenter":"/legal","takedown":"/legal/takedown","privacy":"/legal/privacy","retention":"/legal/data-retention","contentRules":"/legal/content-rules"},"linkedPolicies":{"retention":"/api/legal/retention-policy","dataRetentionRecord":"takedown-request"},"contact":{"env":"LEGAL_CONTACT_EMAIL","productionRequired":true,"configured":false,"validFormat":true,"invalidValueConfigured":false,"primaryChannel":"telegram-fallback","email":null,"mailto":null,"fallbackTelegram":"https://t.me/artesc_support"},"intake":{"localMode":"No local takedown form and no local ticket storage until an approved inbox or ticketing workflow is configured.","productionMode":"Use LEGAL_CONTACT_EMAIL or an approved legal inbox/ticketing workflow for takedown, deletion, correction, and data-subject requests.","requestTypes":["content takedown","copyright or image-rights claim","personal data correction","data deletion or restriction","legal hold or dispute notice"],"requiredFields":["page URL or profile slug","claim summary","relationship to the material","verification evidence when applicable","reply contact channel"]},"serviceLevels":{"acknowledgementTarget":"within 2 business days","urgentContentReviewTarget":"same business day when credible safety, consent, or rights risk is identified","standardResolutionTarget":"within 10 business days unless legal hold or external-provider review is required"},"controls":["Do not store legal request payloads in the public site runtime.","Do not publish disputed content changes automatically from an inbound request.","Escalate credible consent, rights, or age-related reports to manual review.","Record final moderation decisions in admin audit logs when production database is connected.","Coordinate deletion across schedule, Telegram, media, analytics, search, and database providers when the request touches external systems."],"productionReady":false,"productionBlockers":["LEGAL_CONTACT_EMAIL is missing"],"legalPages":[{"slug":"terms","path":"/legal/terms","title":"Условия использования"},{"slug":"privacy","path":"/legal/privacy","title":"Политика конфиденциальности"},{"slug":"data-retention","path":"/legal/data-retention","title":"Хранение данных"},{"slug":"content-rules","path":"/legal/content-rules","title":"Правила контента"},{"slug":"takedown","path":"/legal/takedown","title":"Жалобы и удаление материалов"}]},"tzv3":{"version":"tzv3-completion-audit-v1","generatedAt":"2026-06-30T13:15:57.836Z","completionPercent":80,"localReady":true,"productionReady":false,"summary":{"done":0,"partial":11,"missing":0,"external":0,"rejected":1},"countsByClass":{"local-ready":0,"production-blocked":10,"implementation-open":0,"external-service":1,"rejected":1},"ownerInputs":["финальное визуальное approval по ARTESC.SHOP palette","approved PWA push provider env","production DATABASE_URL","admin secret ownership decision","Elastic/Redis provider decision","Supabase/Neon/PostgreSQL DATABASE_URL","production region decision","real provider data for schedule tenant site=artesc","server-side schedule API base URL only if iframe/widget is not enough","schedule API token only if optional server API requires auth","Telegram verification workflow","legal/payment approval before subscriptions","Telegram bot/workflow","TELEGRAM_WEBHOOK_SECRET","OPENAI_API_KEY","OPENAI_MODEL","approved translation provider keys","final production domain","production DB inventory","approved analytics/search console access","LEGAL_CONTACT_EMAIL","final legal review","final jurisdiction/payment model decision","production domain","CDN/R2 decision","analytics or Web Vitals sink","actual Artesc website Vercel project","final domain/DNS/Cloudflare access","production env values"],"productionBlockers":["проверить frontend на preview/final domain через Browser/Lighthouse","approved PWA push provider is not configured","production database is not connected","Elastic/Redis are not configured or indexed","migrations are not applied to production","seed import is not verified against production DB","site=artesc currently returns providers: []","external VIP verification workflow is not connected","subscription/payment flow is intentionally disabled","Telegram bot is not connected","production webhook secret is not configured","OpenAI/translation/media providers are not configured","real generated or translated drafts have not passed admin content-review in production","technical SEO audits have not run against the final domain","real moderated reviews are not seeded in production","legal text is not lawyer-approved","dedicated legal contact is not configured","Lighthouse/Web Vitals are not verified on final domain","Cloudflare R2/CDN is not configured or uploaded",".vercel/project.json currently points to australia-wlkk","required production env variables are missing","Cloudflare/DNS/WAF setup is not externally verified"],"rejectedItems":[{"area":"Накрутка поведенческих факторов","safetyNote":"Deceptive user-imitation automation is intentionally not implemented. The project uses compliant retention, performance, and real-content SEO instead."}],"items":[{"area":"Frontend / премиальный каталог","status":"partial","evidence":["Next.js App Router, React 18, TypeScript, Tailwind","Добавлены TanStack Query, React Hook Form, Zod resolver и Framer Motion","Smart Match использует TanStack mutation и Framer Motion для результатов","VIP Club verification форма использует React Hook Form + Zod resolver","Главная, карточки, фильтры без перезагрузки, страницы анкет, подборки","Добавлено privacy-first избранное: карточки, страница /favorites и localStorage policy","Добавлен Smart Match блок на главной для подбора по фразе","Добавлены реальные lazy video-визитки MP4 для карточек и страниц анкет","Добавлен PWA/offline shell с manifest, service worker и /offline","Добавлен explicit PWA push opt-in на /favorites: browser permission, privacy checkbox, provider forwarding и DELETE unsubscribe через /api/pwa/push/subscribe","Добавлен /api/pwa/push/audit-policy и npm run pwa-push:audit как no-write production gate для VAPID/provider/delete evidence","Добавлена закрытая зона /club с VIP/Private preview и заявкой на верификацию","Добавлена /intl страница с EN/AR/ZH translation preview","Фильтры каталога синхронизируются с URL query params без reload","Визуальная палитра приведена к оригинальному ARTESC.SHOP","Добавлен /api/frontend/brand и npm run brand:audit: no-network gate точного ARTESC.SHOP accent #db006e, ink #212331 и premium typography guard","Header, metadata и OpenGraph используют бренд ARTESC.SHOP вместо временного ART-ESCORT","Применен owner-supplied premium-website.skill: шрифтовой стек без Inter, editorial hero, SVG icon strip, subtle grain, PremiumMotion scroll reveal, premium-lift hover depth и reduced-motion fallback","Browser QA на localhost подтвердила отсутствие горизонтального overflow на главной и странице анкеты в mobile viewport 390px","На мобильной странице анкеты добавлены ранний CTA после intro/цены и sticky-панель действий с profile-aware ссылкой в готовое расписание","Добавлен shadcn-compatible UI primitive layer: Button, AnchorButton, buttonVariants, Panel и panelVariants"],"next":["production Lighthouse/preview approval","approved PWA push provider env + provider-side delete/export evidence"],"completionClass":"production-blocked","completionPercent":97,"ownerInputs":["финальное визуальное approval по ARTESC.SHOP palette","approved PWA push provider env"],"productionBlockers":["проверить frontend на preview/final domain через Browser/Lighthouse","approved PWA push provider is not configured"]},{"area":"Backend / API","status":"partial","evidence":["Read API для каталога, анкет, подборок, статусов","Zod-валидация входных параметров","Добавлен /api/match как Smart Match контракт для natural-language подбора","Добавлены /api/media/video-policy и /api/pwa/policy","Добавлен /api/security/policy и app-level proxy guard против scraping/rate-limit","Защищенный admin CRUD-контракт через x-admin-token","Добавлен защищенный /api/admin/audit и публичный /api/admin/audit/policy для audit log контракта","Добавлены /api/club/policy и /api/club/verify для VIP Club verification workflow","Добавлены /api/i18n/policy, /api/i18n/profiles и /api/i18n/profiles/[slug] для авто-перевода","Добавлен /api/search/policy как контракт Elastic-ready мгновенного поиска","Добавлен Elastic/Upstash adapter для /api/search с Redis cache keys на SHA-256 и local fallback","Добавлен /api/search/index-manifest с Elastic mapping, settings, документами профилей и sha256 hashes для production index import","Добавлен /api/search/bulk-payload и npm run search:bulk-payload для copy-ready Elastic create-index body и bulk NDJSON","Добавлен read-only npm run search:audit для проверки Elastic _search и Upstash Redis GET перед production launch","Публичные /api/profiles, /api/profiles/[slug], /api/collections и /api/search переключаются на PostgreSQL при наличии DATABASE_URL","Добавлен /api/admin/session для подписанной HttpOnly admin-сессии с header fallback","Операторский /admin/profiles UI блокирует редактор до активной HttpOnly admin session; x-admin-token остается только API/script fallback","Добавлен /api/admin/security-audit-policy и npm run admin:audit как no-write gate для HttpOnly session, noindex admin shell и anonymous rejection","Защищенный /api/admin/seo-copy генерирует draft SEO-текста без автосохранения","Добавлен /api/filters для URL-фильтров каталога","Есть /admin/profiles для операторского upsert/delete анкет"],"next":["подключить БД в production","импортировать search bulk payload в Elastic Cloud","provider-backed NextAuth/SSO поверх admin UI"],"completionClass":"production-blocked","completionPercent":85,"ownerInputs":["production DATABASE_URL","admin secret ownership decision","Elastic/Redis provider decision"],"productionBlockers":["production database is not connected","Elastic/Redis are not configured or indexed"]},{"area":"База данных","status":"partial","evidence":["Добавлены Drizzle/PostgreSQL schema и SQL migration","Добавлен /api/database/bootstrap-policy для migration/seed/runbook контракта","Добавлен /api/database/audit-policy с SELECT-only query inventory, required env, expected tables/indexes, seed baseline и no-secret boundary","Добавлен /api/database/migration-manifest с read-only sha256 manifest для SQL миграций","Добавлен /api/database/seed-manifest с read-only counts/sha256 manifest для static seed baseline","Добавлен /api/database/seed-payload и npm run database:seed-payload для no-write экспорта точного payload перед POST /api/admin/seed","Runtime умеет работать в static-seed режиме без DATABASE_URL","Добавлен защищенный /api/admin/seed для импорта seed-анкет, media assets, services, подборок и связей в PostgreSQL","Admin write-операции фиксируются в admin_audit_logs при подключенной PostgreSQL"],"next":["подключить Supabase/Neon DATABASE_URL","применить миграции","запустить seed import и сверить production data через /api/health"],"completionClass":"production-blocked","completionPercent":74,"ownerInputs":["Supabase/Neon/PostgreSQL DATABASE_URL","production region decision"],"productionBlockers":["migrations are not applied to production","seed import is not verified against production DB"]},{"area":"Отдельное расписание","status":"partial","evidence":["Все CTA ведут в NEXT_PUBLIC_SCHEDULE_URL с profile-параметром","Готовый schedule-проект подключен через iframe/widget: https://australia-wlkk.vercel.app","Скрытая /schedule-preview страница встраивает site=artesc и поддерживает site-next только для временной визуальной QA","Добавлен /api/schedule/provider-handoff-policy и npm run schedule:provider-handoff для profile-mapped provider drafts перед наполнением site=artesc","Добавлен /api/schedule/provider-import-payload и npm run schedule:provider-import-payload для copy-ready providerImportPayload в готовый schedule admin/import","Добавлен /api/schedule/provider-reconciliation и npm run schedule:provider-reconciliation для сверки импортируемых provider IDs с публичным tenant site=artesc","Добавлен /api/schedule/link-audit-policy и npm run schedule:links:audit для read-only проверки profile/site/lang ссылок каталога в готовое расписание","npm run schedule:audit подтверждает iframe 200 и JS widget 200; production tenant site=artesc пока возвращает 0 providers","Добавлены /api/schedule/status, /api/schedule/availability и /api/schedule/request","Локальный режим dry-run-static валидирует payload и возвращает seed-слоты без фиктивного бронирования","SCHEDULE_API_URL переведен в optional server adapter: iframe/widget остаются основным способом подключения готового расписания","Добавлен read-only /api/schedule/tenant-status для проверки provider count у site=artesc внутри Artesc site","/api/schedule/status отдает copy-ready iframe/widget snippets, draft QA URL и production QA URL"],"next":["завести реальные providers для site=artesc","подключить optional SCHEDULE_API_URL/API contract только если нужен server-side forwarding","синхронизация статусов"],"completionClass":"external-service","completionPercent":89,"ownerInputs":["real provider data for schedule tenant site=artesc","server-side schedule API base URL only if iframe/widget is not enough","schedule API token only if optional server API requires auth"],"productionBlockers":["site=artesc currently returns providers: []"]},{"area":"VIP-клуб / закрытая зона","status":"partial","evidence":["Добавлена страница /club с закрытым позиционированием и preview VIP/Private анкет","Добавлен dry-run /api/club/verify с Zod-валидацией 18+ и privacy consent","Добавлен /api/club/policy с отключенными платежами/подписками до legal/payment approval","Добавлен browser-session gate для /club: после валидной заявки создается 12-часовая sessionStorage сессия с ticket id и scope vip-preview-links","Контур готов к внешнему Telegram workflow через VIP_CLUB_WEBHOOK_URL","Внешний VIP webhook получает ticketId, idempotency header, timestamp и HMAC-SHA256 подпись при VIP_CLUB_WEBHOOK_TOKEN","Добавлен /api/club/handoff-policy и npm run club:handoff как no-secret external receiver contract для headers, HMAC, idempotency и human approval","Добавлен /api/club/audit-policy и npm run club:audit как no-write production gate без создания verification tickets"],"next":["подключить Telegram verification bot","утвердить payment/legal model перед подписками"],"completionClass":"production-blocked","completionPercent":75,"ownerInputs":["Telegram verification workflow","legal/payment approval before subscriptions"],"productionBlockers":["external VIP verification workflow is not connected","subscription/payment flow is intentionally disabled"]},{"area":"Telegram / live-статусы","status":"partial","evidence":["Подготовлен webhook-контур для статусов","Webhook проверяет x-telegram-bot-api-secret-token и x-webhook-token constant-time при TELEGRAM_WEBHOOK_SECRET","Webhook принимает готовый JSON payload и raw Telegram message.text команды: /status, /available, /tonight, /private","Webhook принимает нативный Telegram secret header x-telegram-bot-api-secret-token из setWebhook(secret_token) и кастомный x-webhook-token для relay workflow","Добавлен /api/webhooks/telegram/setup-policy и npm run telegram:handoff как no-secret BotFather/setWebhook handoff без вызова Telegram API","Добавлен npm run telegram:audit: проверка policy, wrong-token 401 и invalid-payload 422 без записи статуса","Webhook ищет анкеты DB-first и использует static seed только в local fallback","Webhook пишет status event в PostgreSQL при наличии DATABASE_URL","Добавлен /api/status/stream как SSE-контракт для браузерных live-статусов","Карточки каталога, фильтр статусов и страницы анкет подписываются на stream через LiveStatusBadge/useLiveStatuses"],"next":["выполнить Telegram setWebhook или подключить relay workflow","production TELEGRAM_WEBHOOK_SECRET","pub/sub или database notification channel для мгновенной доставки между heartbeat-снимками"],"completionClass":"production-blocked","completionPercent":76,"ownerInputs":["Telegram bot/workflow","TELEGRAM_WEBHOOK_SECRET"],"productionBlockers":["Telegram bot is not connected","production webhook secret is not configured"]},{"area":"AI-инновации / авто-перевод","status":"partial","evidence":["Добавлен AI/SEO copy contract с безопасным draft-режимом","Admin-only SEO copy endpoint вызывает OpenAI Responses API при OPENAI_API_KEY и валидирует JSON через Zod","При ошибке OpenAI endpoint возвращает template fallback без автосохранения","Добавлен deterministic dry-run перевод профилей на EN/AR/ZH","Добавлена страница /intl с preview переводов каталога","Добавлены /api/i18n/policy, /api/i18n/profiles?lang= и /api/i18n/profiles/[slug]?lang=","Добавлен /api/content-review/policy и защищенный /api/admin/content-review для ручного review generated/translated drafts без автопубликации","Добавлен /api/media/enhancement-policy для upscaling/color correction pipeline с human review","Добавлен /api/media/asset-manifest с publicPath/R2 key/contentType/bytes/sha256 для CDN/R2 upload contract","Добавлен /api/media/public-url-policy и npm run media:public-urls для проверки production-safe HTTPS media URLs перед CDN/schedule import","Media/CDN env теперь production-required, а npm run media:audit проверяет CDN assets и R2 env без записи медиа","Контракт готов к Google Translate или approved LLM provider через GOOGLE_TRANSLATE_API_KEY"],"next":["задать OPENAI_API_KEY и OPENAI_MODEL в production","подключить production translation provider","загрузить media asset manifest в R2/CDN","подключить approved media enhancement provider","прогнать реальные generated/translated drafts через admin content-review","решить какие языковые страницы индексировать"],"completionClass":"production-blocked","completionPercent":75,"ownerInputs":["OPENAI_API_KEY","OPENAI_MODEL","approved translation provider keys"],"productionBlockers":["OpenAI/translation/media providers are not configured","real generated or translated drafts have not passed admin content-review in production"]},{"area":"SEO","status":"partial","evidence":["Metadata, sitemap, robots, JSON-LD WebSite/LocalBusiness/Person/Service/CollectionPage","Добавлены ручные и seed-generated programmatic SEO страницы /spb/... и /api/seo/pages","Добавлена PostgreSQL-ready таблица programmatic_seo_pages и seed import всей URL matrix","/api/seo/pages, /spb/... и sitemap используют DB-first inventory при наличии DATABASE_URL","Интерактивные URL-фильтры получают canonical / и X-Robots-Tag noindex, follow","Добавлен безопасный policy для Review/AggregateRating JSON-LD без синтетических отзывов","Добавлен /api/reviews, /api/reviews/policy и /api/admin/reviews для реального intake/moderation отзывов","Profile JSON-LD и /api/seo/review-schema теперь используют PostgreSQL published moderated reviews при наличии DATABASE_URL","Добавлен /api/reviews/audit-policy и npm run reviews:audit как no-write gate для real-review JSON-LD без synthetic reviews","Добавлен AI/SEO copy contract: /api/seo/copy-policy и admin draft endpoint","Добавлен Smart Match policy для future OpenAI/embeddings provider","Добавлен Elastic-ready search policy для мгновенного поиска и Redis cache boundary","Добавлен search index manifest для Elastic mapping/document hashes перед импортом индекса","Добавлен search bulk payload для Elastic create-index body и bulk NDJSON перед search:audit","Добавлен npm run search:audit как production gate для Elastic/Redis без записи поисковых данных","Добавлен /api/growth/safe-policy по high-risk skills v2: быстрый рост без фейков, ботов и обходов","Добавлен npm run seo:audit и /api/seo/technical-audit/policy для проверки sitemap, robots, canonical, JSON-LD и noindex","Video-визитки подключены лениво, без индексации отдельного media мусора"],"next":["подключить production DB для реальных moderated reviews","импортировать search bulk payload и подключить Elastic/Redis","подключить approved OpenAI/embeddings provider","прогнать TZV3_BASE_URL на production domain"],"completionClass":"production-blocked","completionPercent":76,"ownerInputs":["final production domain","production DB inventory","approved analytics/search console access"],"productionBlockers":["technical SEO audits have not run against the final domain","real moderated reviews are not seeded in production"]},{"area":"Юридический контур","status":"partial","evidence":["Есть age gate","Добавлены /legal, /legal/terms, /legal/privacy, /legal/content-rules и /legal/takedown","Добавлены /legal/data-retention и /api/legal/retention-policy для сроков хранения и удаления данных","Добавлен /api/legal/contact-policy для dedicated inbox requirement, takedown/data-subject request fields, SLA targets и no-local-storage boundary","Добавлен /api/legal/audit-policy и npm run legal:audit как no-write production gate для legal pages, retention records и dedicated inbox","Описаны правила 18+, роль каталога, privacy, модерация контента и takedown-процесс","LEGAL_CONTACT_EMAIL теперь является обязательным production env и readiness fail-gate для takedown/data-subject канала","Добавлен safe-growth policy: запрет фейковых отзывов/профилей, ботов, обходов и агрессивного парсинга"],"next":["финальная проверка юристом","выделенный legal/contact email через LEGAL_CONTACT_EMAIL"],"completionClass":"production-blocked","completionPercent":76,"ownerInputs":["LEGAL_CONTACT_EMAIL","final legal review","final jurisdiction/payment model decision"],"productionBlockers":["legal text is not lawyer-approved","dedicated legal contact is not configured"]},{"area":"Производительность","status":"partial","evidence":["Next Image, static generation, AVIF/WebP formats, успешный production build","MP4 video-визитки суммарно занимают около 124 KB и грузятся лениво","Добавлен media asset manifest для полного CDN/R2 inventory всех public model/video assets","Добавлен media public URL policy для проверки production-safe HTTPS URLs всех model/video assets","Добавлен PWA offline shell с runtime cache для статических/media assets","Добавлен /api/performance/budget с Web Vitals и route-response бюджетами","Добавлен WebVitalsReporter и /api/performance/vitals для browser field metrics","WEB_VITALS_ENDPOINT_URL теперь production-required, а npm run vitals:audit проверяет endpoint без POST метрик","Добавлен Vitest unit-test контур для фильтров, Smart Match, VIP Club schema и admin session","Добавлен npm run env:check для deploy/env readiness","Добавлен npm run load:smoke и /api/quality/load-policy для легкого read-only stress smoke","Добавлен npm run readiness для smoke-проверки критичных маршрутов и SSE","Добавлен npm run seo:audit как release gate для technical SEO","Добавлен npm run media:audit как read-only gate для CDN delivery и R2 env","Добавлен npm run vitals:audit как no-write gate для approved Web Vitals sink","Добавлен npm run pwa-push:audit как no-write gate для PWA push provider readiness"],"next":["Lighthouse на реальном домене","полноценное provider-side load testing после WAF/rate-limit approval","подключить WEB_VITALS_ENDPOINT_URL или approved analytics","загрузить manifest assets в R2/CDN"],"completionClass":"production-blocked","completionPercent":83,"ownerInputs":["production domain","CDN/R2 decision","analytics or Web Vitals sink"],"productionBlockers":["Lighthouse/Web Vitals are not verified on final domain","Cloudflare R2/CDN is not configured or uploaded"]},{"area":"Инфраструктура / деплой","status":"partial","evidence":["Есть netlify.toml, env example, health endpoint, readiness endpoint и security headers","Добавлен vercel.json для Vercel Next.js деплоя","Добавлен /api/infrastructure/deployment/policy и npm run env:check:production для production env gate","Добавлен no-network npm run vercel:link:audit и production preflight guard против deploy/env writes в protected schedule project australia-wlkk","Добавлен /api/infrastructure/vercel-link для read-only проверки, что проект привязан к website project, а не к australia-wlkk schedule project","Добавлен /api/infrastructure/public-origin-policy и npm run origin:audit для проверки canonical domain, schedule URL, media CDN, route proofs и Vercel link guard","Добавлен /api/infrastructure/production-evidence и npm run evidence:audit как no-write манифест evidence-команд по всем blocking launch stages","Добавлен /api/infrastructure/owner-inputs и npm run owner-inputs для no-secret owner-input packet по всем production stages","Добавлен /api/infrastructure/secret-rotation и npm run secrets:rotation для no-write разделения generated secrets, owner/provider credentials, public defaults и post-rotation audits","Добавлен GitHub Actions workflow .github/workflows/tzv3-ci.yml, /api/infrastructure/ci-policy и npm run ci:audit для no-write TZV3 quality gate на push/pull_request main","Добавлен /api/infrastructure/source-control и npm run source:audit для no-network проверки owner-supplied GitHub repo parkourcafe/artesc перед Vercel env/deploy","/admin показывает production gap matrix и owner-input critical path, включая provider-data blocker для готового schedule tenant site=artesc","Proxy применяет X-Robots-Tag для фильтров, блокирует известные scraping user-agents на API и отдает X-RateLimit headers","Добавлены /api/infrastructure/mirrors/policy и /api/infrastructure/mirrors/check для мониторинга основного домена и зеркал","Добавлен read-only npm run cloudflare:audit для проверки Cloudflare zone settings и rulesets без внесения изменений","Production preflight включает no-write gates для secret rotation, public origin, production evidence, admin, schedule provider handoff, schedule provider import payload, schedule link audit, schedule provider audit, media public URLs, media CDN audit, PWA push, legal, reviews, search, vitals, database, Telegram, VIP Club и Cloudflare"],"next":["реальный Vercel/Cloudflare проект","задать production env без placeholder","WAF/rate limit настройки в Cloudflare","прогнать npm run cloudflare:audit","настроить MIRROR_DOMAINS и Cloudflare failover"],"completionClass":"production-blocked","completionPercent":78,"ownerInputs":["actual Artesc website Vercel project","final domain/DNS/Cloudflare access","production env values"],"productionBlockers":[".vercel/project.json currently points to australia-wlkk","required production env variables are missing","Cloudflare/DNS/WAF setup is not externally verified"]},{"area":"Накрутка поведенческих факторов","status":"rejected","evidence":["Не реализуется как deceptive automation","Добавлена легальная retention-механика: локальное избранное без серверного tracking"],"next":["видео-визитки","opt-in PWA push для избранного после privacy review"],"completionClass":"rejected","completionPercent":100,"ownerInputs":[],"productionBlockers":[],"safetyNote":"Deceptive user-imitation automation is intentionally not implemented. The project uses compliant retention, performance, and real-content SEO instead."}]}}}